port fix from branch_1_1
authoraland <aland>
Mon, 26 Mar 2007 09:49:19 +0000 (09:49 +0000)
committeraland <aland>
Mon, 26 Mar 2007 09:49:19 +0000 (09:49 +0000)
608 files changed:
INSTALL
Make.inc.in
Makefile
README
acconfig.h [deleted file]
acinclude.m4 [new file with mode: 0644]
aclocal.m4
autogen.sh [new file with mode: 0755]
config.guess
config.h.in [deleted file]
config.sub
configure
configure.in
debian/changelog
debian/copyright
debian/freeradius-dialupadmin.dirs [new file with mode: 0644]
debian/freeradius-dialupadmin.docs [new file with mode: 0644]
debian/freeradius-dialupadmin.examples [new file with mode: 0644]
debian/freeradius-dialupadmin.links [new file with mode: 0644]
debian/freeradius.examples
debian/freeradius.init
dialup_admin/Changelog
dialup_admin/README
dialup_admin/bin/backup_radacct [new file with mode: 0755]
dialup_admin/bin/clean_radacct
dialup_admin/bin/clearsession [new file with mode: 0755]
dialup_admin/bin/log_badlogins
dialup_admin/bin/monthly_tot_stats
dialup_admin/bin/snmpfinger
dialup_admin/bin/sqlrelay_query [new file with mode: 0755]
dialup_admin/bin/tot_stats
dialup_admin/bin/truncate_radacct
dialup_admin/conf/admin.conf
dialup_admin/conf/config.php3
dialup_admin/conf/extra.ldap-attrmap
dialup_admin/conf/naslist.conf
dialup_admin/conf/sql.attrmap
dialup_admin/conf/user_edit.attrs
dialup_admin/conf/username.mappings
dialup_admin/doc/AUTHORS
dialup_admin/doc/FAQ
dialup_admin/doc/TODO
dialup_admin/htdocs/about.html
dialup_admin/htdocs/accounting.php3
dialup_admin/htdocs/badusers.php3
dialup_admin/htdocs/buttons.php3
dialup_admin/htdocs/clear_opensessions.php3
dialup_admin/htdocs/content.html
dialup_admin/htdocs/failed_logins.php3
dialup_admin/htdocs/find.php3
dialup_admin/htdocs/group_admin.php3
dialup_admin/htdocs/group_new.php3
dialup_admin/htdocs/help/help.php3
dialup_admin/htdocs/index.html
dialup_admin/htdocs/login_time_create.php3
dialup_admin/htdocs/nas_admin.php3
dialup_admin/htdocs/session_destroy.php3
dialup_admin/htdocs/show_groups.php3
dialup_admin/htdocs/stats.php3
dialup_admin/htdocs/style.css
dialup_admin/htdocs/user_accounting.php3
dialup_admin/htdocs/user_admin.php3
dialup_admin/htdocs/user_delete.php3
dialup_admin/htdocs/user_edit.php3
dialup_admin/htdocs/user_finger.php3
dialup_admin/htdocs/user_info.php3
dialup_admin/htdocs/user_new.php3
dialup_admin/htdocs/user_state.php3
dialup_admin/htdocs/user_stats.php3
dialup_admin/htdocs/user_test.php3
dialup_admin/html/buttons/default/buttons.html.php3
dialup_admin/html/group_toolbar.html.php3
dialup_admin/html/user_admin.html.php3
dialup_admin/html/user_toolbar.html.php3
dialup_admin/lib/acctshow.php3
dialup_admin/lib/add_badusers.php3
dialup_admin/lib/attrshow.php3
dialup_admin/lib/defaults.php3
dialup_admin/lib/functions.php3
dialup_admin/lib/ldap/attrmap.php3
dialup_admin/lib/ldap/defaults.php3
dialup_admin/lib/ldap/find.php3
dialup_admin/lib/ldap/functions.php3
dialup_admin/lib/ldap/user_info.php3
dialup_admin/lib/missing.php3 [new file with mode: 0644]
dialup_admin/lib/sql/attrmap.php3
dialup_admin/lib/sql/change_attrs.php3
dialup_admin/lib/sql/change_passwd.php3
dialup_admin/lib/sql/create_group.php3
dialup_admin/lib/sql/create_user.php3
dialup_admin/lib/sql/defaults.php3
dialup_admin/lib/sql/drivers/dbx/functions.php3 [new file with mode: 0644]
dialup_admin/lib/sql/drivers/mysql/functions.php3
dialup_admin/lib/sql/drivers/oracle/functions.php3 [new file with mode: 0644]
dialup_admin/lib/sql/drivers/pg/functions.php3
dialup_admin/lib/sql/drivers/sqlrelay/functions.php3 [new file with mode: 0644]
dialup_admin/lib/sql/find.php3
dialup_admin/lib/sql/functions.php3
dialup_admin/lib/sql/group_change.php3 [new file with mode: 0644]
dialup_admin/lib/sql/group_info.php3
dialup_admin/lib/sql/nas_list.php3 [new file with mode: 0644]
dialup_admin/lib/sql/password_check.php3
dialup_admin/lib/xlat.php3 [new file with mode: 0644]
dialup_admin/sql/mysql/badusers.sql [moved from dialup_admin/sql/badusers.sql with 80% similarity]
dialup_admin/sql/mysql/mtotacct.sql [moved from dialup_admin/sql/mtotacct.sql with 100% similarity]
dialup_admin/sql/mysql/totacct.sql [moved from dialup_admin/sql/totacct.sql with 100% similarity]
dialup_admin/sql/mysql/userinfo.sql [moved from dialup_admin/sql/userinfo.sql with 91% similarity]
dialup_admin/sql/oracle/badusers.sql [new file with mode: 0644]
dialup_admin/sql/oracle/mtotacct.sql [new file with mode: 0644]
dialup_admin/sql/oracle/totacct.sql [new file with mode: 0644]
dialup_admin/sql/oracle/userinfo.sql [new file with mode: 0644]
dialup_admin/sql/postgresql/badusers.sql [new file with mode: 0644]
dialup_admin/sql/postgresql/mtotacct.sql [new file with mode: 0644]
dialup_admin/sql/postgresql/totacct.sql [new file with mode: 0644]
dialup_admin/sql/postgresql/userinfo.sql [new file with mode: 0644]
doc/ChangeLog
doc/DIFFS
doc/Post-Auth-Type
doc/RADIUS-SQL.schema
doc/README
doc/ascend
doc/configurable_failover
doc/duplicate-users [deleted file]
doc/examples/iplanet.ldif [new file with mode: 0644]
doc/examples/iplanet.schema [new file with mode: 0644]
doc/examples/mssql.sql
doc/examples/mysql.sql
doc/examples/openldap.schema [new file with mode: 0644]
doc/examples/oracle.sql
doc/examples/postgresql.sql
doc/examples/postgresql_update_radacct_group_trigger.sql [new file with mode: 0644]
doc/ldap_howto.txt
doc/load-balance.txt
doc/radrelay [deleted file]
doc/rfc/Makefile
doc/rfc/attributes.html
doc/rfc/genref.pl
doc/rfc/per-rfc.pl [new file with mode: 0755]
doc/rfc/rewrite.pl
doc/rfc/rfc2607.txt [new file with mode: 0644]
doc/rfc/rfc3748.txt [new file with mode: 0644]
doc/rfc/rfc4590.txt [new file with mode: 0644]
doc/rfc/update.sh [new file with mode: 0755]
doc/rlm_attr_filter [deleted file]
doc/rlm_digest [deleted file]
doc/rlm_expiration [new file with mode: 0644]
doc/rlm_ldap
doc/rlm_sql
doc/rlm_sqlcounter
doc/rlm_sqlippool
doc/variables.txt
libltdl/ltdl.c
ltconfig [deleted file]
man/man1/radclient.1
man/man1/radwho.1
man/man1/radzap.1
man/man5/clients.5
man/man5/clients.conf.5 [new file with mode: 0644]
man/man5/naslist.5
man/man5/radrelay.conf.5 [new file with mode: 0644]
man/man5/rlm_attr_filter.5
man/man5/rlm_counter.5
man/man5/rlm_digest.5 [new file with mode: 0644]
man/man5/rlm_files.5
man/man5/rlm_mschap.5
man/man5/rlm_pap.5
man/man5/rlm_passwd.5
man/man5/rlm_policy.5 [new file with mode: 0644]
man/man5/rlm_realm.5
man/man5/rlm_sql_log.5
man/man5/rlm_unix.5
man/man8/radiusd.8
man/man8/radrelay.8
man/man8/radwatch.8
raddb/Makefile
raddb/acct_users
raddb/attrs
raddb/attrs.access_reject [new file with mode: 0644]
raddb/attrs.accounting_response [new file with mode: 0644]
raddb/attrs.pre-proxy [new file with mode: 0644]
raddb/clients [deleted file]
raddb/clients.conf
raddb/experimental.conf
raddb/ldap.attrmap
raddb/naslist [deleted file]
raddb/otp.conf
raddb/policy.txt [new file with mode: 0755]
raddb/postgresql.conf [deleted file]
raddb/preproxy_users
raddb/protocol_filter.conf [new file with mode: 0755]
raddb/proxy.conf
raddb/radiusd.conf.in
raddb/radrelay.conf.in [new file with mode: 0644]
raddb/sql.conf
raddb/sql/mssql-dialup.conf [moved from raddb/mssql.conf with 80% similarity]
raddb/sql/mysql-dialup.conf [new file with mode: 0644]
raddb/sql/oracle-dialup.conf [moved from raddb/oraclesql.conf with 84% similarity]
raddb/sql/postgresql-dialup.conf [new file with mode: 0644]
raddb/sql/postgresql-voip-postpaid.conf [moved from raddb/pgsql-voip.conf with 94% similarity]
raddb/sqlippool.conf
raddb/users
redhat/freeradius.spec
redhat/rc.radiusd-redhat
scripts/Makefile
scripts/certs.sh
scripts/clients.pl [new file with mode: 0755]
scripts/cryptpasswd.in
scripts/exec-program-wait
scripts/min-includes.pl [new file with mode: 0755]
scripts/radiusd2ldif.pl
scripts/rc.radiusd.in
scripts/xpextensions
share/Makefile [new file with mode: 0644]
share/dictionary
share/dictionary.ascend
share/dictionary.chillispot [new file with mode: 0644]
share/dictionary.cisco
share/dictionary.freeradius.internal
share/dictionary.lucent
share/dictionary.nortel [new file with mode: 0644]
share/dictionary.rfc4590 [deleted file]
share/dictionary.roaringpenguin
share/dictionary.schulzrinne-sipping [deleted file]
share/format.pl
src/Makefile
src/billing/README
src/billing/cisco_h323_db_sample_functions-postgres.sql
src/billing/cisco_h323_db_schema-postgres.sql
src/billing/h323detail2db.pl
src/include/Makefile
src/include/autoconf.h.in
src/include/conffile.h
src/include/hash.h [new file with mode: 0644]
src/include/ident.h [moved from src/modules/rlm_otp/ident.h with 100% similarity]
src/include/libradius.h
src/include/md4.h
src/include/md5.h
src/include/missing.h
src/include/modcall.h
src/include/modpriv.h
src/include/modules.h
src/include/packet.h [new file with mode: 0644]
src/include/rad_assert.h
src/include/radius.h
src/include/radius_snmp.h
src/include/radiusd.h
src/include/radsniff.h [new file with mode: 0644]
src/include/radutmp.h
src/include/request_list.h
src/include/smux.h
src/include/sysutmp.h
src/include/token.h
src/include/udpfromto.h
src/lib/LICENSE [new file with mode: 0644]
src/lib/Makefile
src/lib/README [new file with mode: 0644]
src/lib/dict.c
src/lib/fifo.c [new file with mode: 0644]
src/lib/filters.c
src/lib/getaddrinfo.c [new file with mode: 0644]
src/lib/hash.c
src/lib/hmac.c
src/lib/hmacsha1.c
src/lib/isaac.c
src/lib/log.c
src/lib/md4.c
src/lib/md5.c
src/lib/misc.c
src/lib/missing.c
src/lib/packet.c [new file with mode: 0644]
src/lib/print.c
src/lib/radius.c
src/lib/rbtree.c
src/lib/sha1.c
src/lib/snprintf.c
src/lib/snprintf.h
src/lib/strlcat.c [new file with mode: 0644]
src/lib/strlcpy.c [new file with mode: 0644]
src/lib/token.c
src/lib/udpfromto.c
src/lib/valuepair.c
src/main/00-OLD/Make.inc [deleted file]
src/main/00-OLD/Makefile [deleted file]
src/main/00-OLD/Makefile.BSD [deleted file]
src/main/00-OLD/Makefile.lnx [deleted file]
src/main/00-OLD/Makefile.osf [deleted file]
src/main/00-OLD/Makefile.sunos5 [deleted file]
src/main/Makefile.in
src/main/acct.c
src/main/auth.c
src/main/client.c
src/main/conffile.c
src/main/crypt.c [moved from src/lib/crypt.c with 64% similarity]
src/main/exec.c
src/main/files.c
src/main/listen.c [new file with mode: 0644]
src/main/log.c
src/main/mainconfig.c
src/main/modcall.c
src/main/modules.c
src/main/nas.c [deleted file]
src/main/proxy.c
src/main/radclient.c
src/main/radius_snmp.c
src/main/radiusd.c
src/main/radrelay.c [deleted file]
src/main/radsniff.c [new file with mode: 0644]
src/main/radwho.c
src/main/radzap [new file with mode: 0755]
src/main/radzap.c [deleted file]
src/main/request_list.c
src/main/request_process.c [new file with mode: 0755]
src/main/session.c
src/main/smux.c
src/main/threads.c
src/main/util.c
src/main/valuepair.c
src/main/version.c
src/main/xlat.c
src/modules/Makefile
src/modules/rlm_acct_unique/rlm_acct_unique.c
src/modules/rlm_acctlog/Makefile.in [new file with mode: 0644]
src/modules/rlm_acctlog/configure [moved from src/modules/rlm_eap/types/rlm_eap_md5/configure with 53% similarity]
src/modules/rlm_acctlog/configure.in [new file with mode: 0644]
src/modules/rlm_acctlog/rlm_acctlog.c [new file with mode: 0644]
src/modules/rlm_always/rlm_always.c
src/modules/rlm_attr_filter/rlm_attr_filter.c
src/modules/rlm_attr_rewrite/Makefile.in
src/modules/rlm_attr_rewrite/configure
src/modules/rlm_attr_rewrite/configure.in
src/modules/rlm_attr_rewrite/rlm_attr_rewrite.c
src/modules/rlm_caching/Makefile.in [new file with mode: 0644]
src/modules/rlm_caching/rlm_caching.c [new file with mode: 0644]
src/modules/rlm_chap/rlm_chap.c
src/modules/rlm_checkval/Makefile.in
src/modules/rlm_checkval/configure
src/modules/rlm_checkval/configure.in
src/modules/rlm_checkval/rlm_checkval.c
src/modules/rlm_copy_packet/Makefile [new file with mode: 0644]
src/modules/rlm_copy_packet/README [new file with mode: 0644]
src/modules/rlm_copy_packet/rlm_copy_packet.c [new file with mode: 0644]
src/modules/rlm_counter/acconfig.h [deleted file]
src/modules/rlm_counter/config.h.in
src/modules/rlm_counter/configure
src/modules/rlm_counter/configure.in
src/modules/rlm_counter/rad_counter.pl
src/modules/rlm_counter/rlm_counter.c
src/modules/rlm_cram/rlm_cram.c
src/modules/rlm_dbm/configure
src/modules/rlm_dbm/configure.in
src/modules/rlm_dbm/rlm_dbm.c
src/modules/rlm_dbm/rlm_dbm_cat.c
src/modules/rlm_dbm/rlm_dbm_parser.c
src/modules/rlm_detail/rlm_detail.c
src/modules/rlm_digest/rlm_digest.c
src/modules/rlm_eap/configure
src/modules/rlm_eap/configure.in
src/modules/rlm_eap/eap.c
src/modules/rlm_eap/eap.h
src/modules/rlm_eap/libeap/Makefile
src/modules/rlm_eap/libeap/cb.c
src/modules/rlm_eap/libeap/eap_sim.h
src/modules/rlm_eap/libeap/eap_tls.c
src/modules/rlm_eap/libeap/eap_tls.h
src/modules/rlm_eap/libeap/eap_types.h
src/modules/rlm_eap/libeap/eapcommon.c
src/modules/rlm_eap/libeap/eapcrypto.c
src/modules/rlm_eap/libeap/eapsimlib.c
src/modules/rlm_eap/libeap/fips186prf.c
src/modules/rlm_eap/libeap/mppe_keys.c
src/modules/rlm_eap/libeap/tls.c
src/modules/rlm_eap/mem.c
src/modules/rlm_eap/radeapclient.c
src/modules/rlm_eap/rlm_eap.c
src/modules/rlm_eap/rlm_eap.h
src/modules/rlm_eap/state.c
src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c
src/modules/rlm_eap/types/rlm_eap_leap/eap_leap.c
src/modules/rlm_eap/types/rlm_eap_leap/eap_leap.h
src/modules/rlm_eap/types/rlm_eap_leap/rlm_eap_leap.c
src/modules/rlm_eap/types/rlm_eap_leap/smbdes.c
src/modules/rlm_eap/types/rlm_eap_md5/Makefile [moved from src/modules/rlm_eap/types/rlm_eap_md5/Makefile.in with 59% similarity]
src/modules/rlm_eap/types/rlm_eap_md5/configure.in [deleted file]
src/modules/rlm_eap/types/rlm_eap_md5/eap_md5.c
src/modules/rlm_eap/types/rlm_eap_md5/eap_md5.h
src/modules/rlm_eap/types/rlm_eap_md5/rlm_eap_md5.c
src/modules/rlm_eap/types/rlm_eap_mschapv2/Makefile [moved from src/modules/rlm_eap/types/rlm_eap_mschapv2/Makefile.in with 58% similarity]
src/modules/rlm_eap/types/rlm_eap_mschapv2/configure [deleted file]
src/modules/rlm_eap/types/rlm_eap_mschapv2/configure.in [deleted file]
src/modules/rlm_eap/types/rlm_eap_mschapv2/eap_mschapv2.h
src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c
src/modules/rlm_eap/types/rlm_eap_peap/config.h.in
src/modules/rlm_eap/types/rlm_eap_peap/configure
src/modules/rlm_eap/types/rlm_eap_peap/configure.in
src/modules/rlm_eap/types/rlm_eap_peap/eap_peap.h
src/modules/rlm_eap/types/rlm_eap_peap/peap.c
src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c
src/modules/rlm_eap/types/rlm_eap_psk/AES.cpp [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/AES.h [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/BlockCipher.h [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/CTR.cpp [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/CTR.h [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/EAX.cpp [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/EAX.h [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/Makefile.in [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/OMAC.cpp [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/OMAC.h [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/SOBMMO.cpp [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/SOBMMO.h [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/eap_psk.cpp [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/eap_psk.h [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/eap_psk_ssm.cpp [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/eap_psk_ssm.h [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/rlm_eap_psk.cpp [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/userinfo.c [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/userinfo.h [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_psk/users.psk [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_sim/Makefile [new file with mode: 0644]
src/modules/rlm_eap/types/rlm_eap_sim/Makefile.in [deleted file]
src/modules/rlm_eap/types/rlm_eap_sim/configure [deleted file]
src/modules/rlm_eap/types/rlm_eap_sim/configure.in [deleted file]
src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c
src/modules/rlm_eap/types/rlm_eap_tls/config.h.in
src/modules/rlm_eap/types/rlm_eap_tls/configure
src/modules/rlm_eap/types/rlm_eap_tls/configure.in
src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c
src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h
src/modules/rlm_eap/types/rlm_eap_ttls/config.h.in
src/modules/rlm_eap/types/rlm_eap_ttls/configure
src/modules/rlm_eap/types/rlm_eap_ttls/configure.in
src/modules/rlm_eap/types/rlm_eap_ttls/eap_ttls.h
src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c
src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c
src/modules/rlm_example/config.h.in
src/modules/rlm_example/configure
src/modules/rlm_example/configure.in
src/modules/rlm_example/other.c
src/modules/rlm_example/other.h
src/modules/rlm_example/rlm_example.c
src/modules/rlm_exec/rlm_exec.c
src/modules/rlm_expiration/Makefile [new file with mode: 0644]
src/modules/rlm_expiration/rlm_expiration.c [new file with mode: 0644]
src/modules/rlm_expr/Makefile
src/modules/rlm_expr/paircmp.c [new file with mode: 0644]
src/modules/rlm_expr/rlm_expr.c
src/modules/rlm_fastusers/rlm_fastusers.c
src/modules/rlm_files/rlm_files.c
src/modules/rlm_ippool/acconfig.h [deleted file]
src/modules/rlm_ippool/config.h.in
src/modules/rlm_ippool/configure
src/modules/rlm_ippool/configure.in
src/modules/rlm_ippool/rlm_ippool.c
src/modules/rlm_ippool/rlm_ippool_tool.c
src/modules/rlm_krb5/configure
src/modules/rlm_krb5/configure.in
src/modules/rlm_krb5/rlm_krb5.c
src/modules/rlm_ldap/configure
src/modules/rlm_ldap/configure.in
src/modules/rlm_ldap/edir_ldapext.c
src/modules/rlm_ldap/rlm_ldap.c
src/modules/rlm_linelog/Makefile [new file with mode: 0755]
src/modules/rlm_linelog/rlm_linelog.c [new file with mode: 0755]
src/modules/rlm_logintime/Makefile [new file with mode: 0644]
src/modules/rlm_logintime/rlm_logintime.c [new file with mode: 0644]
src/modules/rlm_logintime/timestr.c [moved from src/main/timestr.c with 94% similarity]
src/modules/rlm_mschap/rlm_mschap.c
src/modules/rlm_mschap/smbdes.c
src/modules/rlm_mschap/smbdes.h
src/modules/rlm_mschap/smbencrypt.c
src/modules/rlm_ns_mta_md5/Makefile [deleted file]
src/modules/rlm_ns_mta_md5/rlm_ns_mta_md5.c [deleted file]
src/modules/rlm_otp/Makefile.in
src/modules/rlm_otp/configure
src/modules/rlm_otp/extern.h
src/modules/rlm_otp/otp.h
src/modules/rlm_otp/otp_mppe.c
src/modules/rlm_otp/otp_mppe.h
src/modules/rlm_otp/otp_pw_valid.c
src/modules/rlm_otp/otp_pw_valid.h
src/modules/rlm_otp/otp_pwe.c
src/modules/rlm_otp/otp_radstate.c
src/modules/rlm_otp/otp_rlm.c
src/modules/rlm_otp/otp_util.c
src/modules/rlm_pam/config.h.in
src/modules/rlm_pam/configure
src/modules/rlm_pam/configure.in
src/modules/rlm_pam/rlm_pam.c
src/modules/rlm_pap/rlm_pap.c
src/modules/rlm_passwd/rlm_passwd.c
src/modules/rlm_perl/config.h.in
src/modules/rlm_perl/configure
src/modules/rlm_perl/configure.in
src/modules/rlm_perl/example.pl
src/modules/rlm_perl/rlm_perl.c
src/modules/rlm_policy/Makefile [new file with mode: 0644]
src/modules/rlm_policy/evaluate.c [new file with mode: 0644]
src/modules/rlm_policy/parse.c [new file with mode: 0644]
src/modules/rlm_policy/rlm_policy.c [new file with mode: 0644]
src/modules/rlm_policy/rlm_policy.h [new file with mode: 0644]
src/modules/rlm_preprocess/rlm_preprocess.c
src/modules/rlm_protocol_filter/Makefile [new file with mode: 0755]
src/modules/rlm_protocol_filter/rlm_protocol_filter.c [new file with mode: 0755]
src/modules/rlm_python/configure
src/modules/rlm_python/configure.in
src/modules/rlm_python/prepaid.py
src/modules/rlm_python/radiusd.py
src/modules/rlm_python/radiusd_test.py
src/modules/rlm_python/rlm_python.c
src/modules/rlm_radutmp/config.h.in
src/modules/rlm_radutmp/configure
src/modules/rlm_radutmp/configure.in
src/modules/rlm_radutmp/rlm_radutmp.c
src/modules/rlm_radutmp/rlm_radutmp2.c [new file with mode: 0644]
src/modules/rlm_realm/rlm_realm.c
src/modules/rlm_sim_files/rlm_sim_files.c
src/modules/rlm_smb/byteorder.h
src/modules/rlm_smb/config.h.in
src/modules/rlm_smb/configure
src/modules/rlm_smb/configure.in
src/modules/rlm_smb/rfcnb-common.h
src/modules/rlm_smb/rfcnb-error.h
src/modules/rlm_smb/rfcnb-io.c
src/modules/rlm_smb/rfcnb-io.h
src/modules/rlm_smb/rfcnb-priv.h
src/modules/rlm_smb/rfcnb-util.c
src/modules/rlm_smb/rfcnb-util.h
src/modules/rlm_smb/rfcnb.h
src/modules/rlm_smb/rlm_smb.c
src/modules/rlm_smb/session.c
src/modules/rlm_smb/smbdes.c
src/modules/rlm_smb/smbencrypt.c
src/modules/rlm_smb/smblib-common.h
src/modules/rlm_smb/smblib-priv.h
src/modules/rlm_smb/smblib-util.c
src/modules/rlm_smb/smblib.c
src/modules/rlm_smb/smblib.h
src/modules/rlm_smb/std-includes.h
src/modules/rlm_smb/valid.c
src/modules/rlm_smb/valid.h
src/modules/rlm_sql/conf.h
src/modules/rlm_sql/configure
src/modules/rlm_sql/configure.in
src/modules/rlm_sql/drivers/rlm_sql_db2/configure
src/modules/rlm_sql/drivers/rlm_sql_db2/sql_db2.c
src/modules/rlm_sql/drivers/rlm_sql_firebird/Makefile.in [deleted file]
src/modules/rlm_sql/drivers/rlm_sql_firebird/configure [deleted file]
src/modules/rlm_sql/drivers/rlm_sql_firebird/configure.in [deleted file]
src/modules/rlm_sql/drivers/rlm_sql_firebird/sql_fbapi.c [deleted file]
src/modules/rlm_sql/drivers/rlm_sql_firebird/sql_fbapi.h [deleted file]
src/modules/rlm_sql/drivers/rlm_sql_firebird/sql_firebird.c [deleted file]
src/modules/rlm_sql/drivers/rlm_sql_freetds/Makefile [deleted file]
src/modules/rlm_sql/drivers/rlm_sql_iodbc/configure
src/modules/rlm_sql/drivers/rlm_sql_iodbc/configure.in
src/modules/rlm_sql/drivers/rlm_sql_iodbc/sql_iodbc.c
src/modules/rlm_sql/drivers/rlm_sql_mysql/config.h.in
src/modules/rlm_sql/drivers/rlm_sql_mysql/configure
src/modules/rlm_sql/drivers/rlm_sql_mysql/configure.in
src/modules/rlm_sql/drivers/rlm_sql_mysql/sql_mysql.c
src/modules/rlm_sql/drivers/rlm_sql_oracle/configure
src/modules/rlm_sql/drivers/rlm_sql_oracle/configure.in
src/modules/rlm_sql/drivers/rlm_sql_oracle/sql_oracle.c
src/modules/rlm_sql/drivers/rlm_sql_postgresql/configure
src/modules/rlm_sql/drivers/rlm_sql_postgresql/configure.in
src/modules/rlm_sql/drivers/rlm_sql_postgresql/sql_postgresql.c
src/modules/rlm_sql/drivers/rlm_sql_postgresql/sql_postgresql.h [new file with mode: 0644]
src/modules/rlm_sql/drivers/rlm_sql_sybase/sql_sybase.c
src/modules/rlm_sql/drivers/rlm_sql_unixodbc/configure
src/modules/rlm_sql/drivers/rlm_sql_unixodbc/sql_unixodbc.c
src/modules/rlm_sql/drivers/rules.mak
src/modules/rlm_sql/rlm_sql.c
src/modules/rlm_sql/rlm_sql.h
src/modules/rlm_sql/sql.c
src/modules/rlm_sql_log/rlm_sql_log.c
src/modules/rlm_sqlcounter/Makefile.in
src/modules/rlm_sqlcounter/acconfig.h [deleted file]
src/modules/rlm_sqlcounter/configure
src/modules/rlm_sqlcounter/configure.in
src/modules/rlm_sqlcounter/rlm_sqlcounter.c
src/modules/rlm_sqlhpwippool/rlm_sqlhpwippool.c
src/modules/rlm_sqlhpwippool/sqlhpwippool.sql
src/modules/rlm_sqlippool/Makefile.in
src/modules/rlm_sqlippool/configure
src/modules/rlm_sqlippool/configure.in
src/modules/rlm_sqlippool/rlm_sqlippool.c
src/modules/rlm_unix/Makefile.in
src/modules/rlm_unix/cache.c [deleted file]
src/modules/rlm_unix/cache.h [deleted file]
src/modules/rlm_unix/compat.c [deleted file]
src/modules/rlm_unix/compat.h [deleted file]
src/modules/rlm_unix/config.h.in
src/modules/rlm_unix/configure
src/modules/rlm_unix/configure.in
src/modules/rlm_unix/rlm_unix.c
src/modules/rules.mak
src/modules/stable
src/tests/eapmd5-01/client.sh
src/tests/eapmd5-01/req.txt
src/tests/eapsim-02/client.sh
src/tests/eapsim-02/req.txt
src/tests/eapsim-03/radiusd-example.txt
suse/dialup_admin.patch [deleted file]
suse/edir.patch [deleted file]
suse/freeradius.spec
suse/lib64.patch [deleted file]
suse/radiusd-pam-old [new file with mode: 0644]
suse/rcradius-relayd [new file with mode: 0644]
suse/rcradiusd
todo/TODO

diff --git a/INSTALL b/INSTALL
index 3f3797d..8c59af0 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -13,7 +13,7 @@ the following steps to build and install the server:
        $ make
        $ make install
 
-  Note that as of 1.0.0, the location of the dictionary files has
+  Note that in this release, the location of the dictionary files has
 changed, to /usr/local/share/freeradius/dictionary.  Please ensure
 that /etc/raddb/dictionary is THE SAME as ./raddb/dictionary.  If not,
 you will have to copy it over by hand;
@@ -50,6 +50,14 @@ following list is a selection from the available flags:
   --with-edir             Compile with support for Novell eDirectory
                               integration.
 
+  To get the defaults that Cistron Radius used up to 1.5.4.3-beta18, use:
+
+       ./configure --localstatedir=/var --sysconfdir=/etc
+
+  That means binaries will get installed in /usr/local/{bin,sbin},
+manpages in /usr/local/man, configuration files in /etc/raddb, and
+logfiles in /var/log and /var/log/radacct.
+
   Now type "make". The binaries will be compiled.
 
   Then do "make install". That will install the binaries, the 'man'
index 1df1643..110f925 100644 (file)
@@ -17,6 +17,7 @@ mandir                = @mandir@
 datadir                = @datadir@
 dictdir                = $(datadir)/freeradius
 logdir         = @logdir@
+includedir     = @includedir@
 raddbdir       = @raddbdir@
 radacctdir     = @radacctdir@
 top_builddir   = @abs_top_builddir@
@@ -26,7 +27,7 @@ MAKE          = @MAKE@
 CC             = @CC@
 RANLIB         = @RANLIB@
 INCLUDE                = 
-CFLAGS         = $(INCLUDE) @CFLAGS@ @LFS_CFLAGS@
+CFLAGS         = $(INCLUDE) @CFLAGS@
 CPPFLAGS       = @CPPFLAGS@
 LIBPREFIX      = @LIBPREFIX@
 EXEEXT         = @EXEEXT@ 
@@ -42,8 +43,8 @@ INSTALL_SCRIPT        = ${INSTALL_PROGRAM}
 INSTALLSTRIP   = @INSTALLSTRIP@
 
 LCRYPT         = @CRYPTLIB@
-LIBS           = @LIBS@ @LFS_LIBS@
-LDFLAGS                = @LDFLAGS@ @LFS_LDFLAGS@
+LIBS           = @LIBS@
+LDFLAGS                = @LDFLAGS@
 
 LOGDIR         = ${logdir}
 RADDBDIR       = ${raddbdir}
index c9436db..21709e8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -107,5 +107,9 @@ config.status: configure
 
 configure.in:
 
+.PHONY: check-includes
+check-includes:
+       scripts/min-includes.pl `find . -name "*.c" -print`
+
 TAGS:
        etags `find src -type f -name '*.[ch]' -print`
diff --git a/README b/README
index 65ff0dc..7ade473 100644 (file)
--- a/README
+++ b/README
@@ -1,8 +1,20 @@
 1. INTRODUCTION
 
   The FreeRADIUS Server Project is a high performance and highly
-configurable GPL'd free RADIUS server. It is stable, and is currently
-being used in many deployments with millions of users.
+configurable GPL'd free RADIUS server. The server is similar in some
+respects to Livingston's 2.0 server.  While FreeRADIUS started as a
+variant of the Cistron RADIUS server, they don't share a lot in common
+any more.  It now has many more features than Cistron or Livingston,
+and is much more configurable.
+
+  FreeRADIUS is an Internet authentication daemon, which implements
+the RADIUS protocol, as defined in RFC 2865 (and others).  It allows
+Network Access Servers (NAS boxes) to perform authentication for
+dial-up users.  There are also RADIUS clients available for Web
+servers, firewalls, Unix logins, and more.  Using RADIUS allows
+authentication and authorization for a network to be centralized, and
+minimizes the amount of re-configuration which has to be done when
+adding or deleting new users.
 
   Please see the main web page (http://www.freeradius.org) for more
 information.
@@ -12,45 +24,6 @@ information.
   To install the server, please see the INSTALL file in this
 directory.
 
-  Version 1.1.4 contains a few key improvements over previous
-versions.  The most important is the addition of the
-Cleartext-Password attribute.  Using this attribute can make your
-configuration MUCH simpler, and MUCH easier to understand.  Please
-read "man rlm_pap" for more details.
-
-  New users of FreeRADIUS should prefer using Cleartext-Password over
-User-Password.  That is, if the documentation or a web page says to
-configure User-Password in a database or server configuration file,
-the documentation is likely out of date, and you should use
-User-Password instead.
-
-  The main differences between 1.1.3 and 1.1.4 are significantly
-improved functionality in rlm_pap.  The module is MUCH smarter, which
-means that many previous complicated configurations are now almost
-trivial to do.  Please read "man rlm_pap" for details.
-
-  Existing deployments of FreeRADIUS will NOT be affected by this
-change to rlm_pap.  Existing configurations will work as before.
-However, we do recommend reading the rlm_pap "man" page, to see how
-your configuration may be made simpler by using the new functionality.
-
-  The differences between 1.0.x and 1.1.0 are documented in the file
-doc/ChangeLog.  What these differences mean for an administrator
-upgrading from 1.0.x are as follows:
-
-  * You MUST use the new dictionaries.  This is NOT done by default,
-    because you may have edited the installed version of /etc/raddb/dictionary.
-    If you have not edited /etc/raddb/dictionary, then you can make
-    the server use the new dictionaries by copying the
-    raddb/dictionary file from this directory to /etc/raddb.  Without
-    this change, the server WILL NOT WORK PROPERLY.
-
-  * Sites using SQL for logging should look into using the new
-    rlm_sql_log module.  See it's "man" page for details.
-
-  * Sites using rlm_x99_token will have to update their configuration
-    to use rlm_otp.
-
 3. DEBUGGING THE SERVER
 
   Run the server in debugging mode, (radiusd -X) and READ the output.
@@ -70,17 +43,11 @@ documentation, other than comments in the configuration file.
 discussions about common problems and solution.
 
 
-  See the Wiki
-
-       http://wiki.freeradius.org
-
 4. ADDITIONAL INFORMATION
 
   See 'doc/README' for more information about FreeRADIUS.
 
-  There is now an O'Reilly book available, which we recommend for
-people new to RADIUS.  It covers an earlier version of the server, but
-much of the information is applicable to this version also.
+  There is now an O'Reilly book available, which we recommend highly:
 
 http://www.amazon.com/exec/obidos/ASIN/0596003226/freeradiusorg-20/
 
diff --git a/acconfig.h b/acconfig.h
deleted file mode 100644 (file)
index c04a5dd..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-
-acconfig.h - template used by autoheader to create config.h.in
-config.h.in - used by autoconf to create config.h
-config.h - created by autoconf; contains defines generated by autoconf
-
-*/
-
-@TOP@
-
-/* style of gethost*_r functions */
-#define GNUSTYLE 1
-#define SYSVSTYLE 2
-#define BSDSTYLE 3
-#undef GETHOSTBYADDRRSTYLE
-#undef GETHOSTBYNAMERSTYLE
-
-/* style of ctime_r function */
-#define POSIXSTYLE 1
-#define SOLARISSTYLE 2
-#undef CTIMERSTYLE
-
-/* Do we have the crypt function ? */
-#undef HAVE_CRYPT
-
-/* Do we have shadow support? */
-#undef HAVE_GETSPNAM
-
-/* Use USR-style vendor specific attributes */
-#undef ATTRIB_NMC
-
-/* Include support for Ascend binary filter attributes */
-#undef ASCEND_BINARY
-
-/* socklen_t is generally 'int' on systems which don't use it */
-#undef socklen_t
-
-/* uint8_t should be the canonical 'octet' for network traffic */
-#undef uint8_t
-
-/* uint16_t should be the canonical '2 octets' for network traffic */
-#undef uint16_t
-
-/* uint32_t should be the canonical 'network integer' */
-#undef uint32_t
-
-/* Define if prototype for strncasecmp needed */
-#undef NEED_DECLARATION_STRNCASECMP
-
-/* Define if prototype for strcasecmp needed */
-#undef NEED_DECLARATION_STRCASECMP
-
-/* Define if prototype for inet_aton needed */
-#undef NEED_DECLARATION_INET_ATON
-
-/* Define if prototype for gethostname needed */
-#undef NEED_DECLARATION_GETHOSTNAME
-
-/* Define if prototype for setlinebuf needed */
-#undef NEED_DECLARATION_SETLINEBUF
-
-/* Define if prototype for getusershell needed */
-#undef NEED_DECLARATION_GETUSERSHELL
-
-/* Define if prototype for endusershell needed */
-#undef NEED_DECLARATION_ENDUSERSHELL
-
-/* use a pool of threads to handle requests, instead of spawning threads? */
-#undef WITH_THREAD_POOL
-
-/* Include SNMP subagent */
-#undef WITH_SNMP
-
-/* Include user collision code*/
-#undef WITH_USERCOLLIDE
-
-/* Define if you have the <ucd-snmp/asn1.h>, <ucd-snmp/snmp_impl.h> and <ucd-snmp/snmp.h> header file.  */
-#undef HAVE_UCD_SNMP_ASN1_SNMP_SNMPIMPL_H
-
-/* Define if you have the <asn1.h>, <snmp_impl.h> and <snmp.h> header file.  */
-#undef HAVE_ASN1_SNMP_SNMPIMPL_H
-
-/* Define if you have the snmp library (-lsnmp).  */
-#undef HAVE_LIBSNMP
-
-/* define if you have the <libpq_fe.h> header file.  */
-#undef HAVE_LIBPQ_FE_H
-
-/* define if you have the <postgres.h> header file.  */
-#undef HAVE_POSTGRES_H
-
-/* define this if we have the <regex.h> header file */
-#undef HAVE_REGEX_H
-
-/* define this if we have REG_EXTENDED (from <regex.h>) */
-#undef HAVE_REG_EXTENDED
-
-/* define this if you have the <mysql.h> header file */
-#undef HAVE_MYSQL_H
-
-/* define this if you have the <isql.h> header file */
-#undef HAVE_ISQL_H
-
-/* define this if you have the <oci.h> header file */
-#undef HAVE_OCI_H
-
-/* define to something if you don't have ut_xtime in struct utmpx */
-#undef ut_xtime
-
-/* define if you have OSFC2 authentication */
-#undef OSFC2
-
-/* define if you have OSFSIA authentication */
-#undef OSFSIA
-
-/* define if you have IP_PKTINFO (Linux) */
-#undef HAVE_IP_PKTINFO
-
-/* define if you want udpfromto */
-#undef WITH_UDPFROMTO
-
-/* define if you have openssl/ssl.h */
-#undef HAVE_OPENSSL_SSL_H
-
-/* define if you have initgroups() */
-#undef HAVE_INITGROUPS
-
-@BOTTOM@
-
-#ifndef HAVE_SNPRINTF
-#define HAVE_LOCAL_SNPRINTF
-#define snprintf lrad_snprintf
-#endif
-
-#ifndef HAVE_VSNPRINTF
-#define HAVE_LOCAL_SNPRINTF
-#define vsnprintf lrad_vsnprintf
-#endif
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644 (file)
index 0000000..8253976
--- /dev/null
@@ -0,0 +1,597 @@
+dnl See whether we need a declaration for a function.
+dnl RADIUSD_NEED_DECLARATION(FUNCTION [, EXTRA-HEADER-FILES])
+AC_DEFUN([RADIUSD_NEED_DECLARATION],
+[AC_MSG_CHECKING([whether $1 must be declared])
+AC_CACHE_VAL(radius_cv_decl_needed_$1,
+[AC_TRY_COMPILE([
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_RESOURCE_H
+#include <resource.h>
+#endif
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#endif
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+#ifdef HAVE_REGEX_H
+#include <regex.h>
+#endif
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+$2],
+[char *(*pfn) = (char *(*)) $1],
+eval "radius_cv_decl_needed_$1=no", eval "radius_cv_decl_needed_$1=yes")])
+if eval "test \"`echo '$radius_cv_decl_needed_'$1`\" = yes"; then
+  AC_MSG_RESULT(yes)
+  radius_tr_decl=NEED_DECLARATION_`echo $1 | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+  AC_DEFINE_UNQUOTED($radius_tr_decl)
+else
+  AC_MSG_RESULT(no)
+fi
+])dnl
+
+dnl Check multiple functions to see whether each needs a declaration.
+dnl RADIUSD_NEED_DECLARATIONS(FUNCTION... [, EXTRA-HEADER-FILES])
+AC_DEFUN([RADIUSD_NEED_DECLARATIONS],
+[for ac_func in $1
+do
+RADIUSD_NEED_DECLARATION($ac_func, $2)
+done
+])
+
+dnl Checks to see if this is SUNPro we're building with
+dnl Usage:
+dnl AC_PROG_CC_SUNPRO
+AC_DEFUN([AC_PROG_CC_SUNPRO],
+[AC_CACHE_CHECK(whether we are using SUNPro C, ac_cv_prog_suncc,
+[dnl The semicolon is to pacify NeXT's syntax-checking cpp.
+cat > conftest.c <<EOF
+#ifdef __SUNPRO_C
+  yes;
+#endif
+EOF
+if AC_TRY_COMMAND(${CC-cc} -E conftest.c) | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_suncc=yes
+else
+  ac_cv_prog_suncc=no
+fi])])
+
+dnl #
+dnl # FR_CHECK_TYPE_INCLUDE([#includes ...], type, default-C-types)
+dnl #
+dnl # This function is like AC_CHECK_TYPE, but you can give this one
+dnl # a list of include files to check.
+dnl #
+AC_DEFUN([FR_CHECK_TYPE_INCLUDE],
+[
+  AC_CACHE_CHECK(for $2, ac_cv_type_$2,
+    [ ac_cv_type_$2=no
+      AC_TRY_COMPILE($1,
+        [$2 foo],
+        ac_cv_type_$2=yes,
+      )
+    ]
+  )
+
+  if test "$ac_cv_type_$2" != "yes"; then
+         AC_DEFINE($2, $3, $4)
+  fi
+])
+
+dnl #######################################################################
+dnl #
+dnl #  Look for SNMP in a variety of places.
+dnl #
+AC_DEFUN([SNMP_CHECKS], [
+       AC_SUBST(SNMP_LIBS)
+       AC_SUBST(SNMP_INCLUDE)
+
+AC_MSG_CHECKING([for asn1.h,snmp.h,snmp_impl.h])
+
+dnl #
+dnl #  First, see if we can build it WITHOUT using any special includes and in ucd-snmp
+dnl #
+AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <ucd-snmp/ucd-snmp-config.h>
+#include <ucd-snmp/asn1.h>
+#include <ucd-snmp/snmp.h>
+#include <ucd-snmp/snmp_impl.h>],
+               [ int a = 1;],
+               SNMP_INCLUDE="";ucdsnmp=yes,
+               ucdsnmp=)
+
+dnl #
+dnl #  If not, look for it in a number of directories and in ucd-snmp.
+dnl #
+if test "x$ucdsnmp" = "x"; then
+  old_CFLAGS="$CFLAGS"
+  for try in /usr/include /usr/local/include $snmp_include_dir; do
+    CFLAGS="$old_CFLAGS -I$try"
+    AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <ucd-snmp/ucd-snmp-config.h>
+#include <ucd-snmp/asn1.h>
+#include <ucd-snmp/snmp.h>
+#include <ucd-snmp/snmp_impl.h>],
+                   [ int a = 1;],
+                   SNMP_INCLUDE="-I$try";ucdsnmp=yes,
+                   ucdsnmp=)
+    if test "x$ucdsnmp" != "x"; then
+      break;
+    fi
+  done
+  CFLAGS="$old_CFLAGS"
+fi
+
+if test "x$ucdsnmp" = "x"; then
+  old_CFLAGS="$CFLAGS"
+  for try in /usr/include/ucd-snmp /usr/local/include/ucd-snmp $snmp_include_dir; do
+    CFLAGS="$old_CFLAGS -I$try"
+dnl #
+dnl #  First, see if we can build it WITHOUT using any special includes and without ucd-snmp
+dnl #
+AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <asn1.h>
+#include <snmp.h>
+#include <snmp_impl.h>],
+               [ int a = 1;],
+               SNMP_INCLUDE="";ucdsnmp=no,
+               ucdsnmp=)
+    if test "x$ucdsnmp" != "x"; then
+      break;
+    fi
+  done
+  CFLAGS="$old_CFLAGS"
+fi
+
+dnl #
+dnl #  If not, look for it in a number of directories and without ucd-snmp
+dnl #
+if test "x$ucdsnmp" = "x"; then
+  old_CFLAGS="$CFLAGS"
+  for try in /usr/include/ucd-snmp /usr/local/include/ucd-snmp $snmp_include_dir; do
+    CFLAGS="$old_CFLAGS -I$try"
+    AC_TRY_COMPILE([
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <asn1.h>
+#include <snmp.h>
+#include <snmp_impl.h>],
+                   [ int a = 1;],
+                   SNMP_INCLUDE="-I$try";ucdsnmp=no,
+                   ucdsnmp=)
+    if test "x$ucdsnmp" != "x"; then
+      break;
+    fi
+  done
+  CFLAGS="$old_CFLAGS"
+fi
+
+if test "x$ucdsnmp" = "x"; then
+  AC_MSG_RESULT(no)
+else
+  if test "x$ucdsnmp" = "xyes"; then
+    AC_MSG_RESULT((ucd-snmp)yes)
+    AC_DEFINE(HAVE_UCD_SNMP_ASN1_SNMP_SNMPIMPL_H, [], [Define if you have the <ucd-snmp/asn1.h>, <ucd-snmp/snmp_impl.h> and <ucd-snmp/snmp.h> header file.])
+  else
+    AC_MSG_RESULT(yes)
+    AC_DEFINE(HAVE_ASN1_SNMP_SNMPIMPL_H, [], [Define if you have the <asn1.h>, <snmp_impl.h> and <snmp.h> header file.])
+  fi
+dnl #
+dnl #  Now do the same thing, looking for the SNMP library directory
+dnl #
+  AC_MSG_CHECKING([for snmp_build_var_op in -lsnmp])
+
+dnl #
+dnl #  First, see if we can build it WITHOUT using any special includes
+dnl #
+  old_LIBS="$LIBS"
+  LIBS="$old_LIBS -lsnmp"
+  AC_TRY_LINK([extern char snmp_build_var_op();],
+              [ snmp_build_var_op()],
+              SNMP_LIBS="-lsnmp",
+              SNMP_LIBS=)
+
+  if test "x$SNMP_LIBS" = "x"; then
+    for try in /usr/lib /usr/local/lib /usr/local/snmp/lib $with_snmp_lib_dir; do
+      LIBS="$old_LIBS -L$try -lsnmp"
+      AC_TRY_LINK([extern char snmp_build_var_op();],
+                  [ snmp_build_var_op()],
+                  SNMP_LIBS="-L$try -lsnmp",
+                  SNMP_LIBS=)
+      if test "x$SNMP_LIBS" != "x"; then
+        break;
+      fi
+dnl   #
+dnl   #  That didn't work.  Try adding the '-lcrypto' line.
+dnl   #  Some SNMP libraries are linked against SSL...
+dnl   #
+      LIBS="$old_LIBS -L$try -lsnmp -lcrypto"
+      AC_TRY_LINK([extern char snmp_build_var_op();],
+                  [ snmp_build_var_op()],
+                  SNMP_LIBS="-L$try -lsnmp -lcrypto",
+                  SNMP_LIBS=)
+      if test "x$SNMP_LIBS" != "x"; then
+        break;
+      fi
+dnl   #
+dnl   #  That didn't work.  Try adding the '-lkstat' line.
+dnl   #  Some SNMP libraries are linked against Kernel Statistics,
+dnl   #  in particular, Solaris 9...
+dnl   #
+      LIBS="$old_LIBS -L$try -lsnmp -lcrypto -lkstat"
+      AC_TRY_LINK([extern char snmp_build_var_op();],
+                  [ snmp_build_var_op()],
+                  SNMP_LIBS="-L$try -lsnmp -lcrypto -lkstat",
+                  SNMP_LIBS=)
+      if test "x$SNMP_LIBS" != "x"; then
+        break;
+      fi
+    done
+  fi
+  LIBS="$old_LIBS"
+
+  dnl #
+  dnl #  If one or the other isn't found, disable them both..
+  dnl #  If both are found, enable them both.
+  dnl #
+  CFLAGS="$old_CFLAGS"
+  if test "x$SNMP_LIBS" = "x"; then
+    AC_MSG_RESULT(no)
+    SNMP_INCLUDE=
+  else
+    AC_MSG_RESULT(yes)
+    AC_DEFINE(WITH_SNMP, [], [Include SNMP subagent])
+    AC_DEFINE(HAVE_LIBSNMP, [], [Define if you have the snmp library (-lsnmp).])
+  fi
+fi
+])
+
+
+dnl #
+dnl #  Locate the directory in which a particular file is found.
+dnl #
+dnl #  Usage: FR_LOCATE_DIR(MYSQLLIB_DIR, libmysqlclient.a)
+dnl #
+dnl #    Defines the variable MYSQLLIB_DIR to be the directory(s) in
+dnl #    which the file libmysqlclient.a is to be found.
+dnl #
+dnl #
+AC_DEFUN([FR_LOCATE_DIR],
+[
+dnl # If we have the program 'locate', then the problem of finding a
+dnl # particular file becomes MUCH easier.
+dnl #
+
+dnl #
+dnl #  No 'locate' defined, do NOT do anything.
+dnl #
+if test "x$LOCATE" != "x"; then
+  dnl #
+  dnl #  Root through a series of directories, looking for the given file.
+  dnl #
+  DIRS=
+  file=$2
+
+  for x in `${LOCATE} $file 2>/dev/null`; do
+    dnl #
+    dnl #  When asked for 'foo', locate will also find 'foo_bar', which we
+    dnl #  don't want.  We want that EXACT filename.
+    dnl #
+    dnl #  We ALSO want to be able to look for files like 'mysql/mysql.h',
+    dnl #  and properly match them, too.  So we try to strip off the last
+    dnl #  part of the filename, using the name of the file we're looking
+    dnl #  for.  If we CANNOT strip it off, then the name will be unchanged.
+    dnl #
+    base=`echo $x | sed "s%/${file}%%"`
+    if test "x$x" = "x$base"; then
+      continue;
+    fi
+
+    dir=`${DIRNAME} $x 2>/dev/null`
+    dnl #
+    dnl #  Exclude a number of directories.
+    dnl #
+    exclude=`echo ${dir} | ${GREP} /home`
+    if test "x$exclude" != "x"; then
+      continue
+    fi
+
+    dnl #
+    dnl #  OK, we have an exact match.  Let's be sure that we only find ONE
+    dnl #  matching directory.
+    dnl #
+    already=`echo \$$1 ${DIRS} | ${GREP} ${dir}`
+    if test "x$already" = "x"; then
+      DIRS="$DIRS $dir"
+    fi
+  done
+fi
+
+dnl #
+dnl #  And remember the directory in which we found the file.
+dnl #
+eval "$1=\"\$$1 $DIRS\""
+])
+
+
+dnl #######################################################################
+dnl #
+dnl #  Look for a library in a number of places.
+dnl #
+dnl #  FR_SMART_CHECK_LIB(library, function)
+dnl #
+AC_DEFUN([FR_SMART_CHECK_LIB], [
+
+sm_lib_safe=`echo "$1" | sed 'y%./+-%__p_%'`
+sm_func_safe=`echo "$2" | sed 'y%./+-%__p_%'`
+AC_MSG_CHECKING([for $2 in -l$1])
+
+old_LIBS="$LIBS"
+smart_lib=
+smart_lib_dir=
+
+dnl #
+dnl #  Try first any user-specified directory, otherwise we may pick up
+dnl #  the wrong version.
+dnl #
+if test "x$smart_try_dir" != "x"; then
+  for try in $smart_try_dir; do
+    LIBS="-L$try -l$1 $old_LIBS"
+    AC_TRY_LINK([extern char $2();],
+               [ $2()],
+               smart_lib="-L$try -l$1")
+    if test "x$smart_lib" != "x"; then
+      break;
+    fi
+  done
+  LIBS="$old_LIBS"
+fi
+
+dnl #
+dnl #  Try using the default library path
+dnl #
+if test "x$smart_lib" = "x"; then
+  LIBS="-l$1 $old_LIBS"
+  AC_TRY_LINK([extern char $2();],
+             [ $2()],
+             smart_lib="-l$1")
+  LIBS="$old_LIBS"
+fi
+
+dnl #
+dnl #  Try to guess possible locations.
+dnl #
+if test "x$smart_lib" = "x"; then
+  FR_LOCATE_DIR(smart_lib_dir,[lib$1${libltdl_cv_shlibext}])
+  FR_LOCATE_DIR(smart_lib_dir,[lib$1.a])
+
+  for try in $smart_lib_dir /usr/local/lib /opt/lib; do
+    LIBS="-L$try -l$1 $old_LIBS"
+    AC_TRY_LINK([extern char $2();],
+               [ $2()],
+               smart_lib="-L$try -l$1")
+    if test "x$smart_lib" != "x"; then
+      break;
+    fi
+  done
+  LIBS="$old_LIBS"
+fi
+
+dnl #
+dnl #  Found it, set the appropriate variable.
+dnl #
+if test "x$smart_lib" != "x"; then
+  AC_MSG_RESULT(yes)
+  eval "ac_cv_lib_${sm_lib_safe}_${sm_func_safe}=yes"
+  LIBS="$smart_lib $old_LIBS"
+  SMART_LIBS="$smart_lib $SMART_LIBS"
+else
+  AC_MSG_RESULT(no)
+fi
+])
+
+dnl #######################################################################
+dnl #
+dnl #  Look for a header file in a number of places.
+dnl #
+dnl #  FR_SMART_CHECK_INCLUDE(foo.h, [ #include <other.h> ])
+dnl #
+AC_DEFUN([FR_SMART_CHECK_INCLUDE], [
+
+ac_safe=`echo "$1" | sed 'y%./+-%__pm%'`
+AC_MSG_CHECKING([for $1])
+
+old_CFLAGS="$CFLAGS"
+smart_include=
+smart_include_dir=
+
+dnl #
+dnl #  Try first any user-specified directory, otherwise we may pick up
+dnl #  the wrong version.
+dnl #
+if test "x$smart_try_dir" != "x"; then
+  for try in $smart_try_dir; do
+    CFLAGS="$old_CFLAGS -I$try"
+    AC_TRY_COMPILE([$2
+                   #include <$1>],
+                  [ int a = 1;],
+                  smart_include="-I$try",
+                  smart_include=)
+    if test "x$smart_include" != "x"; then
+      break;
+    fi
+  done
+  CFLAGS="$old_CFLAGS"
+fi
+
+dnl #
+dnl #  Try using the default includes.
+dnl #
+if test "x$smart_include" = "x"; then
+  AC_TRY_COMPILE([$2
+                 #include <$1>],
+                [ int a = 1;],
+                smart_include=" ",
+                smart_include=)
+fi
+
+dnl #
+dnl #  Try to guess possible locations.
+dnl #
+if test "x$smart_include" = "x"; then
+  FR_LOCATE_DIR(smart_include_dir,$1)
+
+  for try in $smart_include_dir /usr/local/include /opt/include; do
+    CFLAGS="$old_CFLAGS -I$try"
+    AC_TRY_COMPILE([$2
+                   #include <$1>],
+                  [ int a = 1;],
+                  smart_include="-I$try",
+                  smart_include=)
+    if test "x$smart_include" != "x"; then
+      break;
+    fi
+  done
+  CFLAGS="$old_CFLAGS"
+fi
+
+dnl #
+dnl #  Found it, set the appropriate variable.
+dnl #
+if test "x$smart_include" != "x"; then
+  AC_MSG_RESULT(yes)
+  eval "ac_cv_header_$ac_safe=yes"
+  CFLAGS="$old_CFLAGS $smart_include"
+  SMART_CFLAGS="$SMART_CFLAGS $smart_include"
+else
+  AC_MSG_RESULT(no)
+fi
+])
+
+dnl #######################################################################
+dnl #
+dnl #  Look for a header file in a number of places.
+dnl #
+dnl #  Usage:  FR_CHECK_STRUCT_HAS_MEMBER([#include <foo.h>], [struct foo], member)
+dnl #  If the member is defined, then the variable
+dnl #     ac_cv_type_struct_foo_has_member is set to 'yes'
+dnl #
+AC_DEFUN([FR_CHECK_STRUCT_HAS_MEMBER], [
+  AC_MSG_CHECKING([for $3 in $2])
+
+dnl BASED on 'offsetof':
+dnl #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+dnl
+
+  AC_TRY_COMPILE([
+$1
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
+#endif
+],
+                 [ int foo = offsetof($2, $3) ],
+                 has_element=" ",
+                 has_element=)
+
+  ac_safe_type=`echo "$2" | sed 'y% %_%'`
+  if test "x$has_element" != "x"; then
+    AC_MSG_RESULT(yes)
+    eval "ac_cv_type_${ac_safe_type}_has_$3=yes"
+  else
+    AC_MSG_RESULT(no) 
+    eval "ac_cv_type_${ac_safe_type}_has_$3="
+ fi
+])
+
+AC_INCLUDE(aclocal.m4)
index ff7ba14..5336a19 100644 (file)
 # This line will prevent autoreconf from running aclocal again.
 # generated automatically by aclocal 1.9.5 -*- Autoconf -*-
 
-m4_include([libtool.m4])
-
-dnl See whether we need a declaration for a function.
-dnl RADIUSD_NEED_DECLARATION(FUNCTION [, EXTRA-HEADER-FILES])
-AC_DEFUN(RADIUSD_NEED_DECLARATION,
-[AC_MSG_CHECKING([whether $1 must be declared])
-AC_CACHE_VAL(radius_cv_decl_needed_$1,
-[AC_TRY_COMPILE([
-#include <stdio.h>
-#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_CRYPT_H
-#include <crypt.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_RESOURCE_H
-#include <resource.h>
-#endif
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-#ifdef HAVE_UTMP_H
-#include <utmp.h>
-#endif
-#ifdef HAVE_UTMPX_H
-#include <utmpx.h>
-#endif
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#ifdef HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-#ifdef HAVE_REGEX_H
-#include <regex.h>
-#endif
-#ifdef HAVE_SYSLOG_H
-#include <syslog.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-$2],
-[char *(*pfn) = (char *(*)) $1],
-eval "radius_cv_decl_needed_$1=no", eval "radius_cv_decl_needed_$1=yes")])
-if eval "test \"`echo '$radius_cv_decl_needed_'$1`\" = yes"; then
-  AC_MSG_RESULT(yes)
-  radius_tr_decl=NEED_DECLARATION_`echo $1 | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
-  AC_DEFINE_UNQUOTED($radius_tr_decl)
-else
-  AC_MSG_RESULT(no)
-fi
-])dnl
-
-dnl Check multiple functions to see whether each needs a declaration.
-dnl RADIUSD_NEED_DECLARATIONS(FUNCTION... [, EXTRA-HEADER-FILES])
-AC_DEFUN(RADIUSD_NEED_DECLARATIONS,
-[for ac_func in $1
-do
-RADIUSD_NEED_DECLARATION($ac_func, $2)
-done
-])
-
-dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
-dnl The program must properly implement --version.
-AC_DEFUN(AM_MISSING_PROG,
-[AC_MSG_CHECKING(for working $2)
-# Run test in a subshell; some versions of sh will print an error if
-# an executable is not found, even if stderr is redirected.
-# Redirect stdin to placate older versions of autoconf.  Sigh.
-if ($2 --version) < /dev/null > /dev/null 2>&1; then
-   $1=$2
-   AC_MSG_RESULT(found)
-else
-   $1="$3/missing $2"
-   AC_MSG_RESULT(missing)
-fi
-AC_SUBST($1)])
-
-
-dnl Checks to see if this is SUNPro we're building with
-dnl Usage:
-dnl AC_PROG_CC_SUNPRO
-AC_DEFUN(AC_PROG_CC_SUNPRO,
-[AC_CACHE_CHECK(whether we are using SUNPro C, ac_cv_prog_suncc,
-[dnl The semicolon is to pacify NeXT's syntax-checking cpp.
-cat > conftest.c <<EOF
-#ifdef __SUNPRO_C
-  yes;
-#endif
-EOF
-if AC_TRY_COMMAND(${CC-cc} -E conftest.c) | egrep yes >/dev/null 2>&1; then
-  ac_cv_prog_suncc=yes
-else
-  ac_cv_prog_suncc=no
-fi])])
-
-dnl #
-dnl # AC_CHECK_TYPE_INCLUDE([#includes ...], type, default-C-types)
-dnl #
-dnl # This function is like AC_CHECK_TYPE, but you can give this one
-dnl # a list of include files to check.
-dnl #
-AC_DEFUN(AC_CHECK_TYPE_INCLUDE,
-[
-  AC_CACHE_CHECK(for $2, ac_cv_type_$2,
-    [ ac_cv_type_$2=no
-      AC_TRY_COMPILE($1,
-        [$2 foo],
-        ac_cv_type_$2=yes,
-      )
-    ]
-  )
-
-  if test "$ac_cv_type_$2" != "yes"; then
-         AC_DEFINE($2, $3)
-  fi
-])
-
-dnl #######################################################################
-dnl #
-dnl #  Look for SNMP in a variety of places.
-dnl #
-AC_DEFUN(SNMP_CHECKS, [
-       AC_SUBST(SNMP_LIBS)
-       AC_SUBST(SNMP_INCLUDE)
-
-AC_MSG_CHECKING([for asn1.h,snmp.h,snmp_impl.h])
-
-dnl #
-dnl #  First, see if we can build it WITHOUT using any special includes and in ucd-snmp
-dnl #
-AC_TRY_COMPILE([
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <ucd-snmp/ucd-snmp-config.h>
-#include <ucd-snmp/asn1.h>
-#include <ucd-snmp/snmp.h>
-#include <ucd-snmp/snmp_impl.h>],
-               [ int a = 1;],
-               SNMP_INCLUDE="";ucdsnmp=yes,
-               ucdsnmp=)
-
-dnl #
-dnl #  If not, look for it in a number of directories and in ucd-snmp.
-dnl #
-if test "x$ucdsnmp" = "x"; then
-  old_CFLAGS="$CFLAGS"
-  for try in /usr/include /usr/local/include $with_snmp_include_dir; do
-    CFLAGS="$old_CFLAGS -I$try"
-    AC_TRY_COMPILE([
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <ucd-snmp/ucd-snmp-config.h>
-#include <ucd-snmp/asn1.h>
-#include <ucd-snmp/snmp.h>
-#include <ucd-snmp/snmp_impl.h>],
-                   [ int a = 1;],
-                   SNMP_INCLUDE="-I$try";ucdsnmp=yes,
-                   ucdsnmp=)
-    if test "x$ucdsnmp" != "x"; then
-      break;
-    fi
-  done
-  CFLAGS="$old_CFLAGS"
-fi
-
-if test "x$ucdsnmp" = "x"; then
-  old_CFLAGS="$CFLAGS"
-  for try in /usr/include/ucd-snmp /usr/local/include/ucd-snmp $with_snmp_include_dir; do
-    CFLAGS="$old_CFLAGS -I$try"
-dnl #
-dnl #  First, see if we can build it WITHOUT using any special includes and without ucd-snmp
-dnl #
-AC_TRY_COMPILE([
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <asn1.h>
-#include <snmp.h>
-#include <snmp_impl.h>],
-               [ int a = 1;],
-               SNMP_INCLUDE="";ucdsnmp=no,
-               ucdsnmp=)
-    if test "x$ucdsnmp" != "x"; then
-      break;
-    fi
-  done
-  CFLAGS="$old_CFLAGS"
-fi
-
-dnl #
-dnl #  If not, look for it in a number of directories and without ucd-snmp
-dnl #
-if test "x$ucdsnmp" = "x"; then
-  old_CFLAGS="$CFLAGS"
-  for try in /usr/include/ucd-snmp /usr/local/include/ucd-snmp $with_snmp_include_dir; do
-    CFLAGS="$old_CFLAGS -I$try"
-    AC_TRY_COMPILE([
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <asn1.h>
-#include <snmp.h>
-#include <snmp_impl.h>],
-                   [ int a = 1;],
-                   SNMP_INCLUDE="-I$try";ucdsnmp=no,
-                   ucdsnmp=)
-    if test "x$ucdsnmp" != "x"; then
-      break;
-    fi
-  done
-  CFLAGS="$old_CFLAGS"
-fi
-
-if test "x$ucdsnmp" = "x"; then
-  AC_MSG_RESULT(no)
-else
-  if test "x$ucdsnmp" = "xyes"; then
-    AC_MSG_RESULT((ucd-snmp)yes)
-    AC_DEFINE(HAVE_UCD_SNMP_ASN1_SNMP_SNMPIMPL_H)
-  else
-    AC_MSG_RESULT(yes)
-    AC_DEFINE(HAVE_ASN1_SNMP_SNMPIMPL_H)
-  fi
-dnl #
-dnl #  Now do the same thing, looking for the SNMP library directory
-dnl #
-  AC_MSG_CHECKING([for snmp_build_var_op in -lsnmp])
-
-dnl #
-dnl #  First, see if we can build it WITHOUT using any special includes
-dnl #
-  old_LIBS="$LIBS"
-  LIBS="$old_LIBS -lsnmp"
-  AC_TRY_LINK([extern char snmp_build_var_op();],
-              [ snmp_build_var_op()],
-              SNMP_LIBS="-lsnmp",
-              SNMP_LIBS=)
-
-  if test "x$SNMP_LIBS" = "x"; then
-    for try in /usr/lib /usr/local/lib /usr/local/snmp/lib $with_snmp_lib_dir; do
-      LIBS="$old_LIBS -L$try -lsnmp"
-      AC_TRY_LINK([extern char snmp_build_var_op();],
-                  [ snmp_build_var_op()],
-                  SNMP_LIBS="-L$try -lsnmp",
-                  SNMP_LIBS=)
-      if test "x$SNMP_LIBS" != "x"; then
-        break;
-      fi
-dnl   #
-dnl   #  That didn't work.  Try adding the '-lcrypto' line.
-dnl   #  Some SNMP libraries are linked against SSL...
-dnl   #
-      LIBS="$old_LIBS -L$try -lsnmp -lcrypto"
-      AC_TRY_LINK([extern char snmp_build_var_op();],
-                  [ snmp_build_var_op()],
-                  SNMP_LIBS="-L$try -lsnmp -lcrypto",
-                  SNMP_LIBS=)
-      if test "x$SNMP_LIBS" != "x"; then
-        break;
-      fi
-dnl   #
-dnl   #  That didn't work.  Try adding the '-lkstat' line.
-dnl   #  Some SNMP libraries are linked against Kernel Statistics,
-dnl   #  in particular, Solaris 9...
-dnl   #
-      LIBS="$old_LIBS -L$try -lsnmp -lcrypto -lkstat"
-      AC_TRY_LINK([extern char snmp_build_var_op();],
-                  [ snmp_build_var_op()],
-                  SNMP_LIBS="-L$try -lsnmp -lcrypto -lkstat",
-                  SNMP_LIBS=)
-      if test "x$SNMP_LIBS" != "x"; then
-        break;
-      fi
-    done
-  fi
-  LIBS="$old_LIBS"
-
-  dnl #
-  dnl #  If one or the other isn't found, disable them both..
-  dnl #  If both are found, enable them both.
-  dnl #
-  CFLAGS="$old_CFLAGS"
-  if test "x$SNMP_LIBS" = "x"; then
-    AC_MSG_RESULT(no)
-    SNMP_INCLUDE=
-  else
-    AC_MSG_RESULT(yes)
-    AC_DEFINE(WITH_SNMP)
-    AC_DEFINE(HAVE_LIBSNMP)
-  fi
-fi
-])
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
 
-dnl #
-dnl #  Locate the directory in which a particular file is found.
-dnl #
-dnl #  Usage: AC_LOCATE_DIR(MYSQLLIB_DIR, libmysqlclient.a)
-dnl #
-dnl #    Defines the variable MYSQLLIB_DIR to be the directory(s) in
-dnl #    which the file libmysqlclient.a is to be found.
-dnl #
-dnl #
-AC_DEFUN(AC_LOCATE_DIR,
-[
-dnl # If we have the program 'locate', then the problem of finding a
-dnl # particular file becomes MUCH easier.
-dnl #
-
-dnl #
-dnl #  No 'locate' defined, do NOT do anything.
-dnl #
-if test "x$LOCATE" != "x"; then
-  dnl #
-  dnl #  Root through a series of directories, looking for the given file.
-  dnl #
-  DIRS=
-  file=$2
-
-  for x in `${LOCATE} $file 2>/dev/null`; do
-    dnl #
-    dnl #  When asked for 'foo', locate will also find 'foo_bar', which we
-    dnl #  don't want.  We want that EXACT filename.
-    dnl #
-    dnl #  We ALSO want to be able to look for files like 'mysql/mysql.h',
-    dnl #  and properly match them, too.  So we try to strip off the last
-    dnl #  part of the filename, using the name of the file we're looking
-    dnl #  for.  If we CANNOT strip it off, then the name will be unchanged.
-    dnl #
-    base=`echo $x | sed "s%/${file}%%"`
-    if test "x$x" = "x$base"; then
-      continue;
-    fi
-
-    dir=`${DIRNAME} $x 2>/dev/null`
-    dnl #
-    dnl #  Exclude a number of directories.
-    dnl #
-    exclude=`echo ${dir} | ${GREP} /home`
-    if test "x$exclude" != "x"; then
-      continue
-    fi
-
-    dnl #
-    dnl #  OK, we have an exact match.  Let's be sure that we only find ONE
-    dnl #  matching directory.
-    dnl #
-    already=`echo \$$1 ${DIRS} | ${GREP} ${dir}`
-    if test "x$already" = "x"; then
-      DIRS="$DIRS $dir"
-    fi
-  done
-fi
-
-dnl #
-dnl #  And remember the directory in which we found the file.
-dnl #
-eval "$1=\"\$$1 $DIRS\""
-])
-
-
-dnl #######################################################################
-dnl #
-dnl #  Look for a library in a number of places.
-dnl #
-dnl #  AC_SMART_CHECK_LIB(library, function)
-dnl #
-AC_DEFUN(AC_SMART_CHECK_LIB, [
-
-sm_lib_safe=`echo "$1" | sed 'y%./+-%__p_%'`
-sm_func_safe=`echo "$2" | sed 'y%./+-%__p_%'`
-AC_MSG_CHECKING([for $2 in -l$1])
-
-old_LIBS="$LIBS"
-smart_lib=
-smart_lib_dir=
-
-dnl #
-dnl #  Try first any user-specified directory, otherwise we may pick up
-dnl #  the wrong version.
-dnl #
-if test "x$smart_try_dir" != "x"; then
-  for try in $smart_try_dir; do
-    LIBS="-L$try -l$1 $old_LIBS"
-    AC_TRY_LINK([extern char $2();],
-               [ $2()],
-               smart_lib="-L$try -l$1")
-    if test "x$smart_lib" != "x"; then
-      break;
-    fi
-  done
-  LIBS="$old_LIBS"
-fi
-
-dnl #
-dnl #  Try using the default library path.
-dnl #
-if test "x$smart_lib" = "x"; then
-  LIBS="-l$1 $old_LIBS"
-  AC_TRY_LINK([extern char $2();],
-             [ $2()],
-             smart_lib="-l$1")
-  LIBS="$old_LIBS"
-fi
-
-dnl #
-dnl #  Try to guess possible locations.
-dnl #
-if test "x$smart_lib" = "x"; then
-  AC_LOCATE_DIR(smart_lib_dir,[lib$1${libltdl_cv_shlibext}])
-  AC_LOCATE_DIR(smart_lib_dir,[lib$1.a])
-
-  for try in $smart_lib_dir /usr/local/lib /opt/lib; do
-    LIBS="-L$try -l$1 $old_LIBS"
-    AC_TRY_LINK([extern char $2();],
-               [ $2()],
-               smart_lib="-L$try -l$1")
-    if test "x$smart_lib" != "x"; then
-      break;
-    fi
-  done
-  LIBS="$old_LIBS"
-fi
+m4_include([libtool.m4])
 
-dnl #
-dnl #  Found it, set the appropriate variable.
-dnl #
-if test "x$smart_lib" != "x"; then
-  AC_MSG_RESULT(yes)
-  eval "ac_cv_lib_${sm_lib_safe}_${sm_func_safe}=yes"
-  LIBS="$smart_lib $old_LIBS"
-  SMART_LIBS="$smart_lib $SMART_LIBS"
-else
-  AC_MSG_RESULT(no)
-fi
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
 ])
 
-dnl #######################################################################
-dnl #
-dnl #  Look for a header file in a number of places.
-dnl #
-dnl #  AC_SMART_CHECK_INCLUDE(foo.h, [ #include <other.h> ])
-dnl #
-AC_DEFUN(AC_SMART_CHECK_INCLUDE, [
-
-ac_safe=`echo "$1" | sed 'y%./+-%__pm%'`
-AC_MSG_CHECKING([for $1])
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
 
-old_CFLAGS="$CFLAGS"
-smart_include=
-smart_include_dir=
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
 
-dnl #
-dnl #  Try first any user-specified directory, otherwise we may pick up
-dnl #  the wrong version.
-dnl #
-if test "x$smart_try_dir" != "x"; then
-  for try in $smart_try_dir; do
-    CFLAGS="$old_CFLAGS -I$try"
-    AC_TRY_COMPILE([$2
-                   #include <$1>],
-                  [ int a = 1;],
-                  smart_include="-I$try",
-                  smart_include=)
-    if test "x$smart_include" != "x"; then
-      break;
-    fi
-  done
-  CFLAGS="$old_CFLAGS"
-fi
+# serial 4
 
-dnl #
-dnl #  Try using the default includes
-dnl #
-if test "x$smart_include" = "x"; then
-  AC_TRY_COMPILE([$2
-                 #include <$1>],
-                [ int a = 1;],
-                smart_include=" ",
-                smart_include=)
-fi
-
-dnl #
-dnl #  Try to guess possible locations.
-dnl #
-if test "x$smart_include" = "x"; then
-  AC_LOCATE_DIR(smart_include_dir,$1)
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
 
-  for try in $smart_include_dir /usr/local/include /opt/include; do
-    CFLAGS="$old_CFLAGS -I$try"
-    AC_TRY_COMPILE([$2
-                   #include <$1>],
-                  [ int a = 1;],
-                  smart_include="-I$try",
-                  smart_include=)
-    if test "x$smart_include" != "x"; then
-      break;
-    fi
-  done
-  CFLAGS="$old_CFLAGS"
-fi
 
-dnl #
-dnl #  Found it, set the appropriate variable.
-dnl #
-if test "x$smart_include" != "x"; then
-  AC_MSG_RESULT(yes)
-  eval "ac_cv_header_$ac_safe=yes"
-  CFLAGS="$old_CFLAGS $smart_include"
-  SMART_CFLAGS="$SMART_CFLAGS $smart_include"
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
 else
-  AC_MSG_RESULT(no)
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
 fi
 ])
 
-dnl #######################################################################
-dnl #
-dnl #  Look for a header file in a number of places.
-dnl #
-dnl #  Usage:  AC_CHECK_STRUCT_HAS_MEMBER([#include <foo.h>], [struct foo], member)
-dnl #  If the member is defined, then the variable
-dnl #     ac_cv_type_struct_foo_has_member is set to 'yes'
-dnl #
-AC_DEFUN(AC_CHECK_STRUCT_HAS_MEMBER, [
-  AC_MSG_CHECKING([for $3 in $2])
-
-dnl BASED on 'offsetof':
-dnl #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-dnl
-
-  AC_TRY_COMPILE([
-$1
-#ifndef offsetof
-#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
-#endif
-],
-                 [ int foo = offsetof($2, $3) ],
-                 has_element=" ",
-                 has_element=)
-
-  ac_safe_type=`echo "$2" | sed 'y% %_%'`
-  if test "x$has_element" != "x"; then
-    AC_MSG_RESULT(yes)
-    eval "ac_cv_type_${ac_safe_type}_has_$3=yes"
-  else
-    AC_MSG_RESULT(no) 
-    eval "ac_cv_type_${ac_safe_type}_has_$3="
- fi
-])
+m4_include([acinclude.m4])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..9cba642
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh -e
+
+parentdir=`dirname $0`
+
+cd $parentdir
+parentdir=`pwd`
+
+libtoolize -f -c
+#aclocal
+autoheader
+autoconf
+
+mysubdirs="$mysubdirs `find src/modules/ -name configure -print | sed 's%/configure%%'`"
+mysubdirs=`echo $mysubdirs`
+
+for F in $mysubdirs
+do
+       echo "Configuring in $F..."
+       (cd $F && grep "^AC_CONFIG_HEADER" configure.in > /dev/null && autoheader -I$parentdir)
+       (cd $F && autoconf -I$parentdir)
+done
index 51fab47..8229471 100755 (executable)
@@ -1,9 +1,9 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
-timestamp='2004-03-12'
+timestamp='2004-11-12'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -53,7 +53,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -203,15 +203,15 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     amiga:OpenBSD:*:*)
        echo m68k-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
-    arc:OpenBSD:*:*)
-       echo mipsel-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
     cats:OpenBSD:*:*)
        echo arm-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
     hp300:OpenBSD:*:*)
        echo m68k-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
+    luna88k:OpenBSD:*:*)
+       echo m88k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
     mac68k:OpenBSD:*:*)
        echo m68k-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
@@ -227,21 +227,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     mvmeppc:OpenBSD:*:*)
        echo powerpc-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
-    pegasos:OpenBSD:*:*)
-       echo powerpc-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
-    pmax:OpenBSD:*:*)
-       echo mipsel-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
     sgi:OpenBSD:*:*)
-       echo mipseb-unknown-openbsd${UNAME_RELEASE}
+       echo mips64-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
     sun3:OpenBSD:*:*)
        echo m68k-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
-    wgrisc:OpenBSD:*:*)
-       echo mipsel-unknown-openbsd${UNAME_RELEASE}
-       exit 0 ;;
     *:OpenBSD:*:*)
        echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
@@ -307,9 +298,6 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
        # 1.2 uses "1.2" for uname -r.
        echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
        exit 0 ;;
-    Alpha*:OpenVMS:*:*)
-       echo alpha-hp-vms
-       exit 0 ;;
     Alpha\ *:Windows_NT*:*)
        # How do we know it's Interix rather than the generic POSIX subsystem?
        # Should we change UNAME_MACHINE based on the output of uname instead
@@ -331,6 +319,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *:OS/390:*:*)
        echo i370-ibm-openedition
        exit 0 ;;
+    *:z/VM:*:*)
+       echo s390-ibm-zvmoe
+       exit 0 ;;
     *:OS400:*:*)
         echo powerpc-ibm-os400
        exit 0 ;;
@@ -354,7 +345,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     DRS?6000:unix:4.0:6*)
        echo sparc-icl-nx6
        exit 0 ;;
-    DRS?6000:UNIX_SV:4.2*:7*)
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
        case `/usr/bin/uname -p` in
            sparc) echo sparc-icl-nx7 && exit 0 ;;
        esac ;;
@@ -764,7 +755,7 @@ EOF
        echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
        exit 0 ;;
     *:UNICOS/mp:*:*)
-       echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
        exit 0 ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
        FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
@@ -787,21 +778,7 @@ EOF
        echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
        exit 0 ;;
     *:FreeBSD:*:*)
-       # Determine whether the default compiler uses glibc.
-       eval $set_cc_for_build
-       sed 's/^        //' << EOF >$dummy.c
-       #include <features.h>
-       #if __GLIBC__ >= 2
-       LIBC=gnu
-       #else
-       LIBC=
-       #endif
-EOF
-       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
-       # GNU/KFreeBSD systems have a "k" prefix to indicate we are using
-       # FreeBSD's kernel, but not the complete OS.
-       case ${LIBC} in gnu) kernel_only='k' ;; esac
-       echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
        exit 0 ;;
     i*:CYGWIN*:*)
        echo ${UNAME_MACHINE}-pc-cygwin
@@ -850,6 +827,12 @@ EOF
     cris:Linux:*:*)
        echo cris-axis-linux-gnu
        exit 0 ;;
+    crisv32:Linux:*:*)
+       echo crisv32-axis-linux-gnu
+       exit 0 ;;
+    frv:Linux:*:*)
+       echo frv-unknown-linux-gnu
+       exit 0 ;;
     ia64:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
        exit 0 ;;
@@ -1096,9 +1079,9 @@ EOF
     M680?0:D-NIX:5.3:*)
        echo m68k-diab-dnix
        exit 0 ;;
-    M68*:*:R3V[567]*:*)
+    M68*:*:R3V[5678]*:*)
        test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
-    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
        OS_REL=''
        test -r /etc/.relid \
        && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
@@ -1196,9 +1179,10 @@ EOF
        echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
        exit 0 ;;
     *:Darwin:*:*)
-       case `uname -p` in
+       UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+       case $UNAME_PROCESSOR in
            *86) UNAME_PROCESSOR=i686 ;;
-           powerpc) UNAME_PROCESSOR=powerpc ;;
+           unknown) UNAME_PROCESSOR=powerpc ;;
        esac
        echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
        exit 0 ;;
@@ -1260,6 +1244,16 @@ EOF
     *:DragonFly:*:*)
        echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
        exit 0 ;;
+    *:*VMS:*:*)
+       UNAME_MACHINE=`(uname -p) 2>/dev/null`
+       case "${UNAME_MACHINE}" in
+           A*) echo alpha-dec-vms && exit 0 ;;
+           I*) echo ia64-dec-vms && exit 0 ;;
+           V*) echo vax-dec-vms && exit 0 ;;
+       esac ;;
+    *:XENIX:*:SysV)
+       echo i386-pc-xenix
+       exit 0 ;;
 esac
 
 #echo '(No uname command or uname output not recognized.)' 1>&2
diff --git a/config.h.in b/config.h.in
deleted file mode 100644 (file)
index 98ed4a3..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
-/*
-
-acconfig.h - template used by autoheader to create config.h.in
-config.h.in - used by autoconf to create config.h
-config.h - created by autoconf; contains defines generated by autoconf
-
-*/
-
-
-#ifndef HAVE_SNPRINTF
-#define HAVE_LOCAL_SNPRINTF
-#define snprintf lrad_snprintf
-#endif
-
-#ifndef HAVE_VSNPRINTF
-#define HAVE_LOCAL_SNPRINTF
-#define vsnprintf lrad_vsnprintf
-#endif
index ba33103..0f84ac2 100755 (executable)
@@ -1,9 +1,9 @@
 #! /bin/sh
 # Configuration validation subroutine script.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
-timestamp='2004-03-12'
+timestamp='2004-11-30'
 
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
@@ -70,7 +70,7 @@ Report bugs and patches to <config-patches@gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -145,7 +145,7 @@ case $os in
        -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
        -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
        -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-       -apple | -axis)
+       -apple | -axis | -knuth | -cray)
                os=
                basic_machine=$1
                ;;
@@ -267,7 +267,7 @@ case $basic_machine in
        | tahoe | thumb | tic4x | tic80 | tron \
        | v850 | v850e \
        | we32k \
-       | x86 | xscale | xstormy16 | xtensa \
+       | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
        | z8k)
                basic_machine=$basic_machine-unknown
                ;;
@@ -300,7 +300,7 @@ case $basic_machine in
        | avr-* \
        | bs2000-* \
        | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
-       | clipper-* | cydra-* \
+       | clipper-* | craynv-* | cydra-* \
        | d10v-* | d30v-* | dlx-* \
        | elxsi-* \
        | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
@@ -326,8 +326,9 @@ case $basic_machine in
        | mipsisa64sb1-* | mipsisa64sb1el-* \
        | mipsisa64sr71k-* | mipsisa64sr71kel-* \
        | mipstx39-* | mipstx39el-* \
+       | mmix-* \
        | msp430-* \
-       | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
+       | none-* | np1-* | ns16k-* | ns32k-* \
        | orion-* \
        | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
        | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
@@ -342,8 +343,8 @@ case $basic_machine in
        | tron-* \
        | v850-* | v850e-* | vax-* \
        | we32k-* \
-       | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
-       | xtensa-* \
+       | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
+       | xstormy16-* | xtensa-* \
        | ymp-* \
        | z8k-*)
                ;;
@@ -445,6 +446,10 @@ case $basic_machine in
                basic_machine=j90-cray
                os=-unicos
                ;;
+       craynv)
+               basic_machine=craynv-cray
+               os=-unicosmp
+               ;;
        cr16c)
                basic_machine=cr16c-unknown
                os=-elf
@@ -452,6 +457,9 @@ case $basic_machine in
        crds | unos)
                basic_machine=m68k-crds
                ;;
+       crisv32 | crisv32-* | etraxfs*)
+               basic_machine=crisv32-axis
+               ;;
        cris | cris-* | etrax*)
                basic_machine=cris-axis
                ;;
@@ -481,6 +489,10 @@ case $basic_machine in
                basic_machine=m88k-motorola
                os=-sysv3
                ;;
+       djgpp)
+               basic_machine=i586-pc
+               os=-msdosdjgpp
+               ;;
        dpx20 | dpx20-*)
                basic_machine=rs6000-bull
                os=-bosx
@@ -659,10 +671,6 @@ case $basic_machine in
        mips3*)
                basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
                ;;
-       mmix*)
-               basic_machine=mmix-knuth
-               os=-mmixware
-               ;;
        monitor)
                basic_machine=m68k-rom68k
                os=-coff
@@ -743,10 +751,6 @@ case $basic_machine in
        np1)
                basic_machine=np1-gould
                ;;
-       nv1)
-               basic_machine=nv1-cray
-               os=-unicosmp
-               ;;
        nsr-tandem)
                basic_machine=nsr-tandem
                ;;
@@ -1029,6 +1033,10 @@ case $basic_machine in
                basic_machine=hppa1.1-winbond
                os=-proelf
                ;;
+       xbox)
+               basic_machine=i686-pc
+               os=-mingw32
+               ;;
        xps | xps100)
                basic_machine=xps100-honeywell
                ;;
@@ -1059,6 +1067,9 @@ case $basic_machine in
        romp)
                basic_machine=romp-ibm
                ;;
+       mmix)
+               basic_machine=mmix-knuth
+               ;;
        rs6000)
                basic_machine=rs6000-ibm
                ;;
@@ -1294,6 +1305,9 @@ case $os in
        -kaos*)
                os=-kaos
                ;;
+       -zvmoe)
+               os=-zvmoe
+               ;;
        -none)
                ;;
        *)
@@ -1374,6 +1388,9 @@ case $basic_machine in
        *-ibm)
                os=-aix
                ;;
+       *-knuth)
+               os=-mmixware
+               ;;
        *-wec)
                os=-proelf
                ;;
index 26506dd..3d3b4eb 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,10 +1,9 @@
 #! /bin/sh
-# From configure.in Revision: 1.198.2.15.2.11 .
+# From configure.in Revision: 1.232 .
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.60.
+# Generated by GNU Autoconf 2.59.
 #
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2003 Free Software Foundation, Inc.
 # This configure script is free software; the Free Software Foundation
 # gives unlimited permission to copy, distribute and modify it.
 ## --------------------- ##
@@ -18,35 +17,11 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
   # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
   # is contrary to our usage.  Disable this feature.
   alias -g '${1+"$@"}'='"$@"'
-  setopt NO_GLOB_SUBST
-else
-  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
 fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
 DUALCASE=1; export DUALCASE # for MKS sh
 
-
-# PATH needs CR
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
-fi
-
 # Support unset when possible.
 if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
   as_unset=unset
@@ -55,43 +30,8 @@ else
 fi
 
 
-# IFS
-# We need space, tab and new line, in precisely that order.  Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-as_nl='
-'
-IFS=" ""       $as_nl"
-
-# Find who we are.  Look in the path if we contain no directory separator.
-case $0 in
-  *[\\/]* ) as_myself=$0 ;;
-  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-IFS=$as_save_IFS
-
-     ;;
-esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
-# in which case we are not to be found in the path.
-if test "x$as_myself" = x; then
-  as_myself=$0
-fi
-if test ! -f "$as_myself"; then
-  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
-  { (exit 1); exit 1; }
-fi
-
 # Work around bugs in pre-3.0 UWIN ksh.
-for as_var in ENV MAIL MAILPATH
-do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-done
+$as_unset ENV MAIL MAILPATH
 PS1='$ '
 PS2='> '
 PS4='+ '
@@ -105,19 +45,18 @@ do
   if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
     eval $as_var=C; export $as_var
   else
-    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+    $as_unset $as_var
   fi
 done
 
 # Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1 &&
-   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+if expr a : '\(a\)' >/dev/null 2>&1; then
   as_expr=expr
 else
   as_expr=false
 fi
 
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
   as_basename=basename
 else
   as_basename=false
@@ -125,386 +64,157 @@ fi
 
 
 # Name of the executable.
-as_me=`$as_basename -- "$0" ||
+as_me=`$as_basename "$0" ||
 $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
         X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
 echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{
-           s//\1/
-           q
-         }
-         /^X\/\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\/\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
-
-# CDPATH.
-$as_unset CDPATH
-
-
-if test "x$CONFIG_SHELL" = x; then
-  if (eval ":") 2>/dev/null; then
-  as_have_required=yes
-else
-  as_have_required=no
-fi
-
-  if test $as_have_required = yes &&    (eval ":
-(as_func_return () {
-  (exit \$1)
-}
-as_func_success () {
-  as_func_return 0
-}
-as_func_failure () {
-  as_func_return 1
-}
-as_func_ret_success () {
-  return 0
-}
-as_func_ret_failure () {
-  return 1
-}
-
-exitcode=0
-if as_func_success; then
-  :
-else
-  exitcode=1
-  echo as_func_success failed.
-fi
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
 
-if as_func_failure; then
-  exitcode=1
-  echo as_func_failure succeeded.
-fi
 
-if as_func_ret_success; then
-  :
-else
-  exitcode=1
-  echo as_func_ret_success failed.
-fi
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
 
-if as_func_ret_failure; then
-  exitcode=1
-  echo as_func_ret_failure succeeded.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
 fi
 
-if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
-  :
-else
-  exitcode=1
-  echo positional parameters were not saved.
-fi
 
-test \$exitcode = 0) || { (exit 1); exit 1; }
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
 
-(
-  as_lineno_1=\$LINENO
-  as_lineno_2=\$LINENO
-  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
-  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
-") 2> /dev/null; then
-  :
-else
-  as_candidate_shells=
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
     as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  case $as_dir in
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
         /*)
-          for as_base in sh bash ksh sh5; do
-            as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
-          done;;
-       esac
-done
-IFS=$as_save_IFS
-
-
-      for as_shell in $as_candidate_shells $SHELL; do
-        # Try only shells that exist, to save several forks.
-        if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
-               { ("$as_shell") 2> /dev/null <<\_ASEOF
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-  setopt NO_GLOB_SUBST
-else
-  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
-fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
-
-:
-_ASEOF
-}; then
-  CONFIG_SHELL=$as_shell
-              as_have_required=yes
-              if { "$as_shell" 2> /dev/null <<\_ASEOF
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-  setopt NO_GLOB_SUBST
-else
-  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
-fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
-DUALCASE=1; export DUALCASE # for MKS sh
-
-:
-(as_func_return () {
-  (exit $1)
-}
-as_func_success () {
-  as_func_return 0
-}
-as_func_failure () {
-  as_func_return 1
-}
-as_func_ret_success () {
-  return 0
-}
-as_func_ret_failure () {
-  return 1
-}
-
-exitcode=0
-if as_func_success; then
-  :
-else
-  exitcode=1
-  echo as_func_success failed.
-fi
-
-if as_func_failure; then
-  exitcode=1
-  echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
-  :
-else
-  exitcode=1
-  echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
-  exitcode=1
-  echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = "$1" ); then
-  :
-else
-  exitcode=1
-  echo positional parameters were not saved.
-fi
-
-test $exitcode = 0) || { (exit 1); exit 1; }
-
-(
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
-
-_ASEOF
-}; then
-  break
-fi
-
-fi
-
-      done
-
-      if test "x$CONFIG_SHELL" != x; then
-  for as_var in BASH_ENV ENV
-        do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-        done
-        export CONFIG_SHELL
-        exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
-fi
-
-
-    if test $as_have_required = no; then
-  echo This script requires a shell more modern than all the
-      echo shells that I found on your system.  Please install a
-      echo modern shell, or manually run the script under such a
-      echo shell if you do have one.
-      { (exit 1); exit 1; }
-fi
-
-
-fi
-
-fi
-
-
-
-(eval "as_func_return () {
-  (exit \$1)
-}
-as_func_success () {
-  as_func_return 0
-}
-as_func_failure () {
-  as_func_return 1
-}
-as_func_ret_success () {
-  return 0
-}
-as_func_ret_failure () {
-  return 1
-}
-
-exitcode=0
-if as_func_success; then
-  :
-else
-  exitcode=1
-  echo as_func_success failed.
-fi
-
-if as_func_failure; then
-  exitcode=1
-  echo as_func_failure succeeded.
-fi
-
-if as_func_ret_success; then
-  :
-else
-  exitcode=1
-  echo as_func_ret_success failed.
-fi
-
-if as_func_ret_failure; then
-  exitcode=1
-  echo as_func_ret_failure succeeded.
-fi
-
-if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
-  :
-else
-  exitcode=1
-  echo positional parameters were not saved.
-fi
-
-test \$exitcode = 0") || {
-  echo No shell found that supports shell functions.
-  echo Please tell autoconf@gnu.org about your system,
-  echo including any error possibly output before this
-  echo message
-}
-
-
-
+          if ("$as_dir/$as_base" -c '
   as_lineno_1=$LINENO
   as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
   test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
 
   # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
   # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line after each line using $LINENO; the second 'sed'
-  # does the real work.  The second script uses 'N' to pair each
-  # line-number line with the line containing $LINENO, and appends
-  # trailing '-' during substitution so that $LINENO is not a special
-  # case at line end.
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
   # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # scripts with optimization help from Paolo Bonzini.  Blame Lee
-  # E. McMahon (1931-1989) for sed's syntax.  :-)
-  sed -n '
-    p
-    /[$]LINENO/=
-  ' <$as_myself |
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
     sed '
-      s/[$]LINENO.*/&-/
-      t lineno
-      b
-      :lineno
       N
-      :loop
-      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
       t loop
-      s/-\n.*//
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
     ' >$as_me.lineno &&
-  chmod +x "$as_me.lineno" ||
+  chmod +x $as_me.lineno ||
     { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
    { (exit 1); exit 1; }; }
 
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensitive to this).
-  . "./$as_me.lineno"
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
   # Exit status is that of the last command.
   exit
 }
 
 
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
-  as_dirname=dirname
-else
-  as_dirname=false
-fi
-
-ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in
--n*)
-  case `echo 'x\c'` in
-  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
-  *)   ECHO_C='\c';;
-  esac;;
-*)
-  ECHO_N='-n';;
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
 esac
 
-if expr a : '\(a\)' >/dev/null 2>&1 &&
-   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+if expr a : '\(a\)' >/dev/null 2>&1; then
   as_expr=expr
 else
   as_expr=false
 fi
 
 rm -f conf$$ conf$$.exe conf$$.file
-if test -d conf$$.dir; then
-  rm -f conf$$.dir/conf$$.file
-else
-  rm -f conf$$.dir
-  mkdir conf$$.dir
-fi
 echo >conf$$.file
 if ln -s conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s='ln -s'
-  # ... but there are two gotchas:
-  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
-  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-  # In both cases, we have to default to `cp -p'.
-  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
     as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
 elif ln conf$$.file conf$$ 2>/dev/null; then
   as_ln_s=ln
 else
   as_ln_s='cp -p'
 fi
-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
-rmdir conf$$.dir 2>/dev/null
+rm -f conf$$ conf$$.exe conf$$.file
 
 if mkdir -p . 2>/dev/null; then
   as_mkdir_p=:
@@ -513,19 +223,7 @@ else
   as_mkdir_p=false
 fi
 
-# Find out whether ``test -x'' works.  Don't use a zero-byte file, as
-# systems may use methods other than mode bits to determine executability.
-cat >conf$$.file <<_ASEOF
-#! /bin/sh
-exit 0
-_ASEOF
-chmod +x conf$$.file
-if test -x conf$$.file >/dev/null 2>&1; then
-  as_executable_p="test -x"
-else
-  as_executable_p=:
-fi
-rm -f conf$$.file
+as_executable_p="test -f"
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -534,6 +232,15 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
 as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
 
 
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
 
 
 # Check that we are running under the correct shell.
@@ -689,26 +396,29 @@ tagnames=${tagnames+${tagnames},}CXX
 
 tagnames=${tagnames+${tagnames},}F77
 
-exec 7<&0 </dev/null 6>&1
-
 # Name of the host.
 # hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
 # so uname gets run too.
 ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
 
+exec 6>&1
+
 #
 # Initializations.
 #
 ac_default_prefix=/usr/local
-ac_clean_files=
 ac_config_libobj_dir=.
-LIBOBJS=
 cross_compiling=no
 subdirs=
 MFLAGS=
 MAKEFLAGS=
 SHELL=${CONFIG_SHELL-/bin/sh}
 
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete.  It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
 # Identity of this package.
 PACKAGE_NAME=
 PACKAGE_TARNAME=
@@ -745,140 +455,18 @@ ac_includes_default="\
 #endif
 #if HAVE_INTTYPES_H
 # include <inttypes.h>
-#endif
-#if HAVE_STDINT_H
-# include <stdint.h>
+#else
+# if HAVE_STDINT_H
+#  include <stdint.h>
+# endif
 #endif
 #if HAVE_UNISTD_H
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL
-PATH_SEPARATOR
-PACKAGE_NAME
-PACKAGE_TARNAME
-PACKAGE_VERSION
-PACKAGE_STRING
-PACKAGE_BUGREPORT
-exec_prefix
-prefix
-program_transform_name
-bindir
-sbindir
-libexecdir
-datarootdir
-datadir
-sysconfdir
-sharedstatedir
-localstatedir
-includedir
-oldincludedir
-docdir
-infodir
-htmldir
-dvidir
-pdfdir
-psdir
-libdir
-localedir
-mandir
-DEFS
-ECHO_C
-ECHO_N
-ECHO_T
-LIBS
-build_alias
-host_alias
-target_alias
-CC
-CFLAGS
-LDFLAGS
-CPPFLAGS
-ac_ct_CC
-EXEEXT
-OBJEXT
-CPP
-GREP
-EGREP
-RANLIB
-abs_top_builddir
-GMAKE
-MAKE
-LTDL_SUBDIRS
-LIBTOOL
-build
-build_cpu
-build_vendor
-build_os
-host
-host_cpu
-host_vendor
-host_os
-LN_S
-ECHO
-AR
-STRIP
-CXX
-CXXFLAGS
-ac_ct_CXX
-CXXCPP
-F77
-FFLAGS
-ac_ct_F77
-logdir
-radacctdir
-raddbdir
-PERL
-SNMPGET
-SNMPWALK
-RUSERS
-ACLOCAL
-AUTOCONF
-AUTOHEADER
-LOCATE
-DIRNAME
-REGEX
-REGEX_EXTENDED
-OPENSSL_INCLUDE
-OPENSSL_LIBS
-LIBPREFIX
-CRYPTLIB
-SNMP_LIBS
-SNMP_INCLUDE
-GETCONF
-LFS_CFLAGS
-LFS_LDFLAGS
-LFS_LIBS
-HOSTINFO
-LIBLTDL
-INCLTDL
-subdirs
-MODULES
-INSTALLSTRIP
-USE_SHARED_LIBS
-USE_STATIC_LIBS
-STATIC_MODULES
-RADIUSD_MAJOR_VERSION
-RADIUSD_MINOR_VERSION
-RADIUSD_VERSION
-LIBOBJS
-LTLIBOBJS'
+ac_subdirs_all="$ac_subdirs_all $LTDL_SUBDIRS $mysubdirs"
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX CPP EGREP RANLIB ac_ct_RANLIB GMAKE MAKE LTDL_SUBDIRS LIBTOOL build build_cpu build_vendor build_os host host_cpu host_vendor host_os LN_S ECHO AR ac_ct_AR STRIP ac_ct_STRIP CXXCPP F77 FFLAGS ac_ct_F77 docdir logdir radacctdir raddbdir PERL SNMPGET SNMPWALK RUSERS ACLOCAL AUTOCONF AUTOHEADER LOCATE DIRNAME GREP REGEX REGEX_EXTENDED OPENSSL_INCLUDE OPENSSL_LIBS PCAP_LIBS LIBPREFIX CRYPTLIB SNMP_LIBS SNMP_INCLUDE HOSTINFO LIBLTDL INCLTDL subdirs MODULES INSTALLSTRIP USE_SHARED_LIBS USE_STATIC_LIBS STATIC_MODULES RADIUSD_MAJOR_VERSION RADIUSD_MINOR_VERSION RADIUSD_VERSION LIBOBJS LTLIBOBJS'
 ac_subst_files=''
-      ac_precious_vars='build_alias
-host_alias
-target_alias
-CC
-CFLAGS
-LDFLAGS
-CPPFLAGS
-CPP
-CXX
-CXXFLAGS
-CCC
-CXXCPP
-F77
-FFLAGS'
-ac_subdirs_all='$LTDL_SUBDIRS $mysubdirs'
 
 # Initialize some variables set by options.
 ac_init_help=
@@ -905,48 +493,34 @@ x_libraries=NONE
 # and all the variables that are supposed to be based on exec_prefix
 # by default will actually change.
 # Use braces instead of parens because sh, perl, etc. also accept them.
-# (The list follows the same order as the GNU Coding Standards.)
 bindir='${exec_prefix}/bin'
 sbindir='${exec_prefix}/sbin'
 libexecdir='${exec_prefix}/libexec'
-datarootdir='${prefix}/share'
-datadir='${datarootdir}'
+datadir='${prefix}/share'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
-docdir='${datarootdir}/doc/${PACKAGE}'
-infodir='${datarootdir}/info'
-htmldir='${docdir}'
-dvidir='${docdir}'
-pdfdir='${docdir}'
-psdir='${docdir}'
-libdir='${exec_prefix}/lib'
-localedir='${datarootdir}/locale'
-mandir='${datarootdir}/man'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
 
 ac_prev=
-ac_dashdash=
 for ac_option
 do
   # If the previous option needs an argument, assign it.
   if test -n "$ac_prev"; then
-    eval $ac_prev=\$ac_option
+    eval "$ac_prev=\$ac_option"
     ac_prev=
     continue
   fi
 
-  case $ac_option in
-  *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
-  *)   ac_optarg=yes ;;
-  esac
+  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
 
   # Accept the important Cygnus configure options, so we can diagnose typos.
 
-  case $ac_dashdash$ac_option in
-  --)
-    ac_dashdash=yes ;;
+  case $ac_option in
 
   -bindir | --bindir | --bindi | --bind | --bin | --bi)
     ac_prev=bindir ;;
@@ -968,18 +542,12 @@ do
   --config-cache | -C)
     cache_file=config.cache ;;
 
-  -datadir | --datadir | --datadi | --datad)
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
     ac_prev=datadir ;;
-  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
     datadir=$ac_optarg ;;
 
-  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
-  | --dataroo | --dataro | --datar)
-    ac_prev=datarootdir ;;
-  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
-  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
-    datarootdir=$ac_optarg ;;
-
   -disable-* | --disable-*)
     ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
     # Reject names that are not valid shell variable names.
@@ -987,17 +555,7 @@ do
       { echo "$as_me: error: invalid feature name: $ac_feature" >&2
    { (exit 1); exit 1; }; }
     ac_feature=`echo $ac_feature | sed 's/-/_/g'`
-    eval enable_$ac_feature=no ;;
-
-  -docdir | --docdir | --docdi | --doc | --do)
-    ac_prev=docdir ;;
-  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
-    docdir=$ac_optarg ;;
-
-  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
-    ac_prev=dvidir ;;
-  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
-    dvidir=$ac_optarg ;;
+    eval "enable_$ac_feature=no" ;;
 
   -enable-* | --enable-*)
     ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
@@ -1006,7 +564,11 @@ do
       { echo "$as_me: error: invalid feature name: $ac_feature" >&2
    { (exit 1); exit 1; }; }
     ac_feature=`echo $ac_feature | sed 's/-/_/g'`
-    eval enable_$ac_feature=\$ac_optarg ;;
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_$ac_feature='$ac_optarg'" ;;
 
   -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
   | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
@@ -1033,12 +595,6 @@ do
   -host=* | --host=* | --hos=* | --ho=*)
     host_alias=$ac_optarg ;;
 
-  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
-    ac_prev=htmldir ;;
-  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
-  | --ht=*)
-    htmldir=$ac_optarg ;;
-
   -includedir | --includedir | --includedi | --included | --include \
   | --includ | --inclu | --incl | --inc)
     ac_prev=includedir ;;
@@ -1063,16 +619,13 @@ do
   | --libexe=* | --libex=* | --libe=*)
     libexecdir=$ac_optarg ;;
 
-  -localedir | --localedir | --localedi | --localed | --locale)
-    ac_prev=localedir ;;
-  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
-    localedir=$ac_optarg ;;
-
   -localstatedir | --localstatedir | --localstatedi | --localstated \
-  | --localstate | --localstat | --localsta | --localst | --locals)
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
     ac_prev=localstatedir ;;
   -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
-  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
     localstatedir=$ac_optarg ;;
 
   -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
@@ -1137,16 +690,6 @@ do
   | --progr-tra=* | --program-tr=* | --program-t=*)
     program_transform_name=$ac_optarg ;;
 
-  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
-    ac_prev=pdfdir ;;
-  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
-    pdfdir=$ac_optarg ;;
-
-  -psdir | --psdir | --psdi | --psd | --ps)
-    ac_prev=psdir ;;
-  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
-    psdir=$ac_optarg ;;
-
   -q | -quiet | --quiet | --quie | --qui | --qu | --q \
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
@@ -1203,7 +746,11 @@ do
       { echo "$as_me: error: invalid package name: $ac_package" >&2
    { (exit 1); exit 1; }; }
     ac_package=`echo $ac_package| sed 's/-/_/g'`
-    eval with_$ac_package=\$ac_optarg ;;
+    case $ac_option in
+      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_$ac_package='$ac_optarg'" ;;
 
   -without-* | --without-*)
     ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
@@ -1212,7 +759,7 @@ do
       { echo "$as_me: error: invalid package name: $ac_package" >&2
    { (exit 1); exit 1; }; }
     ac_package=`echo $ac_package | sed 's/-/_/g'`
-    eval with_$ac_package=no ;;
+    eval "with_$ac_package=no" ;;
 
   --x)
     # Obsolete; use --with-x.
@@ -1243,7 +790,8 @@ Try \`$0 --help' for more information." >&2
     expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
       { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
    { (exit 1); exit 1; }; }
-    eval $ac_envvar=\$ac_optarg
+    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+    eval "$ac_envvar='$ac_optarg'"
     export $ac_envvar ;;
 
   *)
@@ -1263,19 +811,27 @@ if test -n "$ac_prev"; then
    { (exit 1); exit 1; }; }
 fi
 
-# Be sure to have absolute directory names.
-for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
-               datadir sysconfdir sharedstatedir localstatedir includedir \
-               oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-               libdir localedir mandir
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
 do
-  eval ac_val=\$$ac_var
+  eval ac_val=$`echo $ac_var`
   case $ac_val in
-    [\\/$]* | ?:[\\/]* )  continue;;
-    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+             localstatedir libdir includedir oldincludedir infodir mandir
+do
+  eval ac_val=$`echo $ac_var`
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* ) ;;
+    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; };;
   esac
-  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
-   { (exit 1); exit 1; }; }
 done
 
 # There might be people who depend on the old broken behavior: `$host'
@@ -1302,76 +858,94 @@ test -n "$host_alias" && ac_tool_prefix=$host_alias-
 test "$silent" = yes && exec 6>/dev/null
 
 
-ac_pwd=`pwd` && test -n "$ac_pwd" &&
-ac_ls_di=`ls -di .` &&
-ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
-  { echo "$as_me: error: Working directory cannot be determined" >&2
-   { (exit 1); exit 1; }; }
-test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
-  { echo "$as_me: error: pwd does not report name of working directory" >&2
-   { (exit 1); exit 1; }; }
-
-
 # Find the source files, if location was not specified.
 if test -z "$srcdir"; then
   ac_srcdir_defaulted=yes
-  # Try the directory containing this script, then the parent directory.
-  ac_confdir=`$as_dirname -- "$0" ||
+  # Try the directory containing this script, then its parent.
+  ac_confdir=`(dirname "$0") 2>/dev/null ||
 $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
         X"$0" : 'X\(//\)[^/]' \| \
         X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+        X"$0" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
 echo X"$0" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)[^/].*/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
   srcdir=$ac_confdir
-  if test ! -r "$srcdir/$ac_unique_file"; then
+  if test ! -r $srcdir/$ac_unique_file; then
     srcdir=..
   fi
 else
   ac_srcdir_defaulted=no
 fi
-if test ! -r "$srcdir/$ac_unique_file"; then
-  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
-  { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+   { (exit 1); exit 1; }; }
+  else
+    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
    { (exit 1); exit 1; }; }
+  fi
 fi
-ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
-ac_abs_confdir=`(
-       cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
    { (exit 1); exit 1; }; }
-       pwd)`
-# When building in place, set srcdir=.
-if test "$ac_abs_confdir" = "$ac_pwd"; then
-  srcdir=.
-fi
-# Remove unnecessary trailing slashes from srcdir.
-# Double slashes in file names in object file debugging info
-# mess up M-x gdb in Emacs.
-case $srcdir in
-*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
-esac
-for ac_var in $ac_precious_vars; do
-  eval ac_env_${ac_var}_set=\${${ac_var}+set}
-  eval ac_env_${ac_var}_value=\$${ac_var}
-  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
-  eval ac_cv_env_${ac_var}_value=\$${ac_var}
-done
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CXX_set=${CXX+set}
+ac_env_CXX_value=$CXX
+ac_cv_env_CXX_set=${CXX+set}
+ac_cv_env_CXX_value=$CXX
+ac_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_env_CXXFLAGS_value=$CXXFLAGS
+ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_cv_env_CXXFLAGS_value=$CXXFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+ac_env_CXXCPP_set=${CXXCPP+set}
+ac_env_CXXCPP_value=$CXXCPP
+ac_cv_env_CXXCPP_set=${CXXCPP+set}
+ac_cv_env_CXXCPP_value=$CXXCPP
+ac_env_F77_set=${F77+set}
+ac_env_F77_value=$F77
+ac_cv_env_F77_set=${F77+set}
+ac_cv_env_F77_value=$F77
+ac_env_FFLAGS_set=${FFLAGS+set}
+ac_env_FFLAGS_value=$FFLAGS
+ac_cv_env_FFLAGS_set=${FFLAGS+set}
+ac_cv_env_FFLAGS_value=$FFLAGS
 
 #
 # Report the --help message.
@@ -1400,6 +974,9 @@ Configuration:
   -n, --no-create         do not create output files
       --srcdir=DIR        find the sources in DIR [configure dir or \`..']
 
+_ACEOF
+
+  cat <<_ACEOF
 Installation directories:
   --prefix=PREFIX         install architecture-independent files in PREFIX
                          [$ac_default_prefix]
@@ -1417,22 +994,15 @@ Fine tuning of the installation directories:
   --bindir=DIR           user executables [EPREFIX/bin]
   --sbindir=DIR          system admin executables [EPREFIX/sbin]
   --libexecdir=DIR       program executables [EPREFIX/libexec]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
   --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
   --libdir=DIR           object code libraries [EPREFIX/lib]
   --includedir=DIR       C header files [PREFIX/include]
   --oldincludedir=DIR    C header files for non-gcc [/usr/include]
-  --datarootdir=DIR      read-only arch.-independent data root [PREFIX/share]
-  --datadir=DIR          read-only architecture-independent data [DATAROOTDIR]
-  --infodir=DIR          info documentation [DATAROOTDIR/info]
-  --localedir=DIR        locale-dependent data [DATAROOTDIR/locale]
-  --mandir=DIR           man documentation [DATAROOTDIR/man]
-  --docdir=DIR           documentation root [DATAROOTDIR/doc/PACKAGE]
-  --htmldir=DIR          html documentation [DOCDIR]
-  --dvidir=DIR           dvi documentation [DOCDIR]
-  --pdfdir=DIR           pdf documentation [DOCDIR]
-  --psdir=DIR            ps documentation [DOCDIR]
+  --infodir=DIR          info documentation [PREFIX/info]
+  --mandir=DIR           man documentation [PREFIX/man]
 _ACEOF
 
   cat <<\_ACEOF
@@ -1450,8 +1020,11 @@ if test -n "$ac_init_help"; then
 Optional Features:
   --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
   --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
-  --enable-shared[=PKGS]  build shared libraries [default=yes]
-  --enable-static[=PKGS]  build static libraries [default=yes]
+  --disable-largefile     omit support for large files
+  --enable-shared[=PKGS]
+                          build shared libraries [default=yes]
+  --enable-static[=PKGS]
+                          build static libraries [default=yes]
   --enable-fast-install[=PKGS]
                           optimize for fast installation [default=yes]
   --disable-libtool-lock  avoid locking (might break parallel builds)
@@ -1465,7 +1038,8 @@ Optional Packages:
   --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
   --with-pic              try to use only PIC/non-PIC objects [default=use
                           both]
-  --with-tags[=TAGS]      include additional configurations [automatic]
+  --with-tags[=TAGS]
+                          include additional configurations [automatic]
   --with-docdir=DIR       Directory for documentation DATADIR/doc/freeradius
   --with-logdir=DIR       Directory for logfiles LOCALSTATEDIR/log/radius
   --with-radacctdir=DIR   Directory for detail files LOGDIR/radacct
@@ -1473,7 +1047,6 @@ Optional Packages:
   --with-ascend-binary    Include support for Ascend binary filter attributes (default=yes)
   --with-threads          Use threads, if available.  (default=yes)
   --with-snmp             Compile in SNMP support. (default=yes)
-  --with-large-files      Compile in large (2G+) file support. (default=no)
   --with-static-modules=QUOTED-MODULE-LIST
  --with-modules=QUOTED-MODULE-LIST
   --with-experimental-modules      Use experimental and unstable modules. (default=no)
@@ -1482,18 +1055,17 @@ Optional Packages:
   --with-rlm-FOO-lib-dir=DIR       Directory to look for library files used by module FOO
   --with-rlm-FOO-include-dir=DIR   Directory to look for include files used by module FOO
   --with-udpfromto        Compile in UDPFROMTO support. (default=no)
-  --with-edir             Enable Novell eDirectory integration.  (default=no)
 
 Some influential environment variables:
   CC          C compiler command
   CFLAGS      C compiler flags
   LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
               nonstandard directory <lib dir>
-  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
-              you have headers in a nonstandard directory <include dir>
-  CPP         C preprocessor
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
   CXX         C++ compiler command
   CXXFLAGS    C++ compiler flags
+  CPP         C preprocessor
   CXXCPP      C++ preprocessor
   F77         Fortran 77 compiler command
   FFLAGS      Fortran 77 compiler flags
@@ -1502,86 +1074,118 @@ Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
 
 _ACEOF
-ac_status=$?
 fi
 
 if test "$ac_init_help" = "recursive"; then
   # If there are subdirs, report their specific --help.
+  ac_popdir=`pwd`
   for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
-    test -d "$ac_dir" || continue
+    test -d $ac_dir || continue
     ac_builddir=.
 
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
+if test "$ac_dir" != .; then
   ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A ".." for each directory in $ac_dir_suffix.
-  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
-  case $ac_top_builddir_sub in
-  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
-  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
-  esac ;;
-esac
-ac_abs_top_builddir=$ac_pwd
-ac_abs_builddir=$ac_pwd$ac_dir_suffix
-# for backward compatibility:
-ac_top_builddir=$ac_top_build_prefix
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
 
 case $srcdir in
-  .)  # We are building in place.
+  .)  # No --srcdir option.  We are building in place.
     ac_srcdir=.
-    ac_top_srcdir=$ac_top_builddir_sub
-    ac_abs_top_srcdir=$ac_pwd ;;
-  [\\/]* | ?:[\\/]* )  # Absolute name.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
     ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir
-    ac_abs_top_srcdir=$srcdir ;;
-  *) # Relative name.
-    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_build_prefix$srcdir
-    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
 esac
-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
-
-    cd "$ac_dir" || { ac_status=$?; continue; }
-    # Check for guested configure.
-    if test -f "$ac_srcdir/configure.gnu"; then
-      echo &&
-      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
-    elif test -f "$ac_srcdir/configure"; then
-      echo &&
-      $SHELL "$ac_srcdir/configure" --help=recursive
+
+    cd $ac_dir
+    # Check for guested configure; otherwise get Cygnus style configure.
+    if test -f $ac_srcdir/configure.gnu; then
+      echo
+      $SHELL $ac_srcdir/configure.gnu  --help=recursive
+    elif test -f $ac_srcdir/configure; then
+      echo
+      $SHELL $ac_srcdir/configure  --help=recursive
+    elif test -f $ac_srcdir/configure.ac ||
+          test -f $ac_srcdir/configure.in; then
+      echo
+      $ac_configure --help
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
-    fi || ac_status=$?
-    cd "$ac_pwd" || { ac_status=$?; break; }
+    fi
+    cd $ac_popdir
   done
 fi
 
-test -n "$ac_init_help" && exit $ac_status
+test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-configure
-generated by GNU Autoconf 2.60
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+Copyright (C) 2003 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 _ACEOF
-  exit
+  exit 0
 fi
-cat >config.log <<_ACEOF
+exec 5>config.log
+cat >&5 <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
 It was created by $as_me, which was
-generated by GNU Autoconf 2.60.  Invocation command line was
+generated by GNU Autoconf 2.59.  Invocation command line was
 
   $ $0 $@
 
 _ACEOF
-exec 5>>config.log
 {
 cat <<_ASUNAME
 ## --------- ##
@@ -1600,7 +1204,7 @@ uname -v = `(uname -v) 2>/dev/null || echo unknown`
 /bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
 /usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
 /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
-/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
 /bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
 /usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
 /bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
@@ -1614,7 +1218,6 @@ do
   test -z "$as_dir" && as_dir=.
   echo "PATH: $as_dir"
 done
-IFS=$as_save_IFS
 
 } >&5
 
@@ -1636,6 +1239,7 @@ _ACEOF
 ac_configure_args=
 ac_configure_args0=
 ac_configure_args1=
+ac_sep=
 ac_must_keep_next=false
 for ac_pass in 1 2
 do
@@ -1646,7 +1250,7 @@ do
     -q | -quiet | --quiet | --quie | --qui | --qu | --q \
     | -silent | --silent | --silen | --sile | --sil)
       continue ;;
-    *\'*)
+    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
       ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
     esac
     case $ac_pass in
@@ -1668,7 +1272,9 @@ do
          -* ) ac_must_keep_next=true ;;
        esac
       fi
-      ac_configure_args="$ac_configure_args '$ac_arg'"
+      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+      # Get rid of the leading space.
+      ac_sep=" "
       ;;
     esac
   done
@@ -1679,8 +1285,8 @@ $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_
 # When interrupted or exit'd, cleanup temporary files, and complete
 # config.log.  We remove comments because anyway the quotes in there
 # would cause problems or look ugly.
-# WARNING: Use '\'' to represent an apostrophe within the trap.
-# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
 trap 'exit_status=$?
   # Save into config.log some information that might help in debugging.
   {
@@ -1693,34 +1299,20 @@ trap 'exit_status=$?
 _ASBOX
     echo
     # The following way of writing the cache mishandles newlines in values,
-(
-  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
-    eval ac_val=\$$ac_var
-    case $ac_val in #(
-    *${as_nl}*)
-      case $ac_var in #(
-      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
-echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
-      esac
-      case $ac_var in #(
-      _ | IFS | as_nl) ;; #(
-      *) $as_unset $ac_var ;;
-      esac ;;
-    esac
-  done
+{
   (set) 2>&1 |
-    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
-    *${as_nl}ac_space=\ *)
+    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
       sed -n \
-       "s/'\''/'\''\\\\'\'''\''/g;
-         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
-      ;; #(
+       "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+      ;;
     *)
-      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      sed -n \
+       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
       ;;
-    esac |
-    sort
-)
+    esac;
+}
     echo
 
     cat <<\_ASBOX
@@ -1731,28 +1323,22 @@ _ASBOX
     echo
     for ac_var in $ac_subst_vars
     do
-      eval ac_val=\$$ac_var
-      case $ac_val in
-      *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
-      esac
-      echo "$ac_var='\''$ac_val'\''"
+      eval ac_val=$`echo $ac_var`
+      echo "$ac_var='"'"'$ac_val'"'"'"
     done | sort
     echo
 
     if test -n "$ac_subst_files"; then
       cat <<\_ASBOX
-## ------------------- ##
-## File substitutions. ##
-## ------------------- ##
+## ------------- ##
+## Output files. ##
+## ------------- ##
 _ASBOX
       echo
       for ac_var in $ac_subst_files
       do
-       eval ac_val=\$$ac_var
-       case $ac_val in
-       *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
-       esac
-       echo "$ac_var='\''$ac_val'\''"
+       eval ac_val=$`echo $ac_var`
+       echo "$ac_var='"'"'$ac_val'"'"'"
       done | sort
       echo
     fi
@@ -1764,24 +1350,26 @@ _ASBOX
 ## ----------- ##
 _ASBOX
       echo
-      cat confdefs.h
+      sed "/^$/d" confdefs.h | sort
       echo
     fi
     test "$ac_signal" != 0 &&
       echo "$as_me: caught signal $ac_signal"
     echo "$as_me: exit $exit_status"
   } >&5
-  rm -f core *.core core.conftest.* &&
-    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+  rm -f core *.core &&
+  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
     exit $exit_status
-' 0
+     ' 0
 for ac_signal in 1 2 13 15; do
   trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
 done
 ac_signal=0
 
 # confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -f -r conftest* confdefs.h
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
 
 # Predefined preprocessor variables.
 
@@ -1812,17 +1400,14 @@ _ACEOF
 
 # Let the site file select an alternate cache file if it wants to.
 # Prefer explicitly selected file to automatically selected ones.
-if test -n "$CONFIG_SITE"; then
-  set x "$CONFIG_SITE"
-elif test "x$prefix" != xNONE; then
-  set x "$prefix/share/config.site" "$prefix/etc/config.site"
-else
-  set x "$ac_default_prefix/share/config.site" \
-       "$ac_default_prefix/etc/config.site"
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
 fi
-shift
-for ac_site_file
-do
+for ac_site_file in $CONFIG_SITE; do
   if test -r "$ac_site_file"; then
     { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
 echo "$as_me: loading site script $ac_site_file" >&6;}
@@ -1838,8 +1423,8 @@ if test -r "$cache_file"; then
     { echo "$as_me:$LINENO: loading cache $cache_file" >&5
 echo "$as_me: loading cache $cache_file" >&6;}
     case $cache_file in
-      [\\/]* | ?:[\\/]* ) . "$cache_file";;
-      *)                      . "./$cache_file";;
+      [\\/]* | ?:[\\/]* ) . $cache_file;;
+      *)                      . ./$cache_file;;
     esac
   fi
 else
@@ -1851,11 +1436,12 @@ fi
 # Check that the precious variables saved in the cache have kept the same
 # value.
 ac_cache_corrupted=false
-for ac_var in $ac_precious_vars; do
+for ac_var in `(set) 2>&1 |
+              sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
   eval ac_old_set=\$ac_cv_env_${ac_var}_set
   eval ac_new_set=\$ac_env_${ac_var}_set
-  eval ac_old_val=\$ac_cv_env_${ac_var}_value
-  eval ac_new_val=\$ac_env_${ac_var}_value
+  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+  eval ac_new_val="\$ac_env_${ac_var}_value"
   case $ac_old_set,$ac_new_set in
     set,)
       { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
@@ -1880,7 +1466,8 @@ echo "$as_me:   current value: $ac_new_val" >&2;}
   # Pass precious variables to config.status.
   if test "$ac_new_set" = set; then
     case $ac_new_val in
-    *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
     *) ac_arg=$ac_var=$ac_new_val ;;
     esac
     case " $ac_configure_args " in
@@ -1897,6 +1484,11 @@ echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start ov
    { (exit 1); exit 1; }; }
 fi
 
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
@@ -1913,20 +1505,16 @@ fi
 
 
 
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
-ac_config_headers="$ac_config_headers src/include/autoconf.h"
 
+          ac_config_headers="$ac_config_headers src/include/autoconf.h"
 
 
-RADIUSD_MAJOR_VERSION=1
-RADIUSD_MINOR_VERSION=1.5
+RADIUSD_MAJOR_VERSION=2
+RADIUSD_MINOR_VERSION=0.0-pre0
 RADIUSD_VERSION="${RADIUSD_MAJOR_VERSION}.${RADIUSD_MINOR_VERSION}"
+PACKAGE=freeradius
 
 
 ac_ext=c
@@ -1937,8 +1525,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
 set dummy ${ac_tool_prefix}gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -1951,34 +1539,32 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
 fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 fi
 if test -z "$ac_cv_prog_CC"; then
   ac_ct_CC=$CC
   # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -1991,51 +1577,36 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="gcc"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
 fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-  if test "x$ac_ct_CC" = x; then
-    CC=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
-    CC=$ac_ct_CC
-  fi
+  CC=$ac_ct_CC
 else
   CC="$ac_cv_prog_CC"
 fi
 
 if test -z "$CC"; then
-          if test -n "$ac_tool_prefix"; then
-    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
 set dummy ${ac_tool_prefix}cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -2048,34 +1619,74 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
 fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
   fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
 fi
 if test -z "$CC"; then
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -2089,7 +1700,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
        continue
@@ -2100,7 +1711,6 @@ do
   fi
 done
 done
-IFS=$as_save_IFS
 
 if test $ac_prog_rejected = yes; then
   # We found a bogon in the path, so make sure we never use it.
@@ -2118,23 +1728,22 @@ fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 fi
 if test -z "$CC"; then
   if test -n "$ac_tool_prefix"; then
-  for ac_prog in cl.exe
+  for ac_prog in cl
   do
     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -2147,38 +1756,36 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
 fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6; }
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
     test -n "$CC" && break
   done
 fi
 if test -z "$CC"; then
   ac_ct_CC=$CC
-  for ac_prog in cl.exe
+  for ac_prog in cl
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -2191,45 +1798,29 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
 fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6; }
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
   test -n "$ac_ct_CC" && break
 done
 
-  if test "x$ac_ct_CC" = x; then
-    CC=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
-    CC=$ac_ct_CC
-  fi
+  CC=$ac_ct_CC
 fi
 
 fi
@@ -2242,35 +1833,21 @@ See \`config.log' for more details." >&2;}
    { (exit 1); exit 1; }; }
 
 # Provide some information about the compiler.
-echo "$as_me:$LINENO: checking for C compiler version" >&5
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
 ac_compiler=`set X $ac_compile; echo $2`
-{ (ac_try="$ac_compiler --version >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler --version >&5") 2>&5
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }
-{ (ac_try="$ac_compiler -v >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -v >&5") 2>&5
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }
-{ (ac_try="$ac_compiler -V >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -V >&5") 2>&5
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }
@@ -2295,70 +1872,46 @@ ac_clean_files="$ac_clean_files a.out a.exe b.out"
 # Try to create an executable without -o first, disregard a.out.
 # It will help us diagnose broken compilers, and finding out an intuition
 # of exeext.
-echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
-echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-#
-# List of possible output files, starting from the most likely.
-# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
-# only as a last resort.  b.out is created by i960 compilers.
-ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
-#
-# The IRIX 6 linker writes into existing files which may not be
-# executable, retaining their permissions.  Remove them first so a
-# subsequent execution test works.
-ac_rmfiles=
-for ac_file in $ac_files
-do
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
-    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
-  esac
-done
-rm -f $ac_rmfiles
-
-if { (ac_try="$ac_link_default"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link_default") 2>&5
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; then
-  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
-# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
-# in a Makefile.  We should not override ac_cv_exeext if it was cached,
-# so that the user can short-circuit this test for compilers unknown to
-# Autoconf.
-for ac_file in $ac_files
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
 do
   test -f "$ac_file" || continue
   case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+       ;;
+    conftest.$ac_ext )
+       # This is the source file.
        ;;
     [ab].out )
        # We found the default executable, but exeext='' is most
        # certainly right.
        break;;
     *.* )
-        if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
-       then :; else
-          ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-       fi
-       # We set ac_cv_exeext here because the later test for it is not
-       # safe: cross compilers may not add the suffix if given an `-o'
-       # argument, so we may need to know it at that point already.
-       # Even if this section looks crufty: it has the advantage of
-       # actually working.
+       ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       # FIXME: I believe we export ac_cv_exeext for Libtool,
+       # but it would be cool to find out if it's true.  Does anybody
+       # maintain Libtool? --akim.
+       export ac_cv_exeext
        break;;
     * )
        break;;
   esac
 done
-test "$ac_cv_exeext" = no && ac_cv_exeext=
-
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
@@ -2371,23 +1924,19 @@ See \`config.log' for more details." >&2;}
 fi
 
 ac_exeext=$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6; }
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
 
-# Check that the compiler produces executables we can run.  If not, either
+# Check the compiler produces executables we can run.  If not, either
 # the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether the C compiler works" >&5
-echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0
 # If not cross compiling, check that we can run a simple program.
 if test "$cross_compiling" != yes; then
   if { ac_try='./$ac_file'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -2406,27 +1955,22 @@ See \`config.log' for more details." >&2;}
     fi
   fi
 fi
-echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
 
 rm -f a.out a.exe conftest$ac_cv_exeext b.out
 ac_clean_files=$ac_clean_files_save
-# Check that the compiler produces executables we can run.  If not, either
+# Check the compiler produces executables we can run.  If not, either
 # the compiler is broken, or we cross compile.
-{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
-echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
-{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
-echo "${ECHO_T}$cross_compiling" >&6; }
-
-{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
-echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; then
@@ -2437,8 +1981,9 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
 for ac_file in conftest.exe conftest conftest.*; do
   test -f "$ac_file" || continue
   case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
     *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         export ac_cv_exeext
          break;;
     * ) break;;
   esac
@@ -2452,14 +1997,14 @@ See \`config.log' for more details." >&2;}
 fi
 
 rm -f conftest$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
-echo "${ECHO_T}$ac_cv_exeext" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
 
 rm -f conftest.$ac_ext
 EXEEXT=$ac_cv_exeext
 ac_exeext=$EXEEXT
-echo "$as_me:$LINENO: checking for suffix of object files" >&5
-echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
 if test "${ac_cv_objext+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -2479,20 +2024,14 @@ main ()
 }
 _ACEOF
 rm -f conftest.o conftest.obj
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>&5
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; then
-  for ac_file in conftest.o conftest.obj conftest.*; do
-  test -f "$ac_file" || continue;
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
   case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
     *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
        break;;
   esac
@@ -2510,12 +2049,12 @@ fi
 
 rm -f conftest.$ac_cv_objext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
-echo "${ECHO_T}$ac_cv_objext" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
 OBJEXT=$ac_cv_objext
 ac_objext=$OBJEXT
-echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
 if test "${ac_cv_c_compiler_gnu+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -2538,36 +2077,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -2576,139 +2103,24 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_compiler_gnu=no
+ac_compiler_gnu=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 ac_cv_c_compiler_gnu=$ac_compiler_gnu
 
 fi
-echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
 GCC=`test $ac_compiler_gnu = yes && echo yes`
 ac_test_CFLAGS=${CFLAGS+set}
 ac_save_CFLAGS=$CFLAGS
-{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
 if test "${ac_cv_prog_cc_g+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_save_c_werror_flag=$ac_c_werror_flag
-   ac_c_werror_flag=yes
-   ac_cv_prog_cc_g=no
-   CFLAGS="-g"
-   cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_prog_cc_g=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-       CFLAGS=""
-      cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-       ac_c_werror_flag=$ac_save_c_werror_flag
-        CFLAGS="-g"
-        cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
@@ -2724,36 +2136,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -2762,20 +2162,12 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_prog_cc_g=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-   ac_c_werror_flag=$ac_save_c_werror_flag
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
 if test "$ac_test_CFLAGS" = set; then
   CFLAGS=$ac_save_CFLAGS
 elif test $ac_cv_prog_cc_g = yes; then
@@ -2791,12 +2183,12 @@ else
     CFLAGS=
   fi
 fi
-{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
-echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cc_c89+set}" = set; then
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_cv_prog_cc_c89=no
+  ac_cv_prog_cc_stdc=no
 ac_save_CC=$CC
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
@@ -2830,17 +2222,12 @@ static char *f (char * (*g) (char **, int), char **p, ...)
 /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
    function prototypes and stuff, but not '\xHH' hex character constants.
    These don't provoke an error unfortunately, instead are silently treated
-   as 'x'.  The following induces an error, until -std is added to get
+   as 'x'.  The following induces an error, until -std1 is added to get
    proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
    array size at least.  It's necessary to write '\x00'==0 to get something
-   that's true only with -std.  */
+   that's true only with -std1.  */
 int osf4_cc_array ['\x00' == 0 ? 1 : -1];
 
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
-   inside strings and character constants.  */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
-
 int test (int i, double x);
 struct s1 {int (*f) (int a);};
 struct s2 {int (*f) (double a);};
@@ -2855,712 +2242,389 @@ return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
   return 0;
 }
 _ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
-       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX                  -qlanglvl=ansi
+# Ultrix and OSF/1     -std1
+# HP-UX 10.20 and later        -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4                 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
 do
   CC="$ac_save_CC $ac_arg"
   rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_prog_cc_c89=$ac_arg
+  ac_cv_prog_cc_stdc=$ac_arg
+break
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext
-  test "x$ac_cv_prog_cc_c89" != "xno" && break
+rm -f conftest.err conftest.$ac_objext
 done
-rm -f conftest.$ac_ext
+rm -f conftest.$ac_ext conftest.$ac_objext
 CC=$ac_save_CC
 
 fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
-  x)
-    { echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6; } ;;
-  xno)
-    { echo "$as_me:$LINENO: result: unsupported" >&5
-echo "${ECHO_T}unsupported" >&6; } ;;
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
   *)
-    CC="$CC $ac_cv_prog_cc_c89"
-    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
 esac
 
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
-echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
-  CPP=
-fi
-if test -z "$CPP"; then
-  if test "${ac_cv_prog_CPP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-      # Double quotes because CPP needs to be expanded
-    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
-    do
-      ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
 #endif
-                    Syntax error
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Broken: fails on valid input.
-continue
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether nonexistent headers
-  # can be detected and how.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  # Broken: success on invalid input.
-continue
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
-  break
-fi
-
-    done
-    ac_cv_prog_CPP=$CPP
-
-fi
-  CPP=$ac_cv_prog_CPP
-else
-  ac_cv_prog_CPP=$CPP
-fi
-{ echo "$as_me:$LINENO: result: $CPP" >&5
-echo "${ECHO_T}$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
 do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-                    Syntax error
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
   :
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-  # Broken: fails on valid input.
 continue
 fi
-
-rm -f conftest.err conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether nonexistent headers
-  # can be detected and how.
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <ac_nonexistent.h>
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  # Broken: success on invalid input.
-continue
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-  # Passes both tests.
-ac_preproc_ok=:
-break
 fi
-
-rm -f conftest.err conftest.$ac_ext
-
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
-  :
-else
-  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&5
-echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
 fi
 
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
-
-{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
-echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
-if test "${ac_cv_path_GREP+set}" = set; then
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CXX+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  # Extract the first word of "grep ggrep" to use in msg output
-if test -z "$GREP"; then
-set dummy grep ggrep; ac_prog_name=$2
-if test "${ac_cv_path_GREP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
 else
-  ac_path_GREP_found=false
-# Loop through the user's path and test for each of PROGNAME-LIST
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_prog in grep ggrep; do
   for ac_exec_ext in '' $ac_executable_extensions; do
-    ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
-    { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue
-    # Check for GNU ac_path_GREP and select it if it is found.
-  # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
-  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
-  ac_count=0
-  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
-  while :
-  do
-    cat "conftest.in" "conftest.in" >"conftest.tmp"
-    mv "conftest.tmp" "conftest.in"
-    cp "conftest.in" "conftest.nl"
-    echo 'GREP' >> "conftest.nl"
-    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
-    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
-    ac_count=`expr $ac_count + 1`
-    if test $ac_count -gt ${ac_path_GREP_max-0}; then
-      # Best one so far, save it but keep looking for a better one
-      ac_cv_path_GREP="$ac_path_GREP"
-      ac_path_GREP_max=$ac_count
-    fi
-    # 10*(2^10) chars as input seems more than enough
-    test $ac_count -gt 10 && break
-  done
-  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
-
-    $ac_path_GREP_found && break 3
-  done
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
 done
-
 done
-IFS=$as_save_IFS
-
 
 fi
-
-GREP="$ac_cv_path_GREP"
-if test -z "$GREP"; then
-  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
-   { (exit 1); exit 1; }; }
 fi
-
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6
 else
-  ac_cv_path_GREP=$GREP
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
+    test -n "$CXX" && break
+  done
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
-echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ echo "$as_me:$LINENO: checking for egrep" >&5
-echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
-if test "${ac_cv_path_EGREP+set}" = set; then
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
-   then ac_cv_path_EGREP="$GREP -E"
-   else
-     # Extract the first word of "egrep" to use in msg output
-if test -z "$EGREP"; then
-set dummy egrep; ac_prog_name=$2
-if test "${ac_cv_path_EGREP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
 else
-  ac_path_EGREP_found=false
-# Loop through the user's path and test for each of PROGNAME-LIST
 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+for as_dir in $PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for ac_prog in egrep; do
   for ac_exec_ext in '' $ac_executable_extensions; do
-    ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
-    { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue
-    # Check for GNU ac_path_EGREP and select it if it is found.
-  # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
-  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
-  ac_count=0
-  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
-  while :
-  do
-    cat "conftest.in" "conftest.in" >"conftest.tmp"
-    mv "conftest.tmp" "conftest.in"
-    cp "conftest.in" "conftest.nl"
-    echo 'EGREP' >> "conftest.nl"
-    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
-    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
-    ac_count=`expr $ac_count + 1`
-    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
-      # Best one so far, save it but keep looking for a better one
-      ac_cv_path_EGREP="$ac_path_EGREP"
-      ac_path_EGREP_max=$ac_count
-    fi
-    # 10*(2^10) chars as input seems more than enough
-    test $ac_count -gt 10 && break
-  done
-  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
-
-    $ac_path_EGREP_found && break 3
-  done
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
 done
-
 done
-IFS=$as_save_IFS
-
 
 fi
-
-EGREP="$ac_cv_path_EGREP"
-if test -z "$EGREP"; then
-  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
-echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
-   { (exit 1); exit 1; }; }
 fi
-
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6
 else
-  ac_cv_path_EGREP=$EGREP
-fi
-
-
-   fi
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
-echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-
-{ echo "$as_me:$LINENO: checking for AIX" >&5
-echo $ECHO_N "checking for AIX... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#ifdef _AIX
-  yes
-#endif
 
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "yes" >/dev/null 2>&1; then
-  { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-cat >>confdefs.h <<\_ACEOF
-#define _ALL_SOURCE 1
-_ACEOF
+  test -n "$ac_ct_CXX" && break
+done
+test -n "$ac_ct_CXX" || ac_ct_CXX="g++"
 
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  CXX=$ac_ct_CXX
 fi
-rm -f conftest*
 
 
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
 
-if test $ac_cv_c_compiler_gnu = yes; then
-    { echo "$as_me:$LINENO: checking whether $CC needs -traditional" >&5
-echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6; }
-if test "${ac_cv_prog_gcc_traditional+set}" = set; then
+echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-    ac_pattern="Autoconf.*'x'"
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <sgtty.h>
-Autoconf TIOCGETP
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "$ac_pattern" >/dev/null 2>&1; then
-  ac_cv_prog_gcc_traditional=yes
-else
-  ac_cv_prog_gcc_traditional=no
-fi
-rm -f conftest*
 
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
 
-  if test $ac_cv_prog_gcc_traditional = no; then
-    cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <termio.h>
-Autoconf TCGETA
+  ;
+  return 0;
+}
 _ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "$ac_pattern" >/dev/null 2>&1; then
-  ac_cv_prog_gcc_traditional=yes
-fi
-rm -f conftest*
-
-  fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_prog_gcc_traditional" >&5
-echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6; }
-  if test $ac_cv_prog_gcc_traditional = yes; then
-    CC="$CC -traditional"
-  fi
-fi
-
-{ echo "$as_me:$LINENO: checking whether we are using SUNPro C" >&5
-echo $ECHO_N "checking whether we are using SUNPro C... $ECHO_C" >&6; }
-if test "${ac_cv_prog_suncc+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat > conftest.c <<EOF
-#ifdef __SUNPRO_C
-  yes;
-#endif
-EOF
-if { ac_try='${CC-cc} -E conftest.c'
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } | egrep yes >/dev/null 2>&1; then
-  ac_cv_prog_suncc=yes
-else
-  ac_cv_prog_suncc=no
-fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_prog_suncc" >&5
-echo "${ECHO_T}$ac_cv_prog_suncc" >&6; }
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
-set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_RANLIB+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$RANLIB"; then
-  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-RANLIB=$ac_cv_prog_RANLIB
-if test -n "$RANLIB"; then
-  { echo "$as_me:$LINENO: result: $RANLIB" >&5
-echo "${ECHO_T}$RANLIB" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_RANLIB"; then
-  ac_ct_RANLIB=$RANLIB
-  # Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_RANLIB"; then
-  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
 else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_ac_ct_RANLIB="ranlib"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-IFS=$as_save_IFS
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
+ac_compiler_gnu=no
 fi
-fi
-ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
-if test -n "$ac_ct_RANLIB"; then
-  { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
-echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
 
-  if test "x$ac_ct_RANLIB" = x; then
-    RANLIB=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
-    RANLIB=$ac_ct_RANLIB
-  fi
-else
-  RANLIB="$ac_cv_prog_RANLIB"
 fi
-
-
-abs_top_builddir=`pwd`
-
-
-
-PACKAGE=freeradius
-
-{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
-echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then
+echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_g+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
@@ -3569,10 +2633,6 @@ _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
 
 int
 main ()
@@ -3583,387 +2643,1070 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_header_stdc=yes
+  ac_cv_prog_cxx_g=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_header_stdc=no
+ac_cv_prog_cxx_g=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
-  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "memchr" >/dev/null 2>&1; then
-  :
-else
-  ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-
-if test $ac_cv_header_stdc = yes; then
-  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "free" >/dev/null 2>&1; then
-  :
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
 else
-  ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
 fi
-
-if test $ac_cv_header_stdc = yes; then
-  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
-  if test "$cross_compiling" = yes; then
-  :
-else
+for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <ctype.h>
+$ac_declaration
 #include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
-                  (('a' <= (c) && (c) <= 'i') \
-                    || ('j' <= (c) && (c) <= 'r') \
-                    || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
 int
 main ()
 {
-  int i;
-  for (i = 0; i < 256; i++)
-    if (XOR (islower (i), ISLOWER (i))
-       || toupper (i) != TOUPPER (i))
-      return 2;
+exit (42);
+  ;
   return 0;
 }
 _ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
   :
 else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
+  echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-( exit $ac_status )
-ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-
-
-fi
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
-echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define STDC_HEADERS 1
-_ACEOF
-
+continue
 fi
-
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-
-
-
-
-
-
-
-
-
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
-                 inttypes.h stdint.h unistd.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
-
-#include <$ac_header>
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  eval "$as_ac_Header=yes"
+  break
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       eval "$as_ac_Header=no"
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
 fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-              { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
 
-fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
-done
 
 
-{ echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
-echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6; }
-if test "${ac_cv_c_bigendian+set}" = set; then
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  # See if sys/param.h defines the BYTE_ORDER macro.
-cat >conftest.$ac_ext <<_ACEOF
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <sys/types.h>
-#include <sys/param.h>
-
-int
-main ()
-{
-#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
- bogus endian macros
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
 #endif
-
-  ;
-  return 0;
-}
+                    Syntax error
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  # It does; now see whether it defined to BIG_ENDIAN or not.
-cat >conftest.$ac_ext <<_ACEOF
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <sys/types.h>
-#include <sys/param.h>
-
-int
-main ()
-{
-#if BYTE_ORDER != BIG_ENDIAN
- not big endian
-#endif
-
-  ;
-  return 0;
-}
+#include <ac_nonexistent.h>
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+
+echo "$as_me:$LINENO: checking for AIX" >&5
+echo $ECHO_N "checking for AIX... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef _AIX
+  yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+cat >>confdefs.h <<\_ACEOF
+#define _ALL_SOURCE 1
+_ACEOF
+
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest*
+
+
+
+if test $ac_cv_c_compiler_gnu = yes; then
+    echo "$as_me:$LINENO: checking whether $CC needs -traditional" >&5
+echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6
+if test "${ac_cv_prog_gcc_traditional+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+    ac_pattern="Autoconf.*'x'"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sgtty.h>
+Autoconf TIOCGETP
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then
+  ac_cv_prog_gcc_traditional=yes
+else
+  ac_cv_prog_gcc_traditional=no
+fi
+rm -f conftest*
+
+
+  if test $ac_cv_prog_gcc_traditional = no; then
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <termio.h>
+Autoconf TCGETA
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "$ac_pattern" >/dev/null 2>&1; then
+  ac_cv_prog_gcc_traditional=yes
+fi
+rm -f conftest*
+
+  fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_gcc_traditional" >&5
+echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6
+  if test $ac_cv_prog_gcc_traditional = yes; then
+    CC="$CC -traditional"
+  fi
+fi
+
+echo "$as_me:$LINENO: checking whether we are using SUNPro C" >&5
+echo $ECHO_N "checking whether we are using SUNPro C... $ECHO_C" >&6
+if test "${ac_cv_prog_suncc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat > conftest.c <<EOF
+#ifdef __SUNPRO_C
+  yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_suncc=yes
+else
+  ac_cv_prog_suncc=no
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_suncc" >&5
+echo "${ECHO_T}$ac_cv_prog_suncc" >&6
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+  ac_ct_RANLIB=$RANLIB
+  # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_RANLIB"; then
+  ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_RANLIB="ranlib"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  RANLIB=$ac_ct_RANLIB
+else
+  RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
+# Check whether --enable-largefile or --disable-largefile was given.
+if test "${enable_largefile+set}" = set; then
+  enableval="$enable_largefile"
+
+fi;
+if test "$enable_largefile" != no; then
+
+  echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
+echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6
+if test "${ac_cv_sys_largefile_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_sys_largefile_CC=no
+     if test "$GCC" != yes; then
+       ac_save_CC=$CC
+       while :; do
+        # IRIX 6.2 and later do not support large files by default,
+        # so use the C compiler's -n32 option if that helps.
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+        rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+        CC="$CC -n32"
+        rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sys_largefile_CC=' -n32'; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+        break
+       done
+       CC=$ac_save_CC
+       rm -f conftest.$ac_ext
+    fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6
+  if test "$ac_cv_sys_largefile_CC" != no; then
+    CC=$CC$ac_cv_sys_largefile_CC
+  fi
+
+  echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6
+if test "${ac_cv_sys_file_offset_bits+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  ac_cv_sys_file_offset_bits=no
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_c_bigendian=yes
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sys_file_offset_bits=64; break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  break
+done
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
+echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6
+if test "$ac_cv_sys_file_offset_bits" != no; then
+
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+
+fi
+rm -f conftest*
+  echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
+echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6
+if test "${ac_cv_sys_large_files+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  while :; do
+  ac_cv_sys_large_files=no
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+    We can't simply define LARGE_OFF_T to be 9223372036854775807,
+    since some C++ compilers masquerading as C compilers
+    incorrectly reject 9223372036854775807.  */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+  int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+                      && LARGE_OFF_T % 2147483647 == 1)
+                     ? 1 : -1];
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_sys_large_files=1; break
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_c_bigendian=no
 fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  break
+done
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
+echo "${ECHO_T}$ac_cv_sys_large_files" >&6
+if test "$ac_cv_sys_large_files" != no; then
+
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+
+fi
+rm -f conftest*
+fi
+
+
+echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5
+echo $ECHO_N "checking whether byte ordering is bigendian... $ECHO_C" >&6
+if test "${ac_cv_c_bigendian+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  # See if sys/param.h defines the BYTE_ORDER macro.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_c_bigendian=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_bigendian=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       # It does not; compile a test program.
+# It does not; compile a test program.
 if test "$cross_compiling" = yes; then
   # try to guess the endianness by grepping values into an object file
   ac_cv_c_bigendian=unknown
@@ -3973,11 +3716,11 @@ _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
-short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+short ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+short ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
 void _ascii () { char *s = (char *) ascii_mm; s = (char *) ascii_ii; }
-short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
-short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+short ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+short ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
 void _ebcdic () { char *s = (char *) ebcdic_mm; s = (char *) ebcdic_ii; }
 int
 main ()
@@ -3988,36 +3731,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -4036,10 +3767,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 else
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
@@ -4047,41 +3776,27 @@ _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
 int
 main ()
 {
-
   /* Are we little or big endian?  From Harbison&Steele.  */
   union
   {
-    long int l;
-    char c[sizeof (long int)];
+    long l;
+    char c[sizeof (long)];
   } u;
   u.l = 1;
-  return u.c[sizeof (long int) - 1] == 1;
-
-  ;
-  return 0;
+  exit (u.c[sizeof (long) - 1] == 1);
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -4094,16 +3809,13 @@ sed 's/^/| /' conftest.$ac_ext >&5
 ( exit $ac_status )
 ac_cv_c_bigendian=yes
 fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
-
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
-echo "${ECHO_T}$ac_cv_c_bigendian" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_c_bigendian" >&5
+echo "${ECHO_T}$ac_cv_c_bigendian" >&6
 case $ac_cv_c_bigendian in
   yes)
 
@@ -4124,8 +3836,8 @@ esac
 
 # Extract the first word of "gmake", so it can be a program name with args.
 set dummy gmake; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_GMAKE+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -4138,33 +3850,31 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_GMAKE="yes"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
   test -z "$ac_cv_prog_GMAKE" && ac_cv_prog_GMAKE="no"
 fi
 fi
 GMAKE=$ac_cv_prog_GMAKE
 if test -n "$GMAKE"; then
-  echo "$as_me:$LINENO: result: $GMAKE" >&5
-echo "${ECHO_T}$GMAKE" >&6; }
+  echo "$as_me:$LINENO: result: $GMAKE" >&5
+echo "${ECHO_T}$GMAKE" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 if test $GMAKE = no; then
   # Extract the first word of "make", so it can be a program name with args.
 set dummy make; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_path_MAKE+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -4179,34 +3889,33 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_MAKE="$as_dir/$ac_word$ac_exec_ext"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
   test -z "$ac_cv_path_MAKE" && ac_cv_path_MAKE="/usr/local/bin/make"
   ;;
 esac
 fi
 MAKE=$ac_cv_path_MAKE
+
 if test -n "$MAKE"; then
-  echo "$as_me:$LINENO: result: $MAKE" >&5
-echo "${ECHO_T}$MAKE" >&6; }
+  echo "$as_me:$LINENO: result: $MAKE" >&5
+echo "${ECHO_T}$MAKE" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 else
   # Extract the first word of "gmake", so it can be a program name with args.
 set dummy gmake; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_path_MAKE+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -4221,29 +3930,28 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_MAKE="$as_dir/$ac_word$ac_exec_ext"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
   test -z "$ac_cv_path_MAKE" && ac_cv_path_MAKE="/usr/local/gnu/bin/make"
   ;;
 esac
 fi
 MAKE=$ac_cv_path_MAKE
+
 if test -n "$MAKE"; then
-  echo "$as_me:$LINENO: result: $MAKE" >&5
-echo "${ECHO_T}$MAKE" >&6; }
+  echo "$as_me:$LINENO: result: $MAKE" >&5
+echo "${ECHO_T}$MAKE" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 fi
 makever=`$ac_cv_path_MAKE --version 2>&1 | grep "GNU Make"`
 if test -z "$makever"; then
@@ -4254,8 +3962,8 @@ echo "$as_me: error: GNU Make is not installed.  Please download and install it
    { (exit 1); exit 1; }; }
 fi
 
-  echo "$as_me:$LINENO: checking for lt_dlinit in -lltdl" >&5
-echo $ECHO_N "checking for lt_dlinit in -lltdl... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for lt_dlinit in -lltdl" >&5
+echo $ECHO_N "checking for lt_dlinit in -lltdl... $ECHO_C" >&6
 if test "${ac_cv_lib_ltdl_lt_dlinit+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -4268,52 +3976,40 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
 char lt_dlinit ();
 int
 main ()
 {
-return lt_dlinit ();
+lt_dlinit ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -4322,15 +4018,14 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_ltdl_lt_dlinit=no
+ac_cv_lib_ltdl_lt_dlinit=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_ltdl_lt_dlinit" >&5
-echo "${ECHO_T}$ac_cv_lib_ltdl_lt_dlinit" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_lib_ltdl_lt_dlinit" >&5
+echo "${ECHO_T}$ac_cv_lib_ltdl_lt_dlinit" >&6
 if test $ac_cv_lib_ltdl_lt_dlinit = yes; then
   test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no
 else
@@ -4361,9 +4056,10 @@ if test x"$enable_ltdl_install" = x"yes"; then
 fi
 
 
-# Check whether --enable-shared was given.
+# Check whether --enable-shared or --disable-shared was given.
 if test "${enable_shared+set}" = set; then
-  enableval=$enable_shared; p=${PACKAGE-default}
+  enableval="$enable_shared"
+  p=${PACKAGE-default}
     case $enableval in
     yes) enable_shared=yes ;;
     no) enable_shared=no ;;
@@ -4382,12 +4078,12 @@ if test "${enable_shared+set}" = set; then
     esac
 else
   enable_shared=yes
-fi
-
+fi;
 
-# Check whether --enable-static was given.
+# Check whether --enable-static or --disable-static was given.
 if test "${enable_static+set}" = set; then
-  enableval=$enable_static; p=${PACKAGE-default}
+  enableval="$enable_static"
+  p=${PACKAGE-default}
     case $enableval in
     yes) enable_static=yes ;;
     no) enable_static=no ;;
@@ -4406,12 +4102,12 @@ if test "${enable_static+set}" = set; then
     esac
 else
   enable_static=yes
-fi
-
+fi;
 
-# Check whether --enable-fast-install was given.
+# Check whether --enable-fast-install or --disable-fast-install was given.
 if test "${enable_fast_install+set}" = set; then
-  enableval=$enable_fast_install; p=${PACKAGE-default}
+  enableval="$enable_fast_install"
+  p=${PACKAGE-default}
     case $enableval in
     yes) enable_fast_install=yes ;;
     no) enable_fast_install=no ;;
@@ -4430,125 +4126,89 @@ if test "${enable_fast_install+set}" = set; then
     esac
 else
   enable_fast_install=yes
-fi
-
+fi;
 
 ac_aux_dir=
-for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
-  if test -f "$ac_dir/install-sh"; then
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+  if test -f $ac_dir/install-sh; then
     ac_aux_dir=$ac_dir
     ac_install_sh="$ac_aux_dir/install-sh -c"
     break
-  elif test -f "$ac_dir/install.sh"; then
+  elif test -f $ac_dir/install.sh; then
     ac_aux_dir=$ac_dir
     ac_install_sh="$ac_aux_dir/install.sh -c"
     break
-  elif test -f "$ac_dir/shtool"; then
+  elif test -f $ac_dir/shtool; then
     ac_aux_dir=$ac_dir
     ac_install_sh="$ac_aux_dir/shtool install -c"
     break
   fi
 done
 if test -z "$ac_aux_dir"; then
-  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
-echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+  { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
    { (exit 1); exit 1; }; }
 fi
-
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
-
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
 
 # Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
-  { { echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
-echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+$ac_config_sub sun4 >/dev/null 2>&1 ||
+  { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5
+echo "$as_me: error: cannot run $ac_config_sub" >&2;}
    { (exit 1); exit 1; }; }
 
-echo "$as_me:$LINENO: checking build system type" >&5
-echo $ECHO_N "checking build system type... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking build system type" >&5
+echo $ECHO_N "checking build system type... $ECHO_C" >&6
 if test "${ac_cv_build+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_build_alias=$build_alias
-test "x$ac_build_alias" = x &&
-  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
-test "x$ac_build_alias" = x &&
+  ac_cv_build_alias=$build_alias
+test -z "$ac_cv_build_alias" &&
+  ac_cv_build_alias=`$ac_config_guess`
+test -z "$ac_cv_build_alias" &&
   { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
 echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
    { (exit 1); exit 1; }; }
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
-  { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
-echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+ac_cv_build=`$ac_config_sub $ac_cv_build_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;}
    { (exit 1); exit 1; }; }
 
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_build" >&5
-echo "${ECHO_T}$ac_cv_build" >&6; }
-case $ac_cv_build in
-*-*-*) ;;
-*) { { echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
-echo "$as_me: error: invalid value of canonical build" >&2;}
-   { (exit 1); exit 1; }; };;
-esac
+echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+echo "${ECHO_T}$ac_cv_build" >&6
 build=$ac_cv_build
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_build
-shift
-build_cpu=$1
-build_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-build_os=$*
-IFS=$ac_save_IFS
-case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-
-
-{ echo "$as_me:$LINENO: checking host system type" >&5
-echo $ECHO_N "checking host system type... $ECHO_C" >&6; }
+build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking host system type" >&5
+echo $ECHO_N "checking host system type... $ECHO_C" >&6
 if test "${ac_cv_host+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  if test "x$host_alias" = x; then
-  ac_cv_host=$ac_cv_build
-else
-  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
-    { { echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
-echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+  ac_cv_host_alias=$host_alias
+test -z "$ac_cv_host_alias" &&
+  ac_cv_host_alias=$ac_cv_build_alias
+ac_cv_host=`$ac_config_sub $ac_cv_host_alias` ||
+  { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5
+echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;}
    { (exit 1); exit 1; }; }
-fi
 
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_host" >&5
-echo "${ECHO_T}$ac_cv_host" >&6; }
-case $ac_cv_host in
-*-*-*) ;;
-*) { { echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
-echo "$as_me: error: invalid value of canonical host" >&2;}
-   { (exit 1); exit 1; }; };;
-esac
+echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+echo "${ECHO_T}$ac_cv_host" >&6
 host=$ac_cv_host
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_host
-shift
-host_cpu=$1
-host_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-host_os=$*
-IFS=$ac_save_IFS
-case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-
-
-{ echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
-echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6; }
+host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+
+echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5
+echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6
 if test "${lt_cv_path_SED+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -4601,22 +4261,22 @@ done
 fi
 
 SED=$lt_cv_path_SED
-echo "$as_me:$LINENO: result: $SED" >&5
-echo "${ECHO_T}$SED" >&6; }
+echo "$as_me:$LINENO: result: $SED" >&5
+echo "${ECHO_T}$SED" >&6
 
 
-# Check whether --with-gnu-ld was given.
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
 if test "${with_gnu_ld+set}" = set; then
-  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+  withval="$with_gnu_ld"
+  test "$withval" = no || with_gnu_ld=yes
 else
   with_gnu_ld=no
-fi
-
+fi;
 ac_prog=ld
 if test "$GCC" = yes; then
   # Check if gcc -print-prog-name=ld gives a path.
-  echo "$as_me:$LINENO: checking for ld used by $CC" >&5
-echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6
   case $host in
   *-*-mingw*)
     # gcc leaves a trailing carriage return which upsets mingw
@@ -4645,11 +4305,11 @@ echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; }
     ;;
   esac
 elif test "$with_gnu_ld" = yes; then
-  echo "$as_me:$LINENO: checking for GNU ld" >&5
-echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
 else
-  echo "$as_me:$LINENO: checking for non-GNU ld" >&5
-echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
 fi
 if test "${lt_cv_path_LD+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -4682,17 +4342,17 @@ fi
 
 LD="$lt_cv_path_LD"
 if test -n "$LD"; then
-  echo "$as_me:$LINENO: result: $LD" >&5
-echo "${ECHO_T}$LD" >&6; }
+  echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
 echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
    { (exit 1); exit 1; }; }
-echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
-echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
 if test "${lt_cv_prog_gnu_ld+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -4706,20 +4366,20 @@ case `$LD -v 2>&1 </dev/null` in
   ;;
 esac
 fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
-echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6
 with_gnu_ld=$lt_cv_prog_gnu_ld
 
 
-echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
-echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5
+echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6
 if test "${lt_cv_ld_reload_flag+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   lt_cv_ld_reload_flag='-r'
 fi
-echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
-echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5
+echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6
 reload_flag=$lt_cv_ld_reload_flag
 case $reload_flag in
 "" | " "*) ;;
@@ -4736,8 +4396,8 @@ case $host_os in
     ;;
 esac
 
-echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
-echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5
+echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6
 if test "${lt_cv_path_NM+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -4785,23 +4445,23 @@ else
   test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
 fi
 fi
-echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5
-echo "${ECHO_T}$lt_cv_path_NM" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5
+echo "${ECHO_T}$lt_cv_path_NM" >&6
 NM="$lt_cv_path_NM"
 
-echo "$as_me:$LINENO: checking whether ln -s works" >&5
-echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether ln -s works" >&5
+echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6
 LN_S=$as_ln_s
 if test "$LN_S" = "ln -s"; then
-  echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
 else
-  echo "$as_me:$LINENO: result: no, using $LN_S" >&5
-echo "${ECHO_T}no, using $LN_S" >&6; }
+  echo "$as_me:$LINENO: result: no, using $LN_S" >&5
+echo "${ECHO_T}no, using $LN_S" >&6
 fi
 
-echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5
-echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5
+echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6
 if test "${lt_cv_deplibs_check_method+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -4976,8 +4636,8 @@ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
 esac
 
 fi
-echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
-echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5
+echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6
 file_magic_cmd=$lt_cv_file_magic_cmd
 deplibs_check_method=$lt_cv_deplibs_check_method
 test -z "$deplibs_check_method" && deplibs_check_method=unknown
@@ -4994,11 +4654,11 @@ LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
 # Allow CC to be a program name with arguments.
 compiler=$CC
 
-# Check whether --enable-libtool-lock was given.
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
 if test "${enable_libtool_lock+set}" = set; then
-  enableval=$enable_libtool_lock;
-fi
+  enableval="$enable_libtool_lock"
 
+fi;
 test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
 
 # Some flags need to be propagated to the compiler or linker for good
@@ -5025,7 +4685,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 5028 "configure"' > conftest.$ac_ext
+  echo '#line 4688 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -5110,8 +4770,8 @@ x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
   # On SCO OpenServer 5, we need -belf to get full-featured binaries.
   SAVE_CFLAGS="$CFLAGS"
   CFLAGS="$CFLAGS -belf"
-  echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
-echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5
+echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6
 if test "${lt_cv_cc_needs_belf+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -5137,36 +4797,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -5175,10 +4823,9 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       lt_cv_cc_needs_belf=no
+lt_cv_cc_needs_belf=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
      ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -5187,8 +4834,8 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 fi
-echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
-echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5
+echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6
   if test x"$lt_cv_cc_needs_belf" != x"yes"; then
     # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
     CFLAGS="$SAVE_CFLAGS"
@@ -5220,323 +4867,107 @@ esac
 need_locks="$enable_libtool_lock"
 
 
-
-for ac_header in dlfcn.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-              { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
 else
-  # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
-#include <$ac_header>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_header_compiler=yes
+  ac_cv_header_stdc=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_header_compiler=no
+ac_cv_header_stdc=no
 fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <$ac_header>
-_ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  ac_header_preproc=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  ac_header_preproc=no
-fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
-  yes:no: )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
-    ac_header_preproc=yes
-    ;;
-  no:yes:* )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
-
-    ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-              { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
+#include <string.h>
 
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
 _ACEOF
-
-fi
-
-done
-
-ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-if test -z "$CXX"; then
-  if test -n "$CCC"; then
-    CXX=$CCC
-  else
-    if test -n "$ac_tool_prefix"; then
-  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
-  do
-    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_CXX+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CXX"; then
-  ac_cv_prog_CXX="$CXX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-CXX=$ac_cv_prog_CXX
-if test -n "$CXX"; then
-  { echo "$as_me:$LINENO: result: $CXX" >&5
-echo "${ECHO_T}$CXX" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-    test -n "$CXX" && break
-  done
-fi
-if test -z "$CXX"; then
-  ac_ct_CXX=$CXX
-  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CXX"; then
-  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_prog_ac_ct_CXX="$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
-if test -n "$ac_ct_CXX"; then
-  { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
-echo "${ECHO_T}$ac_ct_CXX" >&6; }
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  ac_cv_header_stdc=no
 fi
+rm -f conftest*
 
-
-  test -n "$ac_ct_CXX" && break
-done
-
-  if test "x$ac_ct_CXX" = x; then
-    CXX="g++"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
-    CXX=$ac_ct_CXX
-  fi
 fi
 
-  fi
-fi
-# Provide some information about the compiler.
-echo "$as_me:$LINENO: checking for C++ compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (ac_try="$ac_compiler --version >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler --version >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (ac_try="$ac_compiler -v >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -v >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (ac_try="$ac_compiler -V >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -V >&5") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
 
-{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; }
-if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
 else
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
@@ -5544,290 +4975,298 @@ _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
 
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
 int
 main ()
 {
-#ifndef __GNUC__
-       choke me
-#endif
-
-  ;
-  return 0;
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
 }
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_compiler_gnu=yes
+  :
 else
-  echo "$as_me: failed program was:" >&5
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_compiler_gnu=no
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
 fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
 
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; }
-GXX=`test $ac_compiler_gnu = yes && echo yes`
-ac_test_CXXFLAGS=${CXXFLAGS+set}
-ac_save_CXXFLAGS=$CXXFLAGS
-{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
-echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; }
-if test "${ac_cv_prog_cxx_g+set}" = set; then
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
-   ac_cxx_werror_flag=yes
-   ac_cv_prog_cxx_g=no
-   CXXFLAGS="-g"
-   cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
+$ac_includes_default
 
-int
-main ()
-{
-
-  ;
-  return 0;
-}
+#include <$ac_header>
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_prog_cxx_g=yes
+  eval "$as_ac_Header=yes"
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       CXXFLAGS=""
-      cat >conftest.$ac_ext <<_ACEOF
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in dlfcn.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
+$ac_includes_default
+#include <$ac_header>
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  :
+  ac_header_compiler=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cxx_werror_flag=$ac_save_cxx_werror_flag
-        CXXFLAGS="-g"
-        cat >conftest.$ac_ext <<_ACEOF
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
+#include <$ac_header>
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_prog_cxx_g=yes
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
+  ac_header_preproc=no
 fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
 fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; }
-if test "$ac_test_CXXFLAGS" = set; then
-  CXXFLAGS=$ac_save_CXXFLAGS
-elif test $ac_cv_prog_cxx_g = yes; then
-  if test "$GXX" = yes; then
-    CXXFLAGS="-g -O2"
-  else
-    CXXFLAGS="-g"
-  fi
-else
-  if test "$GXX" = yes; then
-    CXXFLAGS="-O2"
-  else
-    CXXFLAGS=
-  fi
 fi
-ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+done
 
 
 
 if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
     ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
     (test "X$CXX" != "Xg++"))) ; then
-  ac_ext=cpp
+  ac_ext=cc
 ac_cpp='$CXXCPP $CPPFLAGS'
 ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
-echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6
 if test -z "$CXXCPP"; then
   if test "${ac_cv_prog_CXXCPP+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -5857,13 +5296,8 @@ cat >>conftest.$ac_ext <<_ACEOF
 #endif
                     Syntax error
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
@@ -5888,10 +5322,9 @@ sed 's/^/| /' conftest.$ac_ext >&5
   # Broken: fails on valid input.
 continue
 fi
-
 rm -f conftest.err conftest.$ac_ext
 
-  # OK, works on sane cases.  Now check whether nonexistent headers
+  # OK, works on sane cases.  Now check whether non-existent headers
   # can be detected and how.
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
@@ -5901,13 +5334,8 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 #include <ac_nonexistent.h>
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
@@ -5934,7 +5362,6 @@ sed 's/^/| /' conftest.$ac_ext >&5
 ac_preproc_ok=:
 break
 fi
-
 rm -f conftest.err conftest.$ac_ext
 
 done
@@ -5952,8 +5379,8 @@ fi
 else
   ac_cv_prog_CXXCPP=$CXXCPP
 fi
-echo "$as_me:$LINENO: result: $CXXCPP" >&5
-echo "${ECHO_T}$CXXCPP" >&6; }
+echo "$as_me:$LINENO: result: $CXXCPP" >&5
+echo "${ECHO_T}$CXXCPP" >&6
 ac_preproc_ok=false
 for ac_cxx_preproc_warn_flag in '' yes
 do
@@ -5976,13 +5403,8 @@ cat >>conftest.$ac_ext <<_ACEOF
 #endif
                     Syntax error
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
@@ -6007,10 +5429,9 @@ sed 's/^/| /' conftest.$ac_ext >&5
   # Broken: fails on valid input.
 continue
 fi
-
 rm -f conftest.err conftest.$ac_ext
 
-  # OK, works on sane cases.  Now check whether nonexistent headers
+  # OK, works on sane cases.  Now check whether non-existent headers
   # can be detected and how.
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
@@ -6020,13 +5441,8 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 #include <ac_nonexistent.h>
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
@@ -6053,7 +5469,6 @@ sed 's/^/| /' conftest.$ac_ext >&5
 ac_preproc_ok=:
 break
 fi
-
 rm -f conftest.err conftest.$ac_ext
 
 done
@@ -6069,7 +5484,7 @@ See \`config.log' for more details." >&2;}
    { (exit 1); exit 1; }; }
 fi
 
-ac_ext=cpp
+ac_ext=cc
 ac_cpp='$CXXCPP $CPPFLAGS'
 ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
@@ -6083,12 +5498,12 @@ ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
 ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_f77_compiler_gnu
 if test -n "$ac_tool_prefix"; then
-  for ac_prog in g77 f77 xlf frt pgf77 cf77 fort77 fl32 af77 f90 xlf90 pgf90 pghpf epcf90 gfortran g95 f95 fort xlf95 ifort ifc efc pgf95 lf95 ftn
+  for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran
   do
     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_F77+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -6101,38 +5516,36 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_F77="$ac_tool_prefix$ac_prog"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
 fi
 fi
 F77=$ac_cv_prog_F77
 if test -n "$F77"; then
-  echo "$as_me:$LINENO: result: $F77" >&5
-echo "${ECHO_T}$F77" >&6; }
+  echo "$as_me:$LINENO: result: $F77" >&5
+echo "${ECHO_T}$F77" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
     test -n "$F77" && break
   done
 fi
 if test -z "$F77"; then
   ac_ct_F77=$F77
-  for ac_prog in g77 f77 xlf frt pgf77 cf77 fort77 fl32 af77 f90 xlf90 pgf90 pghpf epcf90 gfortran g95 f95 fort xlf95 ifort ifc efc pgf95 lf95 ftn
+  for ac_prog in g77 f77 xlf frt pgf77 fort77 fl32 af77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 ifc efc pgf95 lf95 gfortran
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_ac_ct_F77+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -6145,78 +5558,48 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_F77="$ac_prog"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
 fi
 fi
 ac_ct_F77=$ac_cv_prog_ac_ct_F77
 if test -n "$ac_ct_F77"; then
-  echo "$as_me:$LINENO: result: $ac_ct_F77" >&5
-echo "${ECHO_T}$ac_ct_F77" >&6; }
+  echo "$as_me:$LINENO: result: $ac_ct_F77" >&5
+echo "${ECHO_T}$ac_ct_F77" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
   test -n "$ac_ct_F77" && break
 done
 
-  if test "x$ac_ct_F77" = x; then
-    F77=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
-    F77=$ac_ct_F77
-  fi
+  F77=$ac_ct_F77
 fi
 
 
 # Provide some information about the compiler.
-echo "$as_me:$LINENO: checking for Fortran 77 compiler version" >&5
+echo "$as_me:5588:" \
+     "checking for Fortran 77 compiler version" >&5
 ac_compiler=`set X $ac_compile; echo $2`
-{ (ac_try="$ac_compiler --version >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler --version >&5") 2>&5
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }
-{ (ac_try="$ac_compiler -v >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -v >&5") 2>&5
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }
-{ (ac_try="$ac_compiler -V >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compiler -V >&5") 2>&5
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }
@@ -6226,8 +5609,8 @@ rm -f a.out
 # input file.  (Note that this only needs to work for GNU compilers.)
 ac_save_ext=$ac_ext
 ac_ext=F
-echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6
 if test "${ac_cv_f77_compiler_gnu+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -6240,36 +5623,24 @@ else
       end
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_f77_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -6278,21 +5649,20 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_compiler_gnu=no
+ac_compiler_gnu=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 ac_cv_f77_compiler_gnu=$ac_compiler_gnu
 
 fi
-echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6
 ac_ext=$ac_save_ext
 ac_test_FFLAGS=${FFLAGS+set}
 ac_save_FFLAGS=$FFLAGS
 FFLAGS=
-echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5
-echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5
+echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6
 if test "${ac_cv_prog_f77_g+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -6303,36 +5673,24 @@ cat >conftest.$ac_ext <<_ACEOF
       end
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_f77_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -6341,14 +5699,13 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_prog_f77_g=no
+ac_cv_prog_f77_g=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 
 fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5
-echo "${ECHO_T}$ac_cv_prog_f77_g" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5
+echo "${ECHO_T}$ac_cv_prog_f77_g" >&6
 if test "$ac_test_FFLAGS" = set; then
   FFLAGS=$ac_save_FFLAGS
 elif test $ac_cv_prog_f77_g = yes; then
@@ -6377,8 +5734,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 # Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
 
 # find the maximum length of command line arguments
-echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5
-echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5
+echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6
 if test "${lt_cv_sys_max_cmd_len+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -6486,19 +5843,19 @@ else
 fi
 
 if test -n $lt_cv_sys_max_cmd_len ; then
-  echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5
-echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6; }
+  echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5
+echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6
 else
-  echo "$as_me:$LINENO: result: none" >&5
-echo "${ECHO_T}none" >&6; }
+  echo "$as_me:$LINENO: result: none" >&5
+echo "${ECHO_T}none" >&6
 fi
 
 
 
 
 # Check for command to grab the raw symbol name followed by C symbol from nm.
-echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5
-echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5
+echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6
 if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -6702,15 +6059,15 @@ if test -z "$lt_cv_sys_global_symbol_pipe"; then
   lt_cv_sys_global_symbol_to_cdecl=
 fi
 if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
-  echo "$as_me:$LINENO: result: failed" >&5
-echo "${ECHO_T}failed" >&6; }
+  echo "$as_me:$LINENO: result: failed" >&5
+echo "${ECHO_T}failed" >&6
 else
-  echo "$as_me:$LINENO: result: ok" >&5
-echo "${ECHO_T}ok" >&6; }
+  echo "$as_me:$LINENO: result: ok" >&5
+echo "${ECHO_T}ok" >&6
 fi
 
-echo "$as_me:$LINENO: checking for objdir" >&5
-echo $ECHO_N "checking for objdir... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for objdir" >&5
+echo $ECHO_N "checking for objdir... $ECHO_C" >&6
 if test "${lt_cv_objdir+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -6724,8 +6081,8 @@ else
 fi
 rmdir .libs 2>/dev/null
 fi
-echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5
-echo "${ECHO_T}$lt_cv_objdir" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5
+echo "${ECHO_T}$lt_cv_objdir" >&6
 objdir=$lt_cv_objdir
 
 
@@ -6776,8 +6133,8 @@ with_gnu_ld="$lt_cv_prog_gnu_ld"
 if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
 set dummy ${ac_tool_prefix}ar; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_AR+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -6790,34 +6147,32 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_AR="${ac_tool_prefix}ar"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
 fi
 fi
 AR=$ac_cv_prog_AR
 if test -n "$AR"; then
-  echo "$as_me:$LINENO: result: $AR" >&5
-echo "${ECHO_T}$AR" >&6; }
+  echo "$as_me:$LINENO: result: $AR" >&5
+echo "${ECHO_T}$AR" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 fi
 if test -z "$ac_cv_prog_AR"; then
   ac_ct_AR=$AR
   # Extract the first word of "ar", so it can be a program name with args.
 set dummy ar; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_ac_ct_AR+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -6830,41 +6185,27 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_AR="ar"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
+  test -z "$ac_cv_prog_ac_ct_AR" && ac_cv_prog_ac_ct_AR="false"
 fi
 fi
 ac_ct_AR=$ac_cv_prog_ac_ct_AR
 if test -n "$ac_ct_AR"; then
-  echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
-echo "${ECHO_T}$ac_ct_AR" >&6; }
+  echo "$as_me:$LINENO: result: $ac_ct_AR" >&5
+echo "${ECHO_T}$ac_ct_AR" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-  if test "x$ac_ct_AR" = x; then
-    AR="false"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
-    AR=$ac_ct_AR
-  fi
+  AR=$ac_ct_AR
 else
   AR="$ac_cv_prog_AR"
 fi
@@ -6872,8 +6213,8 @@ fi
 if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
 set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_RANLIB+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -6886,34 +6227,32 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
 fi
 fi
 RANLIB=$ac_cv_prog_RANLIB
 if test -n "$RANLIB"; then
-  echo "$as_me:$LINENO: result: $RANLIB" >&5
-echo "${ECHO_T}$RANLIB" >&6; }
+  echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 fi
 if test -z "$ac_cv_prog_RANLIB"; then
   ac_ct_RANLIB=$RANLIB
   # Extract the first word of "ranlib", so it can be a program name with args.
 set dummy ranlib; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -6926,41 +6265,27 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_RANLIB="ranlib"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
+  test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
 fi
 fi
 ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
 if test -n "$ac_ct_RANLIB"; then
-  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
-echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
+  echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-  if test "x$ac_ct_RANLIB" = x; then
-    RANLIB=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
-    RANLIB=$ac_ct_RANLIB
-  fi
+  RANLIB=$ac_ct_RANLIB
 else
   RANLIB="$ac_cv_prog_RANLIB"
 fi
@@ -6968,8 +6293,8 @@ fi
 if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
 set dummy ${ac_tool_prefix}strip; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_STRIP+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -6982,34 +6307,32 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_STRIP="${ac_tool_prefix}strip"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
 fi
 fi
 STRIP=$ac_cv_prog_STRIP
 if test -n "$STRIP"; then
-  echo "$as_me:$LINENO: result: $STRIP" >&5
-echo "${ECHO_T}$STRIP" >&6; }
+  echo "$as_me:$LINENO: result: $STRIP" >&5
+echo "${ECHO_T}$STRIP" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 fi
 if test -z "$ac_cv_prog_STRIP"; then
   ac_ct_STRIP=$STRIP
   # Extract the first word of "strip", so it can be a program name with args.
 set dummy strip; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -7022,41 +6345,27 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_STRIP="strip"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
+  test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":"
 fi
 fi
 ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
 if test -n "$ac_ct_STRIP"; then
-  echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
-echo "${ECHO_T}$ac_ct_STRIP" >&6; }
+  echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+echo "${ECHO_T}$ac_ct_STRIP" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-  if test "x$ac_ct_STRIP" = x; then
-    STRIP=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&5
-echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
-whose name does not start with the host triplet.  If you think this
-configuration is useful to you, please write to autoconf@gnu.org." >&2;}
-ac_tool_warned=yes ;;
-esac
-    STRIP=$ac_ct_STRIP
-  fi
+  STRIP=$ac_ct_STRIP
 else
   STRIP="$ac_cv_prog_STRIP"
 fi
@@ -7115,8 +6424,8 @@ cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
 case $deplibs_check_method in
 file_magic*)
   if test "$file_magic_cmd" = '$MAGIC_CMD'; then
-    echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
-echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6; }
+    echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5
+echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6
 if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -7168,17 +6477,17 @@ fi
 
 MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
 if test -n "$MAGIC_CMD"; then
-  echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
-echo "${ECHO_T}$MAGIC_CMD" >&6; }
+  echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
 if test -z "$lt_cv_path_MAGIC_CMD"; then
   if test -n "$ac_tool_prefix"; then
-    echo "$as_me:$LINENO: checking for file" >&5
-echo $ECHO_N "checking for file... $ECHO_C" >&6; }
+    echo "$as_me:$LINENO: checking for file" >&5
+echo $ECHO_N "checking for file... $ECHO_C" >&6
 if test "${lt_cv_path_MAGIC_CMD+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -7230,11 +6539,11 @@ fi
 
 MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
 if test -n "$MAGIC_CMD"; then
-  echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
-echo "${ECHO_T}$MAGIC_CMD" >&6; }
+  echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5
+echo "${ECHO_T}$MAGIC_CMD" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
   else
@@ -7249,21 +6558,21 @@ esac
 enable_dlopen=yes
 enable_win32_dll=no
 
-# Check whether --enable-libtool-lock was given.
+# Check whether --enable-libtool-lock or --disable-libtool-lock was given.
 if test "${enable_libtool_lock+set}" = set; then
-  enableval=$enable_libtool_lock;
-fi
+  enableval="$enable_libtool_lock"
 
+fi;
 test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
 
 
-# Check whether --with-pic was given.
+# Check whether --with-pic or --without-pic was given.
 if test "${with_pic+set}" = set; then
-  withval=$with_pic; pic_mode="$withval"
+  withval="$with_pic"
+  pic_mode="$withval"
 else
   pic_mode=default
-fi
-
+fi;
 test -z "$pic_mode" && pic_mode=default
 
 # Use C for the default configuration in the libtool script
@@ -7325,8 +6634,8 @@ if test "$GCC" = yes; then
   lt_prog_compiler_no_builtin_flag=' -fno-builtin'
 
 
-echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
-echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6
 if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -7343,11 +6652,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:7346: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6655: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7350: \$? = $ac_status" >&5
+   echo "$as_me:6659: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -7360,8 +6669,8 @@ else
    $rm conftest*
 
 fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
-echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6
 
 if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
     lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
@@ -7375,8 +6684,8 @@ lt_prog_compiler_wl=
 lt_prog_compiler_pic=
 lt_prog_compiler_static=
 
-echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
-echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
 
   if test "$GCC" = yes; then
     lt_prog_compiler_wl='-Wl,'
@@ -7585,16 +6894,16 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
     esac
   fi
 
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic" >&6; }
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic" >&6
 
 #
 # Check to make sure the PIC flag actually works.
 #
 if test -n "$lt_prog_compiler_pic"; then
 
-echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
-echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6
 if test "${lt_prog_compiler_pic_works+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -7611,11 +6920,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:7614: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:6923: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7618: \$? = $ac_status" >&5
+   echo "$as_me:6927: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -7628,8 +6937,8 @@ else
    $rm conftest*
 
 fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6; }
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6
 
 if test x"$lt_prog_compiler_pic_works" = xyes; then
     case $lt_prog_compiler_pic in
@@ -7656,8 +6965,8 @@ esac
 # Check to make sure the static flag actually works.
 #
 wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
-echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
-echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
 if test "${lt_prog_compiler_static_works+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -7684,8 +6993,8 @@ else
    LDFLAGS="$save_LDFLAGS"
 
 fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5
-echo "${ECHO_T}$lt_prog_compiler_static_works" >&6; }
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works" >&6
 
 if test x"$lt_prog_compiler_static_works" = xyes; then
     :
@@ -7694,8 +7003,8 @@ else
 fi
 
 
-echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
-echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
 if test "${lt_cv_prog_compiler_c_o+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -7715,11 +7024,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:7718: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7027: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:7722: \$? = $ac_status" >&5
+   echo "$as_me:7031: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -7741,23 +7050,23 @@ else
    $rm conftest*
 
 fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
-echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6
 
 
 hard_links="nottested"
 if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then
   # do not overwrite the value of need_locks provided by the user
-  echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
-echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
   hard_links=yes
   $rm conftest*
   ln conftest.a conftest.b 2>/dev/null && hard_links=no
   touch conftest.a
   ln conftest.a conftest.b 2>&5 || hard_links=no
   ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  echo "$as_me:$LINENO: result: $hard_links" >&5
-echo "${ECHO_T}$hard_links" >&6; }
+  echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
   if test "$hard_links" = no; then
     { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
@@ -7767,8 +7076,8 @@ else
   need_locks=no
 fi
 
-echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
-echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
 
   runpath_var=
   allow_undefined_flag=
@@ -8183,36 +7492,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -8226,10 +7523,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
@@ -8258,36 +7553,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -8301,10 +7584,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
@@ -8753,8 +8034,8 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
     esac
   fi
 
-echo "$as_me:$LINENO: result: $ld_shlibs" >&5
-echo "${ECHO_T}$ld_shlibs" >&6; }
+echo "$as_me:$LINENO: result: $ld_shlibs" >&5
+echo "${ECHO_T}$ld_shlibs" >&6
 test "$ld_shlibs" = no && can_build_shared=no
 
 #
@@ -8774,8 +8055,8 @@ x|xyes)
       # Test whether the compiler implicitly links with -lc since on some
       # systems, -lgcc has to come before -lc. If gcc already passes -lc
       # to ld, don't add -lc before -lgcc.
-      echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
-echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+      echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
       $rm conftest*
       printf "$lt_simple_compile_test_code" > conftest.$ac_ext
 
@@ -8812,16 +8093,16 @@ echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&
         cat conftest.err 1>&5
       fi
       $rm conftest*
-      echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5
-echo "${ECHO_T}$archive_cmds_need_lc" >&6; }
+      echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5
+echo "${ECHO_T}$archive_cmds_need_lc" >&6
       ;;
     esac
   fi
   ;;
 esac
 
-echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
-echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
 library_names_spec=
 libname_spec='lib$name'
 soname_spec=
@@ -9408,8 +8689,8 @@ uts4*)
   dynamic_linker=no
   ;;
 esac
-echo "$as_me:$LINENO: result: $dynamic_linker" >&5
-echo "${ECHO_T}$dynamic_linker" >&6; }
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
 test "$dynamic_linker" = no && can_build_shared=no
 
 variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
@@ -9417,8 +8698,8 @@ if test "$GCC" = yes; then
   variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
 fi
 
-echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
-echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
 hardcode_action=
 if test -n "$hardcode_libdir_flag_spec" || \
    test -n "$runpath_var" || \
@@ -9442,8 +8723,8 @@ else
   # directories.
   hardcode_action=unsupported
 fi
-echo "$as_me:$LINENO: result: $hardcode_action" >&5
-echo "${ECHO_T}$hardcode_action" >&6; }
+echo "$as_me:$LINENO: result: $hardcode_action" >&5
+echo "${ECHO_T}$hardcode_action" >&6
 
 if test "$hardcode_action" = relink; then
   # Fast installation is not supported
@@ -9456,29 +8737,29 @@ fi
 
 striplib=
 old_striplib=
-echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
-echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5
+echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6
 if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
   test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
   test -z "$striplib" && striplib="$STRIP --strip-unneeded"
-  echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
 else
 # FIXME - insert some real tests, host_os isn't really good enough
   case $host_os in
    darwin*)
        if test -n "$STRIP" ; then
          striplib="$STRIP -x"
-         echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
+         echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
        else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
        ;;
    *)
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
     ;;
   esac
 fi
@@ -9510,8 +8791,8 @@ else
 
   darwin*)
   # if libdl is installed we need to link against it
-    echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
-echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+    echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
 if test "${ac_cv_lib_dl_dlopen+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -9524,52 +8805,40 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
 char dlopen ();
 int
 main ()
 {
-return dlopen ();
+dlopen ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -9578,15 +8847,14 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_dl_dlopen=no
+ac_cv_lib_dl_dlopen=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
-echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
 if test $ac_cv_lib_dl_dlopen = yes; then
   lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
 else
@@ -9600,8 +8868,8 @@ fi
    ;;
 
   *)
-    echo "$as_me:$LINENO: checking for shl_load" >&5
-echo $ECHO_N "checking for shl_load... $ECHO_C" >&6; }
+    echo "$as_me:$LINENO: checking for shl_load" >&5
+echo $ECHO_N "checking for shl_load... $ECHO_C" >&6
 if test "${ac_cv_func_shl_load+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -9628,59 +8896,53 @@ cat >>conftest.$ac_ext <<_ACEOF
 
 #undef shl_load
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
+{
 #endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
 char shl_load ();
 /* The GNU C library defines this for functions which it implements
     to always fail with ENOSYS.  Some functions are actually named
     something starting with __ and the normal name is an alias.  */
-#if defined __stub_shl_load || defined __stub___shl_load
+#if defined (__stub_shl_load) || defined (__stub___shl_load)
 choke me
+#else
+char (*f) () = shl_load;
+#endif
+#ifdef __cplusplus
+}
 #endif
 
 int
 main ()
 {
-return shl_load ();
+return f != shl_load;
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -9689,19 +8951,18 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_func_shl_load=no
+ac_cv_func_shl_load=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
-echo "${ECHO_T}$ac_cv_func_shl_load" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5
+echo "${ECHO_T}$ac_cv_func_shl_load" >&6
 if test $ac_cv_func_shl_load = yes; then
   lt_cv_dlopen="shl_load"
 else
-  echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
-echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5
+echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6
 if test "${ac_cv_lib_dld_shl_load+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -9714,52 +8975,40 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
 char shl_load ();
 int
 main ()
 {
-return shl_load ();
+shl_load ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -9768,20 +9017,19 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_dld_shl_load=no
+ac_cv_lib_dld_shl_load=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
-echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6
 if test $ac_cv_lib_dld_shl_load = yes; then
   lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"
 else
-  echo "$as_me:$LINENO: checking for dlopen" >&5
-echo $ECHO_N "checking for dlopen... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for dlopen" >&5
+echo $ECHO_N "checking for dlopen... $ECHO_C" >&6
 if test "${ac_cv_func_dlopen+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -9808,59 +9056,53 @@ cat >>conftest.$ac_ext <<_ACEOF
 
 #undef dlopen
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
+{
 #endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
 char dlopen ();
 /* The GNU C library defines this for functions which it implements
     to always fail with ENOSYS.  Some functions are actually named
     something starting with __ and the normal name is an alias.  */
-#if defined __stub_dlopen || defined __stub___dlopen
+#if defined (__stub_dlopen) || defined (__stub___dlopen)
 choke me
+#else
+char (*f) () = dlopen;
+#endif
+#ifdef __cplusplus
+}
 #endif
 
 int
 main ()
 {
-return dlopen ();
+return f != dlopen;
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -9869,19 +9111,18 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_func_dlopen=no
+ac_cv_func_dlopen=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
-echo "${ECHO_T}$ac_cv_func_dlopen" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5
+echo "${ECHO_T}$ac_cv_func_dlopen" >&6
 if test $ac_cv_func_dlopen = yes; then
   lt_cv_dlopen="dlopen"
 else
-  echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
-echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5
+echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6
 if test "${ac_cv_lib_dl_dlopen+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -9894,52 +9135,40 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
 char dlopen ();
 int
 main ()
 {
-return dlopen ();
+dlopen ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -9948,20 +9177,19 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_dl_dlopen=no
+ac_cv_lib_dl_dlopen=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
-echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6
 if test $ac_cv_lib_dl_dlopen = yes; then
   lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
 else
-  echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
-echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5
+echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6
 if test "${ac_cv_lib_svld_dlopen+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -9974,52 +9202,40 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
 char dlopen ();
 int
 main ()
 {
-return dlopen ();
+dlopen ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -10028,20 +9244,19 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_svld_dlopen=no
+ac_cv_lib_svld_dlopen=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
-echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5
+echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6
 if test $ac_cv_lib_svld_dlopen = yes; then
   lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"
 else
-  echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
-echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5
+echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6
 if test "${ac_cv_lib_dld_dld_link+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -10054,52 +9269,40 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
 char dld_link ();
 int
 main ()
 {
-return dld_link ();
+dld_link ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -10108,15 +9311,14 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_dld_dld_link=no
+ac_cv_lib_dld_dld_link=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
-echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5
+echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6
 if test $ac_cv_lib_dld_dld_link = yes; then
   lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"
 fi
@@ -10156,8 +9358,8 @@ fi
     save_LIBS="$LIBS"
     LIBS="$lt_cv_dlopen_libs $LIBS"
 
-    echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
-echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6; }
+    echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5
+echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6
 if test "${lt_cv_dlopen_self+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -10167,7 +9369,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10170 "configure"
+#line 9372 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10251,13 +9453,13 @@ rm -fr conftest*
 
 
 fi
-echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
-echo "${ECHO_T}$lt_cv_dlopen_self" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self" >&6
 
     if test "x$lt_cv_dlopen_self" = xyes; then
       wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
-      echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
-echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6; }
+      echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5
+echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6
 if test "${lt_cv_dlopen_self_static+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -10267,7 +9469,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10270 "configure"
+#line 9472 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10351,8 +9553,8 @@ rm -fr conftest*
 
 
 fi
-echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
-echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5
+echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6
     fi
 
     CPPFLAGS="$save_CPPFLAGS"
 
 
 # Report which library types will actually be built
-echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
-echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; }
-echo "$as_me:$LINENO: result: $can_build_shared" >&5
-echo "${ECHO_T}$can_build_shared" >&6; }
+echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6
 
-echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
-echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6
 test "$can_build_shared" = "no" && enable_shared=no
 
 # On AIX, shared libraries and static libraries use the same namespace, and
@@ -10400,15 +9602,15 @@ aix4* | aix5*)
   fi
     ;;
 esac
-echo "$as_me:$LINENO: result: $enable_shared" >&5
-echo "${ECHO_T}$enable_shared" >&6; }
+echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6
 
-echo "$as_me:$LINENO: checking whether to build static libraries" >&5
-echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6
 # Make sure either enable_shared or enable_static is yes.
 test "$enable_shared" = yes || enable_static=yes
-echo "$as_me:$LINENO: result: $enable_static" >&5
-echo "${ECHO_T}$enable_static" >&6; }
+echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6
 
 # The else clause should only fire when bootstrapping the
 # libtool distribution, otherwise you forgot to ship ltmain.sh
@@ -10900,11 +10102,11 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 CC="$lt_save_CC"
 
 
-# Check whether --with-tags was given.
+# Check whether --with-tags or --without-tags was given.
 if test "${with_tags+set}" = set; then
-  withval=$with_tags; tagnames="$withval"
-fi
-
+  withval="$with_tags"
+  tagnames="$withval"
+fi;
 
 if test -f "$ltmain" && test -n "$tagnames"; then
   if test ! -f "${ofile}"; then
@@ -10958,7 +10160,7 @@ echo "$as_me: error: tag name \"$tagname\" already exists" >&2;}
        if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
            ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
            (test "X$CXX" != "Xg++"))) ; then
-         ac_ext=cpp
+         ac_ext=cc
 ac_cpp='$CXXCPP $CPPFLAGS'
 ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
@@ -11077,18 +10279,18 @@ if test "$GXX" = yes; then
   # Set up default GNU C++ configuration
 
 
-# Check whether --with-gnu-ld was given.
+# Check whether --with-gnu-ld or --without-gnu-ld was given.
 if test "${with_gnu_ld+set}" = set; then
-  withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+  withval="$with_gnu_ld"
+  test "$withval" = no || with_gnu_ld=yes
 else
   with_gnu_ld=no
-fi
-
+fi;
 ac_prog=ld
 if test "$GCC" = yes; then
   # Check if gcc -print-prog-name=ld gives a path.
-  echo "$as_me:$LINENO: checking for ld used by $CC" >&5
-echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for ld used by $CC" >&5
+echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6
   case $host in
   *-*-mingw*)
     # gcc leaves a trailing carriage return which upsets mingw
@@ -11117,11 +10319,11 @@ echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6; }
     ;;
   esac
 elif test "$with_gnu_ld" = yes; then
-  echo "$as_me:$LINENO: checking for GNU ld" >&5
-echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for GNU ld" >&5
+echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6
 else
-  echo "$as_me:$LINENO: checking for non-GNU ld" >&5
-echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for non-GNU ld" >&5
+echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6
 fi
 if test "${lt_cv_path_LD+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 
 LD="$lt_cv_path_LD"
 if test -n "$LD"; then
-  echo "$as_me:$LINENO: result: $LD" >&5
-echo "${ECHO_T}$LD" >&6; }
+  echo "$as_me:$LINENO: result: $LD" >&5
+echo "${ECHO_T}$LD" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5
 echo "$as_me: error: no acceptable ld found in \$PATH" >&2;}
    { (exit 1); exit 1; }; }
-echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
-echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5
+echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6
 if test "${lt_cv_prog_gnu_ld+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -11178,8 +10380,8 @@ case `$LD -v 2>&1 </dev/null` in
   ;;
 esac
 fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
-echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5
+echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6
 with_gnu_ld=$lt_cv_prog_gnu_ld
 
 
@@ -11229,8 +10431,8 @@ else
 fi
 
 # PORTME: fill in a description of your system's C++ link characteristics
-echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
-echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
 ld_shlibs_CXX=yes
 case $host_os in
   aix3*)
@@ -11342,36 +10544,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -11385,10 +10575,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
@@ -11418,36 +10606,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_cxx_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -11461,10 +10637,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
@@ -12195,8 +11369,8 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
     ld_shlibs_CXX=no
     ;;
 esac
-echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
-echo "${ECHO_T}$ld_shlibs_CXX" >&6; }
+echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6
 test "$ld_shlibs_CXX" = no && can_build_shared=no
 
 GCC_CXX="$GXX"
@@ -12339,8 +11513,8 @@ lt_prog_compiler_wl_CXX=
 lt_prog_compiler_pic_CXX=
 lt_prog_compiler_static_CXX=
 
-echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
-echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
 
   # C++ specific cases for pic, static, wl, etc.
   if test "$GXX" = yes; then
@@ -12613,16 +11787,16 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
     esac
   fi
 
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6; }
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6
 
 #
 # Check to make sure the PIC flag actually works.
 #
 if test -n "$lt_prog_compiler_pic_CXX"; then
 
-echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
-echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6
 if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -12639,11 +11813,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:12642: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:11816: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:12646: \$? = $ac_status" >&5
+   echo "$as_me:11820: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -12656,8 +11830,8 @@ else
    $rm conftest*
 
 fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6; }
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6
 
 if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then
     case $lt_prog_compiler_pic_CXX in
@@ -12684,8 +11858,8 @@ esac
 # Check to make sure the static flag actually works.
 #
 wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
-echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
-echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
 if test "${lt_prog_compiler_static_works_CXX+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -12712,8 +11886,8 @@ else
    LDFLAGS="$save_LDFLAGS"
 
 fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5
-echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6; }
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_CXX" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_CXX" >&6
 
 if test x"$lt_prog_compiler_static_works_CXX" = xyes; then
     :
@@ -12722,8 +11896,8 @@ else
 fi
 
 
-echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
-echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
 if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -12743,11 +11917,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:12746: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:11920: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:12750: \$? = $ac_status" >&5
+   echo "$as_me:11924: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -12769,23 +11943,23 @@ else
    $rm conftest*
 
 fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5
-echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6
 
 
 hard_links="nottested"
 if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then
   # do not overwrite the value of need_locks provided by the user
-  echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
-echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
   hard_links=yes
   $rm conftest*
   ln conftest.a conftest.b 2>/dev/null && hard_links=no
   touch conftest.a
   ln conftest.a conftest.b 2>&5 || hard_links=no
   ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  echo "$as_me:$LINENO: result: $hard_links" >&5
-echo "${ECHO_T}$hard_links" >&6; }
+  echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
   if test "$hard_links" = no; then
     { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
@@ -12795,8 +11969,8 @@ else
   need_locks=no
 fi
 
-echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
-echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
 
   export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
   case $host_os in
@@ -12820,8 +11994,8 @@ echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared librar
   ;;
   esac
 
-echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
-echo "${ECHO_T}$ld_shlibs_CXX" >&6; }
+echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5
+echo "${ECHO_T}$ld_shlibs_CXX" >&6
 test "$ld_shlibs_CXX" = no && can_build_shared=no
 
 #
@@ -12841,8 +12015,8 @@ x|xyes)
       # Test whether the compiler implicitly links with -lc since on some
       # systems, -lgcc has to come before -lc. If gcc already passes -lc
       # to ld, don't add -lc before -lgcc.
-      echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
-echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+      echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
       $rm conftest*
       printf "$lt_simple_compile_test_code" > conftest.$ac_ext
 
@@ -12879,16 +12053,16 @@ echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&
         cat conftest.err 1>&5
       fi
       $rm conftest*
-      echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5
-echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6; }
+      echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6
       ;;
     esac
   fi
   ;;
 esac
 
-echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
-echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
 library_names_spec=
 libname_spec='lib$name'
 soname_spec=
@@ -13475,8 +12649,8 @@ uts4*)
   dynamic_linker=no
   ;;
 esac
-echo "$as_me:$LINENO: result: $dynamic_linker" >&5
-echo "${ECHO_T}$dynamic_linker" >&6; }
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
 test "$dynamic_linker" = no && can_build_shared=no
 
 variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
@@ -13484,8 +12658,8 @@ if test "$GCC" = yes; then
   variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
 fi
 
-echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
-echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
 hardcode_action_CXX=
 if test -n "$hardcode_libdir_flag_spec_CXX" || \
    test -n "$runpath_var_CXX" || \
@@ -13509,8 +12683,8 @@ else
   # directories.
   hardcode_action_CXX=unsupported
 fi
-echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5
-echo "${ECHO_T}$hardcode_action_CXX" >&6; }
+echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5
+echo "${ECHO_T}$hardcode_action_CXX" >&6
 
 if test "$hardcode_action_CXX" = relink; then
   # Fast installation is not supported
@@ -14035,13 +13209,13 @@ done
 cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
 
 
-echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
-echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6; }
-echo "$as_me:$LINENO: result: $can_build_shared" >&5
-echo "${ECHO_T}$can_build_shared" >&6; }
+echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5
+echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $can_build_shared" >&5
+echo "${ECHO_T}$can_build_shared" >&6
 
-echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
-echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether to build shared libraries" >&5
+echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6
 test "$can_build_shared" = "no" && enable_shared=no
 
 # On AIX, shared libraries and static libraries use the same namespace, and
@@ -14060,15 +13234,15 @@ aix4* | aix5*)
   fi
   ;;
 esac
-echo "$as_me:$LINENO: result: $enable_shared" >&5
-echo "${ECHO_T}$enable_shared" >&6; }
+echo "$as_me:$LINENO: result: $enable_shared" >&5
+echo "${ECHO_T}$enable_shared" >&6
 
-echo "$as_me:$LINENO: checking whether to build static libraries" >&5
-echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether to build static libraries" >&5
+echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6
 # Make sure either enable_shared or enable_static is yes.
 test "$enable_shared" = yes || enable_static=yes
-echo "$as_me:$LINENO: result: $enable_static" >&5
-echo "${ECHO_T}$enable_static" >&6; }
+echo "$as_me:$LINENO: result: $enable_static" >&5
+echo "${ECHO_T}$enable_static" >&6
 
 GCC_F77="$G77"
 LD_F77="$LD"
@@ -14077,8 +13251,8 @@ lt_prog_compiler_wl_F77=
 lt_prog_compiler_pic_F77=
 lt_prog_compiler_static_F77=
 
-echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
-echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
 
   if test "$GCC" = yes; then
     lt_prog_compiler_wl_F77='-Wl,'
@@ -14287,16 +13461,16 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
     esac
   fi
 
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6; }
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6
 
 #
 # Check to make sure the PIC flag actually works.
 #
 if test -n "$lt_prog_compiler_pic_F77"; then
 
-echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5
-echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6
 if test "${lt_prog_compiler_pic_works_F77+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -14313,11 +13487,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14316: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13490: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:14320: \$? = $ac_status" >&5
+   echo "$as_me:13494: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -14330,8 +13504,8 @@ else
    $rm conftest*
 
 fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6; }
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6
 
 if test x"$lt_prog_compiler_pic_works_F77" = xyes; then
     case $lt_prog_compiler_pic_F77 in
@@ -14358,8 +13532,8 @@ esac
 # Check to make sure the static flag actually works.
 #
 wl=$lt_prog_compiler_wl_F77 eval lt_tmp_static_flag=\"$lt_prog_compiler_static_F77\"
-echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
-echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
 if test "${lt_prog_compiler_static_works_F77+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -14386,8 +13560,8 @@ else
    LDFLAGS="$save_LDFLAGS"
 
 fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5
-echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6; }
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_F77" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_F77" >&6
 
 if test x"$lt_prog_compiler_static_works_F77" = xyes; then
     :
@@ -14396,8 +13570,8 @@ else
 fi
 
 
-echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
-echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
 if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -14417,11 +13591,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14420: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13594: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:14424: \$? = $ac_status" >&5
+   echo "$as_me:13598: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -14443,23 +13617,23 @@ else
    $rm conftest*
 
 fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5
-echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6
 
 
 hard_links="nottested"
 if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then
   # do not overwrite the value of need_locks provided by the user
-  echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
-echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
   hard_links=yes
   $rm conftest*
   ln conftest.a conftest.b 2>/dev/null && hard_links=no
   touch conftest.a
   ln conftest.a conftest.b 2>&5 || hard_links=no
   ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  echo "$as_me:$LINENO: result: $hard_links" >&5
-echo "${ECHO_T}$hard_links" >&6; }
+  echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
   if test "$hard_links" = no; then
     { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
@@ -14469,8 +13643,8 @@ else
   need_locks=no
 fi
 
-echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
-echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
 
   runpath_var=
   allow_undefined_flag_F77=
@@ -14875,36 +14049,24 @@ _LT_EOF
       end
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_f77_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -14918,10 +14080,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
@@ -14940,36 +14100,24 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       end
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_f77_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_f77_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -14983,10 +14131,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
@@ -15435,8 +14581,8 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
     esac
   fi
 
-echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5
-echo "${ECHO_T}$ld_shlibs_F77" >&6; }
+echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5
+echo "${ECHO_T}$ld_shlibs_F77" >&6
 test "$ld_shlibs_F77" = no && can_build_shared=no
 
 #
@@ -15456,8 +14602,8 @@ x|xyes)
       # Test whether the compiler implicitly links with -lc since on some
       # systems, -lgcc has to come before -lc. If gcc already passes -lc
       # to ld, don't add -lc before -lgcc.
-      echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
-echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+      echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
       $rm conftest*
       printf "$lt_simple_compile_test_code" > conftest.$ac_ext
 
@@ -15494,16 +14640,16 @@ echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&
         cat conftest.err 1>&5
       fi
       $rm conftest*
-      echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5
-echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6; }
+      echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6
       ;;
     esac
   fi
   ;;
 esac
 
-echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
-echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
 library_names_spec=
 libname_spec='lib$name'
 soname_spec=
@@ -16090,8 +15236,8 @@ uts4*)
   dynamic_linker=no
   ;;
 esac
-echo "$as_me:$LINENO: result: $dynamic_linker" >&5
-echo "${ECHO_T}$dynamic_linker" >&6; }
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
 test "$dynamic_linker" = no && can_build_shared=no
 
 variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
@@ -16099,8 +15245,8 @@ if test "$GCC" = yes; then
   variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
 fi
 
-echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
-echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
 hardcode_action_F77=
 if test -n "$hardcode_libdir_flag_spec_F77" || \
    test -n "$runpath_var_F77" || \
@@ -16124,8 +15270,8 @@ else
   # directories.
   hardcode_action_F77=unsupported
 fi
-echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5
-echo "${ECHO_T}$hardcode_action_F77" >&6; }
+echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5
+echo "${ECHO_T}$hardcode_action_F77" >&6
 
 if test "$hardcode_action_F77" = relink; then
   # Fast installation is not supported
@@ -16562,6 +15708,7 @@ CC="$lt_save_CC"
        if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
 
 
+
 # Source file extension for Java test sources.
 ac_ext=java
 
@@ -16633,8 +15780,8 @@ if test "$GCC" = yes; then
   lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin'
 
 
-echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
-echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6
 if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -16651,11 +15798,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:16654: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15801: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:16658: \$? = $ac_status" >&5
+   echo "$as_me:15805: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -16668,8 +15815,8 @@ else
    $rm conftest*
 
 fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
-echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6
 
 if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then
     lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions"
@@ -16683,8 +15830,8 @@ lt_prog_compiler_wl_GCJ=
 lt_prog_compiler_pic_GCJ=
 lt_prog_compiler_static_GCJ=
 
-echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
-echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5
+echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6
 
   if test "$GCC" = yes; then
     lt_prog_compiler_wl_GCJ='-Wl,'
@@ -16893,16 +16040,16 @@ echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6; }
     esac
   fi
 
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6; }
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6
 
 #
 # Check to make sure the PIC flag actually works.
 #
 if test -n "$lt_prog_compiler_pic_GCJ"; then
 
-echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5
-echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5
+echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6
 if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -16919,11 +16066,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:16922: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16069: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:16926: \$? = $ac_status" >&5
+   echo "$as_me:16073: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -16936,8 +16083,8 @@ else
    $rm conftest*
 
 fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5
-echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6; }
+echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6
 
 if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then
     case $lt_prog_compiler_pic_GCJ in
@@ -16964,8 +16111,8 @@ esac
 # Check to make sure the static flag actually works.
 #
 wl=$lt_prog_compiler_wl_GCJ eval lt_tmp_static_flag=\"$lt_prog_compiler_static_GCJ\"
-echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
-echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+echo $ECHO_N "checking if $compiler static flag $lt_tmp_static_flag works... $ECHO_C" >&6
 if test "${lt_prog_compiler_static_works_GCJ+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -16992,8 +16139,8 @@ else
    LDFLAGS="$save_LDFLAGS"
 
 fi
-echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5
-echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6; }
+echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works_GCJ" >&5
+echo "${ECHO_T}$lt_prog_compiler_static_works_GCJ" >&6
 
 if test x"$lt_prog_compiler_static_works_GCJ" = xyes; then
     :
@@ -17002,8 +16149,8 @@ else
 fi
 
 
-echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
-echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5
+echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6
 if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -17023,11 +16170,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17026: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16173: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:17030: \$? = $ac_status" >&5
+   echo "$as_me:16177: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -17049,23 +16196,23 @@ else
    $rm conftest*
 
 fi
-echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5
-echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6; }
+echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5
+echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6
 
 
 hard_links="nottested"
 if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then
   # do not overwrite the value of need_locks provided by the user
-  echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
-echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking if we can lock with hard links" >&5
+echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6
   hard_links=yes
   $rm conftest*
   ln conftest.a conftest.b 2>/dev/null && hard_links=no
   touch conftest.a
   ln conftest.a conftest.b 2>&5 || hard_links=no
   ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  echo "$as_me:$LINENO: result: $hard_links" >&5
-echo "${ECHO_T}$hard_links" >&6; }
+  echo "$as_me:$LINENO: result: $hard_links" >&5
+echo "${ECHO_T}$hard_links" >&6
   if test "$hard_links" = no; then
     { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
 echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
@@ -17075,8 +16222,8 @@ else
   need_locks=no
 fi
 
-echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
-echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6
 
   runpath_var=
   allow_undefined_flag_GCJ=
@@ -17491,36 +16638,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -17534,10 +16669,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
@@ -17566,36 +16699,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -17609,10 +16730,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
 
@@ -18061,8 +17180,8 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
     esac
   fi
 
-echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5
-echo "${ECHO_T}$ld_shlibs_GCJ" >&6; }
+echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5
+echo "${ECHO_T}$ld_shlibs_GCJ" >&6
 test "$ld_shlibs_GCJ" = no && can_build_shared=no
 
 #
@@ -18082,8 +17201,8 @@ x|xyes)
       # Test whether the compiler implicitly links with -lc since on some
       # systems, -lgcc has to come before -lc. If gcc already passes -lc
       # to ld, don't add -lc before -lgcc.
-      echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
-echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6; }
+      echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5
+echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6
       $rm conftest*
       printf "$lt_simple_compile_test_code" > conftest.$ac_ext
 
@@ -18120,16 +17239,16 @@ echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&
         cat conftest.err 1>&5
       fi
       $rm conftest*
-      echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5
-echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6; }
+      echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5
+echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6
       ;;
     esac
   fi
   ;;
 esac
 
-echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
-echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5
+echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6
 library_names_spec=
 libname_spec='lib$name'
 soname_spec=
@@ -18716,8 +17835,8 @@ uts4*)
   dynamic_linker=no
   ;;
 esac
-echo "$as_me:$LINENO: result: $dynamic_linker" >&5
-echo "${ECHO_T}$dynamic_linker" >&6; }
+echo "$as_me:$LINENO: result: $dynamic_linker" >&5
+echo "${ECHO_T}$dynamic_linker" >&6
 test "$dynamic_linker" = no && can_build_shared=no
 
 variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
@@ -18725,8 +17844,8 @@ if test "$GCC" = yes; then
   variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
 fi
 
-echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
-echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5
+echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6
 hardcode_action_GCJ=
 if test -n "$hardcode_libdir_flag_spec_GCJ" || \
    test -n "$runpath_var_GCJ" || \
@@ -18750,8 +17869,8 @@ else
   # directories.
   hardcode_action_GCJ=unsupported
 fi
-echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5
-echo "${ECHO_T}$hardcode_action_GCJ" >&6; }
+echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5
+echo "${ECHO_T}$hardcode_action_GCJ" >&6
 
 if test "$hardcode_action_GCJ" = relink; then
   # Fast installation is not supported
@@ -19187,6 +18306,7 @@ CC="$lt_save_CC"
       RC)
 
 
+
 # Source file extension for RC test sources.
 ac_ext=rc
 
@@ -19709,12 +18829,13 @@ LIBTOOL='$(SHELL) $(top_builddir)/libtool'
 
 
 
-# Check whether --with-system-libtool was given.
+# Check whether --with-system-libtool or --without-system-libtool was given.
 if test "${with_system_libtool+set}" = set; then
-  withval=$with_system_libtool;  # Extract the first word of "libtool", so it can be a program name with args.
+  withval="$with_system_libtool"
+   # Extract the first word of "libtool", so it can be a program name with args.
 set dummy libtool; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_path_LIBTOOL+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_LIBTOOL="$as_dir/$ac_word$ac_exec_ext"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
   ;;
 esac
 fi
 LIBTOOL=$ac_cv_path_LIBTOOL
+
 if test -n "$LIBTOOL"; then
-  echo "$as_me:$LINENO: result: $LIBTOOL" >&5
-echo "${ECHO_T}$LIBTOOL" >&6; }
+  echo "$as_me:$LINENO: result: $LIBTOOL" >&5
+echo "${ECHO_T}$LIBTOOL" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 else
 
   LIBTOOL="`pwd`/libtool"
@@ -19769,24 +18889,24 @@ else
 
 
 
-fi
-
+fi;
 
 
 
-# Check whether --enable-strict-dependencies was given.
+# Check whether --enable-strict-dependencies or --disable-strict-dependencies was given.
 if test "${enable_strict_dependencies+set}" = set; then
-  enableval=$enable_strict_dependencies;
-fi
+  enableval="$enable_strict_dependencies"
 
+fi;
 
 docdir='${datadir}/doc/freeradius'
-echo "$as_me:$LINENO: checking docdir" >&5
-echo $ECHO_N "checking docdir... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking docdir" >&5
+echo $ECHO_N "checking docdir... $ECHO_C" >&6
 
-# Check whether --with-docdir was given.
+# Check whether --with-docdir or --without-docdir was given.
 if test "${with_docdir+set}" = set; then
-  withval=$with_docdir;  case "$withval" in
+  withval="$with_docdir"
+   case "$withval" in
     no)
        { { echo "$as_me:$LINENO: error: Need docdir" >&5
 echo "$as_me: error: Need docdir" >&2;}
@@ -19804,19 +18924,19 @@ echo "$as_me: error: expected an absolute directory name for --with-docdir: $wit
        ;;
   esac
 
-fi
-
+fi;
 
-echo "$as_me:$LINENO: result: $docdir" >&5
-echo "${ECHO_T}$docdir" >&6; }
+echo "$as_me:$LINENO: result: $docdir" >&5
+echo "${ECHO_T}$docdir" >&6
 
 logdir='${localstatedir}/log/radius'
-echo "$as_me:$LINENO: checking logdir" >&5
-echo $ECHO_N "checking logdir... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking logdir" >&5
+echo $ECHO_N "checking logdir... $ECHO_C" >&6
 
-# Check whether --with-logdir was given.
+# Check whether --with-logdir or --without-logdir was given.
 if test "${with_logdir+set}" = set; then
-  withval=$with_logdir;  case "$withval" in
+  withval="$with_logdir"
+   case "$withval" in
     no)
        { { echo "$as_me:$LINENO: error: Need logdir" >&5
 echo "$as_me: error: Need logdir" >&2;}
@@ -19834,19 +18954,19 @@ echo "$as_me: error: expected an absolute directory name for --with-logdir: $wit
        ;;
   esac
 
-fi
-
+fi;
 
-echo "$as_me:$LINENO: result: $logdir" >&5
-echo "${ECHO_T}$logdir" >&6; }
+echo "$as_me:$LINENO: result: $logdir" >&5
+echo "${ECHO_T}$logdir" >&6
 
 radacctdir='${logdir}/radacct'
-echo "$as_me:$LINENO: checking radacctdir" >&5
-echo $ECHO_N "checking radacctdir... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking radacctdir" >&5
+echo $ECHO_N "checking radacctdir... $ECHO_C" >&6
 
-# Check whether --with-radacctdir was given.
+# Check whether --with-radacctdir or --without-radacctdir was given.
 if test "${with_radacctdir+set}" = set; then
-  withval=$with_radacctdir;  case "$withval" in
+  withval="$with_radacctdir"
+   case "$withval" in
     no)
        { { echo "$as_me:$LINENO: error: Need radacctdir" >&5
 echo "$as_me: error: Need radacctdir" >&2;}
@@ -19864,19 +18984,19 @@ echo "$as_me: error: expected an absolute directory name for --with-radacctdir:
        ;;
   esac
 
-fi
-
+fi;
 
-echo "$as_me:$LINENO: result: $radacctdir" >&5
-echo "${ECHO_T}$radacctdir" >&6; }
+echo "$as_me:$LINENO: result: $radacctdir" >&5
+echo "${ECHO_T}$radacctdir" >&6
 
 raddbdir='${sysconfdir}/raddb'
-echo "$as_me:$LINENO: checking raddbdir" >&5
-echo $ECHO_N "checking raddbdir... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking raddbdir" >&5
+echo $ECHO_N "checking raddbdir... $ECHO_C" >&6
 
-# Check whether --with-raddbdir was given.
+# Check whether --with-raddbdir or --without-raddbdir was given.
 if test "${with_raddbdir+set}" = set; then
-  withval=$with_raddbdir;  case "$withval" in
+  withval="$with_raddbdir"
+   case "$withval" in
     no)
        { { echo "$as_me:$LINENO: error: Need raddbdir" >&5
 echo "$as_me: error: Need raddbdir" >&2;}
@@ -19894,103 +19014,88 @@ echo "$as_me: error: expected an absolute directory name for --with-raddbdir: $w
        ;;
   esac
 
-fi
-
+fi;
 
-echo "$as_me:$LINENO: result: $raddbdir" >&5
-echo "${ECHO_T}$raddbdir" >&6; }
+echo "$as_me:$LINENO: result: $raddbdir" >&5
+echo "${ECHO_T}$raddbdir" >&6
 
 ASCEND_BINARY=yes
 
-# Check whether --with-ascend-binary was given.
+# Check whether --with-ascend-binary or --without-ascend-binary was given.
 if test "${with_ascend_binary+set}" = set; then
-  withval=$with_ascend_binary;  case "$withval" in
+  withval="$with_ascend_binary"
+   case "$withval" in
     yes)
        ;;
     *)
        ASCEND_BINARY=""
   esac
 
-fi
-
+fi;
 if test "X$ASCEND_BINARY" = "Xyes"; then
-  cat >>confdefs.h <<\_ACEOF
-#define ASCEND_BINARY 1
+
+cat >>confdefs.h <<\_ACEOF
+#define ASCEND_BINARY
 _ACEOF
 
 fi
 
 WITH_THREADS=yes
 
-# Check whether --with-threads was given.
+# Check whether --with-threads or --without-threads was given.
 if test "${with_threads+set}" = set; then
-  withval=$with_threads;  case "$withval" in
+  withval="$with_threads"
+   case "$withval" in
     yes)
        ;;
     *)
        WITH_THREADS=""
   esac
 
-fi
-
+fi;
 
 WITH_SNMP=yes
 
-# Check whether --with-snmp was given.
+# Check whether --with-snmp or --without-snmp was given.
 if test "${with_snmp+set}" = set; then
-  withval=$with_snmp;  case "$withval" in
+  withval="$with_snmp"
+   case "$withval" in
     yes)
         ;;
     *)
        WITH_SNMP=no
   esac
 
-fi
-
-
-rad_enable_largefiles=no
-
-# Check whether --with-large-files was given.
-if test "${with_large_files+set}" = set; then
-  withval=$with_large_files;  case "$withval" in
-    yes)
-        rad_enable_largefiles=yes
-       ;;
-    *)
-       ;;
-  esac
-
-fi
-
-
+fi;
 
 STATIC_MODULES=
 
-# Check whether --with-static_modules was given.
+# Check whether --with-static_modules or --without-static_modules was given.
 if test "${with_static_modules+set}" = set; then
-  withval=$with_static_modules;
+  withval="$with_static_modules"
+
   for i in $withval; do
     STATIC_MODULES="$STATIC_MODULES -dlpreopen ../modules/rlm_$i/rlm_$i.la"
   done
 
-fi
-
+fi;
 
 MODULES=
 
-# Check whether --with-modules was given.
+# Check whether --with-modules or --without-modules was given.
 if test "${with_modules+set}" = set; then
-  withval=$with_modules;
+  withval="$with_modules"
+
  for i in $withval; do
    MODULES="$MODULES $i"
  done
 
-fi
-
+fi;
 
-# Check whether --enable-developer was given.
+# Check whether --enable-developer or --disable-developer was given.
 if test "${enable_developer+set}" = set; then
-  enableval=$enable_developer;  case "$enableval" in
+  enableval="$enable_developer"
+   case "$enableval" in
     no)
        developer=no
        ;;
@@ -19998,8 +19103,7 @@ if test "${enable_developer+set}" = set; then
        developer=yes
   esac
 
-fi
-
+fi;
 
 if test "x$developer" != "xno" -a -d $srcdir/CVS; then
     developer="yes"
 
 EXPERIMENTAL=
 
-# Check whether --with-experimental-modules was given.
+# Check whether --with-experimental-modules or --without-experimental-modules was given.
 if test "${with_experimental_modules+set}" = set; then
-  withval=$with_experimental_modules;  case "$withval" in
+  withval="$with_experimental_modules"
+   case "$withval" in
     yes)
        EXPERIMENTAL=yes
        ;;
     *)
   esac
 
-fi
-
+fi;
 
 OPENSSL_INCLUDE_DIR=
 
-# Check whether --with-openssl-includes was given.
+# Check whether --with-openssl-includes or --without-openssl-includes was given.
 if test "${with_openssl_includes+set}" = set; then
-  withval=$with_openssl_includes;  case "$withval" in
+  withval="$with_openssl_includes"
+   case "$withval" in
     *) OPENSSL_INCLUDE_DIR="$withval"
        ;;
   esac
 
-fi
-
+fi;
 
 OPENSSL_LIB_DIR=
 
-# Check whether --with-openssl-libraries was given.
+# Check whether --with-openssl-libraries or --without-openssl-libraries was given.
 if test "${with_openssl_libraries+set}" = set; then
-  withval=$with_openssl_libraries;  case "$withval" in
+  withval="$with_openssl_libraries"
+   case "$withval" in
     *) OPENSSL_LIB_DIR="$withval"
        ;;
   esac
 
-fi
-
+fi;
 
 
 
-# Check whether --with-rlm-FOO-lib-dir was given.
+# Check whether --with-rlm-FOO-lib-dir or --without-rlm-FOO-lib-dir was given.
 if test "${with_rlm_FOO_lib_dir+set}" = set; then
-  withval=$with_rlm_FOO_lib_dir;  case "$withval" in
+  withval="$with_rlm_FOO_lib_dir"
+   case "$withval" in
     *)
        ;;
   esac
 
-fi
-
+fi;
 
 
-# Check whether --with-rlm-FOO-include-dir was given.
+# Check whether --with-rlm-FOO-include-dir or --without-rlm-FOO-include-dir was given.
 if test "${with_rlm_FOO_include_dir+set}" = set; then
-  withval=$with_rlm_FOO_include_dir;  case "$withval" in
+  withval="$with_rlm_FOO_include_dir"
+   case "$withval" in
     *)
        ;;
   esac
 
-fi
-
+fi;
 
 
 WITH_UDPFROMTO=no
 
-# Check whether --with-udpfromto was given.
+# Check whether --with-udpfromto or --without-udpfromto was given.
 if test "${with_udpfromto+set}" = set; then
-  withval=$with_udpfromto;  case "$withval" in
+  withval="$with_udpfromto"
+   case "$withval" in
     yes)
        WITH_UDPFROMTO=yes
         ;;
     *)
        WITH_UDPFROMTO=no
-  esac
-
-fi
+  esac
 
+fi;
 
 if test "x$WITH_UDPFROMTO" = "xyes"; then
-       cat >>confdefs.h <<\_ACEOF
-#define WITH_UDPFROMTO 1
-_ACEOF
-
-fi
 
+cat >>confdefs.h <<\_ACEOF
+#define WITH_UDPFROMTO
+_ACEOF
 
-# Check whether --with-edir was given.
-if test "${with_edir+set}" = set; then
-  withval=$with_edir;
 fi
 
 
-
 CHECKRAD=checkrad.pl
 # Extract the first word of "perl", so it can be a program name with args.
 set dummy perl; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_path_PERL+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
   test -z "$ac_cv_path_PERL" && ac_cv_path_PERL="/usr/local/bin/perl"
   ;;
 esac
 fi
 PERL=$ac_cv_path_PERL
+
 if test -n "$PERL"; then
-  echo "$as_me:$LINENO: result: $PERL" >&5
-echo "${ECHO_T}$PERL" >&6; }
+  echo "$as_me:$LINENO: result: $PERL" >&5
+echo "${ECHO_T}$PERL" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 if test "x$ac_cv_path_PERL" = "x"; then
   { echo "$as_me:$LINENO: WARNING: perl not found - Simultaneous-Use and checkrad.pl may not work" >&5
 echo "$as_me: WARNING: perl not found - Simultaneous-Use and checkrad.pl may not work" >&2;}
 fi
 # Extract the first word of "snmpget", so it can be a program name with args.
 set dummy snmpget; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_path_SNMPGET+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_SNMPGET="$as_dir/$ac_word$ac_exec_ext"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
   ;;
 esac
 fi
 SNMPGET=$ac_cv_path_SNMPGET
+
 if test -n "$SNMPGET"; then
-  echo "$as_me:$LINENO: result: $SNMPGET" >&5
-echo "${ECHO_T}$SNMPGET" >&6; }
+  echo "$as_me:$LINENO: result: $SNMPGET" >&5
+echo "${ECHO_T}$SNMPGET" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 if test "x$ac_cv_path_SNMPGET" = "x"; then
   { echo "$as_me:$LINENO: WARNING: snmpget not found - Simultaneous-Use and checkrad.pl may not work" >&5
 echo "$as_me: WARNING: snmpget not found - Simultaneous-Use and checkrad.pl may not work" >&2;}
@@ -20190,8 +19286,8 @@ fi
 
 # Extract the first word of "snmpwalk", so it can be a program name with args.
 set dummy snmpwalk; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_path_SNMPWALK+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_SNMPWALK="$as_dir/$ac_word$ac_exec_ext"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
   ;;
 esac
 fi
 SNMPWALK=$ac_cv_path_SNMPWALK
+
 if test -n "$SNMPWALK"; then
-  echo "$as_me:$LINENO: result: $SNMPWALK" >&5
-echo "${ECHO_T}$SNMPWALK" >&6; }
+  echo "$as_me:$LINENO: result: $SNMPWALK" >&5
+echo "${ECHO_T}$SNMPWALK" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 if test "x$ac_cv_path_SNMPWALK" = "x"; then
   { echo "$as_me:$LINENO: WARNING: snmpwalk not found - Simultaneous-Use and checkrad.pl may not work" >&5
 echo "$as_me: WARNING: snmpwalk not found - Simultaneous-Use and checkrad.pl may not work" >&2;}
@@ -20235,8 +19330,8 @@ fi
 
 # Extract the first word of "rusers", so it can be a program name with args.
 set dummy rusers; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_path_RUSERS+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_RUSERS="$as_dir/$ac_word$ac_exec_ext"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
   test -z "$ac_cv_path_RUSERS" && ac_cv_path_RUSERS="/usr/bin/rusers"
   ;;
 esac
 fi
 RUSERS=$ac_cv_path_RUSERS
+
 if test -n "$RUSERS"; then
-  echo "$as_me:$LINENO: result: $RUSERS" >&5
-echo "${ECHO_T}$RUSERS" >&6; }
+  echo "$as_me:$LINENO: result: $RUSERS" >&5
+echo "${ECHO_T}$RUSERS" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
 
-
 missing_dir=`cd $ac_aux_dir && pwd`
-{ echo "$as_me:$LINENO: checking for working aclocal" >&5
-echo $ECHO_N "checking for working aclocal... $ECHO_C" >&6; }
-# Run test in a subshell; some versions of sh will print an error if
-# an executable is not found, even if stderr is redirected.
-# Redirect stdin to placate older versions of autoconf.  Sigh.
-if (aclocal --version) < /dev/null > /dev/null 2>&1; then
-   ACLOCAL=aclocal
-   { echo "$as_me:$LINENO: result: found" >&5
-echo "${ECHO_T}found" >&6; }
-else
-   ACLOCAL="$missing_dir/missing aclocal"
-   { echo "$as_me:$LINENO: result: missing" >&5
-echo "${ECHO_T}missing" >&6; }
-fi
-
-{ echo "$as_me:$LINENO: checking for working autoconf" >&5
-echo $ECHO_N "checking for working autoconf... $ECHO_C" >&6; }
-# Run test in a subshell; some versions of sh will print an error if
-# an executable is not found, even if stderr is redirected.
-# Redirect stdin to placate older versions of autoconf.  Sigh.
-if (autoconf --version) < /dev/null > /dev/null 2>&1; then
-   AUTOCONF=autoconf
-   { echo "$as_me:$LINENO: result: found" >&5
-echo "${ECHO_T}found" >&6; }
-else
-   AUTOCONF="$missing_dir/missing autoconf"
-   { echo "$as_me:$LINENO: result: missing" >&5
-echo "${ECHO_T}missing" >&6; }
-fi
-
-{ echo "$as_me:$LINENO: checking for working autoheader" >&5
-echo $ECHO_N "checking for working autoheader... $ECHO_C" >&6; }
-# Run test in a subshell; some versions of sh will print an error if
-# an executable is not found, even if stderr is redirected.
-# Redirect stdin to placate older versions of autoconf.  Sigh.
-if (autoheader --version) < /dev/null > /dev/null 2>&1; then
-   AUTOHEADER=autoheader
-   { echo "$as_me:$LINENO: result: found" >&5
-echo "${ECHO_T}found" >&6; }
-else
-   AUTOHEADER="$missing_dir/missing autoheader"
-   { echo "$as_me:$LINENO: result: missing" >&5
-echo "${ECHO_T}missing" >&6; }
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
 fi
 
 
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
 # Extract the first word of "locate", so it can be a program name with args.
 set dummy locate; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_path_LOCATE+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_LOCATE="$as_dir/$ac_word$ac_exec_ext"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
   ;;
 esac
 fi
 LOCATE=$ac_cv_path_LOCATE
+
 if test -n "$LOCATE"; then
-  echo "$as_me:$LINENO: result: $LOCATE" >&5
-echo "${ECHO_T}$LOCATE" >&6; }
+  echo "$as_me:$LINENO: result: $LOCATE" >&5
+echo "${ECHO_T}$LOCATE" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 # Extract the first word of "dirname", so it can be a program name with args.
 set dummy dirname; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_path_DIRNAME+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_DIRNAME="$as_dir/$ac_word$ac_exec_ext"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
   ;;
 esac
 fi
 DIRNAME=$ac_cv_path_DIRNAME
+
 if test -n "$DIRNAME"; then
-  echo "$as_me:$LINENO: result: $DIRNAME" >&5
-echo "${ECHO_T}$DIRNAME" >&6; }
+  echo "$as_me:$LINENO: result: $DIRNAME" >&5
+echo "${ECHO_T}$DIRNAME" >&6
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
-
 # Extract the first word of "grep", so it can be a program name with args.
 set dummy grep; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
 if test "${ac_cv_path_GREP+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_GREP="$as_dir/$ac_word$ac_exec_ext"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
-IFS=$as_save_IFS
 
-  ;;
-esac
+  ;;
+esac
+fi
+GREP=$ac_cv_path_GREP
+
+if test -n "$GREP"; then
+  echo "$as_me:$LINENO: result: $GREP" >&5
+echo "${ECHO_T}$GREP" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+
+
+old_CFLAGS=$CFLAGS
+if test "x$WITH_THREADS" = "xyes"; then
+  if test $ac_cv_prog_suncc = "yes"; then
+    CFLAGS="$CFLAGS -mt"
+  fi
+
+
+for ac_header in pthread.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+   WITH_THREADS="no"
+fi
+
+done
+
+
+  echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5
+echo $ECHO_N "checking for pthread_create in -lpthread... $ECHO_C" >&6
+if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char pthread_create ();
+int
+main ()
+{
+pthread_create ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_pthread_pthread_create=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_pthread_pthread_create=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5
+echo "${ECHO_T}$ac_cv_lib_pthread_pthread_create" >&6
+if test $ac_cv_lib_pthread_pthread_create = yes; then
+   CFLAGS="$CFLAGS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS"
+                  LIBS="$LIBS -lpthread"
+else
+  echo "$as_me:$LINENO: checking for pthread_create in -lc_r" >&5
+echo $ECHO_N "checking for pthread_create in -lc_r... $ECHO_C" >&6
+if test "${ac_cv_lib_c_r_pthread_create+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc_r  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char pthread_create ();
+int
+main ()
+{
+pthread_create ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_c_r_pthread_create=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_c_r_pthread_create=no
 fi
-GREP=$ac_cv_path_GREP
-if test -n "$GREP"; then
-  { echo "$as_me:$LINENO: result: $GREP" >&5
-echo "${ECHO_T}$GREP" >&6; }
-else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
 fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_c_r_pthread_create" >&5
+echo "${ECHO_T}$ac_cv_lib_c_r_pthread_create" >&6
+if test $ac_cv_lib_c_r_pthread_create = yes; then
+   CFLAGS="$CFLAGS -pthread -D_THREAD_SAFE"
+else
+   WITH_THREADS="no"
 
+fi
 
 
+fi
 
-old_CFLAGS=$CFLAGS
-if test "x$WITH_THREADS" = "xyes"; then
-  if test $ac_cv_prog_suncc = "yes"; then
-    CFLAGS="$CFLAGS -mt"
-  fi
+fi
 
+if test "x$WITH_THREADS" != "xyes"; then
+  CFLAGS=$old_CFLAGS
+  ac_cv_header_pthread_h="no"
+  WITH_THREADS=no
+else
 
-for ac_header in pthread.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo "$as_me:$LINENO: checking for library containing sem_init" >&5
+echo $ECHO_N "checking for library containing sem_init... $ECHO_C" >&6
+if test "${ac_cv_search_sem_init+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-              { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
 else
-  # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_sem_init=no
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
-#include <$ac_header>
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char sem_init ();
+int
+main ()
+{
+sem_init ();
+  ;
+  return 0;
+}
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_header_compiler=yes
+  ac_cv_search_sem_init="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_sem_init" = no; then
+  for ac_lib in pthread sem posix4 rt semaphore; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char sem_init ();
+int
+main ()
+{
+sem_init ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_sem_init="-l$ac_lib"
+break
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_header_compiler=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  done
+fi
+LIBS=$ac_func_search_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_search_sem_init" >&5
+echo "${ECHO_T}$ac_cv_search_sem_init" >&6
+if test "$ac_cv_search_sem_init" != no; then
+  test "$ac_cv_search_sem_init" = "none required" || LIBS="$ac_cv_search_sem_init $LIBS"
+
+else
+  { { echo "$as_me:$LINENO: error: -lsem not found.  You may want to download it from ftp://ftp.to.gd-es.com/pub/BSDI/libsem.tar.bz2 or ftp://ftp.freeradius.org/pub/radius/contrib/libsem.tar.gz" >&5
+echo "$as_me: error: -lsem not found.  You may want to download it from ftp://ftp.to.gd-es.com/pub/BSDI/libsem.tar.bz2 or ftp://ftp.freeradius.org/pub/radius/contrib/libsem.tar.gz" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+
 fi
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
 
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for getsockname in -lsocket" >&5
+echo $ECHO_N "checking for getsockname in -lsocket... $ECHO_C" >&6
+if test "${ac_cv_lib_socket_getsockname+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <$ac_header>
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char getsockname ();
+int
+main ()
+{
+getsockname ();
+  ;
+  return 0;
+}
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  ac_header_preproc=yes
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_socket_getsockname=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-  ac_header_preproc=no
+ac_cv_lib_socket_getsockname=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
 fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_socket_getsockname" >&5
+echo "${ECHO_T}$ac_cv_lib_socket_getsockname" >&6
+if test $ac_cv_lib_socket_getsockname = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSOCKET 1
+_ACEOF
 
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
+  LIBS="-lsocket $LIBS"
 
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
-  yes:no: )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
-    ac_header_preproc=yes
-    ;;
-  no:yes:* )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+fi
 
-    ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+
+
+echo "$as_me:$LINENO: checking for inet_aton in -lresolv" >&5
+echo $ECHO_N "checking for inet_aton in -lresolv... $ECHO_C" >&6
+if test "${ac_cv_lib_resolv_inet_aton+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  eval "$as_ac_Header=\$ac_header_preproc"
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-              { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lresolv  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char inet_aton ();
+int
+main ()
+{
+inet_aton ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_resolv_inet_aton=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
+ac_cv_lib_resolv_inet_aton=no
 fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_resolv_inet_aton" >&5
+echo "${ECHO_T}$ac_cv_lib_resolv_inet_aton" >&6
+if test $ac_cv_lib_resolv_inet_aton = yes; then
   cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+#define HAVE_LIBRESOLV 1
 _ACEOF
 
-else
-   WITH_THREADS="no"
+  LIBS="-lresolv $LIBS"
+
 fi
 
-done
 
 
-  { echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5
-echo $ECHO_N "checking for pthread_create in -lpthread... $ECHO_C" >&6; }
-if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then
+echo "$as_me:$LINENO: checking for inet_ntoa in -lnsl" >&5
+echo $ECHO_N "checking for inet_ntoa in -lnsl... $ECHO_C" >&6
+if test "${ac_cv_lib_nsl_inet_ntoa+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpthread  $LIBS"
+LIBS="-lnsl  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -20631,80 +20119,78 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
-char pthread_create ();
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char inet_ntoa ();
 int
 main ()
 {
-return pthread_create ();
+inet_ntoa ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_pthread_pthread_create=yes
+  ac_cv_lib_nsl_inet_ntoa=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_pthread_pthread_create=no
+ac_cv_lib_nsl_inet_ntoa=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5
-echo "${ECHO_T}$ac_cv_lib_pthread_pthread_create" >&6; }
-if test $ac_cv_lib_pthread_pthread_create = yes; then
-   CFLAGS="$CFLAGS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS"
-                  LIBS="$LIBS -lpthread"
-else
-  { echo "$as_me:$LINENO: checking for pthread_create in -lc_r" >&5
-echo $ECHO_N "checking for pthread_create in -lc_r... $ECHO_C" >&6; }
-if test "${ac_cv_lib_c_r_pthread_create+set}" = set; then
+echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_inet_ntoa" >&5
+echo "${ECHO_T}$ac_cv_lib_nsl_inet_ntoa" >&6
+if test $ac_cv_lib_nsl_inet_ntoa = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBNSL 1
+_ACEOF
+
+  LIBS="-lnsl $LIBS"
+
+fi
+
+
+OPENSSL_LIBS=
+old_LIBS=$LIBS
+if test "x$OPENSSL_LIB_DIR" != "x"; then
+    LIBS="-L$OPENSSL_LIB_DIR $LIBS"
+fi
+echo "$as_me:$LINENO: checking for DH_new in -lcrypto" >&5
+echo $ECHO_N "checking for DH_new in -lcrypto... $ECHO_C" >&6
+if test "${ac_cv_lib_crypto_DH_new+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lc_r  $LIBS"
+LIBS="-lcrypto  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -20712,93 +20198,70 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
-char pthread_create ();
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char DH_new ();
 int
 main ()
 {
-return pthread_create ();
+DH_new ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_c_r_pthread_create=yes
+  ac_cv_lib_crypto_DH_new=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_c_r_pthread_create=no
+ac_cv_lib_crypto_DH_new=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_c_r_pthread_create" >&5
-echo "${ECHO_T}$ac_cv_lib_c_r_pthread_create" >&6; }
-if test $ac_cv_lib_c_r_pthread_create = yes; then
-   CFLAGS="$CFLAGS -pthread -D_THREAD_SAFE"
-else
-   WITH_THREADS="no"
-
-fi
-
-
-fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_crypto_DH_new" >&5
+echo "${ECHO_T}$ac_cv_lib_crypto_DH_new" >&6
+if test $ac_cv_lib_crypto_DH_new = yes; then
 
-fi
 
-if test "x$WITH_THREADS" != "xyes"; then
-  CFLAGS=$old_CFLAGS
-  ac_cv_header_pthread_h="no"
-  WITH_THREADS=no
-else
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBCRYPTO 1
+_ACEOF
 
-  { echo "$as_me:$LINENO: checking for library containing sem_init" >&5
-echo $ECHO_N "checking for library containing sem_init... $ECHO_C" >&6; }
-if test "${ac_cv_search_sem_init+set}" = set; then
+       echo "$as_me:$LINENO: checking for SSL_new in -lssl" >&5
+echo $ECHO_N "checking for SSL_new in -lssl... $ECHO_C" >&6
+if test "${ac_cv_lib_ssl_SSL_new+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_func_search_save_LIBS=$LIBS
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lssl  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -20806,107 +20269,83 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
-char sem_init ();
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char SSL_new ();
 int
 main ()
 {
-return sem_init ();
+SSL_new ();
   ;
   return 0;
 }
 _ACEOF
-for ac_lib in '' pthread sem posix4 rt; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_search_sem_init=$ac_res
+  ac_cv_lib_ssl_SSL_new=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext \
-      conftest$ac_exeext
-  if test "${ac_cv_search_sem_init+set}" = set; then
-  break
-fi
-done
-if test "${ac_cv_search_sem_init+set}" = set; then
-  :
-else
-  ac_cv_search_sem_init=no
+ac_cv_lib_ssl_SSL_new=no
 fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_sem_init" >&5
-echo "${ECHO_T}$ac_cv_search_sem_init" >&6; }
-ac_res=$ac_cv_search_sem_init
-if test "$ac_res" != no; then
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+echo "$as_me:$LINENO: result: $ac_cv_lib_ssl_SSL_new" >&5
+echo "${ECHO_T}$ac_cv_lib_ssl_SSL_new" >&6
+if test $ac_cv_lib_ssl_SSL_new = yes; then
 
-else
-  { { echo "$as_me:$LINENO: error: -lsem not found.  You may want to download it from ftp://ftp.to.gd-es.com/pub/BSDI/libsem.tar.bz2 or ftp://ftp.freeradius.org/pub/radius/contrib/libsem.tar.gz" >&5
-echo "$as_me: error: -lsem not found.  You may want to download it from ftp://ftp.to.gd-es.com/pub/BSDI/libsem.tar.bz2 or ftp://ftp.freeradius.org/pub/radius/contrib/libsem.tar.gz" >&2;}
-   { (exit 1); exit 1; }; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBSSL 1
+_ACEOF
+
+               if test "x$OPENSSL_LIB_DIR" != "x"; then
+                   OPENSSL_LIBS="-L$OPENSSL_LIB_DIR"
+               fi
+               OPENSSL_LIBS="$OPENSSL_LIBS -lcrypto -lssl -lcrypto"
 
 fi
 
+
 fi
 
+LIBS=$old_LIBS
 
-{ echo "$as_me:$LINENO: checking for getsockname in -lsocket" >&5
-echo $ECHO_N "checking for getsockname in -lsocket... $ECHO_C" >&6; }
-if test "${ac_cv_lib_socket_getsockname+set}" = set; then
+PCAP_LIBS=
+echo "$as_me:$LINENO: checking for pcap_open_live in -lpcap" >&5
+echo $ECHO_N "checking for pcap_open_live in -lpcap... $ECHO_C" >&6
+if test "${ac_cv_lib_pcap_pcap_open_live+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lsocket  $LIBS"
+LIBS="-lpcap  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -20914,175 +20353,162 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
-char getsockname ();
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char pcap_open_live ();
 int
 main ()
 {
-return getsockname ();
+pcap_open_live ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_socket_getsockname=yes
+  ac_cv_lib_pcap_pcap_open_live=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_socket_getsockname=no
+ac_cv_lib_pcap_pcap_open_live=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_socket_getsockname" >&5
-echo "${ECHO_T}$ac_cv_lib_socket_getsockname" >&6; }
-if test $ac_cv_lib_socket_getsockname = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBSOCKET 1
+echo "$as_me:$LINENO: result: $ac_cv_lib_pcap_pcap_open_live" >&5
+echo "${ECHO_T}$ac_cv_lib_pcap_pcap_open_live" >&6
+if test $ac_cv_lib_pcap_pcap_open_live = yes; then
+   PCAP_LIBS="-lpcap"
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBPCAP 1
 _ACEOF
 
-  LIBS="-lsocket $LIBS"
 
+else
+   { echo "$as_me:$LINENO: WARNING: pcap library not found, silently disabling the RADIUS sniffer." >&5
+echo "$as_me: WARNING: pcap library not found, silently disabling the RADIUS sniffer." >&2;}
 fi
 
 
 
-{ echo "$as_me:$LINENO: checking for inet_aton in -lresolv" >&5
-echo $ECHO_N "checking for inet_aton in -lresolv... $ECHO_C" >&6; }
-if test "${ac_cv_lib_resolv_inet_aton+set}" = set; then
+case "$host" in
+*-interix*)
+       CFLAGS="$CFLAGS -D_ALL_SOURCE"
+       ;;
+*-darwin*)
+       CFLAGS="$CFLAGS -DDARWIN"
+       ;;
+esac
+
+
+
+
+
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
+  as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
+echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lresolv  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
+#include <sys/types.h>
+#include <$ac_hdr>
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char inet_aton ();
 int
 main ()
 {
-return inet_aton ();
+if ((DIR *) 0)
+return 0;
   ;
   return 0;
 }
 _ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
-        { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_resolv_inet_aton=yes
+  eval "$as_ac_Header=yes"
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_resolv_inet_aton=no
+eval "$as_ac_Header=no"
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_resolv_inet_aton" >&5
-echo "${ECHO_T}$ac_cv_lib_resolv_inet_aton" >&6; }
-if test $ac_cv_lib_resolv_inet_aton = yes; then
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
   cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBRESOLV 1
+#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
 _ACEOF
 
-  LIBS="-lresolv $LIBS"
-
+ac_header_dirent=$ac_hdr; break
 fi
 
-
-
-{ echo "$as_me:$LINENO: checking for inet_ntoa in -lnsl" >&5
-echo $ECHO_N "checking for inet_ntoa in -lnsl... $ECHO_C" >&6; }
-if test "${ac_cv_lib_nsl_inet_ntoa+set}" = set; then
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lnsl  $LIBS"
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -21090,91 +20516,126 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
+int
+main ()
+{
+opendir ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_search_opendir="none required"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in dir; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
-char inet_ntoa ();
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
 int
 main ()
 {
-return inet_ntoa ();
+opendir ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_nsl_inet_ntoa=yes
+  ac_cv_search_opendir="-l$ac_lib"
+break
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_nsl_inet_ntoa=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+  done
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_inet_ntoa" >&5
-echo "${ECHO_T}$ac_cv_lib_nsl_inet_ntoa" >&6; }
-if test $ac_cv_lib_nsl_inet_ntoa = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBNSL 1
-_ACEOF
-
-  LIBS="-lnsl $LIBS"
-
+LIBS=$ac_func_search_save_LIBS
 fi
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
 
-
-OPENSSL_LIBS=
-old_LIBS=$LIBS
-if test "x$OPENSSL_LIB_DIR" != "x"; then
-    LIBS="-L$OPENSSL_LIB_DIR $LIBS"
 fi
-{ echo "$as_me:$LINENO: checking for DH_new in -lcrypto" >&5
-echo $ECHO_N "checking for DH_new in -lcrypto... $ECHO_C" >&6; }
-if test "${ac_cv_lib_crypto_DH_new+set}" = set; then
+
+else
+  echo "$as_me:$LINENO: checking for library containing opendir" >&5
+echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6
+if test "${ac_cv_search_opendir+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcrypto  $LIBS"
+  ac_func_search_save_LIBS=$LIBS
+ac_cv_search_opendir=no
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -21182,193 +20643,123 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
-char DH_new ();
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
 int
 main ()
 {
-return DH_new ();
+opendir ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_crypto_DH_new=yes
+  ac_cv_search_opendir="none required"
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_crypto_DH_new=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_crypto_DH_new" >&5
-echo "${ECHO_T}$ac_cv_lib_crypto_DH_new" >&6; }
-if test $ac_cv_lib_crypto_DH_new = yes; then
-
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_LIBCRYPTO 1
-_ACEOF
-
-       { echo "$as_me:$LINENO: checking for SSL_new in -lssl" >&5
-echo $ECHO_N "checking for SSL_new in -lssl... $ECHO_C" >&6; }
-if test "${ac_cv_lib_ssl_SSL_new+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lssl  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
+if test "$ac_cv_search_opendir" = no; then
+  for ac_lib in x; do
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+    cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
-char SSL_new ();
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char opendir ();
 int
 main ()
 {
-return SSL_new ();
+opendir ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_ssl_SSL_new=yes
+  ac_cv_search_opendir="-l$ac_lib"
+break
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_ssl_SSL_new=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+  done
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_ssl_SSL_new" >&5
-echo "${ECHO_T}$ac_cv_lib_ssl_SSL_new" >&6; }
-if test $ac_cv_lib_ssl_SSL_new = yes; then
-
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_LIBSSL 1
-_ACEOF
-
-               if test "x$OPENSSL_LIB_DIR" != "x"; then
-                   OPENSSL_LIBS="-L$OPENSSL_LIB_DIR"
-               fi
-               OPENSSL_LIBS="$OPENSSL_LIBS -lcrypto -lssl -lcrypto"
-
+LIBS=$ac_func_search_save_LIBS
 fi
-
+echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
+echo "${ECHO_T}$ac_cv_search_opendir" >&6
+if test "$ac_cv_search_opendir" != no; then
+  test "$ac_cv_search_opendir" = "none required" || LIBS="$ac_cv_search_opendir $LIBS"
 
 fi
 
-LIBS=$old_LIBS
-
-
-case "$host" in
-*-interix*)
-       CFLAGS="$CFLAGS -D_ALL_SOURCE"
-       ;;
-*-darwin*)
-       CFLAGS="$CFLAGS -DDARWIN"
-       ;;
-esac
-
-
-
-
-
+fi
 
-ac_header_dirent=no
-for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do
-  as_ac_Header=`echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh`
-{ echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5
-echo $ECHO_N "checking for $ac_hdr that defines DIR... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
@@ -21377,280 +20768,229 @@ _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <sys/types.h>
-#include <$ac_hdr>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
 
 int
 main ()
 {
-if ((DIR *) 0)
-return 0;
+
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  eval "$as_ac_Header=yes"
+  ac_cv_header_stdc=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       eval "$as_ac_Header=no"
+ac_cv_header_stdc=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
 fi
+rm -f conftest*
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-              { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_hdr" | $as_tr_cpp` 1
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
 _ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
 
-ac_header_dirent=$ac_hdr; break
 fi
 
-done
-# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
-if test $ac_header_dirent = dirent.h; then
-  { echo "$as_me:$LINENO: checking for library containing opendir" >&5
-echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; }
-if test "${ac_cv_search_opendir+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
 else
-  ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
 #endif
-char opendir ();
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
 int
 main ()
 {
-return opendir ();
-  ;
-  return 0;
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      exit(2);
+  exit (0);
 }
 _ACEOF
-for ac_lib in '' dir; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_search_opendir=$ac_res
+  :
 else
-  echo "$as_me: failed program was:" >&5
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
+( exit $ac_status )
+ac_cv_header_stdc=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
-      conftest$ac_exeext
-  if test "${ac_cv_search_opendir+set}" = set; then
-  break
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
-done
-if test "${ac_cv_search_opendir+set}" = set; then
-  :
-else
-  ac_cv_search_opendir=no
 fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
-echo "${ECHO_T}$ac_cv_search_opendir" >&6; }
-ac_res=$ac_cv_search_opendir
-if test "$ac_res" != no; then
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
 
 fi
 
-else
-  { echo "$as_me:$LINENO: checking for library containing opendir" >&5
-echo $ECHO_N "checking for library containing opendir... $ECHO_C" >&6; }
-if test "${ac_cv_search_opendir+set}" = set; then
+echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
+echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6
+if test "${ac_cv_header_time+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_func_search_save_LIBS=$LIBS
-cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char opendir ();
 int
 main ()
 {
-return opendir ();
+if ((struct tm *) 0)
+return 0;
   ;
   return 0;
 }
 _ACEOF
-for ac_lib in '' x; do
-  if test -z "$ac_lib"; then
-    ac_res="none required"
-  else
-    ac_res=-l$ac_lib
-    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
-  fi
-  rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
-        { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_search_opendir=$ac_res
+  ac_cv_header_time=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
-fi
-
-rm -f core conftest.err conftest.$ac_objext \
-      conftest$ac_exeext
-  if test "${ac_cv_search_opendir+set}" = set; then
-  break
-fi
-done
-if test "${ac_cv_search_opendir+set}" = set; then
-  :
-else
-  ac_cv_search_opendir=no
+ac_cv_header_time=no
 fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5
-echo "${ECHO_T}$ac_cv_search_opendir" >&6; }
-ac_res=$ac_cv_search_opendir
-if test "$ac_res" != no; then
-  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
+echo "${ECHO_T}$ac_cv_header_time" >&6
+if test $ac_cv_header_time = yes; then
 
-fi
+cat >>confdefs.h <<\_ACEOF
+#define TIME_WITH_SYS_TIME 1
+_ACEOF
 
 fi
 
-{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
-echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
-if test "${ac_cv_header_stdc+set}" = set; then
+echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5
+echo $ECHO_N "checking for sys/wait.h that is POSIX.1 compatible... $ECHO_C" >&6
+if test "${ac_cv_header_sys_wait_h+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
@@ -21659,426 +20999,503 @@ _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
 
 int
 main ()
 {
-
+  int s;
+  wait (&s);
+  s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_header_stdc=yes
+  ac_cv_header_sys_wait_h=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_header_stdc=no
+ac_cv_header_sys_wait_h=no
 fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5
+echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6
+if test $ac_cv_header_sys_wait_h = yes; then
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
-  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SYS_WAIT_H 1
 _ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <string.h>
 
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "memchr" >/dev/null 2>&1; then
-  :
-else
-  ac_cv_header_stdc=no
 fi
-rm -f conftest*
 
-fi
 
-if test $ac_cv_header_stdc = yes; then
-  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
-  cat >conftest.$ac_ext <<_ACEOF
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_header in \
+       unistd.h \
+       crypt.h \
+       errno.h \
+       resource.h \
+       getopt.h \
+       malloc.h \
+       utmp.h \
+       utmpx.h \
+       signal.h \
+       sys/select.h \
+       syslog.h \
+       inttypes.h \
+       stdint.h \
+       stdio.h \
+       netdb.h \
+       semaphore.h \
+       arpa/inet.h \
+       netinet/in.h \
+       sys/types.h \
+       sys/socket.h \
+       sys/time.h \
+       sys/wait.h \
+       sys/security.h \
+       fcntl.h \
+       sys/fcntl.h \
+       net/if.h \
+       prot.h \
+       sia.h \
+       siad.h
+
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+else
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <stdlib.h>
-
+$ac_includes_default
+#include <$ac_header>
 _ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "free" >/dev/null 2>&1; then
-  :
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_header_compiler=yes
 else
-  ac_cv_header_stdc=no
-fi
-rm -f conftest*
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
+ac_header_compiler=no
 fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
 
-if test $ac_cv_header_stdc = yes; then
-  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
-  if test "$cross_compiling" = yes; then
-  :
-else
-  cat >conftest.$ac_ext <<_ACEOF
+# Is the header present?
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
-                  (('a' <= (c) && (c) <= 'i') \
-                    || ('j' <= (c) && (c) <= 'r') \
-                    || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
-  int i;
-  for (i = 0; i < 256; i++)
-    if (XOR (islower (i), ISLOWER (i))
-       || toupper (i) != TOUPPER (i))
-      return 2;
-  return 0;
-}
+#include <$ac_header>
 _ACEOF
-rm -f conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  :
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
 else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-( exit $ac_status )
-ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+  ac_header_preproc=no
 fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
 
-
-fi
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
-echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
 
-cat >>confdefs.h <<\_ACEOF
-#define STDC_HEADERS 1
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
 _ACEOF
 
 fi
 
-{ echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5
-echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6; }
-if test "${ac_cv_header_time+set}" = set; then
+done
+
+
+REGEX=no
+if test "${ac_cv_header_regex_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for regex.h" >&5
+echo $ECHO_N "checking for regex.h... $ECHO_C" >&6
+if test "${ac_cv_header_regex_h+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_regex_h" >&5
+echo "${ECHO_T}$ac_cv_header_regex_h" >&6
 else
-  cat >conftest.$ac_ext <<_ACEOF
+  # Is the header compilable?
+echo "$as_me:$LINENO: checking regex.h usability" >&5
+echo $ECHO_N "checking regex.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <sys/types.h>
-#include <sys/time.h>
-#include <time.h>
-
-int
-main ()
-{
-if ((struct tm *) 0)
-return 0;
-  ;
-  return 0;
-}
+$ac_includes_default
+#include <regex.h>
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_header_time=yes
+  ac_header_compiler=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_header_time=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5
-echo "${ECHO_T}$ac_cv_header_time" >&6; }
-if test $ac_cv_header_time = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define TIME_WITH_SYS_TIME 1
-_ACEOF
-
+ac_header_compiler=no
 fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
 
-{ echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5
-echo $ECHO_N "checking for sys/wait.h that is POSIX.1 compatible... $ECHO_C" >&6; }
-if test "${ac_cv_header_sys_wait_h+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
+# Is the header present?
+echo "$as_me:$LINENO: checking regex.h presence" >&5
+echo $ECHO_N "checking regex.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <sys/types.h>
-#include <sys/wait.h>
-#ifndef WEXITSTATUS
-# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8)
-#endif
-#ifndef WIFEXITED
-# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
-#endif
-
-int
-main ()
-{
-  int s;
-  wait (&s);
-  s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
-  ;
-  return 0;
-}
+#include <regex.h>
 _ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_header_sys_wait_h=yes
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  ac_header_preproc=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_header_sys_wait_h=no
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: regex.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: regex.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: regex.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: regex.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: regex.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: regex.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: regex.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: regex.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: regex.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: regex.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: regex.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: regex.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: regex.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: regex.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: regex.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: regex.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+echo "$as_me:$LINENO: checking for regex.h" >&5
+echo $ECHO_N "checking for regex.h... $ECHO_C" >&6
+if test "${ac_cv_header_regex_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_regex_h=$ac_header_preproc
 fi
+echo "$as_me:$LINENO: result: $ac_cv_header_regex_h" >&5
+echo "${ECHO_T}$ac_cv_header_regex_h" >&6
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5
-echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6; }
-if test $ac_cv_header_sys_wait_h = yes; then
+if test $ac_cv_header_regex_h = yes; then
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_SYS_WAIT_H 1
+#define HAVE_REGEX_H
 _ACEOF
 
 fi
 
 
+if test "x$ac_cv_header_regex_h" = "xyes"; then
+  REGEX_EXTENDED=no
+  REGEX=yes
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <regex.h>
+     #ifdef REG_EXTENDED
+       yes
+     #endif
 
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then
 
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_REG_EXTENDED
+_ACEOF
+ REGEX_EXTENDED=yes
+fi
+rm -f conftest*
 
+fi
 
 
 
+if test "x$ac_cv_header_sys_security_h" = "xyes" && test "x$ac_cv_header_prot_h" = "xyes"
+then
 
+cat >>confdefs.h <<\_ACEOF
+#define OSFC2
+_ACEOF
 
+fi
 
+if test "x$ac_cv_header_sia_h" = "xyes" && test "x$ac_cv_header_siad_h" = "xyes"
+then
+
+cat >>confdefs.h <<\_ACEOF
+#define OSFSIA
+_ACEOF
+
+fi
+
+OPENSSL_INCLUDE="-DNO_OPENSSL"
+if test "x$OPENSSL_LIBS" = "x"; then
+    { echo "$as_me:$LINENO: skipping test for openssl/ssl.h" >&5
+echo "$as_me: skipping test for openssl/ssl.h" >&6;}
+else
+    old_CPPFLAGS=$CPPFLAGS
+    if test "x$OPENSSL_INCLUDE_DIR" != "x"; then
+       CPPFLAGS="$CPPFLAGS -I$OPENSSL_INCLUDE_DIR"
+    fi
+        CPPFLAGS="$CPPFLAGS -DOPENSSL_NO_KRB5"
 
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-for ac_header in \
-       unistd.h \
-       crypt.h \
-       errno.h \
-       resource.h \
-       getopt.h \
-       malloc.h \
-       utmp.h \
-       utmpx.h \
-       signal.h \
-       sys/select.h \
-       syslog.h \
-       inttypes.h \
-       stdint.h \
-       stdio.h \
-       netdb.h \
-       semaphore.h \
-       arpa/inet.h \
-       netinet/in.h \
-       sys/types.h \
-       sys/socket.h \
-       sys/time.h \
-       sys/wait.h \
-       sys/security.h \
-       fcntl.h \
-       sys/fcntl.h \
-       sys/stat.h \
-       sys/prctl.h \
-       prot.h \
-       sia.h \
-       siad.h
-
+for ac_header in \
+       openssl/ssl.h \
+       openssl/crypto.h \
+       openssl/err.h \
+       openssl/engine.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+  echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-              { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
 else
   # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -22089,36 +21506,24 @@ $ac_includes_default
 #include <$ac_header>
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -22127,16 +21532,15 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_header_compiler=no
+ac_header_compiler=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
 
 # Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -22145,13 +21549,8 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 #include <$ac_header>
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
@@ -22175,10 +21574,9 @@ sed 's/^/| /' conftest.$ac_ext >&5
 
   ac_header_preproc=no
 fi
-
 rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
 
 # So?  What about this header?
 case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
@@ -22202,19 +21600,25 @@ echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\
 echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
     { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
 echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
-
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
     ;;
 esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   eval "$as_ac_Header=\$ac_header_preproc"
 fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-              { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
 
 fi
 if test `eval echo '${'$as_ac_Header'}'` = yes; then
@@ -22222,24 +21626,70 @@ if test `eval echo '${'$as_ac_Header'}'` = yes; then
 #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
 _ACEOF
 
+else
+  OPENSSL_LIBS=
+
 fi
 
 done
 
+    if test "x$OPENSSL_LIBS" != "x"; then
+       echo "$as_me:$LINENO: checking for OpenSSL version >= 0.9.7" >&5
+echo $ECHO_N "checking for OpenSSL version >= 0.9.7... $ECHO_C" >&6
+       cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <openssl/crypto.h>
+            #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
+            yes
+            #endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then
+  goodssl="yes"
+fi
+rm -f conftest*
+
+       if test "x$goodssl" != "xyes"; then
+           echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+           OPENSSL_LIBS=
+       else
+           echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+           if test "x$OPENSSL_INCLUDE_DIR" != "x"; then
+               OPENSSL_INCLUDE="-I$OPENSSL_INCLUDE_DIR -DOPENSSL_NO_KRB5"
+           else
+               OPENSSL_INCLUDE="-DOPENSSL_NO_KRB5"
+           fi
+       fi
+    fi
+    CPPFLAGS=$old_CPPFLAGS
+fi
 
-REGEX=no
-if test "${ac_cv_header_regex_h+set}" = set; then
-  { echo "$as_me:$LINENO: checking for regex.h" >&5
-echo $ECHO_N "checking for regex.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_regex_h+set}" = set; then
+
+export OPENSSL_LIBS
+
+if test "x$PCAP_LIBS" = x; then
+    { echo "$as_me:$LINENO: skipping test for pcap.h." >&5
+echo "$as_me: skipping test for pcap.h." >&6;}
+else
+    if test "${ac_cv_header_pcap_h+set}" = set; then
+  echo "$as_me:$LINENO: checking for pcap.h" >&5
+echo $ECHO_N "checking for pcap.h... $ECHO_C" >&6
+if test "${ac_cv_header_pcap_h+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_regex_h" >&5
-echo "${ECHO_T}$ac_cv_header_regex_h" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_header_pcap_h" >&5
+echo "${ECHO_T}$ac_cv_header_pcap_h" >&6
 else
   # Is the header compilable?
-{ echo "$as_me:$LINENO: checking regex.h usability" >&5
-echo $ECHO_N "checking regex.h usability... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking pcap.h usability" >&5
+echo $ECHO_N "checking pcap.h usability... $ECHO_C" >&6
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -22247,39 +21697,27 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 $ac_includes_default
-#include <regex.h>
+#include <pcap.h>
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -22288,31 +21726,25 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_header_compiler=no
+ac_header_compiler=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
 
 # Is the header present?
-{ echo "$as_me:$LINENO: checking regex.h presence" >&5
-echo $ECHO_N "checking regex.h presence... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking pcap.h presence" >&5
+echo $ECHO_N "checking pcap.h presence... $ECHO_C" >&6
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <regex.h>
+#include <pcap.h>
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
@@ -22336,942 +21768,887 @@ sed 's/^/| /' conftest.$ac_ext >&5
 
   ac_header_preproc=no
 fi
-
 rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
 
 # So?  What about this header?
 case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
   yes:no: )
-    { echo "$as_me:$LINENO: WARNING: regex.h: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: regex.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { echo "$as_me:$LINENO: WARNING: regex.h: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: regex.h: proceeding with the compiler's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: pcap.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: pcap.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: pcap.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: pcap.h: proceeding with the compiler's result" >&2;}
     ac_header_preproc=yes
     ;;
   no:yes:* )
-    { echo "$as_me:$LINENO: WARNING: regex.h: present but cannot be compiled" >&5
-echo "$as_me: WARNING: regex.h: present but cannot be compiled" >&2;}
-    { echo "$as_me:$LINENO: WARNING: regex.h:     check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: regex.h:     check for missing prerequisite headers?" >&2;}
-    { echo "$as_me:$LINENO: WARNING: regex.h: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: regex.h: see the Autoconf documentation" >&2;}
-    { echo "$as_me:$LINENO: WARNING: regex.h:     section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: regex.h:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { echo "$as_me:$LINENO: WARNING: regex.h: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: regex.h: proceeding with the preprocessor's result" >&2;}
-    { echo "$as_me:$LINENO: WARNING: regex.h: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: regex.h: in the future, the compiler will take precedence" >&2;}
-
+    { echo "$as_me:$LINENO: WARNING: pcap.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: pcap.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: pcap.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: pcap.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: pcap.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: pcap.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: pcap.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: pcap.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: pcap.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: pcap.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: pcap.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: pcap.h: in the future, the compiler will take precedence" >&2;}
+    (
+      cat <<\_ASBOX
+## ------------------------------------------ ##
+## Report this to the AC_PACKAGE_NAME lists.  ##
+## ------------------------------------------ ##
+_ASBOX
+    ) |
+      sed "s/^/$as_me: WARNING:     /" >&2
     ;;
 esac
-{ echo "$as_me:$LINENO: checking for regex.h" >&5
-echo $ECHO_N "checking for regex.h... $ECHO_C" >&6; }
-if test "${ac_cv_header_regex_h+set}" = set; then
+echo "$as_me:$LINENO: checking for pcap.h" >&5
+echo $ECHO_N "checking for pcap.h... $ECHO_C" >&6
+if test "${ac_cv_header_pcap_h+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_cv_header_regex_h=$ac_header_preproc
+  ac_cv_header_pcap_h=$ac_header_preproc
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_header_regex_h" >&5
-echo "${ECHO_T}$ac_cv_header_regex_h" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_header_pcap_h" >&5
+echo "${ECHO_T}$ac_cv_header_pcap_h" >&6
 
 fi
-if test $ac_cv_header_regex_h = yes; then
-  cat >>confdefs.h <<\_ACEOF
-#define HAVE_REGEX_H 1
+if test $ac_cv_header_pcap_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PCAP_H 1
 _ACEOF
 
+else
+   PCAP_LIBS=
+       { echo "$as_me:$LINENO: WARNING: pcap.h not found, silently disabling the RADIUS sniffer." >&5
+echo "$as_me: WARNING: pcap.h not found, silently disabling the RADIUS sniffer." >&2;}
+
 fi
 
 
-if test "x$ac_cv_header_regex_h" = "xyes"; then
-  REGEX_EXTENDED=no
-  REGEX=yes
+fi
+
+
+
+echo "$as_me:$LINENO: checking for off_t" >&5
+echo $ECHO_N "checking for off_t... $ECHO_C" >&6
+if test "${ac_cv_type_off_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <regex.h>
-     #ifdef REG_EXTENDED
-       yes
-     #endif
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "yes" >/dev/null 2>&1; then
-  cat >>confdefs.h <<\_ACEOF
-#define HAVE_REG_EXTENDED 1
+$ac_includes_default
+int
+main ()
+{
+if ((off_t *) 0)
+  return 0;
+if (sizeof (off_t))
+  return 0;
+  ;
+  return 0;
+}
 _ACEOF
- REGEX_EXTENDED=yes
-fi
-rm -f conftest*
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_off_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
+ac_cv_type_off_t=no
 fi
-
-
-
-if test "x$ac_cv_header_sys_security_h" = "xyes" && test "x$ac_cv_header_prot_h" = "xyes"
-then
-  cat >>confdefs.h <<\_ACEOF
-#define OSFC2 1
-_ACEOF
-
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
+echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
+echo "${ECHO_T}$ac_cv_type_off_t" >&6
+if test $ac_cv_type_off_t = yes; then
+  :
+else
 
-if test "x$ac_cv_header_sia_h" = "xyes" && test "x$ac_cv_header_siad_h" = "xyes"
-then
-  cat >>confdefs.h <<\_ACEOF
-#define OSFSIA 1
+cat >>confdefs.h <<_ACEOF
+#define off_t long
 _ACEOF
 
 fi
 
-OPENSSL_INCLUDE="-DNO_OPENSSL"
-if test "x$OPENSSL_LIBS" = "x"; then
-    { echo "$as_me:$LINENO: WARNING: skipping test for openssl/ssl.h" >&5
-echo "$as_me: WARNING: skipping test for openssl/ssl.h" >&2;}
-else
-    old_CPPFLAGS=$CPPFLAGS
-    if test "x$OPENSSL_INCLUDE_DIR" != "x"; then
-       CPPFLAGS="$CPPFLAGS -I$OPENSSL_INCLUDE_DIR"
-    fi
-        CPPFLAGS="$CPPFLAGS -DOPENSSL_NO_KRB5"
-
-
-
-
-for ac_header in \
-       openssl/ssl.h \
-       openssl/crypto.h \
-       openssl/err.h \
-       openssl/engine.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  { echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+echo "$as_me:$LINENO: checking for pid_t" >&5
+echo $ECHO_N "checking for pid_t... $ECHO_C" >&6
+if test "${ac_cv_type_pid_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-              { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
 else
-  # Is the header compilable?
-{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 $ac_includes_default
-#include <$ac_header>
+int
+main ()
+{
+if ((pid_t *) 0)
+  return 0;
+if (sizeof (pid_t))
+  return 0;
+  ;
+  return 0;
+}
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_header_compiler=yes
+  ac_cv_type_pid_t=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_header_compiler=no
+ac_cv_type_pid_t=no
 fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5
+echo "${ECHO_T}$ac_cv_type_pid_t" >&6
+if test $ac_cv_type_pid_t = yes; then
+  :
+else
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6; }
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
 
-# Is the header present?
-{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
-cat >conftest.$ac_ext <<_ACEOF
+fi
+
+echo "$as_me:$LINENO: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6
+if test "${ac_cv_type_size_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <$ac_header>
+$ac_includes_default
+int
+main ()
+{
+if ((size_t *) 0)
+  return 0;
+if (sizeof (size_t))
+  return 0;
+  ;
+  return 0;
+}
 _ACEOF
-if { (ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  ac_header_preproc=yes
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_size_t=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-  ac_header_preproc=no
+ac_cv_type_size_t=no
 fi
-
-rm -f conftest.err conftest.$ac_ext
-{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6; }
-
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
-  yes:no: )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
-    ac_header_preproc=yes
-    ;;
-  no:yes:* )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
-
-    ;;
-esac
-{ echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
-if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  eval "$as_ac_Header=\$ac_header_preproc"
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-ac_res=`eval echo '${'$as_ac_Header'}'`
-              { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6
+if test $ac_cv_type_size_t = yes; then
+  :
+else
 
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned
 _ACEOF
 
-else
-  OPENSSL_LIBS=
-
 fi
 
-done
-
-    if test "x$OPENSSL_LIBS" != "x"; then
-       { echo "$as_me:$LINENO: checking for OpenSSL version >= 0.9.7" >&5
-echo $ECHO_N "checking for OpenSSL version >= 0.9.7... $ECHO_C" >&6; }
-       cat >conftest.$ac_ext <<_ACEOF
+echo "$as_me:$LINENO: checking for uid_t in sys/types.h" >&5
+echo $ECHO_N "checking for uid_t in sys/types.h... $ECHO_C" >&6
+if test "${ac_cv_type_uid_t+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <openssl/crypto.h>
-            #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
-            yes
-            #endif
+#include <sys/types.h>
 
 _ACEOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "yes" >/dev/null 2>&1; then
-  goodssl="yes"
+  $EGREP "uid_t" >/dev/null 2>&1; then
+  ac_cv_type_uid_t=yes
+else
+  ac_cv_type_uid_t=no
 fi
 rm -f conftest*
 
-       if test "x$goodssl" != "xyes"; then
-           { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-           OPENSSL_LIBS=
-       else
-           { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-           if test "x$OPENSSL_INCLUDE_DIR" != "x"; then
-               OPENSSL_INCLUDE="-I$OPENSSL_INCLUDE_DIR -DOPENSSL_NO_KRB5"
-           else
-               OPENSSL_INCLUDE="-DOPENSSL_NO_KRB5"
-           fi
-       fi
-    fi
-    CPPFLAGS=$old_CPPFLAGS
 fi
+echo "$as_me:$LINENO: result: $ac_cv_type_uid_t" >&5
+echo "${ECHO_T}$ac_cv_type_uid_t" >&6
+if test $ac_cv_type_uid_t = no; then
 
+cat >>confdefs.h <<\_ACEOF
+#define uid_t int
+_ACEOF
 
-export OPENSSL_LIBS
 
+cat >>confdefs.h <<\_ACEOF
+#define gid_t int
+_ACEOF
 
-{ echo "$as_me:$LINENO: checking for off_t" >&5
-echo $ECHO_N "checking for off_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_off_t+set}" = set; then
+fi
+
+
+
+  echo "$as_me:$LINENO: checking for socklen_t" >&5
+echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6
+if test "${ac_cv_type_socklen_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  cat >conftest.$ac_ext <<_ACEOF
+   ac_cv_type_socklen_t=no
+      cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
-typedef off_t ac__type_new_;
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
 int
 main ()
 {
-if ((ac__type_new_ *) 0)
-  return 0;
-if (sizeof (ac__type_new_))
-  return 0;
+socklen_t foo
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_type_off_t=yes
+  ac_cv_type_socklen_t=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_type_off_t=no
 fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_off_t" >&5
-echo "${ECHO_T}$ac_cv_type_off_t" >&6; }
-if test $ac_cv_type_off_t = yes; then
-  :
-else
+echo "$as_me:$LINENO: result: $ac_cv_type_socklen_t" >&5
+echo "${ECHO_T}$ac_cv_type_socklen_t" >&6
 
-cat >>confdefs.h <<_ACEOF
-#define off_t long int
+  if test "$ac_cv_type_socklen_t" != "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define socklen_t int
 _ACEOF
 
-fi
+  fi
 
-{ echo "$as_me:$LINENO: checking for pid_t" >&5
-echo $ECHO_N "checking for pid_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_pid_t+set}" = set; then
+
+
+  echo "$as_me:$LINENO: checking for uint8_t" >&5
+echo $ECHO_N "checking for uint8_t... $ECHO_C" >&6
+if test "${ac_cv_type_uint8_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  cat >conftest.$ac_ext <<_ACEOF
+   ac_cv_type_uint8_t=no
+      cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
-typedef pid_t ac__type_new_;
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
 int
 main ()
 {
-if ((ac__type_new_ *) 0)
-  return 0;
-if (sizeof (ac__type_new_))
-  return 0;
+uint8_t foo
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_type_pid_t=yes
+  ac_cv_type_uint8_t=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_type_pid_t=no
 fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5
-echo "${ECHO_T}$ac_cv_type_pid_t" >&6; }
-if test $ac_cv_type_pid_t = yes; then
-  :
-else
+echo "$as_me:$LINENO: result: $ac_cv_type_uint8_t" >&5
+echo "${ECHO_T}$ac_cv_type_uint8_t" >&6
 
-cat >>confdefs.h <<_ACEOF
-#define pid_t int
+  if test "$ac_cv_type_uint8_t" != "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define uint8_t unsigned char
 _ACEOF
 
-fi
+  fi
 
-{ echo "$as_me:$LINENO: checking for size_t" >&5
-echo $ECHO_N "checking for size_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_size_t+set}" = set; then
+
+
+  echo "$as_me:$LINENO: checking for uint16_t" >&5
+echo $ECHO_N "checking for uint16_t... $ECHO_C" >&6
+if test "${ac_cv_type_uint16_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  cat >conftest.$ac_ext <<_ACEOF
+   ac_cv_type_uint16_t=no
+      cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-$ac_includes_default
-typedef size_t ac__type_new_;
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
 int
 main ()
 {
-if ((ac__type_new_ *) 0)
-  return 0;
-if (sizeof (ac__type_new_))
-  return 0;
+uint16_t foo
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_type_size_t=yes
+  ac_cv_type_uint16_t=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_type_size_t=no
 fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5
-echo "${ECHO_T}$ac_cv_type_size_t" >&6; }
-if test $ac_cv_type_size_t = yes; then
-  :
-else
+echo "$as_me:$LINENO: result: $ac_cv_type_uint16_t" >&5
+echo "${ECHO_T}$ac_cv_type_uint16_t" >&6
 
-cat >>confdefs.h <<_ACEOF
-#define size_t unsigned int
+  if test "$ac_cv_type_uint16_t" != "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define uint16_t unsigned short
 _ACEOF
 
-fi
+  fi
 
-{ echo "$as_me:$LINENO: checking for uid_t in sys/types.h" >&5
-echo $ECHO_N "checking for uid_t in sys/types.h... $ECHO_C" >&6; }
-if test "${ac_cv_type_uid_t+set}" = set; then
+
+
+  echo "$as_me:$LINENO: checking for uint32_t" >&5
+echo $ECHO_N "checking for uint32_t... $ECHO_C" >&6
+if test "${ac_cv_type_uint32_t+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <sys/types.h>
+   ac_cv_type_uint32_t=no
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+int
+main ()
+{
+uint32_t foo
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_uint32_t=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
 
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "uid_t" >/dev/null 2>&1; then
-  ac_cv_type_uid_t=yes
-else
-  ac_cv_type_uid_t=no
 fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_uid_t" >&5
-echo "${ECHO_T}$ac_cv_type_uid_t" >&6; }
-if test $ac_cv_type_uid_t = no; then
 
-cat >>confdefs.h <<\_ACEOF
-#define uid_t int
-_ACEOF
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_uint32_t" >&5
+echo "${ECHO_T}$ac_cv_type_uint32_t" >&6
 
+  if test "$ac_cv_type_uint32_t" != "yes"; then
 
 cat >>confdefs.h <<\_ACEOF
-#define gid_t int
+#define uint32_t unsigned int
 _ACEOF
 
-fi
-
+  fi
 
 
-  { echo "$as_me:$LINENO: checking for socklen_t" >&5
-echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_socklen_t+set}" = set; then
+echo "$as_me:$LINENO: checking for struct in6_addr" >&5
+echo $ECHO_N "checking for struct in6_addr... $ECHO_C" >&6
+if test "${ac_cv_type_struct_in6_addr+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-   ac_cv_type_socklen_t=no
-      cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
 #endif
 
+
 int
 main ()
 {
-socklen_t foo
+if ((struct in6_addr *) 0)
+  return 0;
+if (sizeof (struct in6_addr))
+  return 0;
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_type_socklen_t=yes
+  ac_cv_type_struct_in6_addr=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
+ac_cv_type_struct_in6_addr=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_socklen_t" >&5
-echo "${ECHO_T}$ac_cv_type_socklen_t" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_type_struct_in6_addr" >&5
+echo "${ECHO_T}$ac_cv_type_struct_in6_addr" >&6
+if test $ac_cv_type_struct_in6_addr = yes; then
 
-  if test "$ac_cv_type_socklen_t" != "yes"; then
-         cat >>confdefs.h <<\_ACEOF
-#define socklen_t int
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRUCT_IN6_ADDR 1
 _ACEOF
 
-  fi
-
+fi
 
 
-  { echo "$as_me:$LINENO: checking for uint8_t" >&5
-echo $ECHO_N "checking for uint8_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_uint8_t+set}" = set; then
+echo "$as_me:$LINENO: checking for struct sockaddr_storage" >&5
+echo $ECHO_N "checking for struct sockaddr_storage... $ECHO_C" >&6
+if test "${ac_cv_type_struct_sockaddr_storage+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-   ac_cv_type_uint8_t=no
-      cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
 #endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
 #endif
 
+
 int
 main ()
 {
-uint8_t foo
+if ((struct sockaddr_storage *) 0)
+  return 0;
+if (sizeof (struct sockaddr_storage))
+  return 0;
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_type_uint8_t=yes
+  ac_cv_type_struct_sockaddr_storage=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
+ac_cv_type_struct_sockaddr_storage=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_uint8_t" >&5
-echo "${ECHO_T}$ac_cv_type_uint8_t" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_type_struct_sockaddr_storage" >&5
+echo "${ECHO_T}$ac_cv_type_struct_sockaddr_storage" >&6
+if test $ac_cv_type_struct_sockaddr_storage = yes; then
 
-  if test "$ac_cv_type_uint8_t" != "yes"; then
-         cat >>confdefs.h <<\_ACEOF
-#define uint8_t unsigned char
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
 _ACEOF
 
-  fi
-
+fi
 
 
-  { echo "$as_me:$LINENO: checking for uint16_t" >&5
-echo $ECHO_N "checking for uint16_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_uint16_t+set}" = set; then
+echo "$as_me:$LINENO: checking for struct sockaddr_in6" >&5
+echo $ECHO_N "checking for struct sockaddr_in6... $ECHO_C" >&6
+if test "${ac_cv_type_struct_sockaddr_in6+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-   ac_cv_type_uint16_t=no
-      cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
 #endif
 
+
 int
 main ()
 {
-uint16_t foo
+if ((struct sockaddr_in6 *) 0)
+  return 0;
+if (sizeof (struct sockaddr_in6))
+  return 0;
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_type_uint16_t=yes
+  ac_cv_type_struct_sockaddr_in6=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
+ac_cv_type_struct_sockaddr_in6=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_uint16_t" >&5
-echo "${ECHO_T}$ac_cv_type_uint16_t" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_type_struct_sockaddr_in6" >&5
+echo "${ECHO_T}$ac_cv_type_struct_sockaddr_in6" >&6
+if test $ac_cv_type_struct_sockaddr_in6 = yes; then
 
-  if test "$ac_cv_type_uint16_t" != "yes"; then
-         cat >>confdefs.h <<\_ACEOF
-#define uint16_t unsigned short
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRUCT_SOCKADDR_IN6 1
 _ACEOF
 
-  fi
-
+fi
 
 
-  { echo "$as_me:$LINENO: checking for uint32_t" >&5
-echo $ECHO_N "checking for uint32_t... $ECHO_C" >&6; }
-if test "${ac_cv_type_uint32_t+set}" = set; then
+echo "$as_me:$LINENO: checking for struct addrinfo" >&5
+echo $ECHO_N "checking for struct addrinfo... $ECHO_C" >&6
+if test "${ac_cv_type_struct_addrinfo+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-   ac_cv_type_uint32_t=no
-      cat >conftest.$ac_ext <<_ACEOF
+  cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
 #endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
 #endif
 
+
 int
 main ()
 {
-uint32_t foo
+if ((struct addrinfo *) 0)
+  return 0;
+if (sizeof (struct addrinfo))
+  return 0;
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_type_uint32_t=yes
+  ac_cv_type_struct_addrinfo=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
+ac_cv_type_struct_addrinfo=no
 fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_struct_addrinfo" >&5
+echo "${ECHO_T}$ac_cv_type_struct_addrinfo" >&6
+if test $ac_cv_type_struct_addrinfo = yes; then
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRUCT_ADDRINFO 1
+_ACEOF
 
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_uint32_t" >&5
-echo "${ECHO_T}$ac_cv_type_uint32_t" >&6; }
 
-  if test "$ac_cv_type_uint32_t" != "yes"; then
-         cat >>confdefs.h <<\_ACEOF
-#define uint32_t unsigned int
-_ACEOF
 
-  fi
+
+
 
 
 
@@ -23322,13 +22699,17 @@ for ac_func in \
        setvbuf \
        getusershell \
        initgroups \
-       closefrom
+       getaddrinfo \
+       getnameinfo \
+       closefrom \
+       strlcat \
+       strlcpy
 
 do
 as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
-if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
@@ -23354,59 +22735,53 @@ cat >>conftest.$ac_ext <<_ACEOF
 
 #undef $ac_func
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
+{
 #endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
 char $ac_func ();
 /* The GNU C library defines this for functions which it implements
     to always fail with ENOSYS.  Some functions are actually named
     something starting with __ and the normal name is an alias.  */
-#if defined __stub_$ac_func || defined __stub___$ac_func
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
 choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
 #endif
 
 int
 main ()
 {
-return $ac_func ();
+return f != $ac_func;
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -23415,15 +22790,13 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       eval "$as_ac_var=no"
+eval "$as_ac_var=no"
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 fi
-ac_res=`eval echo '${'$as_ac_var'}'`
-              { echo "$as_me:$LINENO: result: $ac_res" >&5
-echo "${ECHO_T}$ac_res" >&6; }
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
 if test `eval echo '${'$as_ac_var'}'` = yes; then
   cat >>confdefs.h <<_ACEOF
 #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
@@ -23443,9 +22816,9 @@ for ac_func in \
        endusershell
 
 do
-echo "$as_me:$LINENO: checking whether $ac_func must be declared" >&5
-echo $ECHO_N "checking whether $ac_func must be declared... $ECHO_C" >&6; }
-if { as_var=radius_cv_decl_needed_$ac_func; eval "test \"\${$as_var+set}\" = set"; }; then
+echo "$as_me:$LINENO: checking whether $ac_func must be declared" >&5
+echo $ECHO_N "checking whether $ac_func must be declared... $ECHO_C" >&6
+if eval "test \"\${radius_cv_decl_needed_$ac_func+set}\" = set"; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
@@ -23512,36 +22885,24 @@ char *(*pfn) = (char *(*)) $ac_func
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -23550,30 +22911,29 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       eval "radius_cv_decl_needed_$ac_func=yes"
+eval "radius_cv_decl_needed_$ac_func=yes"
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 
 if eval "test \"`echo '$radius_cv_decl_needed_'$ac_func`\" = yes"; then
-  echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
+  echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
   radius_tr_decl=NEED_DECLARATION_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
   cat >>confdefs.h <<_ACEOF
 #define $radius_tr_decl 1
 _ACEOF
 
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 fi
 
 done
 
 
-echo "$as_me:$LINENO: checking return type of signal handlers" >&5
-echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking return type of signal handlers" >&5
+echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6
 if test "${ac_cv_type_signal+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -23585,73 +22945,145 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 #include <sys/types.h>
 #include <signal.h>
+#ifdef signal
+# undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int
+main ()
+{
+int i;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_type_signal=void
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_type_signal=int
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
+echo "${ECHO_T}$ac_cv_type_signal" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define RETSIGTYPE $ac_cv_type_signal
+_ACEOF
+
+
+
+if test "x$ac_cv_header_utmpx_h" = "xyes"
+then
+
+  echo "$as_me:$LINENO: checking for ut_xtime in struct utmpx" >&5
+echo $ECHO_N "checking for ut_xtime in struct utmpx... $ECHO_C" >&6
+
+
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <utmpx.h>
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
+#endif
 
 int
 main ()
 {
-return *(signal (0, 0)) (0) == 1;
+ int foo = offsetof(struct utmpx, ut_xtime)
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_type_signal=int
+  has_element=" "
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_type_signal=void
+has_element=
 fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5
-echo "${ECHO_T}$ac_cv_type_signal" >&6; }
+  ac_safe_type=`echo "struct utmpx" | sed 'y% %_%'`
+  if test "x$has_element" != "x"; then
+    echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+    eval "ac_cv_type_${ac_safe_type}_has_ut_xtime=yes"
+  else
+    echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+    eval "ac_cv_type_${ac_safe_type}_has_ut_xtime="
+ fi
 
-cat >>confdefs.h <<_ACEOF
-#define RETSIGTYPE $ac_cv_type_signal
-_ACEOF
+ if test "x$ac_cv_type_struct_utmpx_has_ut_xtime" = "x"
+ then
 
+cat >>confdefs.h <<\_ACEOF
+#define ut_xtime ut_tv.tv_sec
+_ACEOF
 
+ fi
+fi
 
-if test "x$ac_cv_header_utmpx_h" = "xyes"
-then
 
-  { echo "$as_me:$LINENO: checking for ut_xtime in struct utmpx" >&5
-echo $ECHO_N "checking for ut_xtime in struct utmpx... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for ipi_addr in struct in_pktinfo" >&5
+echo $ECHO_N "checking for ipi_addr in struct in_pktinfo... $ECHO_C" >&6
 
 
   cat >conftest.$ac_ext <<_ACEOF
@@ -23661,7 +23093,7 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-#include <utmpx.h>
+#include <netinet/in.h>
 #ifndef offsetof
 #define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
 #endif
@@ -23669,42 +23101,30 @@ cat >>conftest.$ac_ext <<_ACEOF
 int
 main ()
 {
- int foo = offsetof(struct utmpx, ut_xtime)
+ int foo = offsetof(struct in_pktinfo, ipi_addr)
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -23713,34 +23133,33 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       has_element=
+has_element=
 fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-  ac_safe_type=`echo "struct utmpx" | sed 'y% %_%'`
+  ac_safe_type=`echo "struct in_pktinfo" | sed 'y% %_%'`
   if test "x$has_element" != "x"; then
-    echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-    eval "ac_cv_type_${ac_safe_type}_has_ut_xtime=yes"
+    echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+    eval "ac_cv_type_${ac_safe_type}_has_ipi_addr=yes"
   else
-    echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-    eval "ac_cv_type_${ac_safe_type}_has_ut_xtime="
+    echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+    eval "ac_cv_type_${ac_safe_type}_has_ipi_addr="
  fi
 
- if test "x$ac_cv_type_struct_utmpx_has_ut_xtime" = "x"
- then
-   cat >>confdefs.h <<\_ACEOF
-#define ut_xtime ut_tv.tv_sec
+if test "x$ac_cv_type_struct_in_pktinfo_has_ipi_addr" = "xyes"
+then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_IP_PKTINFO
 _ACEOF
 
- fi
 fi
 
 
-  { echo "$as_me:$LINENO: checking for ipi_addr in struct in_pktinfo" >&5
-echo $ECHO_N "checking for ipi_addr in struct in_pktinfo... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for ipi6_addr in struct in6_pktinfo" >&5
+echo $ECHO_N "checking for ipi6_addr in struct in6_pktinfo... $ECHO_C" >&6
 
 
   cat >conftest.$ac_ext <<_ACEOF
@@ -23758,42 +23177,30 @@ cat >>conftest.$ac_ext <<_ACEOF
 int
 main ()
 {
- int foo = offsetof(struct in_pktinfo, ipi_addr)
+ int foo = offsetof(struct in6_pktinfo, ipi6_addr)
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -23802,33 +23209,33 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       has_element=
+has_element=
 fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-  ac_safe_type=`echo "struct in_pktinfo" | sed 'y% %_%'`
+  ac_safe_type=`echo "struct in6_pktinfo" | sed 'y% %_%'`
   if test "x$has_element" != "x"; then
-    echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-    eval "ac_cv_type_${ac_safe_type}_has_ipi_addr=yes"
+    echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+    eval "ac_cv_type_${ac_safe_type}_has_ipi6_addr=yes"
   else
-    echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-    eval "ac_cv_type_${ac_safe_type}_has_ipi_addr="
+    echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+    eval "ac_cv_type_${ac_safe_type}_has_ipi6_addr="
  fi
 
-if test "x$ac_cv_type_struct_in_pktinfo_has_ipi_addr" = "xyes"
+if test "x$ac_cv_type_struct_in6_pktinfo_has_ipi6_addr" = "xyes"
 then
-       cat >>confdefs.h <<\_ACEOF
-#define HAVE_IP_PKTINFO 1
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_IN6_PKTINFO
 _ACEOF
 
 fi
 
 
-echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
-echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
 if test "${ac_cv_c_const+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -23868,7 +23275,6 @@ main ()
     char const *s = 0 ? (char *) 0 : (char const *) 0;
 
     *t++ = 0;
-    if (s) return 0;
   }
   { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
     int x[] = {25, 17};
@@ -23887,9 +23293,7 @@ main ()
   }
   { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
     const int foo = 10;
-    if (!foo) return 0;
   }
-  return !x[0] && !zero.x;
 #endif
 
   ;
@@ -23897,36 +23301,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -23935,13 +23327,12 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_c_const=no
+ac_cv_c_const=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
-echo "${ECHO_T}$ac_cv_c_const" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
 if test $ac_cv_c_const = no; then
 
 cat >>confdefs.h <<\_ACEOF
@@ -23951,11 +23342,11 @@ _ACEOF
 fi
 
 
-echo "$as_me:$LINENO: checking type of OS" >&5
-echo $ECHO_N "checking type of OS... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking type of OS" >&5
+echo $ECHO_N "checking type of OS... $ECHO_C" >&6
 OS=`uname -s`
-echo "$as_me:$LINENO: result: $OS" >&5
-echo "${ECHO_T}$OS" >&6; }
+echo "$as_me:$LINENO: result: $OS" >&5
+echo "${ECHO_T}$OS" >&6
 if test "$OS" = "OS/2"; then
        LIBPREFIX=
 else
@@ -23967,25 +23358,25 @@ if test "x$GCC" = "xyes"; then
     CFLAGS="$CFLAGS -Wall -D_GNU_SOURCE"
 fi
 
-echo "$as_me:$LINENO: checking for developer gcc flags" >&5
-echo $ECHO_N "checking for developer gcc flags... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for developer gcc flags" >&5
+echo $ECHO_N "checking for developer gcc flags... $ECHO_C" >&6
 if test "x$developer" = "xyes" -a "x$GCC" = "xyes"; then
   devflags="-g -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -W -Wredundant-decls -Wundef"
   CFLAGS="$CFLAGS $devflags"
   INSTALLSTRIP=""
-  echo "$as_me:$LINENO: result: yes.  Using $devflags" >&5
-echo "${ECHO_T}yes.  Using $devflags" >&6; }
+  echo "$as_me:$LINENO: result: yes.  Using $devflags" >&5
+echo "${ECHO_T}yes.  Using $devflags" >&6
 else
   devflags=""
   CFLAGS="$CFLAGS -DNDEBUG"
   INSTALLSTRIP="-s"
-  echo "$as_me:$LINENO: result: no." >&5
-echo "${ECHO_T}no." >&6; }
+  echo "$as_me:$LINENO: result: no." >&5
+echo "${ECHO_T}no." >&6
 fi
 
 
-echo "$as_me:$LINENO: checking for crypt in -lcrypt" >&5
-echo $ECHO_N "checking for crypt in -lcrypt... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for crypt in -lcrypt" >&5
+echo $ECHO_N "checking for crypt in -lcrypt... $ECHO_C" >&6
 if test "${ac_cv_lib_crypt_crypt+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -23998,52 +23389,40 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
 char crypt ();
 int
 main ()
 {
-return crypt ();
+crypt ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -24052,28 +23431,28 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_crypt_crypt=no
+ac_cv_lib_crypt_crypt=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_crypt" >&5
-echo "${ECHO_T}$ac_cv_lib_crypt_crypt" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_crypt" >&5
+echo "${ECHO_T}$ac_cv_lib_crypt_crypt" >&6
 if test $ac_cv_lib_crypt_crypt = yes; then
   CRYPTLIB="-lcrypt"
 
 fi
 
 if test "$CRYPTLIB" != ""; then
-  cat >>confdefs.h <<\_ACEOF
-#define HAVE_CRYPT 1
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CRYPT
 _ACEOF
 
 else
-  echo "$as_me:$LINENO: checking for crypt" >&5
-echo $ECHO_N "checking for crypt... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for crypt" >&5
+echo $ECHO_N "checking for crypt... $ECHO_C" >&6
 if test "${ac_cv_func_crypt+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -24100,59 +23479,53 @@ cat >>conftest.$ac_ext <<_ACEOF
 
 #undef crypt
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
+{
 #endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
 char crypt ();
 /* The GNU C library defines this for functions which it implements
     to always fail with ENOSYS.  Some functions are actually named
     something starting with __ and the normal name is an alias.  */
-#if defined __stub_crypt || defined __stub___crypt
+#if defined (__stub_crypt) || defined (__stub___crypt)
 choke me
+#else
+char (*f) () = crypt;
+#endif
+#ifdef __cplusplus
+}
 #endif
 
 int
 main ()
 {
-return crypt ();
+return f != crypt;
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -24161,25 +23534,25 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_func_crypt=no
+ac_cv_func_crypt=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $ac_cv_func_crypt" >&5
-echo "${ECHO_T}$ac_cv_func_crypt" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_func_crypt" >&5
+echo "${ECHO_T}$ac_cv_func_crypt" >&6
 if test $ac_cv_func_crypt = yes; then
-  cat >>confdefs.h <<\_ACEOF
-#define HAVE_CRYPT 1
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_CRYPT
 _ACEOF
 
 fi
 
 fi
 
-echo "$as_me:$LINENO: checking for setkey in -lcipher" >&5
-echo $ECHO_N "checking for setkey in -lcipher... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for setkey in -lcipher" >&5
+echo $ECHO_N "checking for setkey in -lcipher... $ECHO_C" >&6
 if test "${ac_cv_lib_cipher_setkey+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -24192,52 +23565,40 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
+/* Override any gcc2 internal prototype to avoid an error.  */
 #ifdef __cplusplus
 extern "C"
 #endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
 char setkey ();
 int
 main ()
 {
-return setkey ();
+setkey ();
   ;
   return 0;
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -24246,15 +23607,14 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ac_cv_lib_cipher_setkey=no
+ac_cv_lib_cipher_setkey=no
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_cipher_setkey" >&5
-echo "${ECHO_T}$ac_cv_lib_cipher_setkey" >&6; }
+echo "$as_me:$LINENO: result: $ac_cv_lib_cipher_setkey" >&5
+echo "${ECHO_T}$ac_cv_lib_cipher_setkey" >&6
 if test $ac_cv_lib_cipher_setkey = yes; then
   CRYPTLIB="${CRYPTLIB} -lcipher"
 
@@ -24267,8 +23627,8 @@ if test "x$WITH_SNMP" = "xyes"; then
 
 
 
-echo "$as_me:$LINENO: checking for asn1.h,snmp.h,snmp_impl.h" >&5
-echo $ECHO_N "checking for asn1.h,snmp.h,snmp_impl.h... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking for asn1.h,snmp.h,snmp_impl.h" >&5
+echo $ECHO_N "checking for asn1.h,snmp.h,snmp_impl.h... $ECHO_C" >&6
 
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
@@ -24305,36 +23665,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -24343,14 +23691,13 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ucdsnmp=
+ucdsnmp=
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 
 if test "x$ucdsnmp" = "x"; then
   old_CFLAGS="$CFLAGS"
-  for try in /usr/include /usr/local/include $with_snmp_include_dir; do
+  for try in /usr/include /usr/local/include $snmp_include_dir; do
     CFLAGS="$old_CFLAGS -I$try"
     cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
@@ -24387,36 +23734,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -24425,10 +23760,9 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ucdsnmp=
+ucdsnmp=
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$ucdsnmp" != "x"; then
       break;
     fi
@@ -24438,7 +23772,7 @@ fi
 
 if test "x$ucdsnmp" = "x"; then
   old_CFLAGS="$CFLAGS"
-  for try in /usr/include/ucd-snmp /usr/local/include/ucd-snmp $with_snmp_include_dir; do
+  for try in /usr/include/ucd-snmp /usr/local/include/ucd-snmp $snmp_include_dir; do
     CFLAGS="$old_CFLAGS -I$try"
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
@@ -24474,36 +23808,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -24512,10 +23834,9 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ucdsnmp=
+ucdsnmp=
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$ucdsnmp" != "x"; then
       break;
     fi
@@ -24525,7 +23846,7 @@ fi
 
 if test "x$ucdsnmp" = "x"; then
   old_CFLAGS="$CFLAGS"
-  for try in /usr/include/ucd-snmp /usr/local/include/ucd-snmp $with_snmp_include_dir; do
+  for try in /usr/include/ucd-snmp /usr/local/include/ucd-snmp $snmp_include_dir; do
     CFLAGS="$old_CFLAGS -I$try"
     cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
@@ -24561,36 +23882,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_compile") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -24599,10 +23908,9 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       ucdsnmp=
+ucdsnmp=
 fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$ucdsnmp" != "x"; then
       break;
     fi
@@ -24611,26 +23919,28 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 
 if test "x$ucdsnmp" = "x"; then
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
 else
   if test "x$ucdsnmp" = "xyes"; then
-    { echo "$as_me:$LINENO: result: (ucd-snmp)yes" >&5
-echo "${ECHO_T}(ucd-snmp)yes" >&6; }
-    cat >>confdefs.h <<\_ACEOF
-#define HAVE_UCD_SNMP_ASN1_SNMP_SNMPIMPL_H 1
+    echo "$as_me:$LINENO: result: (ucd-snmp)yes" >&5
+echo "${ECHO_T}(ucd-snmp)yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_UCD_SNMP_ASN1_SNMP_SNMPIMPL_H
 _ACEOF
 
   else
-    { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-    cat >>confdefs.h <<\_ACEOF
-#define HAVE_ASN1_SNMP_SNMPIMPL_H 1
+    echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ASN1_SNMP_SNMPIMPL_H
 _ACEOF
 
   fi
-  echo "$as_me:$LINENO: checking for snmp_build_var_op in -lsnmp" >&5
-echo $ECHO_N "checking for snmp_build_var_op in -lsnmp... $ECHO_C" >&6; }
+  echo "$as_me:$LINENO: checking for snmp_build_var_op in -lsnmp" >&5
+echo $ECHO_N "checking for snmp_build_var_op in -lsnmp... $ECHO_C" >&6
 
   old_LIBS="$LIBS"
   LIBS="$old_LIBS -lsnmp"
@@ -24650,36 +23960,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -24688,10 +23986,9 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       SNMP_LIBS=
+SNMP_LIBS=
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 
   if test "x$SNMP_LIBS" = "x"; then
@@ -24713,36 +24010,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -24751,10 +24036,9 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       SNMP_LIBS=
+SNMP_LIBS=
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
       if test "x$SNMP_LIBS" != "x"; then
         break;
@@ -24776,36 +24060,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -24814,10 +24086,9 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       SNMP_LIBS=
+SNMP_LIBS=
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
       if test "x$SNMP_LIBS" != "x"; then
         break;
@@ -24839,36 +24110,24 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -24877,10 +24136,9 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-       SNMP_LIBS=
+SNMP_LIBS=
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
       if test "x$SNMP_LIBS" != "x"; then
         break;
@@ -24891,18 +24149,20 @@ rm -f core conftest.err conftest.$ac_objext \
 
           CFLAGS="$old_CFLAGS"
   if test "x$SNMP_LIBS" = "x"; then
-    echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
+    echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
     SNMP_INCLUDE=
   else
-    { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-    cat >>confdefs.h <<\_ACEOF
-#define WITH_SNMP 1
+    echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+cat >>confdefs.h <<\_ACEOF
+#define WITH_SNMP
 _ACEOF
 
-    cat >>confdefs.h <<\_ACEOF
-#define HAVE_LIBSNMP 1
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBSNMP
 _ACEOF
 
   fi
 
 fi
 
+
+cat >>confdefs.h <<\_ACEOF
+#define GNUSTYLE 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define SYSVSTYLE 2
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define BSDSTYLE 3
+_ACEOF
+
 gethostbyaddrrstyle=""
-echo "$as_me:$LINENO: checking gethostbyaddr_r() syntax" >&5
-echo $ECHO_N "checking gethostbyaddr_r() syntax... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking gethostbyaddr_r() syntax" >&5
+echo $ECHO_N "checking gethostbyaddr_r() syntax... $ECHO_C" >&6
 case "$host" in
 *-freebsd*)
-       cat >>confdefs.h <<\_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
 #define GETHOSTBYADDRRSTYLE BSDSTYLE
 _ACEOF
 
@@ -24944,41 +24220,30 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
 
-       cat >>confdefs.h <<\_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
 #define GETHOSTBYADDRRSTYLE GNUSTYLE
 _ACEOF
 
@@ -24988,10 +24253,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 fi
 if test "x$gethostbyaddrrstyle" = "x"; then
@@ -25014,41 +24277,30 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
 
-               cat >>confdefs.h <<\_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
 #define GETHOSTBYADDRRSTYLE SYSVSTYLE
 _ACEOF
 
@@ -25058,10 +24310,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 fi
 if test "x$gethostbyaddrrstyle" = "x"; then
@@ -25084,41 +24334,30 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
 
-               cat >>confdefs.h <<\_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
 #define GETHOSTBYADDRRSTYLE BSDSTYLE
 _ACEOF
 
@@ -25128,19 +24367,17 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 fi
 
 if test "x$gethostbyaddrrstyle" = "x"; then
-       echo "$as_me:$LINENO: result: none!  It must not exist, here." >&5
-echo "${ECHO_T}none!  It must not exist, here." >&6; }
+       echo "$as_me:$LINENO: result: none!  It must not exist, here." >&5
+echo "${ECHO_T}none!  It must not exist, here." >&6
 else
-       echo "$as_me:$LINENO: result: ${gethostbyaddrrstyle}-style" >&5
-echo "${ECHO_T}${gethostbyaddrrstyle}-style" >&6; }
+       echo "$as_me:$LINENO: result: ${gethostbyaddrrstyle}-style" >&5
+echo "${ECHO_T}${gethostbyaddrrstyle}-style" >&6
 fi
 
 if test "x$gethostbyaddrrstyle" = "xBSD"; then
@@ -25149,8 +24386,8 @@ echo "$as_me: WARNING:  ****** BSD-style gethostbyaddr might NOT be thread-safe!
 fi
 
 gethostbynamerstyle=""
-echo "$as_me:$LINENO: checking gethostbyname_r() syntax" >&5
-echo $ECHO_N "checking gethostbyname_r() syntax... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking gethostbyname_r() syntax" >&5
+echo $ECHO_N "checking gethostbyname_r() syntax... $ECHO_C" >&6
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -25170,41 +24407,30 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
 
-       cat >>confdefs.h <<\_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
 #define GETHOSTBYNAMERSTYLE GNUSTYLE
 _ACEOF
 
@@ -25214,10 +24440,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 if test "x$gethostbynamerstyle" = "x"; then
        cat >conftest.$ac_ext <<_ACEOF
@@ -25239,41 +24463,30 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
 
-               cat >>confdefs.h <<\_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
 #define GETHOSTBYNAMERSTYLE SYSVSTYLE
 _ACEOF
 
@@ -25283,10 +24496,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 fi
 if test "x$gethostbynamerstyle" = "x"; then
@@ -25309,41 +24520,30 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
 
-               cat >>confdefs.h <<\_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
 #define GETHOSTBYNAMERSTYLE BSDSTYLE
 _ACEOF
 
@@ -25353,19 +24553,17 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 fi
 
 if test "x$gethostbynamerstyle" = "x"; then
-       echo "$as_me:$LINENO: result: none!  It must not exist, here." >&5
-echo "${ECHO_T}none!  It must not exist, here." >&6; }
+       echo "$as_me:$LINENO: result: none!  It must not exist, here." >&5
+echo "${ECHO_T}none!  It must not exist, here." >&6
 else
-       echo "$as_me:$LINENO: result: ${gethostbynamerstyle}-style" >&5
-echo "${ECHO_T}${gethostbynamerstyle}-style" >&6; }
+       echo "$as_me:$LINENO: result: ${gethostbynamerstyle}-style" >&5
+echo "${ECHO_T}${gethostbynamerstyle}-style" >&6
 fi
 
 if test "x$gethostbynamerstyle" = "xBSD"; then
@@ -25373,9 +24571,19 @@ if test "x$gethostbynamerstyle" = "xBSD"; then
 echo "$as_me: WARNING:  ****** BSD-style gethostbyname might NOT be thread-safe! ****** " >&2;}
 fi
 
+
+cat >>confdefs.h <<\_ACEOF
+#define POSIXSTYLE 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define SOLARISSTYLE 2
+_ACEOF
+
 ctimerstyle=""
-echo "$as_me:$LINENO: checking ctime_r() syntax" >&5
-echo $ECHO_N "checking ctime_r() syntax... $ECHO_C" >&6; }
+echo "$as_me:$LINENO: checking ctime_r() syntax" >&5
+echo $ECHO_N "checking ctime_r() syntax... $ECHO_C" >&6
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -25394,41 +24602,30 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
 
-       cat >>confdefs.h <<\_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
 #define CTIMERSTYLE SOLARISSTYLE
 _ACEOF
 
@@ -25438,10 +24635,8 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 if test "x$ctimerstyle" = "x"; then
        cat >conftest.$ac_ext <<_ACEOF
@@ -25462,41 +24657,30 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext conftest$ac_exeext
-if { (ac_try="$ac_link"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_link") 2>conftest.er1
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+        { ac_try='test -z "$ac_c_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest$ac_exeext'
-  { (case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-  (eval "$ac_try") 2>&5
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
 
-               cat >>confdefs.h <<\_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
 #define CTIMERSTYLE POSIXSTYLE
 _ACEOF
 
@@ -25506,129 +24690,17 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-
 fi
-
-rm -f core conftest.err conftest.$ac_objext \
+rm -f conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 fi
 
 if test "x$ctimerstyle" = "x"; then
-       { echo "$as_me:$LINENO: result: none!  It must not exist, here." >&5
-echo "${ECHO_T}none!  It must not exist, here." >&6; }
-else
-        { echo "$as_me:$LINENO: result: ${ctimerstyle}-style" >&5
-echo "${ECHO_T}${ctimerstyle}-style" >&6; }
-fi
-
-
-if test x"$rad_enable_largefiles" = xyes ; then
-    { echo "$as_me:$LINENO: checking for largefile linkage" >&5
-echo $ECHO_N "checking for largefile linkage... $ECHO_C" >&6; }
-    case "$host" in
-    *-aix4.01*)
-        { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-        { { echo "$as_me:$LINENO: error: AIX before 4.2 does not support large files" >&5
-echo "$as_me: error: AIX before 4.2 does not support large files" >&2;}
-   { (exit 1); exit 1; }; }
-        ;;
-    *-aix4*)
-        { echo "$as_me:$LINENO: result: ok" >&5
-echo "${ECHO_T}ok" >&6; }
-        LFS_CFLAGS="-D_LARGE_FILES"
-        LFS_LDFLAGS=""
-        LFS_LIBS=""
-        ;;
-    *-hpux*)
-        { echo "$as_me:$LINENO: result: ok" >&5
-echo "${ECHO_T}ok" >&6; }
-        LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
-        LFS_LDFLAGS=""
-        LFS_LIBS=""
-        ;;
-    *-irix*)
-        { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-        { { echo "$as_me:$LINENO: error: Large files not supported on this platform" >&5
-echo "$as_me: error: Large files not supported on this platform" >&2;}
-   { (exit 1); exit 1; }; }
-        ;;
-    *-linux*)
-        { echo "$as_me:$LINENO: result: maybe" >&5
-echo "${ECHO_T}maybe" >&6; }
-        LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
-        LFS_LDFLAGS=""
-        LFS_LIBS=""
-
-cat >>confdefs.h <<\_ACEOF
-#define _GNU_SOURCE 1
-_ACEOF
-
-        ;;
-    *-solaris*)
-        { echo "$as_me:$LINENO: result: ok" >&5
-echo "${ECHO_T}ok" >&6; }
-        # Extract the first word of "getconf", so it can be a program name with args.
-set dummy getconf; ac_word=$2
-{ echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
-if test "${ac_cv_path_GETCONF+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  case $GETCONF in
-  [\\/]* | ?:[\\/]*)
-  ac_cv_path_GETCONF="$GETCONF" # Let the user override the test with a path.
-  ;;
-  *)
-  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
-    ac_cv_path_GETCONF="$as_dir/$ac_word$ac_exec_ext"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-IFS=$as_save_IFS
-
-  ;;
-esac
-fi
-GETCONF=$ac_cv_path_GETCONF
-if test -n "$GETCONF"; then
-  { echo "$as_me:$LINENO: result: $GETCONF" >&5
-echo "${ECHO_T}$GETCONF" >&6; }
+       echo "$as_me:$LINENO: result: none!  It must not exist, here." >&5
+echo "${ECHO_T}none!  It must not exist, here." >&6
 else
-  { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
-fi
-
-
-        if test -z "$GETCONF" ; then
-            { { echo "$as_me:$LINENO: error: getconf required to configure large file support" >&5
-echo "$as_me: error: getconf required to configure large file support" >&2;}
-   { (exit 1); exit 1; }; }
-        fi
-        LFS_CFLAGS=`$GETCONF LFS_CFLAGS`
-        LFS_LDFLAGS=`$GETCONF LFS_LDFLAGS`
-        LFS_LIBS=`$GETCONF LFS_LIBS`
-        ;;
-    *)
-        { echo "$as_me:$LINENO: result: maybe" >&5
-echo "${ECHO_T}maybe" >&6; }
-        LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
-        LFS_LDFLAGS=""
-        LFS_LIBS=""
-        ;;
-    esac
-
-
-
+        echo "$as_me:$LINENO: result: ${ctimerstyle}-style" >&5
+echo "${ECHO_T}${ctimerstyle}-style" >&6
 fi
 
 HOSTINFO=$host
@@ -25637,40 +24709,51 @@ HOSTINFO=$host
 
 top_builddir=`pwd`
 export top_builddir
-echo "$as_me:$LINENO: result: top_builddir=$top_builddir" >&5
-echo "${ECHO_T}top_builddir=$top_builddir" >&6; }
+echo "$as_me:$LINENO: result: top_builddir=$top_builddir" >&5
+echo "${ECHO_T}top_builddir=$top_builddir" >&6
 
 
 
 
 
-mysubdirs=
+mysubdirs="$LIBLTDLPATH"
 if test "x$EXPERIMENTAL" = "xyes"; then
-  bar=`ls -1 src/modules/rlm_*/configure | sed 's%/configure%%'`
-    mysubdirs=`echo $bar`
+  bar=`ls -1 "${srcdir}"/src/modules/rlm_*/configure | sed 's%/configure%%'`
+    mysubdirs=`echo $mysubdirs $bar`
 else
-        for bar in `cat src/modules/stable`; do
-    if test -f src/modules/$bar/configure; then
+        for bar in `cat "${srcdir}"/src/modules/stable`; do
+    if test -f "${srcdir}"/src/modules/$bar/configure; then
       mysubdirs="$mysubdirs src/modules/$bar"
     fi
   done
 fi
 
 if test "x$EXPERIMENTAL" = "xyes"; then
-  for foo in `ls -1 src/modules | grep rlm_`; do
+  for foo in `ls -1 "${srcdir}"/src/modules | grep rlm_`; do
     MODULES="$MODULES $foo"
   done
 else
-            for foo in `cat src/modules/stable`; do
+            for foo in `cat "${srcdir}"/src/modules/stable`; do
     MODULES="$MODULES $foo"
    done
 fi
 
+
+
 subdirs="$subdirs $LTDL_SUBDIRS $mysubdirs"
 
 
 
 
+          ac_config_commands="$ac_config_commands stamp-h"
+
+          ac_config_commands="$ac_config_commands build-radpaths-h"
+
+          ac_config_commands="$ac_config_commands main-chmod"
+
+          ac_config_commands="$ac_config_commands scripts-chmod"
+
+
 
 
 
@@ -25682,10 +24765,8 @@ USE_STATIC_LIBS=$enable_static
 
 
 
-export CFLAGS LIBS
-
-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/check-radiusd-config ./scripts/radiusd.cron.daily ./scripts/radiusd.cron.monthly ./scripts/cryptpasswd ./raddb/dictionary ./raddb/radiusd.conf"
 
+                                                                                                                                                      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/check-radiusd-config ./scripts/radiusd.cron.daily ./scripts/radiusd.cron.monthly ./scripts/cryptpasswd ./raddb/dictionary ./raddb/radiusd.conf ./raddb/radrelay.conf"
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
 # tests run on this system so they can be shared between configure
@@ -25704,58 +24785,39 @@ _ACEOF
 
 # The following way of writing the cache mishandles newlines in values,
 # but we know of no workaround that is simple, portable, and efficient.
-# So, we kill variables containing newlines.
+# So, don't put newlines in cache variables' values.
 # Ultrix sh set writes to stderr and can't be redirected directly,
 # and sets the high bit in the cache file unless we assign to the vars.
-(
-  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
-    eval ac_val=\$$ac_var
-    case $ac_val in #(
-    *${as_nl}*)
-      case $ac_var in #(
-      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
-echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
-      esac
-      case $ac_var in #(
-      _ | IFS | as_nl) ;; #(
-      *) $as_unset $ac_var ;;
-      esac ;;
-    esac
-  done
-
+{
   (set) 2>&1 |
-    case $as_nl`(ac_space=' '; set) 2>&1` in #(
-    *${as_nl}ac_space=\ *)
+    case `(ac_space=' '; set | grep ac_space) 2>&1` in
+    *ac_space=\ *)
       # `set' does not quote correctly, so add quotes (double-quote
       # substitution turns \\\\ into \\, and sed turns \\ into \).
       sed -n \
        "s/'/'\\\\''/g;
          s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
-      ;; #(
+      ;;
     *)
       # `set' quotes correctly as required by POSIX, so do not add quotes.
-      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      sed -n \
+       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
       ;;
-    esac |
-    sort
-) |
+    esac;
+} |
   sed '
-     /^ac_cv_env_/b end
      t clear
-     :clear
+     : clear
      s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
      t end
-     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
-     :end' >>confcache
-if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
-  if test -w "$cache_file"; then
-    test "x$cache_file" != "x/dev/null" &&
-      { echo "$as_me:$LINENO: updating cache $cache_file" >&5
-echo "$as_me: updating cache $cache_file" >&6;}
+     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+  if test -w $cache_file; then
+    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
     cat confcache >$cache_file
   else
-    { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
-echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+    echo "not updating unwritable cache $cache_file"
   fi
 fi
 rm -f confcache
@@ -25764,18 +24826,32 @@ test "x$prefix" = xNONE && prefix=$ac_default_prefix
 # Let make expand exec_prefix.
 test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
 
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[    ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[      ]*$//;
+}'
+fi
+
 DEFS=-DHAVE_CONFIG_H
 
 ac_libobjs=
 ac_ltlibobjs=
 for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
   # 1. Remove the extension, and $U if already installed.
-  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
-  ac_i=`echo "$ac_i" | sed "$ac_script"`
-  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
-  #    will be set to the directory where LIBOBJS objects are built.
-  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
-  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+  ac_i=`echo "$ac_i" |
+        sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+  # 2. Add them.
+  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
 done
 LIBOBJS=$ac_libobjs
 
@@ -25813,35 +24889,11 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
   # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
   # is contrary to our usage.  Disable this feature.
   alias -g '${1+"$@"}'='"$@"'
-  setopt NO_GLOB_SUBST
-else
-  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+  set -o posix
 fi
-BIN_SH=xpg4; export BIN_SH # for Tru64
 DUALCASE=1; export DUALCASE # for MKS sh
 
-
-# PATH needs CR
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
-fi
-
 # Support unset when possible.
 if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
   as_unset=unset
@@ -25850,43 +24902,8 @@ else
 fi
 
 
-# IFS
-# We need space, tab and new line, in precisely that order.  Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-as_nl='
-'
-IFS=" ""       $as_nl"
-
-# Find who we are.  Look in the path if we contain no directory separator.
-case $0 in
-  *[\\/]* ) as_myself=$0 ;;
-  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-IFS=$as_save_IFS
-
-     ;;
-esac
-# We did not find ourselves, most probably we were run as `sh COMMAND'
-# in which case we are not to be found in the path.
-if test "x$as_myself" = x; then
-  as_myself=$0
-fi
-if test ! -f "$as_myself"; then
-  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
-  { (exit 1); exit 1; }
-fi
-
 # Work around bugs in pre-3.0 UWIN ksh.
-for as_var in ENV MAIL MAILPATH
-do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
-done
+$as_unset ENV MAIL MAILPATH
 PS1='$ '
 PS2='> '
 PS4='+ '
   if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
     eval $as_var=C; export $as_var
   else
-    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+    $as_unset $as_var
   fi
 done
 
 # Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1 &&
-   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+if expr a : '\(a\)' >/dev/null 2>&1; then
   as_expr=expr
 else
   as_expr=false
 fi
 
-if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
   as_basename=basename
 else
   as_basename=false
 
 
 # Name of the executable.
-as_me=`$as_basename -- "$0" ||
+as_me=`$as_basename "$0" ||
 $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
         X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+        X"$0" : 'X\(/\)$' \| \
+        .     : '\(.\)' 2>/dev/null ||
 echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{
-           s//\1/
-           q
-         }
-         /^X\/\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\/\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
+    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+         /^X\/\(\/\/\)$/{ s//\1/; q; }
+         /^X\/\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
 
-# CDPATH.
-$as_unset CDPATH
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
 
 
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
+  # Find who we are.  Look in the path if we contain no path at all
+  # relative or not.
+  case $0 in
+    *[\\/]* ) as_myself=$0 ;;
+    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
 
+       ;;
+  esac
+  # We did not find ourselves, most probably we were run as `sh COMMAND'
+  # in which case we are not to be found in the path.
+  if test "x$as_myself" = x; then
+    as_myself=$0
+  fi
+  if test ! -f "$as_myself"; then
+    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+  case $CONFIG_SHELL in
+  '')
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for as_base in sh bash ksh sh5; do
+        case $as_dir in
+        /*)
+          if ("$as_dir/$as_base" -c '
   as_lineno_1=$LINENO
   as_lineno_2=$LINENO
+  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
   test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
+            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+            CONFIG_SHELL=$as_dir/$as_base
+            export CONFIG_SHELL
+            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+          fi;;
+        esac
+       done
+done
+;;
+  esac
 
   # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
   # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line after each line using $LINENO; the second 'sed'
-  # does the real work.  The second script uses 'N' to pair each
-  # line-number line with the line containing $LINENO, and appends
-  # trailing '-' during substitution so that $LINENO is not a special
-  # case at line end.
+  # line-number line before each line; the second 'sed' does the real
+  # work.  The second script uses 'N' to pair each line-number line
+  # with the numbered line, and appends trailing '-' during
+  # substitution so that $LINENO is not a special case at line end.
   # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # scripts with optimization help from Paolo Bonzini.  Blame Lee
-  # E. McMahon (1931-1989) for sed's syntax.  :-)
-  sed -n '
-    p
-    /[$]LINENO/=
-  ' <$as_myself |
+  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
+  sed '=' <$as_myself |
     sed '
-      s/[$]LINENO.*/&-/
-      t lineno
-      b
-      :lineno
       N
-      :loop
-      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      s,$,-,
+      : loop
+      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
       t loop
-      s/-\n.*//
+      s,-$,,
+      s,^['$as_cr_digits']*\n,,
     ' >$as_me.lineno &&
-  chmod +x "$as_me.lineno" ||
-    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+  chmod +x $as_me.lineno ||
+    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
    { (exit 1); exit 1; }; }
 
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensitive to this).
-  . "./$as_me.lineno"
+  # original and so on.  Autoconf is especially sensible to this).
+  . ./$as_me.lineno
   # Exit status is that of the last command.
   exit
 }
 
 
-if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
-  as_dirname=dirname
-else
-  as_dirname=false
-fi
-
-ECHO_C= ECHO_N= ECHO_T=
-case `echo -n x` in
--n*)
-  case `echo 'x\c'` in
-  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
-  *)   ECHO_C='\c';;
-  esac;;
-*)
-  ECHO_N='-n';;
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+  *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T='     ' ;;
+  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
 esac
 
-if expr a : '\(a\)' >/dev/null 2>&1 &&
-   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+if expr a : '\(a\)' >/dev/null 2>&1; then
   as_expr=expr
 else
   as_expr=false
 fi
 
 rm -f conf$$ conf$$.exe conf$$.file
-if test -d conf$$.dir; then
-  rm -f conf$$.dir/conf$$.file
-else
-  rm -f conf$$.dir
-  mkdir conf$$.dir
-fi
 echo >conf$$.file
 if ln -s conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s='ln -s'
-  # ... but there are two gotchas:
-  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
-  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-  # In both cases, we have to default to `cp -p'.
-  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+  # We could just check for DJGPP; but this test a) works b) is more generic
+  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+  if test -f conf$$.exe; then
+    # Don't use ln at all; we don't have any links
     as_ln_s='cp -p'
+  else
+    as_ln_s='ln -s'
+  fi
 elif ln conf$$.file conf$$ 2>/dev/null; then
   as_ln_s=ln
 else
   as_ln_s='cp -p'
 fi
-rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
-rmdir conf$$.dir 2>/dev/null
+rm -f conf$$ conf$$.exe conf$$.file
 
 if mkdir -p . 2>/dev/null; then
   as_mkdir_p=:
@@ -26042,19 +25097,7 @@ else
   as_mkdir_p=false
 fi
 
-# Find out whether ``test -x'' works.  Don't use a zero-byte file, as
-# systems may use methods other than mode bits to determine executability.
-cat >conf$$.file <<_ASEOF
-#! /bin/sh
-exit 0
-_ASEOF
-chmod +x conf$$.file
-if test -x conf$$.file >/dev/null 2>&1; then
-  as_executable_p="test -x"
-else
-  as_executable_p=:
-fi
-rm -f conf$$.file
+as_executable_p="test -f"
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -26063,14 +25106,31 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
 as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
 
 
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS="  $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
 exec 6>&1
 
-# Save the log message, to keep $[0] and so on meaningful, and to
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
 # report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling.
-ac_log="
+# values after options handling.  Logging --version etc. is OK.
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
 This file was extended by $as_me, which was
-generated by GNU Autoconf 2.60.  Invocation command line was
+generated by GNU Autoconf 2.59.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -26078,19 +25138,30 @@ generated by GNU Autoconf 2.60.  Invocation command line was
   CONFIG_COMMANDS = $CONFIG_COMMANDS
   $ $0 $@
 
-on `(hostname || uname -n) 2>/dev/null | sed 1q`
-"
-
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
 _ACEOF
 
-cat >>$CONFIG_STATUS <<_ACEOF
 # Files that config.status was made for.
-config_files="$ac_config_files"
-config_headers="$ac_config_headers"
+if test -n "$ac_config_files"; then
+  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
 
-_ACEOF
+if test -n "$ac_config_headers"; then
+  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
 
 cat >>$CONFIG_STATUS <<\_ACEOF
+
 ac_cs_usage="\
 \`$as_me' instantiates files from templates according to the
 current configuration.
@@ -26113,21 +25184,22 @@ $config_files
 Configuration headers:
 $config_headers
 
-Report bugs to <bug-autoconf@gnu.org>."
+Configuration commands:
+$config_commands
 
+Report bugs to <bug-autoconf@gnu.org>."
 _ACEOF
+
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
 config.status
-configured by $0, generated by GNU Autoconf 2.60,
-  with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+configured by $0, generated by GNU Autoconf 2.59,
+  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
 
-Copyright (C) 2006 Free Software Foundation, Inc.
+Copyright (C) 2003 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
-
-ac_pwd='$ac_pwd'
-srcdir='$srcdir'
+srcdir=$srcdir
 _ACEOF
 
 cat >>$CONFIG_STATUS <<\_ACEOF
@@ -26138,24 +25210,39 @@ while test $# != 0
 do
   case $1 in
   --*=*)
-    ac_option=`expr "X$1" : 'X\([^=]*\)='`
-    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_option=`expr "x$1" : 'x\([^=]*\)='`
+    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
     ac_shift=:
     ;;
-  *)
+  -*)
     ac_option=$1
     ac_optarg=$2
     ac_shift=shift
     ;;
+  *) # This is not an option, so the user has probably given explicit
+     # arguments.
+     ac_option=$1
+     ac_need_defaults=false;;
   esac
 
   case $ac_option in
   # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
   -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
     ac_cs_recheck=: ;;
-  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
-    echo "$ac_cs_version"; exit ;;
-  --debug | --debu | --deb | --de | --d | -d )
+  --version | --vers* | -V )
+    echo "$ac_cs_version"; exit 0 ;;
+  --he | --h)
+    # Conflict between --help and --header
+    { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit 0 ;;
+  --debug | --d* | -d )
     debug=: ;;
   --file | --fil | --fi | --f )
     $ac_shift
     $ac_shift
     CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
     ac_need_defaults=false;;
-  --he | --h)
-    # Conflict between --help and --header
-    { echo "$as_me: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&2
-   { (exit 1); exit 1; }; };;
-  --help | --hel | -h )
-    echo "$ac_cs_usage"; exit ;;
   -q | -quiet | --quiet | --quie | --qui | --qu | --q \
   | -silent | --silent | --silen | --sile | --sil | --si | --s)
     ac_cs_silent=: ;;
 
   # This is an error.
-  -*) { echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2
+  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
    { (exit 1); exit 1; }; } ;;
 
-  *) ac_config_targets="$ac_config_targets $1"
-     ac_need_defaults=false ;;
+  *) ac_config_targets="$ac_config_targets $1" ;;
 
   esac
   shift
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 if \$ac_cs_recheck; then
-  echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
-  CONFIG_SHELL=$SHELL
-  export CONFIG_SHELL
-  exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
 fi
 
 _ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-exec 5>>config.log
-{
-  echo
-  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
-  echo "$ac_log"
-} >&5
 
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-_ACEOF
 
-cat >>$CONFIG_STATUS <<\_ACEOF
 
-# Handling of arguments.
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
 for ac_config_target in $ac_config_targets
 do
-  case $ac_config_target in
-    "src/include/autoconf.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/autoconf.h" ;;
-    "./Make.inc") CONFIG_FILES="$CONFIG_FILES ./Make.inc" ;;
-    "./src/include/build-radpaths-h") CONFIG_FILES="$CONFIG_FILES ./src/include/build-radpaths-h" ;;
-    "./src/main/Makefile") CONFIG_FILES="$CONFIG_FILES ./src/main/Makefile" ;;
-    "./src/main/checkrad.pl") CONFIG_FILES="$CONFIG_FILES ./src/main/checkrad.pl" ;;
-    "./src/main/radlast") CONFIG_FILES="$CONFIG_FILES ./src/main/radlast" ;;
-    "./src/main/radtest") CONFIG_FILES="$CONFIG_FILES ./src/main/radtest" ;;
-    "./scripts/rc.radiusd") CONFIG_FILES="$CONFIG_FILES ./scripts/rc.radiusd" ;;
-    "./scripts/radwatch") CONFIG_FILES="$CONFIG_FILES ./scripts/radwatch" ;;
-    "./scripts/check-radiusd-config") CONFIG_FILES="$CONFIG_FILES ./scripts/check-radiusd-config" ;;
-    "./scripts/radiusd.cron.daily") CONFIG_FILES="$CONFIG_FILES ./scripts/radiusd.cron.daily" ;;
-    "./scripts/radiusd.cron.monthly") CONFIG_FILES="$CONFIG_FILES ./scripts/radiusd.cron.monthly" ;;
-    "./scripts/cryptpasswd") CONFIG_FILES="$CONFIG_FILES ./scripts/cryptpasswd" ;;
-    "./raddb/dictionary") CONFIG_FILES="$CONFIG_FILES ./raddb/dictionary" ;;
-    "./raddb/radiusd.conf") CONFIG_FILES="$CONFIG_FILES ./raddb/radiusd.conf" ;;
-
+  case "$ac_config_target" in
+  # Handling of arguments.
+  "./Make.inc" ) CONFIG_FILES="$CONFIG_FILES ./Make.inc" ;;
+  "./src/include/build-radpaths-h" ) CONFIG_FILES="$CONFIG_FILES ./src/include/build-radpaths-h" ;;
+  "./src/main/Makefile" ) CONFIG_FILES="$CONFIG_FILES ./src/main/Makefile" ;;
+  "./src/main/checkrad.pl" ) CONFIG_FILES="$CONFIG_FILES ./src/main/checkrad.pl" ;;
+  "./src/main/radlast" ) CONFIG_FILES="$CONFIG_FILES ./src/main/radlast" ;;
+  "./src/main/radtest" ) CONFIG_FILES="$CONFIG_FILES ./src/main/radtest" ;;
+  "./scripts/rc.radiusd" ) CONFIG_FILES="$CONFIG_FILES ./scripts/rc.radiusd" ;;
+  "./scripts/radwatch" ) CONFIG_FILES="$CONFIG_FILES ./scripts/radwatch" ;;
+  "./scripts/check-radiusd-config" ) CONFIG_FILES="$CONFIG_FILES ./scripts/check-radiusd-config" ;;
+  "./scripts/radiusd.cron.daily" ) CONFIG_FILES="$CONFIG_FILES ./scripts/radiusd.cron.daily" ;;
+  "./scripts/radiusd.cron.monthly" ) CONFIG_FILES="$CONFIG_FILES ./scripts/radiusd.cron.monthly" ;;
+  "./scripts/cryptpasswd" ) CONFIG_FILES="$CONFIG_FILES ./scripts/cryptpasswd" ;;
+  "./raddb/dictionary" ) CONFIG_FILES="$CONFIG_FILES ./raddb/dictionary" ;;
+  "./raddb/radiusd.conf" ) CONFIG_FILES="$CONFIG_FILES ./raddb/radiusd.conf" ;;
+  "./raddb/radrelay.conf" ) CONFIG_FILES="$CONFIG_FILES ./raddb/radrelay.conf" ;;
+  "stamp-h" ) CONFIG_COMMANDS="$CONFIG_COMMANDS stamp-h" ;;
+  "build-radpaths-h" ) CONFIG_COMMANDS="$CONFIG_COMMANDS build-radpaths-h" ;;
+  "main-chmod" ) CONFIG_COMMANDS="$CONFIG_COMMANDS main-chmod" ;;
+  "scripts-chmod" ) CONFIG_COMMANDS="$CONFIG_COMMANDS scripts-chmod" ;;
+  "src/include/autoconf.h" ) CONFIG_HEADERS="$CONFIG_HEADERS src/include/autoconf.h" ;;
   *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
 echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
    { (exit 1); exit 1; }; };;
   esac
 done
 
-
 # If the user did not use the arguments to specify the items to instantiate,
 # then the envvar interface is used.  Set only those that are not.
 # We use the long form for the default assignment because of an extremely
 if $ac_need_defaults; then
   test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
   test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
 fi
 
 # Have a temporary directory for convenience.  Make it in the build tree
-# simply because there is no reason against having it here, and in addition,
+# simply because there is no reason to put it here, and in addition,
 # creating and moving files from /tmp can sometimes cause problems.
-# Hook for its removal unless debugging.
-# Note that there is a small window in which the directory will not be cleaned:
-# after its creation but before its name has been assigned to `$tmp'.
+# Create a temporary directory, and hook for its removal unless debugging.
 $debug ||
 {
-  tmp=
-  trap 'exit_status=$?
-  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
-' 0
+  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
   trap '{ (exit 1); exit 1; }' 1 2 13 15
 }
+
 # Create a (secure) tmp directory for tmp files.
 
 {
-  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
   test -n "$tmp" && test -d "$tmp"
 }  ||
 {
-  tmp=./conf$$-$RANDOM
-  (umask 077 && mkdir "$tmp")
+  tmp=./confstat$$-$RANDOM
+  (umask 077 && mkdir $tmp)
 } ||
 {
    echo "$me: cannot create a temporary directory in ." >&2
    { (exit 1); exit 1; }
 }
 
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
 #
-# Set up the sed scripts for CONFIG_FILES section.
+# CONFIG_FILES section.
 #
 
 # No need to generate the scripts if there are no CONFIG_FILES.
 # This happens for instance when ./config.status config.h
-if test -n "$CONFIG_FILES"; then
-
-_ACEOF
-
-
-
-ac_delim='%!_!# '
-for ac_last_try in false false false false false :; do
-  cat >conf$$subs.sed <<_ACEOF
-SHELL!$SHELL$ac_delim
-PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
-PACKAGE_NAME!$PACKAGE_NAME$ac_delim
-PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
-PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
-PACKAGE_STRING!$PACKAGE_STRING$ac_delim
-PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
-exec_prefix!$exec_prefix$ac_delim
-prefix!$prefix$ac_delim
-program_transform_name!$program_transform_name$ac_delim
-bindir!$bindir$ac_delim
-sbindir!$sbindir$ac_delim
-libexecdir!$libexecdir$ac_delim
-datarootdir!$datarootdir$ac_delim
-datadir!$datadir$ac_delim
-sysconfdir!$sysconfdir$ac_delim
-sharedstatedir!$sharedstatedir$ac_delim
-localstatedir!$localstatedir$ac_delim
-includedir!$includedir$ac_delim
-oldincludedir!$oldincludedir$ac_delim
-docdir!$docdir$ac_delim
-infodir!$infodir$ac_delim
-htmldir!$htmldir$ac_delim
-dvidir!$dvidir$ac_delim
-pdfdir!$pdfdir$ac_delim
-psdir!$psdir$ac_delim
-libdir!$libdir$ac_delim
-localedir!$localedir$ac_delim
-mandir!$mandir$ac_delim
-DEFS!$DEFS$ac_delim
-ECHO_C!$ECHO_C$ac_delim
-ECHO_N!$ECHO_N$ac_delim
-ECHO_T!$ECHO_T$ac_delim
-LIBS!$LIBS$ac_delim
-build_alias!$build_alias$ac_delim
-host_alias!$host_alias$ac_delim
-target_alias!$target_alias$ac_delim
-CC!$CC$ac_delim
-CFLAGS!$CFLAGS$ac_delim
-LDFLAGS!$LDFLAGS$ac_delim
-CPPFLAGS!$CPPFLAGS$ac_delim
-ac_ct_CC!$ac_ct_CC$ac_delim
-EXEEXT!$EXEEXT$ac_delim
-OBJEXT!$OBJEXT$ac_delim
-CPP!$CPP$ac_delim
-GREP!$GREP$ac_delim
-EGREP!$EGREP$ac_delim
-RANLIB!$RANLIB$ac_delim
-abs_top_builddir!$abs_top_builddir$ac_delim
-GMAKE!$GMAKE$ac_delim
-MAKE!$MAKE$ac_delim
-LTDL_SUBDIRS!$LTDL_SUBDIRS$ac_delim
-LIBTOOL!$LIBTOOL$ac_delim
-build!$build$ac_delim
-build_cpu!$build_cpu$ac_delim
-build_vendor!$build_vendor$ac_delim
-build_os!$build_os$ac_delim
-host!$host$ac_delim
-host_cpu!$host_cpu$ac_delim
-host_vendor!$host_vendor$ac_delim
-host_os!$host_os$ac_delim
-LN_S!$LN_S$ac_delim
-ECHO!$ECHO$ac_delim
-AR!$AR$ac_delim
-STRIP!$STRIP$ac_delim
-CXX!$CXX$ac_delim
-CXXFLAGS!$CXXFLAGS$ac_delim
-ac_ct_CXX!$ac_ct_CXX$ac_delim
-CXXCPP!$CXXCPP$ac_delim
-F77!$F77$ac_delim
-FFLAGS!$FFLAGS$ac_delim
-ac_ct_F77!$ac_ct_F77$ac_delim
-logdir!$logdir$ac_delim
-radacctdir!$radacctdir$ac_delim
-raddbdir!$raddbdir$ac_delim
-PERL!$PERL$ac_delim
-SNMPGET!$SNMPGET$ac_delim
-SNMPWALK!$SNMPWALK$ac_delim
-RUSERS!$RUSERS$ac_delim
-ACLOCAL!$ACLOCAL$ac_delim
-AUTOCONF!$AUTOCONF$ac_delim
-AUTOHEADER!$AUTOHEADER$ac_delim
-LOCATE!$LOCATE$ac_delim
-DIRNAME!$DIRNAME$ac_delim
-REGEX!$REGEX$ac_delim
-REGEX_EXTENDED!$REGEX_EXTENDED$ac_delim
-OPENSSL_INCLUDE!$OPENSSL_INCLUDE$ac_delim
-OPENSSL_LIBS!$OPENSSL_LIBS$ac_delim
-LIBPREFIX!$LIBPREFIX$ac_delim
-CRYPTLIB!$CRYPTLIB$ac_delim
-SNMP_LIBS!$SNMP_LIBS$ac_delim
-SNMP_INCLUDE!$SNMP_INCLUDE$ac_delim
-GETCONF!$GETCONF$ac_delim
-LFS_CFLAGS!$LFS_CFLAGS$ac_delim
-LFS_LDFLAGS!$LFS_LDFLAGS$ac_delim
-LFS_LIBS!$LFS_LIBS$ac_delim
-HOSTINFO!$HOSTINFO$ac_delim
-_ACEOF
-
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
-    break
-  elif $ac_last_try; then
-    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
-echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
-   { (exit 1); exit 1; }; }
-  else
-    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
-  fi
-done
-
-ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
-if test -n "$ac_eof"; then
-  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
-  ac_eof=`expr $ac_eof + 1`
-fi
-
-cat >>$CONFIG_STATUS <<_ACEOF
-cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-_ACEOF
-sed '
-s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
-s/^/s,@/; s/!/@,|#_!!_#|/
-:n
-t n
-s/'"$ac_delim"'$/,g/; t
-s/$/\\/; p
-N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
-' >>$CONFIG_STATUS <conf$$subs.sed
-rm -f conf$$subs.sed
-cat >>$CONFIG_STATUS <<_ACEOF
-CEOF$ac_eof
-_ACEOF
-
-
-ac_delim='%!_!# '
-for ac_last_try in false false false false false :; do
-  cat >conf$$subs.sed <<_ACEOF
-LIBLTDL!$LIBLTDL$ac_delim
-INCLTDL!$INCLTDL$ac_delim
-subdirs!$subdirs$ac_delim
-MODULES!$MODULES$ac_delim
-INSTALLSTRIP!$INSTALLSTRIP$ac_delim
-USE_SHARED_LIBS!$USE_SHARED_LIBS$ac_delim
-USE_STATIC_LIBS!$USE_STATIC_LIBS$ac_delim
-STATIC_MODULES!$STATIC_MODULES$ac_delim
-RADIUSD_MAJOR_VERSION!$RADIUSD_MAJOR_VERSION$ac_delim
-RADIUSD_MINOR_VERSION!$RADIUSD_MINOR_VERSION$ac_delim
-RADIUSD_VERSION!$RADIUSD_VERSION$ac_delim
-LIBOBJS!$LIBOBJS$ac_delim
-LTLIBOBJS!$LTLIBOBJS$ac_delim
-_ACEOF
-
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 13; then
-    break
-  elif $ac_last_try; then
-    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
-echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
-   { (exit 1); exit 1; }; }
-  else
-    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+if test -n "\$CONFIG_FILES"; then
+  # Protect against being on the right side of a sed subst in config.status.
+  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@CXX@,$CXX,;t t
+s,@CXXFLAGS@,$CXXFLAGS,;t t
+s,@ac_ct_CXX@,$ac_ct_CXX,;t t
+s,@CPP@,$CPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@GMAKE@,$GMAKE,;t t
+s,@MAKE@,$MAKE,;t t
+s,@LTDL_SUBDIRS@,$LTDL_SUBDIRS,;t t
+s,@LIBTOOL@,$LIBTOOL,;t t
+s,@build@,$build,;t t
+s,@build_cpu@,$build_cpu,;t t
+s,@build_vendor@,$build_vendor,;t t
+s,@build_os@,$build_os,;t t
+s,@host@,$host,;t t
+s,@host_cpu@,$host_cpu,;t t
+s,@host_vendor@,$host_vendor,;t t
+s,@host_os@,$host_os,;t t
+s,@LN_S@,$LN_S,;t t
+s,@ECHO@,$ECHO,;t t
+s,@AR@,$AR,;t t
+s,@ac_ct_AR@,$ac_ct_AR,;t t
+s,@STRIP@,$STRIP,;t t
+s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t
+s,@CXXCPP@,$CXXCPP,;t t
+s,@F77@,$F77,;t t
+s,@FFLAGS@,$FFLAGS,;t t
+s,@ac_ct_F77@,$ac_ct_F77,;t t
+s,@docdir@,$docdir,;t t
+s,@logdir@,$logdir,;t t
+s,@radacctdir@,$radacctdir,;t t
+s,@raddbdir@,$raddbdir,;t t
+s,@PERL@,$PERL,;t t
+s,@SNMPGET@,$SNMPGET,;t t
+s,@SNMPWALK@,$SNMPWALK,;t t
+s,@RUSERS@,$RUSERS,;t t
+s,@ACLOCAL@,$ACLOCAL,;t t
+s,@AUTOCONF@,$AUTOCONF,;t t
+s,@AUTOHEADER@,$AUTOHEADER,;t t
+s,@LOCATE@,$LOCATE,;t t
+s,@DIRNAME@,$DIRNAME,;t t
+s,@GREP@,$GREP,;t t
+s,@REGEX@,$REGEX,;t t
+s,@REGEX_EXTENDED@,$REGEX_EXTENDED,;t t
+s,@OPENSSL_INCLUDE@,$OPENSSL_INCLUDE,;t t
+s,@OPENSSL_LIBS@,$OPENSSL_LIBS,;t t
+s,@PCAP_LIBS@,$PCAP_LIBS,;t t
+s,@LIBPREFIX@,$LIBPREFIX,;t t
+s,@CRYPTLIB@,$CRYPTLIB,;t t
+s,@SNMP_LIBS@,$SNMP_LIBS,;t t
+s,@SNMP_INCLUDE@,$SNMP_INCLUDE,;t t
+s,@HOSTINFO@,$HOSTINFO,;t t
+s,@LIBLTDL@,$LIBLTDL,;t t
+s,@INCLTDL@,$INCLTDL,;t t
+s,@subdirs@,$subdirs,;t t
+s,@MODULES@,$MODULES,;t t
+s,@INSTALLSTRIP@,$INSTALLSTRIP,;t t
+s,@USE_SHARED_LIBS@,$USE_SHARED_LIBS,;t t
+s,@USE_STATIC_LIBS@,$USE_STATIC_LIBS,;t t
+s,@STATIC_MODULES@,$STATIC_MODULES,;t t
+s,@RADIUSD_MAJOR_VERSION@,$RADIUSD_MAJOR_VERSION,;t t
+s,@RADIUSD_MINOR_VERSION@,$RADIUSD_MINOR_VERSION,;t t
+s,@RADIUSD_VERSION@,$RADIUSD_VERSION,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+  cat >>$CONFIG_STATUS <<\_ACEOF
+  # Split the substitutions into bite-sized pieces for seds with
+  # small command number limits, like on Digital OSF/1 and HP-UX.
+  ac_max_sed_lines=48
+  ac_sed_frag=1 # Number of current file.
+  ac_beg=1 # First line for current file.
+  ac_end=$ac_max_sed_lines # Line after last line for current file.
+  ac_more_lines=:
+  ac_sed_cmds=
+  while $ac_more_lines; do
+    if test $ac_beg -gt 1; then
+      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    else
+      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+    fi
+    if test ! -s $tmp/subs.frag; then
+      ac_more_lines=false
+    else
+      # The purpose of the label and of the branching condition is to
+      # speed up the sed processing (if there are no `@' at all, there
+      # is no need to browse any of the substitutions).
+      # These are the two extra sed commands mentioned above.
+      (echo ':t
+  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+      if test -z "$ac_sed_cmds"; then
+       ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+      else
+       ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+      fi
+      ac_sed_frag=`expr $ac_sed_frag + 1`
+      ac_beg=$ac_end
+      ac_end=`expr $ac_end + $ac_max_sed_lines`
+    fi
+  done
+  if test -z "$ac_sed_cmds"; then
+    ac_sed_cmds=cat
   fi
-done
-
-ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
-if test -n "$ac_eof"; then
-  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
-  ac_eof=`expr $ac_eof + 1`
-fi
+fi # test -n "$CONFIG_FILES"
 
-cat >>$CONFIG_STATUS <<_ACEOF
-cat >"\$tmp/subs-2.sed" <<\CEOF$ac_eof
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
-_ACEOF
-sed '
-s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
-s/^/s,@/; s/!/@,|#_!!_#|/
-:n
-t n
-s/'"$ac_delim"'$/,g/; t
-s/$/\\/; p
-N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
-' >>$CONFIG_STATUS <conf$$subs.sed
-rm -f conf$$subs.sed
-cat >>$CONFIG_STATUS <<_ACEOF
-:end
-s/|#_!!_#|//g
-CEOF$ac_eof
 _ACEOF
-
-
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
-# trailing colons and then remove the whole line if VPATH becomes empty
-# (actually we leave an empty line to preserve line numbers).
-if test "x$srcdir" = x.; then
-  ac_vpsub='/^[         ]*VPATH[        ]*=/{
-s/:*\$(srcdir):*/:/
-s/:*\${srcdir}:*/:/
-s/:*@srcdir@:*/:/
-s/^\([^=]*=[    ]*\):*/\1/
-s/:*$//
-s/^[^=]*=[      ]*$//
-}'
-fi
-
 cat >>$CONFIG_STATUS <<\_ACEOF
-fi # test -n "$CONFIG_FILES"
-
-
-for ac_tag in  :F $CONFIG_FILES  :H $CONFIG_HEADERS
-do
-  case $ac_tag in
-  :[FHLC]) ac_mode=$ac_tag; continue;;
-  esac
-  case $ac_mode$ac_tag in
-  :[FHL]*:*);;
-  :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
-echo "$as_me: error: Invalid tag $ac_tag." >&2;}
-   { (exit 1); exit 1; }; };;
-  :[FH]-) ac_tag=-:-;;
-  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
-  esac
-  ac_save_IFS=$IFS
-  IFS=:
-  set x $ac_tag
-  IFS=$ac_save_IFS
-  shift
-  ac_file=$1
-  shift
-
-  case $ac_mode in
-  :L) ac_source=$1;;
-  :[FH])
-    ac_file_inputs=
-    for ac_f
-    do
-      case $ac_f in
-      -) ac_f="$tmp/stdin";;
-      *) # Look for the file first in the build tree, then in the source tree
-        # (if the path is not absolute).  The absolute path cannot be DOS-style,
-        # because $ac_f cannot contain `:'.
-        test -f "$ac_f" ||
-          case $ac_f in
-          [\\/$]*) false;;
-          *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
-          esac ||
-          { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
-echo "$as_me: error: cannot find input file: $ac_f" >&2;}
-   { (exit 1); exit 1; }; };;
-      esac
-      ac_file_inputs="$ac_file_inputs $ac_f"
-    done
-
-    # Let's still pretend it is `configure' which instantiates (i.e., don't
-    # use $as_me), people would be surprised to read:
-    #    /* config.h.  Generated by config.status.  */
-    configure_input="Generated from "`IFS=:
-         echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
-    if test x"$ac_file" != x-; then
-      configure_input="$ac_file.  $configure_input"
-      { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    fi
-
-    case $ac_tag in
-    *:-:* | *:-) cat >"$tmp/stdin";;
-    esac
-    ;;
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+       cat >$tmp/stdin
+       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
   esac
 
-  ac_dir=`$as_dirname -- "$ac_file" ||
+  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
 $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
         X"$ac_file" : 'X\(//\)[^/]' \| \
         X"$ac_file" : 'X\(//\)$' \| \
-        X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+        X"$ac_file" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
 echo X"$ac_file" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)[^/].*/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
-  { as_dir="$ac_dir"
-  case $as_dir in #(
-  -*) as_dir=./$as_dir;;
-  esac
-  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
     as_dirs=
-    while :; do
-      case $as_dir in #(
-      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
-      *) as_qdir=$as_dir;;
-      esac
-      as_dirs="'$as_qdir' $as_dirs"
-      as_dir=`$as_dirname -- "$as_dir" ||
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
 $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
         X"$as_dir" : 'X\(//\)[^/]' \| \
         X"$as_dir" : 'X\(//\)$' \| \
-        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
 echo X"$as_dir" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)[^/].*/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
-      test -d "$as_dir" && break
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
     done
-    test -z "$as_dirs" || eval "mkdir $as_dirs"
-  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
-echo "$as_me: error: cannot create directory $as_dir" >&2;}
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
    { (exit 1); exit 1; }; }; }
+
   ac_builddir=.
 
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
+if test "$ac_dir" != .; then
   ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A ".." for each directory in $ac_dir_suffix.
-  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
-  case $ac_top_builddir_sub in
-  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
-  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
-  esac ;;
-esac
-ac_abs_top_builddir=$ac_pwd
-ac_abs_builddir=$ac_pwd$ac_dir_suffix
-# for backward compatibility:
-ac_top_builddir=$ac_top_build_prefix
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
 
 case $srcdir in
-  .)  # We are building in place.
+  .)  # No --srcdir option.  We are building in place.
     ac_srcdir=.
-    ac_top_srcdir=$ac_top_builddir_sub
-    ac_abs_top_srcdir=$ac_pwd ;;
-  [\\/]* | ?:[\\/]* )  # Absolute name.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
     ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir
-    ac_abs_top_srcdir=$srcdir ;;
-  *) # Relative name.
-    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_build_prefix$srcdir
-    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
 esac
-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
 
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
 
-  case $ac_mode in
-  :F)
-  #
-  # CONFIG_FILE
-  #
-
-_ACEOF
 
-cat >>$CONFIG_STATUS <<\_ACEOF
-# If the template does not know about datarootdir, expand it.
-# FIXME: This hack should be removed a few years after 2.60.
-ac_datarootdir_hack=; ac_datarootdir_seen=
 
-case `sed -n '/datarootdir/ {
-  p
-  q
-}
-/@datadir@/p
-/@docdir@/p
-/@infodir@/p
-/@localedir@/p
-/@mandir@/p
-' $ac_file_inputs` in
-*datarootdir*) ac_datarootdir_seen=yes;;
-*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
-  { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-  ac_datarootdir_hack='
-  s&@datadir@&$datadir&g
-  s&@docdir@&$docdir&g
-  s&@infodir@&$infodir&g
-  s&@localedir@&$localedir&g
-  s&@mandir@&$mandir&g
-    s&\\\${datarootdir}&$datarootdir&g' ;;
-esac
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    configure_input=
+  else
+    configure_input="$ac_file.  "
+  fi
+  configure_input=$configure_input"Generated from `echo $ac_file_in |
+                                    sed 's,.*/,,'` by configure."
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+        # Absolute (can't be DOS-style, as IFS=:)
+        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        echo "$f";;
+      *) # Relative
+        if test -f "$f"; then
+          # Build tree
+          echo "$f"
+        elif test -f "$srcdir/$f"; then
+          # Source tree
+          echo "$srcdir/$f"
+        else
+          # /dev/null tree
+          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        fi;;
+      esac
+    done` || { (exit 1); exit 1; }
 _ACEOF
-
-# Neutralize VPATH when `$srcdir' = `.'.
-# Shell code in configure.ac might set extrasub.
-# FIXME: do we really want to maintain this feature?
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
 $extrasub
@@ -26720,136 +25685,372 @@ _ACEOF
 cat >>$CONFIG_STATUS <<\_ACEOF
 :t
 /@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s&@configure_input@&$configure_input&;t t
-s&@top_builddir@&$ac_top_builddir_sub&;t t
-s&@srcdir@&$ac_srcdir&;t t
-s&@abs_srcdir@&$ac_abs_srcdir&;t t
-s&@top_srcdir@&$ac_top_srcdir&;t t
-s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
-s&@builddir@&$ac_builddir&;t t
-s&@abs_builddir@&$ac_abs_builddir&;t t
-s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
-$ac_datarootdir_hack
-" $ac_file_inputs | sed -f "$tmp/subs-1.sed" | sed -f "$tmp/subs-2.sed" >$tmp/out
-
-test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
-  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
-  { ac_out=`sed -n '/^[         ]*datarootdir[  ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
-  { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined.  Please make sure it is defined." >&5
-echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
-which seems to be undefined.  Please make sure it is defined." >&2;}
-
-  rm -f "$tmp/stdin"
-  case $ac_file in
-  -) cat "$tmp/out"; rm -f "$tmp/out";;
-  *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
-  esac
- ;;
-  :H)
-  #
-  # CONFIG_HEADER
-  #
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+  rm -f $tmp/stdin
+  if test x"$ac_file" != x-; then
+    mv $tmp/out $ac_file
+  else
+    cat $tmp/out
+    rm -f $tmp/out
+  fi
+
+done
 _ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
 
-# Transform confdefs.h into a sed script `conftest.defines', that
-# substitutes the proper values into config.h.in to produce config.h.
-rm -f conftest.defines conftest.tail
-# First, append a space to every undef/define line, to ease matching.
-echo 's/$/ /' >conftest.defines
-# Then, protect against being on the right side of a sed subst, or in
-# an unquoted here document, in config.status.  If some macros were
-# called several times there might be several #defines for the same
-# symbol, which is useless.  But do not sort them, since the last
-# AC_DEFINE must be honored.
-ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
-# These sed commands are passed to sed as "A NAME B PARAMS C VALUE D", where
-# NAME is the cpp macro being defined, VALUE is the value it is being given.
-# PARAMS is the parameter list in the macro definition--in most cases, it's
-# just an empty string.
-ac_dA='s,^\\([  #]*\\)[^        ]*\\([  ]*'
-ac_dB='\\)[     (].*,\\1define\\2'
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([   ]*\)#\([        ]*define[       ][      ]*\)'
+ac_dB='[        ].*$,\1#\2'
 ac_dC=' '
-ac_dD=' ,'
-
-uniq confdefs.h |
-  sed -n '
-       t rset
-       :rset
-       s/^[     ]*#[    ]*define[       ][      ]*//
-       t ok
-       d
-       :ok
-       s/[\\&,]/\\&/g
-       s/^\('"$ac_word_re"'\)\(([^()]*)\)[      ]*\(.*\)/ '"$ac_dA"'\1'"$ac_dB"'\2'"${ac_dC}"'\3'"$ac_dD"'/p
-       s/^\('"$ac_word_re"'\)[  ]*\(.*\)/'"$ac_dA"'\1'"$ac_dB$ac_dC"'\2'"$ac_dD"'/p
-  ' >>conftest.defines
-
-# Remove the space that was appended to ease matching.
-# Then replace #undef with comments.  This is necessary, for
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([   ]*\)#\([        ]*\)undef\([    ][      ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case $ac_file in
+  - | *:- | *:-:* ) # input from stdin
+       cat >$tmp/stdin
+       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+  * )   ac_file_in=$ac_file.in ;;
+  esac
+
+  test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+  # First look for the input files in the build tree, otherwise in the
+  # src tree.
+  ac_file_inputs=`IFS=:
+    for f in $ac_file_in; do
+      case $f in
+      -) echo $tmp/stdin ;;
+      [\\/$]*)
+        # Absolute (can't be DOS-style, as IFS=:)
+        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        # Do quote $f, to prevent DOS paths from being IFS'd.
+        echo "$f";;
+      *) # Relative
+        if test -f "$f"; then
+          # Build tree
+          echo "$f"
+        elif test -f "$srcdir/$f"; then
+          # Source tree
+          echo "$srcdir/$f"
+        else
+          # /dev/null tree
+          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+   { (exit 1); exit 1; }; }
+        fi;;
+      esac
+    done` || { (exit 1); exit 1; }
+  # Remove the trailing spaces.
+  sed 's/[      ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h.  The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status.  Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[    ]*#[    ]*define[       ][      ]*\([^  (][^    (]*\)\(([^)]*)\)[       ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[    ]*#[    ]*define[       ][      ]*\([^  ][^     ]*\)[   ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless.  Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments.  This is necessary, for
 # example, in the case of _POSIX_SOURCE, which is predefined and required
 # on some systems where configure will not decide to define it.
-# (The regexp can be short, since the line contains either #define or #undef.)
-echo 's/ $//
-s,^[    #]*u.*,/* & */,' >>conftest.defines
-
-# Break up conftest.defines:
-ac_max_sed_lines=50
-
-# First sed command is:         sed -f defines.sed $ac_file_inputs >"$tmp/out1"
-# Second one is:        sed -f defines.sed "$tmp/out1" >"$tmp/out2"
-# Third one will be:    sed -f defines.sed "$tmp/out2" >"$tmp/out1"
-# et cetera.
-ac_in='$ac_file_inputs'
-ac_out='"$tmp/out1"'
-ac_nxt='"$tmp/out2"'
-
-while :
+cat >>conftest.undefs <<\_ACEOF
+s,^[    ]*#[    ]*undef[        ][      ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo '  if grep "^[     ]*#[    ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo '  # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo '  :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
 do
-  # Write a here document:
-    cat >>$CONFIG_STATUS <<_ACEOF
-    # First, check the format of the line:
-    cat >"\$tmp/defines.sed" <<\\CEOF
-/^[     ]*#[    ]*undef[        ][      ]*$ac_word_re[  ]*\$/b def
-/^[     ]*#[    ]*define[       ][      ]*$ac_word_re[(         ]/b def
-b
-:def
-_ACEOF
-  sed ${ac_max_sed_lines}q conftest.defines >>$CONFIG_STATUS
+  # Write a limited-size here document to $tmp/defines.sed.
+  echo '  cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#define' lines.
+  echo '/^[     ]*#[    ]*define/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
   echo 'CEOF
-    sed -f "$tmp/defines.sed"' "$ac_in >$ac_out" >>$CONFIG_STATUS
-  ac_in=$ac_out; ac_out=$ac_nxt; ac_nxt=$ac_in
-  sed 1,${ac_max_sed_lines}d conftest.defines >conftest.tail
-  grep . conftest.tail >/dev/null || break
+  sed -f $tmp/defines.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
   rm -f conftest.defines
   mv conftest.tail conftest.defines
 done
-rm -f conftest.defines conftest.tail
+rm -f conftest.defines
+echo '  fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo '  # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+  # Write a limited-size here document to $tmp/undefs.sed.
+  echo '  cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+  # Speed up: don't consider the non `#undef'
+  echo '/^[     ]*#[    ]*undef/!b' >>$CONFIG_STATUS
+  # Work around the forget-to-reset-the-flag bug.
+  echo 't clr' >>$CONFIG_STATUS
+  echo ': clr' >>$CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+  echo 'CEOF
+  sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+  rm -f $tmp/in
+  mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+  rm -f conftest.undefs
+  mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
 
-echo "ac_result=$ac_in" >>$CONFIG_STATUS
 cat >>$CONFIG_STATUS <<\_ACEOF
+  # Let's still pretend it is `configure' which instantiates (i.e., don't
+  # use $as_me), people would be surprised to read:
+  #    /* config.h.  Generated by config.status.  */
+  if test x"$ac_file" = x-; then
+    echo "/* Generated by configure.  */" >$tmp/config.h
+  else
+    echo "/* $ac_file.  Generated by configure.  */" >$tmp/config.h
+  fi
+  cat $tmp/in >>$tmp/config.h
+  rm -f $tmp/in
   if test x"$ac_file" != x-; then
-    echo "/* $configure_input  */" >"$tmp/config.h"
-    cat "$ac_result" >>"$tmp/config.h"
-    if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
+    if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
       { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
 echo "$as_me: $ac_file is unchanged" >&6;}
     else
+      ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+      { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
+
       rm -f $ac_file
-      mv "$tmp/config.h" $ac_file
+      mv $tmp/config.h $ac_file
     fi
   else
-    echo "/* $configure_input  */"
-    cat "$ac_result"
+    cat $tmp/config.h
+    rm -f $tmp/config.h
   fi
-  rm -f "$tmp/out12"
- ;;
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+  ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+  ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+  ac_dir=`(dirname "$ac_dest") 2>/dev/null ||
+$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_dest" : 'X\(//\)[^/]' \| \
+        X"$ac_dest" : 'X\(//\)$' \| \
+        X"$ac_dest" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$ac_dest" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+  { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
+    as_dirs=
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
+    done
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+   { (exit 1); exit 1; }; }; }
 
+  ac_builddir=.
+
+if test "$ac_dir" != .; then
+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+  .)  # No --srcdir option.  We are building in place.
+    ac_srcdir=.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
+esac
 
-  esac
 
-done # for ac_tag
+  { echo "$as_me:$LINENO: executing $ac_dest commands" >&5
+echo "$as_me: executing $ac_dest commands" >&6;}
+  case $ac_dest in
+    stamp-h ) echo timestamp > src/include/stamp-h ;;
+    build-radpaths-h ) (cd ./src/include && /bin/sh ./build-radpaths-h) ;;
+    main-chmod ) (cd ./src/main   && chmod +x checkrad.pl radlast radtest) ;;
+    scripts-chmod ) (cd ./scripts    && chmod +x rc.radiusd radwatch check-radiusd-config radiusd.cron.daily radiusd.cron.monthly cryptpasswd) ;;
+  esac
+done
+_ACEOF
 
+cat >>$CONFIG_STATUS <<\_ACEOF
 
 { (exit 0); exit 0; }
 _ACEOF
@@ -26886,10 +26087,7 @@ if test "$no_recursion" != yes; then
   # Remove --cache-file and --srcdir arguments so they do not pile up.
   ac_sub_configure_args=
   ac_prev=
-  eval "set x $ac_configure_args"
-  shift
-  for ac_arg
-  do
+  for ac_arg in $ac_configure_args; do
     if test -n "$ac_prev"; then
       ac_prev=
       continue
@@ -26912,118 +26110,123 @@ if test "$no_recursion" != yes; then
       ac_prev=prefix ;;
     -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
       ;;
-    *)
-      case $ac_arg in
-      *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
-      esac
-      ac_sub_configure_args="$ac_sub_configure_args '$ac_arg'" ;;
+    *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;;
     esac
   done
 
   # Always prepend --prefix to ensure using the same prefix
   # in subdir configurations.
-  ac_arg="--prefix=$prefix"
-  case $ac_arg in
-  *\'*) ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
-  esac
-  ac_sub_configure_args="$ac_arg $ac_sub_configure_args"
+  ac_sub_configure_args="--prefix=$prefix $ac_sub_configure_args"
 
   ac_popdir=`pwd`
   for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue
 
     # Do not complain, so a configure script can configure whichever
     # parts of a large source tree are present.
-    test -d "$srcdir/$ac_dir" || continue
-
-    ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)"
-    echo "$as_me:$LINENO: $ac_msg" >&5
-    echo "$ac_msg" >&6
-    { as_dir="$ac_dir"
-  case $as_dir in #(
-  -*) as_dir=./$as_dir;;
-  esac
-  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    test -d $srcdir/$ac_dir || continue
+
+    { echo "$as_me:$LINENO: configuring in $ac_dir" >&5
+echo "$as_me: configuring in $ac_dir" >&6;}
+    { if $as_mkdir_p; then
+    mkdir -p "$ac_dir"
+  else
+    as_dir="$ac_dir"
     as_dirs=
-    while :; do
-      case $as_dir in #(
-      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
-      *) as_qdir=$as_dir;;
-      esac
-      as_dirs="'$as_qdir' $as_dirs"
-      as_dir=`$as_dirname -- "$as_dir" ||
+    while test ! -d "$as_dir"; do
+      as_dirs="$as_dir $as_dirs"
+      as_dir=`(dirname "$as_dir") 2>/dev/null ||
 $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
         X"$as_dir" : 'X\(//\)[^/]' \| \
         X"$as_dir" : 'X\(//\)$' \| \
-        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+        X"$as_dir" : 'X\(/\)' \| \
+        .     : '\(.\)' 2>/dev/null ||
 echo X"$as_dir" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)[^/].*/{
-           s//\1/
-           q
-         }
-         /^X\(\/\/\)$/{
-           s//\1/
-           q
-         }
-         /^X\(\/\).*/{
-           s//\1/
-           q
-         }
-         s/.*/./; q'`
-      test -d "$as_dir" && break
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+         /^X\(\/\/\)$/{ s//\1/; q; }
+         /^X\(\/\).*/{ s//\1/; q; }
+         s/.*/./; q'`
     done
-    test -z "$as_dirs" || eval "mkdir $as_dirs"
-  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
-echo "$as_me: error: cannot create directory $as_dir" >&2;}
+    test ! -n "$as_dirs" || mkdir $as_dirs
+  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
    { (exit 1); exit 1; }; }; }
+
     ac_builddir=.
 
-case "$ac_dir" in
-.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
-*)
+if test "$ac_dir" != .; then
   ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A ".." for each directory in $ac_dir_suffix.
-  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
-  case $ac_top_builddir_sub in
-  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
-  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
-  esac ;;
-esac
-ac_abs_top_builddir=$ac_pwd
-ac_abs_builddir=$ac_pwd$ac_dir_suffix
-# for backward compatibility:
-ac_top_builddir=$ac_top_build_prefix
+  # A "../" for each directory in $ac_dir_suffix.
+  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+  ac_dir_suffix= ac_top_builddir=
+fi
 
 case $srcdir in
-  .)  # We are building in place.
+  .)  # No --srcdir option.  We are building in place.
     ac_srcdir=.
-    ac_top_srcdir=$ac_top_builddir_sub
-    ac_abs_top_srcdir=$ac_pwd ;;
-  [\\/]* | ?:[\\/]* )  # Absolute name.
+    if test -z "$ac_top_builddir"; then
+       ac_top_srcdir=.
+    else
+       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+    fi ;;
+  [\\/]* | ?:[\\/]* )  # Absolute path.
     ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir
-    ac_abs_top_srcdir=$srcdir ;;
-  *) # Relative name.
-    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_build_prefix$srcdir
-    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+    ac_top_srcdir=$srcdir ;;
+  *) # Relative path.
+    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+
+# Do not use `cd foo && pwd` to compute absolute paths, because
+# the directories may not exist.
+case `pwd` in
+.) ac_abs_builddir="$ac_dir";;
+*)
+  case "$ac_dir" in
+  .) ac_abs_builddir=`pwd`;;
+  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
+  *) ac_abs_builddir=`pwd`/"$ac_dir";;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_builddir=${ac_top_builddir}.;;
+*)
+  case ${ac_top_builddir}. in
+  .) ac_abs_top_builddir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
+  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_srcdir=$ac_srcdir;;
+*)
+  case $ac_srcdir in
+  .) ac_abs_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
+  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
+  esac;;
+esac
+case $ac_abs_builddir in
+.) ac_abs_top_srcdir=$ac_top_srcdir;;
+*)
+  case $ac_top_srcdir in
+  .) ac_abs_top_srcdir=$ac_abs_builddir;;
+  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
+  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
+  esac;;
 esac
-ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
 
 
-    cd "$ac_dir"
+    cd $ac_dir
 
     # Check for guested configure; otherwise get Cygnus style configure.
-    if test -f "$ac_srcdir/configure.gnu"; then
-      ac_sub_configure=$ac_srcdir/configure.gnu
-    elif test -f "$ac_srcdir/configure"; then
-      ac_sub_configure=$ac_srcdir/configure
-    elif test -f "$ac_srcdir/configure.in"; then
-      # This should be Cygnus configure.
-      ac_sub_configure=$ac_aux_dir/configure
+    if test -f $ac_srcdir/configure.gnu; then
+      ac_sub_configure="$SHELL '$ac_srcdir/configure.gnu'"
+    elif test -f $ac_srcdir/configure; then
+      ac_sub_configure="$SHELL '$ac_srcdir/configure'"
+    elif test -f $ac_srcdir/configure.in; then
+      ac_sub_configure=$ac_configure
     else
       { echo "$as_me:$LINENO: WARNING: no configuration information is in $ac_dir" >&5
 echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;}
@@ -27035,30 +26238,21 @@ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;}
       # Make the cache file name correct relative to the subdirectory.
       case $cache_file in
       [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;;
-      *) # Relative name.
-       ac_sub_cache_file=$ac_top_build_prefix$cache_file ;;
+      *) # Relative path.
+       ac_sub_cache_file=$ac_top_builddir$cache_file ;;
       esac
 
-      { echo "$as_me:$LINENO: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5
-echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;}
+      { echo "$as_me:$LINENO: running $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5
+echo "$as_me: running $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;}
       # The eval makes quoting arguments work.
-      eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \
-          --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" ||
+      eval $ac_sub_configure $ac_sub_configure_args \
+          --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir ||
        { { echo "$as_me:$LINENO: error: $ac_sub_configure failed for $ac_dir" >&5
 echo "$as_me: error: $ac_sub_configure failed for $ac_dir" >&2;}
    { (exit 1); exit 1; }; }
     fi
 
-    cd "$ac_popdir"
+    cd $ac_popdir
   done
 fi
 
-
-ac_config_commands="$ac_config_commands default-1"
-
-ac_config_commands="$ac_config_commands default-2"
-
-ac_config_commands="$ac_config_commands default-3"
-
-ac_config_commands="$ac_config_commands default-4"
-
index 771cb0f..b187377 100644 (file)
@@ -3,7 +3,7 @@ dnl #
 dnl #  For information about autoconf, see:
 dnl #
 dnl #  http://www.gnu.org/software/autoconf/
-dnl #  
+dnl #
 dnl #  The recommended order is:
 dnl #
 dnl #  AC_INIT(file)
@@ -20,15 +20,17 @@ dnl #  AC_OUTPUT([file...])
 dnl #
 dnl #############################################################
 
+AC_PREREQ([2.59])
+export CFLAGS LIBS LDFLAGS CPPFLAGS
 AC_INIT(src/main/radiusd.c)
 AC_CONFIG_HEADER(src/include/autoconf.h)
 AC_REVISION($Revision$)dnl
-AC_PREREQ([2.50])
 
 dnl # The version of the software
-RADIUSD_MAJOR_VERSION=1
-RADIUSD_MINOR_VERSION=1.5
+RADIUSD_MAJOR_VERSION=2
+RADIUSD_MINOR_VERSION=0.0-pre0
 RADIUSD_VERSION="${RADIUSD_MAJOR_VERSION}.${RADIUSD_MINOR_VERSION}"
+PACKAGE=freeradius
 
 dnl #############################################################
 dnl #
@@ -38,6 +40,7 @@ dnl #############################################################
 
 dnl Check for GNU cc
 AC_PROG_CC
+AC_PROG_CXX
 
 dnl #
 dnl # check for AIX, to allow us to use some BSD functions
@@ -49,13 +52,8 @@ AC_PROG_GCC_TRADITIONAL
 AC_PROG_CC_SUNPRO
 AC_PROG_RANLIB
 
-abs_top_builddir=`pwd`
-AC_SUBST(abs_top_builddir)
-
-dnl # autoconf 2.50 and later
-dnl # AC_SYS_LARGEFILE
-
-PACKAGE=freeradius
+dnl Compile in large (2G+) file support.
+AC_SYS_LARGEFILE
 
 dnl # check for system bytesex
 dnl # AC_DEFINES WORDS_BIGENDIAN
@@ -84,7 +82,7 @@ fi
 AC_SUBST(LTDL_SUBDIRS)
 
 dnl use system-wide libtool, if it exists
-AC_ARG_WITH(system-libtool, 
+AC_ARG_WITH(system-libtool,
 [  --with-system-libtool              try to use libtool installed in your system [default=use our own]],
 [ AC_PATH_PROG(LIBTOOL, libtool,,$PATH:/usr/local/bin) ],
 [
@@ -208,7 +206,7 @@ AC_ARG_WITH(ascend-binary,
   esac ]
 )
 if test "X$ASCEND_BINARY" = "Xyes"; then
-  AC_DEFINE(ASCEND_BINARY)
+  AC_DEFINE(ASCEND_BINARY, [], [Include support for Ascend binary filter attributes])
 fi
 
 dnl extra argument: --with-threads
@@ -235,20 +233,6 @@ AC_ARG_WITH(snmp,
   esac ]
 )
 
-dnl extra argument: --with-large-files
-rad_enable_largefiles=no
-AC_ARG_WITH(large-files,
-[  --with-large-files      Compile in large (2G+) file support. (default=no)],
-[ case "$withval" in
-    yes)
-        rad_enable_largefiles=yes
-       ;;
-    *)
-       ;;
-  esac ]
-)
-
-
 dnl #
 dnl #  Allow the user to specify a list of modules to be linked
 dnl #  statically to the server.
@@ -384,14 +368,9 @@ AC_ARG_WITH(udpfromto,
 )
 
 if test "x$WITH_UDPFROMTO" = "xyes"; then
-       AC_DEFINE(WITH_UDPFROMTO)
+       AC_DEFINE(WITH_UDPFROMTO, [], [define if you want udpfromto])
 fi
 
-dnl extra argument: --with-edir
-dnl If using Novell eDirectory, enable UP and Novell specific code
-AC_ARG_WITH(edir,
-[  --with-edir             Enable Novell eDirectory integration.  (default=no) ] , [] )
-
 dnl #############################################################
 dnl #
 dnl #  1. Checks for programs
@@ -433,20 +412,20 @@ dnl #############################################################
 
 dnl If using pthreads, check for -lpthread (posix) or -lc_r (*BSD)
 old_CFLAGS=$CFLAGS
-if test "x$WITH_THREADS" = "xyes"; then 
+if test "x$WITH_THREADS" = "xyes"; then
   if test $ac_cv_prog_suncc = "yes"; then
     CFLAGS="$CFLAGS -mt"
   fi
 
   AC_CHECK_HEADERS(pthread.h, [], [ WITH_THREADS="no" ])
 
-dnl # 
+dnl #
 dnl # pthread stuff is usually in -lpthread
 dnl # or in -lc_r, on *BSD
-dnl # 
+dnl #
 dnl # On Some systems, we need extra pre-processor flags, to get them to
 dnl # to do the threading properly.
-dnl # 
+dnl #
   AC_CHECK_LIB(pthread, pthread_create,
                [ CFLAGS="$CFLAGS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS"
                   LIBS="$LIBS -lpthread" ],
@@ -457,9 +436,9 @@ dnl #
                )
 fi
 
-dnl # 
+dnl #
 dnl # If we have NO pthread libraries, remove any knowledge of threads.
-dnl # 
+dnl #
 if test "x$WITH_THREADS" != "xyes"; then
   CFLAGS=$old_CFLAGS
   ac_cv_header_pthread_h="no"
@@ -472,8 +451,9 @@ else
   dnl # HP/UX requires linking with librt, too, to get the sem_* symbols.
   dnl # Some systems have them in -lsem
   dnl # Solaris has them in -lposix4
+  dnl # NetBSD has them in -lsemaphore
 
-  AC_SEARCH_LIBS(sem_init, pthread sem posix4 rt,
+  AC_SEARCH_LIBS(sem_init, pthread sem posix4 rt semaphore,
        [],
        [AC_MSG_ERROR(-lsem not found.  You may want to download it from ftp://ftp.to.gd-es.com/pub/BSDI/libsem.tar.bz2 or ftp://ftp.freeradius.org/pub/radius/contrib/libsem.tar.gz)]
    )
@@ -512,6 +492,15 @@ AC_CHECK_LIB(crypto, DH_new,
     ], [])
 LIBS=$old_LIBS
 
+dnl Check the pcap library for the RADIUS sniffer.
+PCAP_LIBS=
+AC_CHECK_LIB(pcap, pcap_open_live,
+       [ PCAP_LIBS="-lpcap"
+       AC_DEFINE(HAVE_LIBPCAP, 1,
+               [Define to 1 if you have the `pcap' library (-lpcap).])
+       ],
+       [ AC_MSG_WARN([pcap library not found, silently disabling the RADIUS sniffer.]) ])
+
 dnl #############################################################
 dnl #
 dnl #  3. Checks for header files
@@ -521,8 +510,8 @@ dnl #############################################################
 dnl #
 dnl # Interix requires us to set -D_ALL_SOURCE, otherwise
 dnl # getopt will be #included, but won't link.  <sigh>
-dnl # 
-dnl # 
+dnl #
+dnl #
 case "$host" in
 *-interix*)
        CFLAGS="$CFLAGS -D_ALL_SOURCE"
@@ -563,15 +552,14 @@ AC_CHECK_HEADERS( \
        sys/security.h \
        fcntl.h \
        sys/fcntl.h \
-       sys/stat.h \
-       sys/prctl.h \
+       net/if.h \
        prot.h \
        sia.h \
        siad.h
 )
 
 REGEX=no
-AC_CHECK_HEADER(regex.h, AC_DEFINE(HAVE_REGEX_H))
+AC_CHECK_HEADER(regex.h, AC_DEFINE(HAVE_REGEX_H, [], [define this if we have the <regex.h> header file]))
 if test "x$ac_cv_header_regex_h" = "xyes"; then
   REGEX_EXTENDED=no
   REGEX=yes
@@ -580,7 +568,7 @@ if test "x$ac_cv_header_regex_h" = "xyes"; then
      #ifdef REG_EXTENDED
        yes
      #endif
-     ], [AC_DEFINE(HAVE_REG_EXTENDED) REGEX_EXTENDED=yes])
+     ], [AC_DEFINE(HAVE_REG_EXTENDED, [], [define this if we have REG_EXTENDED (from <regex.h>)]) REGEX_EXTENDED=yes])
 fi
 AC_SUBST(REGEX)
 AC_SUBST(REGEX_EXTENDED)
@@ -590,18 +578,18 @@ dnl #  other checks which require headers
 dnl #
 if test "x$ac_cv_header_sys_security_h" = "xyes" && test "x$ac_cv_header_prot_h" = "xyes"
 then
-  AC_DEFINE(OSFC2)
+  AC_DEFINE(OSFC2, [], [define if you have OSFC2 authentication])
 fi
 
 if test "x$ac_cv_header_sia_h" = "xyes" && test "x$ac_cv_header_siad_h" = "xyes"
 then
-  AC_DEFINE(OSFSIA)
+  AC_DEFINE(OSFSIA, [], [define if you have OSFSIA authentication])
 fi
 
 dnl Check for OpenSSL includes.
 OPENSSL_INCLUDE="-DNO_OPENSSL"
 if test "x$OPENSSL_LIBS" = "x"; then
-    AC_MSG_WARN([skipping test for openssl/ssl.h])
+    AC_MSG_NOTICE([skipping test for openssl/ssl.h])
 else
     old_CPPFLAGS=$CPPFLAGS
     if test "x$OPENSSL_INCLUDE_DIR" != "x"; then
@@ -643,6 +631,19 @@ AC_SUBST(OPENSSL_INCLUDE)
 AC_SUBST(OPENSSL_LIBS)
 export OPENSSL_LIBS
 
+dnl Check the pcap includes for the RADIUS sniffer.
+if test "x$PCAP_LIBS" = x; then
+    AC_MSG_NOTICE([skipping test for pcap.h.])
+else
+    AC_CHECK_HEADER(pcap.h,
+       AC_DEFINE(HAVE_PCAP_H, 1,
+               [Define to 1 if you have the <pcap.h> header file.]),
+       [ PCAP_LIBS=
+       AC_MSG_WARN([pcap.h not found, silently disabling the RADIUS sniffer.])
+       ])
+fi
+AC_SUBST(PCAP_LIBS)
+
 dnl #############################################################
 dnl #
 dnl #  4. Checks for typedefs
@@ -652,50 +653,83 @@ dnl #############################################################
 dnl #
 dnl # Ensure that these are defined
 dnl #
-AC_TYPE_OFF_T 
+AC_TYPE_OFF_T
 AC_TYPE_PID_T
 AC_TYPE_SIZE_T
 AC_TYPE_UID_T
 
 dnl check for socklen_t
-AC_CHECK_TYPE_INCLUDE([
+FR_CHECK_TYPE_INCLUDE([
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
-],socklen_t, int)
+],socklen_t, int, [socklen_t is generally 'int' on systems which don't use it])
 
 dnl check for uint8_t
-AC_CHECK_TYPE_INCLUDE([
+FR_CHECK_TYPE_INCLUDE([
 #ifdef HAVE_INTTYPES_H
 #include <inttypes.h>
 #endif
 #ifdef HAVE_STDINT_H
 #include <stdint.h>
 #endif
-],uint8_t, unsigned char)
+],uint8_t, unsigned char, [uint8_t should be the canonical 'octet' for network traffic])
 
 dnl check for uint16_t
-AC_CHECK_TYPE_INCLUDE([
+FR_CHECK_TYPE_INCLUDE([
 #ifdef HAVE_INTTYPES_H
 #include <inttypes.h>
 #endif
 #ifdef HAVE_STDINT_H
 #include <stdint.h>
 #endif
-],uint16_t, unsigned short)
+],uint16_t, unsigned short, [uint16_t should be the canonical '2 octets' for network traffic])
 
 dnl check for uint32_t
-AC_CHECK_TYPE_INCLUDE([
+FR_CHECK_TYPE_INCLUDE([
 #ifdef HAVE_INTTYPES_H
 #include <inttypes.h>
 #endif
 #ifdef HAVE_STDINT_H
 #include <stdint.h>
 #endif
-],uint32_t, unsigned int)
+],uint32_t, unsigned int, [uint32_t should be the canonical 'network integer])
+
+AC_CHECK_TYPE(struct in6_addr, AC_DEFINE(HAVE_STRUCT_IN6_ADDR, 1, [IPv6 address structure]), [], [
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+])
+
+AC_CHECK_TYPE(struct sockaddr_storage, AC_DEFINE(HAVE_STRUCT_SOCKADDR_STORAGE, 1, [Generic socket addresses]), [], [
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+])
+
+AC_CHECK_TYPE(struct sockaddr_in6, AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6, 1, [IPv6 socket addresses]), [], [
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+])
+
+AC_CHECK_TYPE(struct addrinfo, AC_DEFINE(HAVE_STRUCT_ADDRINFO, 1, [Generic DNS lookups]), [], [
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+])
 
 dnl #############################################################
 dnl #
@@ -726,7 +760,11 @@ AC_CHECK_FUNCS( \
        setvbuf \
        getusershell \
        initgroups \
-       closefrom
+       getaddrinfo \
+       getnameinfo \
+       closefrom \
+       strlcat \
+       strlcpy
 )
 RADIUSD_NEED_DECLARATIONS( \
        crypt \
@@ -746,18 +784,25 @@ dnl # if so, check if struct utmpx has entry ut_xtime
 dnl # if not, set it to define ut_xtime == ut_tv.tv_sec
 if test "x$ac_cv_header_utmpx_h" = "xyes"
 then
AC_CHECK_STRUCT_HAS_MEMBER([#include <utmpx.h>], [struct utmpx], ut_xtime)
FR_CHECK_STRUCT_HAS_MEMBER([#include <utmpx.h>], [struct utmpx], ut_xtime)
  if test "x$ac_cv_type_struct_utmpx_has_ut_xtime" = "x"
  then
-   AC_DEFINE(ut_xtime,ut_tv.tv_sec)
+   AC_DEFINE(ut_xtime,ut_tv.tv_sec, [define to something if you don't have ut_xtime in struct utmpx])
  fi
 fi
 
 dnl # struct ip_pktinfo
-AC_CHECK_STRUCT_HAS_MEMBER([#include <netinet/in.h>], [struct in_pktinfo], ipi_addr)
+FR_CHECK_STRUCT_HAS_MEMBER([#include <netinet/in.h>], [struct in_pktinfo], ipi_addr)
 if test "x$ac_cv_type_struct_in_pktinfo_has_ipi_addr" = "xyes"
 then
-       AC_DEFINE(HAVE_IP_PKTINFO)
+       AC_DEFINE(HAVE_IP_PKTINFO, [], [define if you have IP_PKTINFO (Linux)])
+fi
+
+dnl # struct in6_pktinfo
+FR_CHECK_STRUCT_HAS_MEMBER([#include <netinet/in.h>], [struct in6_pktinfo], ipi6_addr)
+if test "x$ac_cv_type_struct_in6_pktinfo_has_ipi6_addr" = "xyes"
+then
+       AC_DEFINE(HAVE_IN6_PKTINFO, [], [define if you have IN6_PKTINFO (Linux)])
 fi
 
 dnl #############################################################
@@ -769,7 +814,7 @@ dnl #############################################################
 dnl #
 dnl # Ensure that these are defined
 dnl #
-AC_C_CONST 
+AC_C_CONST
 
 dnl #
 dnl # See if this is OS/2
@@ -816,9 +861,9 @@ AC_CHECK_LIB(crypt, crypt,
   CRYPTLIB="-lcrypt"
 )
 if test "$CRYPTLIB" != ""; then
-  AC_DEFINE(HAVE_CRYPT)
+  AC_DEFINE(HAVE_CRYPT, [], [Do we have the crypt function])
 else
-  AC_CHECK_FUNC(crypt, AC_DEFINE(HAVE_CRYPT))
+  AC_CHECK_FUNC(crypt, AC_DEFINE(HAVE_CRYPT, [], [Do we have the crypt function]))
 fi
 
 dnl Check for libcipher
@@ -833,8 +878,11 @@ fi
 
 dnl Check the style of gethostbyaddr, in order of preference
 dnl GNU (_r eight args)
+AC_DEFINE(GNUSTYLE, [1], [GNU-Style get*byaddr_r])
 dnl SYSV (_r six args)
+AC_DEFINE(SYSVSTYLE, [2], [SYSV-Style get*byaddr_r])
 dnl BSD (three args, may not be thread safe)
+AC_DEFINE(BSDSTYLE, [3], [BSD-Style get*byaddr_r])
 dnl Tru64 has BSD version, but it is thread safe
 dnl    http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/V51B_HTML/MAN/MAN3/1739____.HTM
 dnl We need #stdio.h to define NULL on FreeBSD (at least)
@@ -842,7 +890,7 @@ gethostbyaddrrstyle=""
 AC_MSG_CHECKING([gethostbyaddr_r() syntax])
 case "$host" in
 *-freebsd*)
-       AC_DEFINE(GETHOSTBYADDRRSTYLE, BSDSTYLE)
+       AC_DEFINE(GETHOSTBYADDRRSTYLE, BSDSTYLE, [style of gethostbyaddr_r functions ])
        gethostbyaddrrstyle=BSD
        AC_MSG_WARN([FreeBSD overridden to BSD-style])
        ;;
@@ -852,7 +900,7 @@ if test "x$gethostbyaddrrstyle" = "x"; then
 #include <stdio.h>
 #include <netdb.h>
 ], [ gethostbyaddr_r(NULL, 0, 0, NULL, NULL, 0, NULL, NULL) ], [
-       AC_DEFINE(GETHOSTBYADDRRSTYLE, GNUSTYLE)
+       AC_DEFINE(GETHOSTBYADDRRSTYLE, GNUSTYLE, [style of gethostbyaddr_r functions ])
        gethostbyaddrrstyle=GNU
 ])
 fi
@@ -861,7 +909,7 @@ if test "x$gethostbyaddrrstyle" = "x"; then
 #include <stdio.h>
 #include <netdb.h>
 ], [ gethostbyaddr_r(NULL, 0, 0, NULL, NULL, 0, NULL) ] , [
-               AC_DEFINE(GETHOSTBYADDRRSTYLE, SYSVSTYLE)
+               AC_DEFINE(GETHOSTBYADDRRSTYLE, SYSVSTYLE, [style of gethostbyaddr_r functions ])
                gethostbyaddrrstyle=SYSV
        ])
 fi
@@ -870,7 +918,7 @@ if test "x$gethostbyaddrrstyle" = "x"; then
 #include <stdio.h>
 #include <netdb.h>
 ], [ gethostbyaddr(NULL, 0, 0)  ], [
-               AC_DEFINE(GETHOSTBYADDRRSTYLE, BSDSTYLE)
+               AC_DEFINE(GETHOSTBYADDRRSTYLE, BSDSTYLE, [style of gethostbyaddr_r functions ])
                gethostbyaddrrstyle=BSD
        ])
 fi
@@ -898,7 +946,7 @@ AC_TRY_LINK([
 #include <stdio.h>
 #include <netdb.h>
 ], [ gethostbyname_r(NULL, NULL, NULL, 0, NULL, NULL) ], [
-       AC_DEFINE(GETHOSTBYNAMERSTYLE, GNUSTYLE)
+       AC_DEFINE(GETHOSTBYNAMERSTYLE, GNUSTYLE, [style of gethostbyname_r functions ])
        gethostbynamerstyle=GNU
 ])
 if test "x$gethostbynamerstyle" = "x"; then
@@ -906,7 +954,7 @@ if test "x$gethostbynamerstyle" = "x"; then
 #include <stdio.h>
 #include <netdb.h>
 ], [ gethostbyname_r(NULL, NULL, NULL, 0, NULL) ] , [
-               AC_DEFINE(GETHOSTBYNAMERSTYLE, SYSVSTYLE)
+               AC_DEFINE(GETHOSTBYNAMERSTYLE, SYSVSTYLE, [style of gethostbyname_r functions ])
                gethostbynamerstyle=SYSV
        ])
 fi
@@ -915,7 +963,7 @@ if test "x$gethostbynamerstyle" = "x"; then
 #include <stdio.h>
 #include <netdb.h>
 ], [ gethostbyname(NULL)  ], [
-               AC_DEFINE(GETHOSTBYNAMERSTYLE, BSDSTYLE)
+               AC_DEFINE(GETHOSTBYNAMERSTYLE, BSDSTYLE, [style of gethostbyname_r functions ])
                gethostbynamerstyle=BSD
        ])
 fi
@@ -931,19 +979,21 @@ if test "x$gethostbynamerstyle" = "xBSD"; then
 fi
 
 dnl check for non-posix solaris ctime_r (extra buflen int arg)
+AC_DEFINE(POSIXSTYLE, [1], [Posix-Style ctime_r])
+AC_DEFINE(SOLARISSTYLE, [2], [Solaris-Style ctime_r])
 ctimerstyle=""
 AC_MSG_CHECKING([ctime_r() syntax])
 AC_TRY_LINK([
 #include <time.h>
 ], [ ctime_r(NULL, NULL, 0) ], [
-       AC_DEFINE(CTIMERSTYLE, SOLARISSTYLE)
+       AC_DEFINE(CTIMERSTYLE, SOLARISSTYLE, [style of ctime_r function])
        ctimerstyle="SOLARIS"
 ])
 if test "x$ctimerstyle" = "x"; then
        AC_TRY_LINK([
 #include <time.h>
 ], [ ctime_r(NULL, NULL) ], [
-               AC_DEFINE(CTIMERSTYLE, POSIXSTYLE)
+               AC_DEFINE(CTIMERSTYLE, POSIXSTYLE, [style of ctime_r function])
                ctimerstyle="POSIX"
        ])
 fi
@@ -954,64 +1004,6 @@ else
         AC_MSG_RESULT([${ctimerstyle}-style])
 fi
 
-
-dnl If configuring with large file support, determine the right flags to
-dnl use based on the platform.  This is the wrong approach; autoconf 2.50
-dnl comes with a macro that takes the right approach.  But this works well
-dnl enough until we switch to autoconf 2.50 or later.
-if test x"$rad_enable_largefiles" = xyes ; then
-    AC_MSG_CHECKING(for largefile linkage)
-    case "$host" in
-    *-aix4.[01]*)
-        AC_MSG_RESULT(no)
-        AC_MSG_ERROR([AIX before 4.2 does not support large files])
-        ;;
-    *-aix4*)
-        AC_MSG_RESULT(ok)
-        LFS_CFLAGS="-D_LARGE_FILES"
-        LFS_LDFLAGS=""
-        LFS_LIBS=""
-        ;;
-    *-hpux*)
-        AC_MSG_RESULT(ok)
-        LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
-        LFS_LDFLAGS=""
-        LFS_LIBS=""
-        ;;
-    *-irix*)
-        AC_MSG_RESULT(no)
-        AC_MSG_ERROR([Large files not supported on this platform])
-        ;;
-    *-linux*)
-        AC_MSG_RESULT(maybe)
-        LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
-        LFS_LDFLAGS=""
-        LFS_LIBS=""
-        AC_DEFINE([_GNU_SOURCE], 1,
-                  [Some versions of glibc need this defined for pread/pwrite.])
-        ;;
-    *-solaris*)
-        AC_MSG_RESULT(ok)
-        AC_PATH_PROG(GETCONF, getconf)
-        if test -z "$GETCONF" ; then
-            AC_MSG_ERROR([getconf required to configure large file support])
-        fi
-        LFS_CFLAGS=`$GETCONF LFS_CFLAGS`
-        LFS_LDFLAGS=`$GETCONF LFS_LDFLAGS`
-        LFS_LIBS=`$GETCONF LFS_LIBS`
-        ;;
-    *)
-        AC_MSG_RESULT(maybe)
-        LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
-        LFS_LDFLAGS=""
-        LFS_LIBS=""
-        ;;
-    esac
-    AC_SUBST(LFS_CFLAGS)
-    AC_SUBST(LFS_LDFLAGS)
-    AC_SUBST(LFS_LIBS)
-fi
-
 AC_SUBST(HOSTINFO, $host)
 
 dnl #############################################################
@@ -1038,17 +1030,17 @@ dnl #  Configure in any module directories.
 dnl #
 dnl #############################################################
 
-mysubdirs=
+mysubdirs="$LIBLTDLPATH"
 if test "x$EXPERIMENTAL" = "xyes"; then
-  bar=`ls -1 src/modules/rlm_*/configure | sed 's%/configure%%'`
+  bar=`ls -1 "${srcdir}"/src/modules/rlm_*/configure | sed 's%/configure%%'`
   dnl # get rid of LF's.
-  mysubdirs=`echo $bar`
+  mysubdirs=`echo $mysubdirs $bar`
 else
-  dnl # 
+  dnl #
   dnl # Find 'configure' in ONLY the stable modules
-  dnl # 
-  for bar in `cat src/modules/stable`; do
-    if test -f src/modules/$bar/configure; then
+  dnl #
+  for bar in `cat "${srcdir}"/src/modules/stable`; do
+    if test -f "${srcdir}"/src/modules/$bar/configure; then
       mysubdirs="$mysubdirs src/modules/$bar"
     fi
   done
@@ -1058,14 +1050,14 @@ dnl ############################################################
 dnl # make modules by list
 dnl #############################################################
 if test "x$EXPERIMENTAL" = "xyes"; then
-  for foo in `ls -1 src/modules | grep rlm_`; do
+  for foo in `ls -1 "${srcdir}"/src/modules | grep rlm_`; do
     MODULES="$MODULES $foo"
   done
 else
    dnl #
    dnl # make ONLY the stable modules
    dnl #
-   for foo in `cat src/modules/stable`; do
+   for foo in `cat "${srcdir}"/src/modules/stable`; do
     MODULES="$MODULES $foo"
    done
 fi
@@ -1083,6 +1075,11 @@ dnl #  And finally, output the results.
 dnl #
 dnl #############################################################
 
+AC_CONFIG_COMMANDS([stamp-h], [echo timestamp > src/include/stamp-h])
+AC_CONFIG_COMMANDS([build-radpaths-h], [(cd ./src/include && /bin/sh ./build-radpaths-h)])
+AC_CONFIG_COMMANDS([main-chmod], [(cd ./src/main   && chmod +x checkrad.pl radlast radtest)])
+AC_CONFIG_COMMANDS([scripts-chmod], [(cd ./scripts    && chmod +x rc.radiusd radwatch check-radiusd-config radiusd.cron.daily radiusd.cron.monthly cryptpasswd)])
+
 dnl #
 dnl #  Substitute whatever libraries we found to be necessary
 dnl #
@@ -1097,7 +1094,6 @@ AC_SUBST(STATIC_MODULES)
 AC_SUBST(RADIUSD_MAJOR_VERSION)
 AC_SUBST(RADIUSD_MINOR_VERSION)
 AC_SUBST(RADIUSD_VERSION)
-export CFLAGS LIBS
 
 AC_OUTPUT(\
        ./Make.inc \
@@ -1113,10 +1109,6 @@ AC_OUTPUT(\
        ./scripts/radiusd.cron.monthly \
        ./scripts/cryptpasswd \
        ./raddb/dictionary \
-       ./raddb/radiusd.conf
+       ./raddb/radiusd.conf \
+       ./raddb/radrelay.conf
 )
-
-AC_OUTPUT_COMMANDS([echo timestamp > src/include/stamp-h])
-AC_OUTPUT_COMMANDS([(cd ./src/include && /bin/sh ./build-radpaths-h)])
-AC_OUTPUT_COMMANDS([(cd ./src/main   && chmod +x checkrad.pl radlast radtest)])
-AC_OUTPUT_COMMANDS([(cd ./scripts    && chmod +x rc.radiusd radwatch check-radiusd-config radiusd.cron.daily radiusd.cron.monthly cryptpasswd)])
index b11dd42..7b5f083 100644 (file)
@@ -1,8 +1,8 @@
-freeradius (1.1.5-0) unstable; urgency=low
+freeradius (2.0.0-pre0) unstable; urgency=low
 
-  * New upstream release.
+  * Current CVS version.
 
- -- Nicolas Baradakis <nicolas.baradakis@cegetel.net>  Tue,  6 Mar 2007 23:52:55 +0100
+ -- Nicolas Baradakis <nicolas.baradakis@cegetel.net>  Thu, 13 Jul 2006 16:41:06 +0200
 
 freeradius (1.1.3-0) unstable; urgency=low
 
index 5877fe1..a9d00a2 100644 (file)
@@ -44,5 +44,5 @@ rlm_x99_token
 Also, the FreeRADIUS core's SNMP support and the rlm_sql_postgresql
 module transitively depend on OpenSSL via libsnmp{4.2,5} and libpq3
 so they cannot be enabled currently, but this is subject to changes
-in the relevant packages within Debian, or having useable alternate
+in the relevant packages within Debian, or having usable alternate
 libraries in Debian.
diff --git a/debian/freeradius-dialupadmin.dirs b/debian/freeradius-dialupadmin.dirs
new file mode 100644 (file)
index 0000000..811a901
--- /dev/null
@@ -0,0 +1,2 @@
+etc/freeradius-dialupadmin/
+usr/share/freeradius-dialupadmin/
diff --git a/debian/freeradius-dialupadmin.docs b/debian/freeradius-dialupadmin.docs
new file mode 100644 (file)
index 0000000..4083a94
--- /dev/null
@@ -0,0 +1,2 @@
+dialup_admin/README
+dialup_admin/doc/*
diff --git a/debian/freeradius-dialupadmin.examples b/debian/freeradius-dialupadmin.examples
new file mode 100644 (file)
index 0000000..5c627ca
--- /dev/null
@@ -0,0 +1 @@
+dialup_admin/bin/dialup_admin.cron
diff --git a/debian/freeradius-dialupadmin.links b/debian/freeradius-dialupadmin.links
new file mode 100644 (file)
index 0000000..8c2e29e
--- /dev/null
@@ -0,0 +1 @@
+etc/freeradius-dialupadmin/ usr/share/freeradius-dialupadmin/conf
index 5511cf1..e39a366 100755 (executable)
@@ -8,8 +8,6 @@
 # Required-Stop:
 # Default-Start:     2 3 4 5
 # Default-Stop:      0 1 6
-# Short-Description: Radius Daemon 
-# Description:       Extensible, configurable radius daemon
 ### END INIT INFO
 
 PROG="freeradius"
index fef9d88..600a0da 100644 (file)
-Ver 1.70.3:
-* Test for unset variable, rather than empty variable in clean_radacct,
-  monthly_tot_stats and truncate_radacct.
-
-Ver 1.70.2:
-* Fix redirects in dialup-admin pages on servers with register_globals
-  turned off.
-* HTTP form fields will always fail is_int, use in_numeric instead.
-
-Ver 1.70.1:
-* Report correct data transfer statistics for users
-* Lower-case sql column names to match creation scripts
-* Fix creation of empty groups
-* Put quote around usernames in HTML output
-* Properly notice when we've got a blank password to SQL
-
+Ver 1.80:
+* Remove snmp_clearsession. It is replaced by clearsession which supports both snmp and telnet
+  methods of removing a user from an access server. Add corresponding configuration directives
+  general_sessionclear_method and nasXX_sessionclear_method
+* Create a new function da_sql_limit() and use that to pass LIMIT arguments to the database layer
+  since the syntax is different between db vendors
+* Rename the badusers date field to incidentdate to avoid reserved words in databases. Bug found by
+  Peter Nixon
+* Count online users correctly (through a separate query) in user_finger.
+* Use the correct max results variable in lib/*/find.php3
+* In time2strclock also show days if applicable
+* In lib/sql/attrmap.php3, only register variables once. Go through $show_attrs and set default attribute
+  mappings for any attribute that a mapping does not exist.
+* Change the order of OID's used in snmpfinger for cisco NASes
+Ver 1.78:
+* Add a snmp_clearsession which can disconnect a user by using the Cisco AAA Session MIB
+* Add a configuration directive general_sessionclear_bin
+* Add a session disconnect button in the 'clear open sessions' page
+* Also clear sessions from the sql extra servers in the 'clear open sessions' page
+* In bin/snmpfinger also accept @,. in the username
+* If we are stripping realms, then if needed strip them from the data returned by snmpfinger in
+  user_finger.php3
+* Add a header with the page encoding before sending any page (header added in config.php3)
+  This closes Bug #153
+* Fix a problem when reading username.mappings
+* If date calculation fails, abort
+* Add a backup_radacct script
+* Add an sqlrelay functions file. The user_admin page does not currently work. Looking into it.
+* Add sqlrelay support in the scripts. Add a sqlrelay_query script to run sqlrelay commands
+* Update password_check to work with all password attributes and use the configuration directives
+* Add more documentation for per user counter limit attributes (daily/weekly/monthly limits)
+* Make all counter limits default to none so that people don't get confused
+* In clear_opensessions depending on sql type use either IS NULL or = 0 in the DELETE statement.
+  We need to find a cleaner solution to this. This closes bug#175
+* Log somewhat more verbose error messages when the sql_command binary is not found in the bin scripts
+* Make nasXX_finger_type actually work since the place where nas information was stored was changed a
+  long time ago. Bug noted by Nick Bright
+* In user_finger only set LD_LIBRARY_PATH once, not each time we call snmpfinger
+* Add support for usrhiper in snmpfinger. Patch from Nick Bright
+* urlencode() all occurrences of the $login variable when used in url's. Bug noted by Dag Landau
+* Show the correct nas type in nas_admin. Bug noted by Nick Bright
+* Correctly calculate the nas ip in lib/sql/nas_list.php3. Add a check_ip() function in lib/functions.php3
+  Bug noted by Nick Bright
+* Correctly check nas validity in nas_admin.php3. Bug noted by Nick Bright
+* Don't use $num in stats.php3, change it to $stats_num
+Ver 1.75:
+* A LOT of security related fixes. Now dialupadmin should hopefully be secure enough to
+  be accessed by normal users (not administrators).
+* Move a few elements in the CSS file from the body tag. Suggestion by Gary McKinney
+* Update FAQ about using php with no sql support.
+* Allow the user to select between viewing FAQ,HOWTO or README in the help page.
+* Use $_SERVER instead of $HTTP_SERVER_VARS
+* Add a drop down menu with existing groups in group_new.php3
+* Check for sql in show_groups.php3
+* In lib/sql/group_info.php3 if $login is not set, find available groups and place them in
+  $existing_groups along with a count of users per group. Use the functionality in group_new.php3
+  and show_groups.php3
+* Update TODO
+* Add the style sheet in the content.html
+* Enlarge the width for the left frame
+* Make show_groups and the drop down menu in group_new work
+* Use lower cased row names in badusers page
+* Wrong foreach in show_groups and group_new.
+* Fix operator escaping in lib/sql/change_attrs.php3
+* In user_state also take into account any open sessions when calculating daily/weekly usage.
+  Add two more lines in the output stating the number of current open sessions and the time used.
+* Move a few header() calls after including config.php3 so that we have access to the relevant
+  variables.
+* Make pagesize 'all' work again. Bug found by apellido jr., wilfredo p.
+* Make 'Add NAS' function in the nas admin page more easily accessible
+* Fix a small bug in user_admin.php3 found by Joerg Staedele
+* Fix a small typo in the userinfo mysql schema. Found by Evert Meulie
+* Fix bug #136, bugs found by Pawel Foremski
+* Small type in login_time_create, close bug #141
+* In config.php3 remove whitespaces from $login. Don't remove '-'
+* Add lib/sql/group_change.php3 to add and delete a user from groups
+* Add a new directive sql_show_all_groups. If set to true then in user edit page we show all available
+  groups with the ones the user is a member of highlighted. The administrator can then directly
+  change user group membership by changing membership in this group list.
+* On group creation, if member list is empty report that, not that the group was created.
+* In the show groups page, note that we only show groups with members
+* In lib/sql/group_info.php3 only unset variables if we need to. In lib/sql/defaults.php3 don't run for groups
+  only for users
+* Fix Bug #167
+Ver 1.72:
+* Move the xlat function to a separate file in lib/xlat.php3
+* Add a lib/sql/nas_list.php3 to also get the nas list from sql (naslist.conf still works)
+* add realms nasdb and nasadmin in username.mappings. nasadmin is used to signify if the
+  user is allowed to use the nas_admin page. nasdb is used to shorten the nas list to only
+  a few specific entries. That way administrator responsible for a few access servers will
+  only be able to administer those access servers and not see the rest of the nas list.
+* Add username searching in the find page as suggested by joram agten
+* Don't use nas_list in nas_admin
+* Add postgresql specific sql schema by apellido jr., wilfredo p. Move each sql schema to a
+  separate directory (mysql and postgresql)
+* Change is_int to is_numeric. This closes Bug #90
+* Escape special characters in the sql password. This closes bug #96
+* Do an xlat for general_accounting_attrs_file and general_user_edit_attrs_file. That way we can
+  have different mappings for each administrator.
+* Use require_once instead of require when including xlat.php3
+* Add debug statements in sql connect functions
+* Add a missing.php3 file with functions that may be missing from the PHP version used. Include it
+  if a function is missing. Currently only array_change_key_case() is included
+* Set general_restrict_nasadmin_access to no by default. It causes confusion.
+* Set the general_username_mappings_file variable
+* Fix a small error in lib/sql/find.php3. This closes bug #103
+* Add a small note in the FAQ about checking for sql/ldap driver availability in PHP if the user get's
+  a blank white page back.
 Ver 1.70:
 * Add the /bin postgresql compatibility patch from Guy Fraser
 * Add ldap_userdn as a configuration directive. If set we use that for
index e5f08bd..2ea2678 100644 (file)
@@ -84,7 +84,8 @@ htdocs:: user_state.php3 =>
        overview of the status of a user. It will return the following fields
        separated by new lines:
        account_status(active or inactive),lock message,weekly limit,daily limit,
-       weekly used,weekly connections,daily used,daily connections
+       weekly used,weekly connections,daily used,daily connections,
+       active sessions number,active sessions time
 htdocs:: user_finger.php3 =>
        It will finger the nas(es) and show the logged in users. If an argument server is passed then
        it will only show users for the specific access server.
diff --git a/dialup_admin/bin/backup_radacct b/dialup_admin/bin/backup_radacct
new file mode 100755 (executable)
index 0000000..1918a49
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/perl
+use POSIX;
+
+$conf=shift||'/data/local/dialupadmin/conf/admin.conf';
+$back_days = 80;
+$backup_directory = "/logs/radiusd/accounting";
+
+open CONF, "<$conf"
+       or die "Could not open configuration file\n";
+while(<CONF>){
+       chomp;
+       ($key,$val)=(split /:\s*/,$_);
+       $sql_server = $val if ($key eq 'sql_server');
+       $sql_type = $val if ($key eq 'sql_type');
+       $sql_port = $val if ($key eq 'sql_port');
+       $sql_username = $val if ($key eq 'sql_username');
+       $sql_password = $val if ($key eq 'sql_password');
+       $sql_database = $val if ($key eq 'sql_database');
+       $sql_accounting_table = $val if ($key eq 'sql_accounting_table');
+       $sqlcmd = $val if ($key eq 'sql_command');
+}
+close CONF;
+
+die "sql_command directive is not set in admin.conf\n" if ($sqlcmd eq '');
+die "sql command '$sqlcmd' not found or does not seem to be executable\n" if (! -x $sqlcmd);
+if ($sql_type eq 'mysql'){
+       $sql_password = ($sql_password eq '') ? '' : "-p$sql_password";
+}
+$sql_password =~ s/(\W)/\\$1/g;
+
+($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
+$date = POSIX::strftime("%Y-%m-%d",$sec,$min,$hour,($mday - ($back_days - 1)),$mon,$year,$wday,$yday,$isdst);
+$date2 = POSIX::strftime("%Y-%m-%d",$sec,$min,$hour,($mday - ($back_days + 1)),$mon,$year,$wday,$yday,$isdst);
+$date3 = POSIX::strftime("%Y%m%d",$sec,$min,$hour,($mday - $back_days),$mon,$year,$wday,$yday,$isdst);
+if (POSIX::strftime("%Y-%m-%d %T",localtime) eq $date){
+       die "Could not set correct back date.\n";
+}
+
+$query = "SELECT * FROM $sql_accounting_table WHERE AcctStopTime < '$date' AND AcctStopTime > '$date2';";
+print "$query\n";
+open TMP, ">/tmp/backup_radacct.query"
+       or die "Could not open tmp file\n";
+print TMP "ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='YYYY-MM-DD HH24:MI:SS.FF TZH:TZM';\n" if ($sql_type eq 'oracle');
+print TMP $query;
+close TMP;
+$comm = "$sqlcmd -B -h $sql_server -u $sql_username $sql_password $sql_database </tmp/backup_radacct.query >$backup_directory/$date3" if ($sql_type eq 'mysql');
+$comm = "$sqlcmd  -U $sql_username -f /tmp/backup_radacct.query $sql_database >$backup_directory/$date3" if ($sql_type eq 'pg');
+$command = "$sqlcmd  $sql_username/$pass" . "@" . "$sql_database <$tmpfile.$server" if ($sql_type eq 'oracle');
+$command = "$sqlcmd '$sql_server' '$sql_port' '' '$sql_username' '$sql_password' </tmp/backup_radacct.query >$backup_directory/$date3" if ($sql_type eq 'sqlrelay');
+`$comm`;
+`/usr/local/bin/gzip -9 $backup_directory/$date3`;
index a2a1ef3..168af3f 100755 (executable)
@@ -26,13 +26,19 @@ while(<CONF>){
 close CONF;
 
 die "sql_command directive is not set in admin.conf\n" if ($sqlcmd eq '');
-die "Could not find sql binary. Please make sure that the \$sqlcmd variable points to the right location\n" if (! -x $sqlcmd);
+die "sql command '$sqlcmd' not found or does not seem to be executable\n" if (! -x $sqlcmd);
 
-$sql_password = (!$sql_password) ? '' : "-p$sql_password";
+if ($sql_type eq 'mysql'){
+       $sql_password = ($sql_password eq '') ? '' : "-p$sql_password";
+}
+$sql_password =~ s/(\W)/\\$1/g;
 
 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
 $date = POSIX::strftime("%Y-%m-%d %T",$sec,$min,$hour,($mday - $back_days),$mon,$year,$wday,$yday,$isdst);
 print "$date\n";
+if (POSIX::strftime("%Y-%m-%d %T",localtime) eq $date){
+       die "Could not set correct back date.\n";
+}
 
 $query = "DELETE FROM $sql_accounting_table WHERE AcctStopTime IS NULL AND AcctStartTime < '$date';";
 print "$query\n";
@@ -42,4 +48,5 @@ print TMP $query;
 close TMP;
 $command = "$sqlcmd -h$sql_server -u$sql_username $sql_password $sql_database </tmp/clean_radacct.query" if ($sql_type eq 'mysql');
 $command = "$sqlcmd  -U $sql_username -f /tmp/clean_radacct.query $sql_database" if ($sql_type eq 'pg');
+$command = "$sqlcmd '$sql_server' '$sql_port' '' '$sql_username' '$sql_password' </tmp/clean_radacct.query" if ($sql_type eq 'sqlrelay');
 `$command`;
diff --git a/dialup_admin/bin/clearsession b/dialup_admin/bin/clearsession
new file mode 100755 (executable)
index 0000000..f7436ff
--- /dev/null
@@ -0,0 +1,69 @@
+#!/usr/bin/perl
+
+$login = 'nas-login';
+$passwd = 'nas-password';
+
+$host=shift || '';
+$type = shift || 'snmp';
+$nastype = shift || 'cisco';
+$username=shift || '';
+$sessionid = shift || '';
+
+$port = 0;
+$comm = '';
+
+if ($type eq 'snmp'){
+$comm = shift || 'public';
+}
+if ($type eq 'telnet'){
+$port = shift || 0;
+}
+
+
+die "No \$host argument given\n" if ($host eq '');
+die "No \$username argument given\n" if ($username eq '');
+
+if ($nastype eq 'cisco' && $type eq 'telnet'){
+       die "Usage: clearsession \$host telnet cisco \$username \$sessionid \$port\n" if ($port  == 0);
+
+       if (eval require Net::Telnet::Cisco){
+               Net::Telnet::Cisco->import();
+
+               my $session = Net::Telnet::Cisco->new(Host => $host);
+               $session->login($login, $passwd);
+
+               if ($port >= 20000){  
+                       my @output = $session->cmd("sh caller user $username");
+                       foreach $line (@output){
+                               if ($line =~ /User: $username, line (Vi\d+),/){
+                                       $session->cmd("clear interface $1");
+                               }
+                       }
+               }
+               else{
+                       $session->cmd("clear line $port\n");
+               }
+
+               $session->close;
+       }
+}
+if ($nastype eq 'cisco' && $type eq 'snmp'){
+
+       $SNMPGET="/usr/local/bin/snmpget";
+       $SNMPSET="/usr/local/bin/snmpset";
+
+       die "Could not find snmpwalk binary. Please make sure that the \$SNMPGET variable points to the right location\n" if (! -x $SNMPGET);
+       die "Could not find snmpset binary. Please make sure that the \$SNMPSET variable points to the right location\n" if (! -x $SNMPSET);
+       die "Usage: clearsession \$host snmp \$username cisco \$sessionid \$community\n" if ($sessionid eq '' || $comm eq '');
+
+       if ($sessionid ne '' && $username ne ''){
+               print "$SNMPGET -v2c -c $comm $host .iso.org.dod.internet.private.enterprises.9.9.150.1.1.3.1.2.$sessionid\n";
+               $walk =`$SNMPGET -v2c -c $comm $host .iso.org.dod.internet.private.enterprises.9.9.150.1.1.3.1.2.$sessionid`;
+               unless ($walk =~ /^$/){
+                       if ($walk =~ /$username/){
+                               print "FOUND: $username\n";
+               `$SNMPSET -v2c -c $comm $host .iso.org.dod.internet.private.enterprises.9.9.150.1.1.3.1.5.$sessionid i 1`;
+                       }
+               }
+       }
+}
index b3bfbb4..f0d3130 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/perl
 #
 # Log failed logins in the sql database
-# Works with mysql and postgresql
+# Works with mysql, postgresql and Oracle
 # It will read the sql parameters from the admin.conf file
 #
 # Usage:
@@ -31,6 +31,7 @@ $all_file=shift||'no';
 #$regexp = 'from client localhost port 135|from client blabla ';
 $tmpfile='/var/tmp/sql.input';
 #
+$verbose = 0;
 #
 
 open CONF, "<$conf"
@@ -93,11 +94,17 @@ close CLIENTS;
 
 $realm_del = '@' if ($realm_del eq '');
 $realm_for = 'suffix' if ($realm_for eq '');
-$pass = (!$sql_password) ? '' : "-p$sql_password";
+if ($sql_type eq 'mysql'){
+       $pass = ($sql_password ne '') ? "-p$sql_password" : '';
+}
+else{
+       $pass = $sql_password;
+}
+$pass =~ s/(\W)/\\$1/g;
 die "SQL server not defined\n" if ($sql_server eq '');
 
 die "sql_command directive is not set in admin.conf\n" if ($sqlcmd eq '');
-die "Could not find sql binary. Please make sure that the \$sqlcmd variable points to the right location\n" if (! -x $sqlcmd);
+die "sql command '$sqlcmd' not found or does not seem to be executable\n" if (! -x $sqlcmd);
 
 $opt = "";
 $opt = "-O connect_timeout=$sql_timeout" if ($sql_timeout);
@@ -107,10 +114,12 @@ unshift @servers, $sql_server;
 
 open LOG, "<$file"
        or die "Could not open file $file\n";
+if ($verbose > 1) { print STDOUT "DEBUG: Opened $file\n" }
 
 seek LOG, 0, 2 if ($all_file eq 'no');
 for(;;){
        while(<LOG>){
+               if ($verbose > 1) { print STDOUT "DEBUG: Reading $file\n" }
                $do=0;  
                chomp;
                next if ($regexp ne '' && !/$regexp/);
@@ -119,8 +128,10 @@ for(;;){
                        if (/Login incorrect/){
                                if (/Login incorrect \((.+?)\):/){
                                        $cause = "Login-Incorrect ($1)";
+                                       if ($verbose > 1) { print STDOUT "DEBUG: Login-Incorrect ($1)\n" }
                                }else{
                                        $cause='Login-Incorrect';
+                                       if ($verbose > 1) { print STDOUT "DEBUG: Login-Incorrect\n" }
                                }
                                $do=1;
                        }
@@ -187,16 +198,21 @@ for(;;){
                                        $ctx->add($time);
                                        $ctx->add('badlogin');
                                        $uniqueid = $ctx->hexdigest;
+                                       print TMP "ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='YYYY-MM-DD HH24:MI:SS.FF TZH:TZM';\n" if ($sql_type eq 'oracle');
 #DEBUG#                                        print "INSERT INTO $sql_accounting_table (UserName,AcctUniqueId,NASIPAddress,NASPortId,AcctStartTime,AcctStopTime,AcctSessionTime,AcctInputOctets,AcctOutputOctets,CallingStationId,AcctTerminateCause) VALUES ('$user','$uniqueid','$addr','$port','$time','$time','0','0','0','$caller','$cause');\n";
-                                       print TMP "INSERT INTO $sql_accounting_table (UserName,AcctUniqueId,NASIPAddress,NASPortId,AcctStartTime,AcctStopTime,AcctSessionTime,AcctInputOctets,AcctOutputOctets,CallingStationId,AcctTerminateCause) VALUES ('$user','$uniqueid','$addr','$port','$time','$time','0','0','0','$caller','$cause');\n";
+                                       print TMP "INSERT INTO $sql_accounting_table (UserName,AcctSessionId,AcctUniqueId,NASIPAddress,NASPortId,AcctStartTime,AcctStopTime,AcctSessionTime,AcctInputOctets,AcctOutputOctets,CallingStationId,AcctTerminateCause) VALUES ('$user','$uniqueid','$uniqueid','$addr','$port','$time','$time','0','0','0','$caller','$cause');\n";
                                        close TMP;
                                        $command = "$sqlcmd -h$server $opt -u$sql_username $pass $sql_database <$tmpfile.$server" if ($sql_type eq 'mysql');
                                        $command = "$sqlcmd  -U $sql_username -f $tmpfile.$server $sql_database" if ($sql_type eq 'pg');
+                                       $command = "$sqlcmd  $sql_username/$pass" . "@" . "$sql_database <$tmpfile.$server" if ($sql_type eq 'oracle');
+                                       $command = "$sqlcmd '$server' '$sql_port' '' '$sql_username' '$sql_pass' <$tmpfile.$server" if ($sql_type eq 'sqlrelay');
+                                       if ($verbose > 1) { print STDOUT "DEBUG: Sending datafile $tmpfile.$server to \"$sql_type\" database\n" }
                                        `$command`;
+                                       if ($verbose > 1) { print STDOUT "DEBUG: Sent data to \"$sql_type\" database\n" }
 
                                        $exit = $? >> 8;
                                        $delete{$server} = ($exit == 0) ? 1 : 0;
-                                       print "ERROR: SQL query failed for host $server\n" if ($exit != 0);
+                                       print STDERR "ERROR: SQL query failed for host $server\n" if ($exit != 0);
                                }
                        }
                }
index 79f1cba..38ffcab 100755 (executable)
@@ -27,9 +27,12 @@ while(<CONF>){
 close CONF;
 
 die "sql_command directive is not set in admin.conf\n" if ($sqlcmd eq '');
-die "Could not find sql binary. Please make sure that the \$sqlcmd variable points to the right location\n" if (! -x $sqlcmd);
+die "sql command '$sqlcmd' not found or does not seem to be executable\n" if (! -x $sqlcmd);
 
-$sql_password = (!$sql_password) ? '' : "-p$sql_password";
+if ($sql_type eq 'mysql'){
+       $sql_password = ($sql_password eq '') ? '' : "-p$sql_password";
+}
+$sql_password =~ s/(\W)/\\$1/g;
 
 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
 if ($mday == 1){
@@ -50,9 +53,12 @@ print "$query1\n";
 print "$query2\n";
 open TMP, ">/tmp/tot_stats.query"
        or die "Could not open tmp file\n";
+print TMP "ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='YYYY-MM-DD HH24:MI:SS.FF TZH:TZM';\n" if ($sql_type eq 'oracle');
 print TMP $query1;
 print TMP $query2;
 close TMP;
 $command = "$sqlcmd -h $sql_server -u $sql_username $sql_password $sql_database </tmp/tot_stats.query" if ($sql_type eq 'mysql');
 $command = "$sqlcmd  -U $sql_username -f /tmp/tot_stats.query $sql_database" if ($sql_type eq 'pg');
+$command = "$sqlcmd  $sql_username/$pass" . "@" . "$sql_database <$tmpfile.$server" if ($sql_type eq 'oracle');
+$command = "$sqlcmd '$sql_server' '$sql_port' '' '$sql_username' '$sql_password' </tmp/tot_stats.query" if ($sql_type eq 'sqlrelay');
 `$command`;
index 68a7cad..5fd04a0 100755 (executable)
@@ -25,16 +25,21 @@ $snmpwalkcmd="$snmpwalk -v 1 -c $comm $host" if ($snmp_type = 'net');
 
 if ($type eq 'cisco'){
        $walk =`$snmpwalkcmd  .iso.org.dod.internet.private.enterprises.9.9.150.1.1.3.1.2`;
-       if ($walk =~ /^$/){
-               $walk =`$snmpwalkcmd .iso.org.dod.internet.private.enterprises.9.2.9.2.1.18`;
-               $walk.=`$snmpwalkcmd .iso.org.dod.internet.private.enterprises.9.10.19.1.3.1.1.3`;
+       if ($walk =~ /^$/ || $walk =~ /No Such Object/){
+               $walk =`$snmpwalkcmd .iso.org.dod.internet.private.enterprises.9.10.19.1.3.1.1.3`;
+               if ($walk =~ /^$/ || $walk =~ /No Such Object/){
+                       $walk =`$snmpwalkcmd .iso.org.dod.internet.private.enterprises.9.2.9.2.1.18`;
+               }
        }
 }
 elsif ($type eq 'lucent'){
        $walk =`$snmpwalkcmd .iso.org.dod.internet.private.enterprises.529.10.4.1.12`;
 }
+elsif ($type eq 'usrhiper'){
+       $walk =`$snmpwalkcmd .iso.org.dod.internet.private.enterprises.429.4.10.1.1.18`;
+}
 
-while($walk=~/\"([\w\-]+?)\"/g){
+while($walk=~/\"([\@\.\w\-]+?)\"/g){
  $user=lc($1);
  if($out) {
   $out=$out.",'$user'";
diff --git a/dialup_admin/bin/sqlrelay_query b/dialup_admin/bin/sqlrelay_query
new file mode 100755 (executable)
index 0000000..65e96b5
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/perl
+$sqlrelay = '/usr/bin/query';
+$host=shift;
+$port=shift;
+$socket=shift;
+$user=shift;
+$passwd=shift;
+while(<>){
+       chomp;
+       `$sqlrelay '$host' '$port' '$socket' '$user' '$passwd' '$_'`;
+       $exit = $? >> 8;       
+       if ($exit != 0){
+               exit $exit;
+       }
+}
index 193364c..f5659e7 100755 (executable)
@@ -26,9 +26,12 @@ while(<CONF>){
 close CONF;
 
 die "sql_command directive is not set in admin.conf\n" if ($sqlcmd eq '');
-die "Could not find sql binary. Please make sure that the \$sqlcmd variable points to the right location\n" if (! -x $sqlcmd);
+die "sql command '$sqlcmd' not found or does not seem to be executable\n" if (! -x $sqlcmd);
 
-$sql_password = (!$sql_password) ? '' : "-p$sql_password";
+if ($sql_type eq 'mysql'){
+       $sql_password = ($sql_password eq '') ? '' : "-p$sql_password";
+}
+$sql_password =~ s/(\W)/\\$1/g;
 
 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
 $date_start = POSIX::strftime("%Y-%m-%d %T",0,0,0,($mday - 1),$mon,$year,$wday,$yday,$isdst);
@@ -47,9 +50,12 @@ print "$query1\n";
 print "$query2\n";
 open TMP, ">/tmp/tot_stats.query"
        or die "Could not open tmp file\n";
+print TMP "ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='YYYY-MM-DD HH24:MI:SS.FF TZH:TZM';\n" if ($sql_type eq 'oracle');
 print TMP $query1;
 print TMP $query2;
 close TMP;
 $command = "$sqlcmd -h $sql_server -u $sql_username $sql_password $sql_database </tmp/tot_stats.query" if ($sql_type eq 'mysql');
 $command = "$sqlcmd  -U $sql_username -f /tmp/tot_stats.query $sql_database" if ($sql_type eq 'pg');
+$command = "$sqlcmd  $sql_username/$pass" . "@" . "$sql_database <$tmpfile.$server" if ($sql_type eq 'oracle');
+$command = "$sqlcmd '$sql_server' '$sql_port' '' '$sql_username' '$sql_password' </tmp/tot_stats.query" if ($sql_type eq 'sqlrelay');
 `$command`;
index 278b910..09f9193 100755 (executable)
@@ -26,13 +26,19 @@ while(<CONF>){
 close CONF;
 
 die "sql_command directive is not set in admin.conf\n" if ($sqlcmd eq '');
-die "Could not find sql binary. Please make sure that the \$sqlcmd variable points to the right location\n" if (! -x $sqlcmd);
+die "sql command '$sqlcmd' not found or does not seem to be executable\n" if (! -x $sqlcmd);
 
-$sql_password = (!$sql_password) ? '' : "-p$sql_password";
+if ($sql_type eq 'mysql'){
+       $sql_password = ($sql_password eq '') ? '' : "-p$sql_password";
+}
+$sql_password =~ s/(\W)/\\$1/g;
 
 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
 $date = POSIX::strftime("%Y-%m-%d %T",$sec,$min,$hour,($mday - $back_days),$mon,$year,$wday,$yday,$isdst);
 print "$date\n";
+if (POSIX::strftime("%Y-%m-%d %T",localtime) eq $date){
+       die "Could not set correct back date.\n";
+}
 $query = "";
 $query = "LOCK TABLES $sql_accounting_table WRITE;" if ($sql_type eq 'mysql');
 $query .= "DELETE FROM $sql_accounting_table WHERE AcctStopTime < '$date' AND AcctStopTime IS NOT NULL ;";
@@ -40,8 +46,11 @@ $query .= "UNLOCK TABLES;" if ($sql_type eq 'mysql');
 print "$query\n";
 open TMP, ">/tmp/truncate_radacct.query"
         or die "Could not open tmp file\n";
+print TMP "ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='YYYY-MM-DD HH24:MI:SS.FF TZH:TZM';\n" if ($sql_type eq 'oracle');
 print TMP $query;
 close TMP;
 $command = "$sqlcmd -h$sql_server -u$sql_username $sql_password $sql_database </tmp/truncate_radacct.query" if ($sql_type eq 'mysql');
 $command = "$sqlcmd  -U $sql_username -f /tmp/truncate_radacct.query $sql_database" if ($sql_type eq 'pg');
+$command = "$sqlcmd  $sql_username/$pass" . "@" . "$sql_database <$tmpfile.$server" if ($sql_type eq 'oracle');
+$command = "$sqlcmd '$sql_server' '$sql_port' '' '$sql_username' '$sql_password' </tmp/truncate_radacct.query" if ($sql_type eq 'sqlrelay');
 `$command`;
index 2062d0b..784de7b 100644 (file)
@@ -46,7 +46,7 @@ general_most_recent_fl: 30
 #
 # Set general_strip_realms to yes in order  to stip realms from usernames.
 # By default realms are not striped
-#general_strip_realms : yes
+#general_strip_realms: yes
 #
 # The delimiter used  in realms. Default is @
 #
@@ -71,6 +71,7 @@ general_clients_conf: /usr/local/etc/raddb/clients.conf
 general_sql_attrmap: %{general_base_dir}/conf/sql.attrmap
 general_accounting_attrs_file: %{general_base_dir}/conf/accounting.attrs
 general_extra_ldap_attrmap: %{general_base_dir}/conf/extra.ldap-attrmap
+general_username_mappings_file: %{general_base_dir}/conf/username.mappings
 #
 # it can be either ldap or sql
 # This affects the user base not accounting. Accounting is always in sql
@@ -97,10 +98,19 @@ general_default_file: %{general_base_dir}/conf/default.vals
 general_finger_type: snmp
 #
 # Defines the nas type. This is only used by snmpfinger
-# cisco and lucent are supported for now
+# cisco, usrhiper and lucent are supported for now
 #
 general_nas_type: cisco
 general_snmpfinger_bin: %{general_base_dir}/bin/snmpfinger
+#
+# Used by the 'Disconnect User' button in the Clear Open Sessions page
+# Uses the Cisco AAA Session MIB or a telnet session
+#
+general_sessionclear_bin: %{general_base_dir}/bin/clearsession
+#
+# Can be one of telnet or snmp
+#
+general_sessionclear_method: snmp
 general_radclient_bin: %{general_radiusd_base_dir}/bin/radclient
 #
 # this information is used from the server check page
@@ -142,6 +152,12 @@ general_stats_use_totacct: no
 # in the badusers table
 #
 general_restrict_badusers_access: no
+#
+# If set to yes then we restrict access to the nas administration page only to those
+# users which are allowed by their username mapping (nasadmin is set to yes)
+#
+general_restrict_nasadmin_access: no
+
 
 INCLUDE: %{general_base_dir}/conf/naslist.conf
 
@@ -188,7 +204,7 @@ ldap_regular_profile_attr: dialupregularprofile
 #
 # Uncomment to enable ldap debug
 #
-#ldap_debug: true
+ldap_debug: true
 #
 # Allow for defining the ldap filter used when searching for a user
 # Variables supported:
@@ -196,6 +212,8 @@ ldap_regular_profile_attr: dialupregularprofile
 # %U: username provided though http authentication
 # %mu: mappings for userdb
 # %ma: mappings for accounting
+# %mn: mappings for nasdb
+# %mN: mappings for nas administration
 #
 # One use of this would be to restrict access to only the user's belonging to
 # a specific administrator like this:
@@ -211,9 +229,11 @@ ldap_regular_profile_attr: dialupregularprofile
 
 
 #
-# can be one of mysql,pg where:
+# can be one of mysql,pg,oracle,sqlrelay where:
 # mysq: MySQL database (port 3306)
 # pg: PostgreSQL database (port 5432)
+# oracle: Oracle database (port 1521)
+# sqlrelay: SQL Relay
 #
 sql_type: mysql
 sql_server: localhost
@@ -232,10 +252,17 @@ sql_usergroup_table: usergroup
 sql_total_accounting_table: totacct
 sql_nas_table: nas
 #
+# If set to true then we show all the available groups with the groups
+# that the user is a member of highlighted in the user edit page.
+# Otherwise we only show the groups he is a member of.
+sql_show_all_groups: true
+#
 # This variable is used by the scripts in the bin folder
 # It should contain the path to the sql binary used to run
-# sql commands (mysql and psql are only supported for now)
+# sql commands (mysql, psql, oracle and sqlrelay are only supported for now)
 sql_command: /usr/local/bin/mysql
+#sql_command: /usr/bin/psql
+#sql_command: /usr/bin/sqlplus
 #
 # This variable is used by the scripts in the bin folder
 # It should contain the snmp type and  path to the binary 
@@ -257,6 +284,13 @@ sql_debug: true
 #
 # If set the query will be added to all of the queries on the accounting
 # table
+# Variables supported:
+# %u: username
+# %U: username provided though http authentication
+# %mu: mappings for userdb
+# %ma: mappings for accounting
+# %mn: mappings for nasdb
+# %mN: mappings for nas administration
 #sql_accounting_extra_query: %ma
 
 
@@ -294,9 +328,16 @@ sql_connect_timeout: 3
 # Default values for the various user limits in case the counter module
 # is used to impose such limits.
 # The value should be the user limit in seconds or none for nothing
-#
-counter_default_daily: 14400
-counter_default_weekly: 72000
+# Check out conf/sql.attrmap or extra.ldap-attrmap (depending on if you are
+# using sql or ldap) for per user attributes. The mapping should be made to
+# the attributes configured in the counter module. The attributes used by
+# dialupadmin will always be the ones appearing in the attribute mapping files
+# so you should make sure they are mapped to the correct attributes
+#
+#counter_default_daily: 14400
+#counter_default_weekly: 72000
+counter_default_daily: none
+counter_default_weekly: none
 counter_default_monthly: none
 #
 # Since calculating monthly usage can be quite expensive we make
index 412d884..cde0b57 100644 (file)
@@ -9,12 +9,17 @@ if( $curVer >= $testVer )
 # If using sessions set use_session to 1 to also cache the config file
 #
 $use_session = 0;
+unset($config);
+unset($nas_list);
 if ($use_session){
        // Start session
        @session_start();
+       if (isset($_SESSION['config']))
+               $config = $_SESSION['config'];
+       if (isset($_SESSION['nas_list']))
+               $nas_list = $_SESSION['nas_list'];
 }
 if (!isset($config)){
-       unset($nas_list);
        $ARR=file("../conf/admin.conf");
        $EXTRA_ARR = array();
        foreach($ARR as $val) {
@@ -61,10 +66,12 @@ if (!isset($config)){
 if ($use_session == 0 && $config[general_use_session] == 'yes'){
        // Start session
        @session_start();
+       if (isset($nas_list))
+               session_register('nas_list');
 }
 //Make sure we are only passed allowed strings in username
 if ($login != '')
-       $login = preg_replace("/[^\w\s\.\/\@\:]\-i\=/",'',$login);
+       $login = preg_replace("/[^\w\.\/\@\:\-]/",'',$login);
 
 if ($login != '' && $config[general_strip_realms] == 'yes'){
        $realm_del = ($config[general_realm_delimiter] != '') ? $config[general_realm_delimiter] : '@';
@@ -73,17 +80,35 @@ if ($login != '' && $config[general_strip_realms] == 'yes'){
        if (count($new) == 2)
                $login = ($realm_for == 'suffix') ? $new[0] : $new[1];
 }
+unset($mappings);
+if (isset($_SESSION['mappings']))
+       $mappings = $_SESSION['mappings'];
 if (!isset($mappings) && $config[general_username_mappings_file] != ''){
        $ARR = file($config[general_username_mappings_file]);
        foreach($ARR as $val){
                $val=chop($val);
                if (ereg('^[[:space:]]*#',$val) || ereg('^[[:space:]]*$',$val))
                        continue;
-               list($key,$realm,$v)=split(":[[:space:]]*",$val,2);
-               if ($realm == 'accounting' || $realm == 'userdb')
+               list($key,$realm,$v)=split(":[[:space:]]*",$val,3);
+               if ($realm == 'accounting' || $realm == 'userdb' || $realm == 'nasdb' || $realm == 'nasadmin')
                        $mappings["$key"][$realm] = $v;
+               if ($realm == 'nasdb'){
+                       $NAS_ARR = array();
+                       $NAS_ARR = split(',',$v);
+                       foreach ($nas_list as $key => $nas){
+                               foreach ($NAS_ARR as $nas_check){
+                                       if ($nas_check == $nas[name])
+                                               unset($nas_list[$key]);
+                               }
+                       }
+               }
        }
        if ($config[general_use_session] == 'yes')
                session_register('mappings');
 }
+
+//Include missing.php3 if needed
+if (!function_exists('array_change_key_case'))
+       include_once('../lib/missing.php3');
+@header('Content-type: text/html; charset='.$config[general_charset].';');
 ?>
index 69b5320..fb0637a 100644 (file)
@@ -5,4 +5,8 @@ checkItem       Dialup-Lock-Msg         radiuslockmsg
 checkItem      User-Password           userpassword
 checkItem      Regular-Profile         radiusProfileDn
 checkItem      Check-Item              radiusCheckItem         generic
+checkItem      Max-Daily-Session       radiusMaxDailySession
+checkItem      Max-Weekly-Session      radiusMaxWeeklySession
+checkItem      Max-Monthly-Session     radiusMaxMonthlySession
+
 replyItem      Reply-Item              radiusReplyItem         generic
index 4096d25..567893c 100644 (file)
@@ -25,3 +25,7 @@ nas3_model: Cisco 5300 access server
 nas3_ip: 147.122.122.124
 nas3_port_num: 210
 nas3_community: public
+#
+# sessionclear method can also be set per NAS
+#
+nas3_sessionclear_method: telnet
index 7fa79fa..a5a44c9 100644 (file)
@@ -16,6 +16,7 @@ checkItem     Calling-Station-Id              Calling-Station-Id
 checkItem      Dialup-Access                   none
 checkItem      Max-Daily-Session               Max-Daily-Session
 checkItem      Max-Weekly-Session              Max-Weekly-Session
+checkItem      Max-Monthly-Session             Max-Monthly-Session
 checkItem      Login-Time                      Login-Time
 checkItem      Expiration                      Expiration
 
index 4e96ee3..8ec5903 100644 (file)
@@ -38,6 +38,7 @@ Dialup-Lock-Msg                       <a href="help/lock_message_help.html" target=lm_help onclick=w
 #Reply-Message <a href="help/reply_message_help.html" target=lm_help onclick=window.open("help/reply_message_help.html","lm_help","width=600,height=210,toolbar=no,scrollbars=no,resizable=yes") title="Reply-Message Help Page"><font color="blue">Reply-Message</font></a>
 #Max-Daily-Session             Daily Limit (secs)
 #Max-Weekly-Session            Weekly Limit (secs)
+#Max-Monthly-Session           Monthly Limit (secs)
 #Login-Time                    <a href="login_time_create.php3?val=$name1&first=yes" target=lt_create onclick=window.open("login_time_create.php3?val=$name1&first=yes","lt_create","width=600,height=490,toolbar=no,scrollbars=yes,resizable=yes") title="Login-Time Creation Page"><font color="blue">User Login Period </font></a>(<a href="help/login_time_help.html" target=lt_help onclick=window.open("help/login_time_help.html","lt_help","width=600,height=370,toolbar=no,scrollbars=no,resizable=yes") title="Login-Time Help Page"><font color="blue">UUCP </font></a>Format)
 #Expiration                    <a href="help/expiration_help.html" target=lt_help onclick=window.open("help/expiration_help.html","lt_help","width=600,height=180,toolbar=no,scrollbars=no,resizable=yes") title="Expiration Help Page"><font color="blue">User Expiration Date</font></a>
 #
index e7d7b12..3180365 100644 (file)
@@ -2,7 +2,20 @@
 # Format:
 # Username:realm:query
 #
-# where realm is accounting or userdb
+# where realm is:
+# accounting: for the map to be used when querying the accounting db
+# userdb: for the map to be used when querying the user db
+# nasdb: To only map specific NASes to the username (separated by ,)
+# nasadmin: To allow the user to use the nas_admin page (yes or no)
 #
 library-admin:accounting:AND nasipaddress = '123.123.123.123'
 library-admin:userdb:AND Admin = 'library-admin'
+library-admin:nasdb:nas.lib.company.com
+library-admin:nasadmin:no
+#
+lab-admin:accounting:AND nasipaddress =  '123.123.124.123'
+lab-admin:userdb:AND Admin = 'lab-admin'
+lab-admin:nasdb:nas.lab.company.com
+lab-admin:nasadmin:no
+#
+admin:nasadmin:yes
index 3b7884b..8ec253f 100644 (file)
@@ -13,6 +13,9 @@ HTML pages layout designer
 Dragan Milivojevic: galileo@MICROSKY.NET
 A number of bug reports and a lot of crash testing
 
+Gary McKinney
+A number of bug reports and a lot of crash testing
+
 Alex Savguira: alexs@ravdata.com
 Ido Shavit
 Patches for auto generate password
index 9c2b211..7c7b13c 100644 (file)
@@ -82,6 +82,13 @@ Set general_prefered_lang to en
 If you are using sessions then remember to use the 'Clear Cache' page after making any changes
 
 >
+> When i try to access a dynamic web page it only shows a blank white page
+>
+
+You may have not enabled support for the corresponding sql driver in PHP. If you are also using ldap, check for
+php ldap support.
+
+>
 > It is still not working
 >
 
index 315d454..5b37592 100644 (file)
@@ -1,8 +1,6 @@
 * Minimize database (ldap,mysql) connections.
 * Clean up html code to make it smaller
 * More messages
-* Skins
-* Other languages in html
 * Multilanguage support for ldap attributes
 * Add language attributes in user_new.php3
 * Finger facility. Should find a way to make it work with all nases. That will
@@ -16,4 +14,8 @@
   are welcome.
 * Parse the radius dictionary files so that we can show a pull down menu of possible values
   for various attributes.
-* Check the sql user code for sql injections
+* Also be able to keep username mappings in sql. Create an administration page
+* Improve sqlrelay support
+* Make the userinfo attributes configurable and create calculation formulas.Like:
+  Attribute-Name:DB-Attribute:Internal-Attribute:Initial-Value:Editable
+  Administrator:admin:admin:%U:No
index 8e4201e..65172e8 100644 (file)
@@ -3,7 +3,7 @@
 <title>About page</title>
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
index 1d42015..0c6a357 100644 (file)
@@ -15,7 +15,7 @@ else{
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <b>Could not include SQL library functions. Aborting</b>
 </body>
@@ -33,6 +33,8 @@ $link = @da_sql_pconnect ($config) or die('cannot connect to sql databse');
 $fields = @da_sql_list_fields($config[sql_accounting_table],$link,$config);
 $no_fields = @da_sql_num_fields($fields,$config);
 
+unset($items);
+
 for($i=0;$i<$no_fields;$i++){
        $key = strtolower(@da_sql_field_name($fields,$i,$config));
        $val = $sql_attrs[$key][desc];
@@ -109,7 +111,7 @@ EOM;
 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $config[general_charset]?>">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 
 <?php
 if(!$queryflag) {
@@ -222,20 +224,30 @@ while (${"item_of_w$i"}){
 
 $order = ($order_by != '') ? "$order_by" : 'username';
 
+if (preg_match("/[\s;]/",$order))
+       die("ORDER BY pattern is illegal. Exiting abnornally.");
+
+if (!is_numeric($maxresults))
+       die("Max Results is not in numeric form. Exiting abnormally.");
+
+unset($query_view);
 foreach ($accounting_show_attrs as $val)
        $query_view .= $val . ',';
 $query_view = ereg_replace(',$','',$query_view);
-$sql_extra_query = '';
+unset($sql_extra_query);
 if ($config[sql_accounting_extra_query] != '')
-       $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config);
-$query="SELECT $query_view FROM $config[sql_accounting_table] $where $sql_extra_query ORDER BY $order LIMIT $maxresults;";
+       $sql_extra_query = xlat($config[sql_accounting_extra_query],$login,$config);
+       $sql_extra_query = da_sql_escape_string($sql_extra_query);
+$query="SELECT " . da_sql_limit($maxresults,0,$config) . " $query_view FROM $config[sql_accounting_table]
+       $where $sql_extra_query " . da_sql_limit($maxresults,1,$config) .
+       " ORDER BY $order " . da_sql_limit($maxresults,2,$config) . ";";
 
 echo <<<EOM
 <html>
 <head>
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <br>
 <table border=0 width=940 cellpadding=1 cellspacing=1>
 <tr valign=top>
@@ -271,8 +283,10 @@ echo "</tr>\n";
                                if ($info == '')
                                        $info = '-';
                                $info = $sql_attrs[$val][func]($info);
-                               if ($val == 'username')
-                                       $info = "<a href=\"user_admin.php3?login=$info\" title=\"Edit user $info\">$info<a/>";
+                               if ($val == 'username'){
+                                       $Info = urlencode($info);
+                                       $info = "<a href=\"user_admin.php3?login=$Info\" title=\"Edit user $info\">$info<a/>";
+                               }
                                echo <<<EOM
                        <td>$info</td>
 EOM;
index ae0d9df..2884c1d 100644 (file)
@@ -13,7 +13,7 @@ else{
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <b>Could not include SQL library functions. Aborting</b>
 </body>
@@ -33,7 +33,7 @@ $num = 0;
 $pagesize = ($pagesize) ? $pagesize : 10;
 if (!is_numeric($pagesize) && $pagesize != 'all')
        $pagesize = 10;
-$limit = ($pagesize == 'all') ? '' : "LIMIT $pagesize";
+$limit = ($pagesize == 'all') ? '' : "$pagesize";
 $selected[$pagesize] = 'selected';
 $login = ($login != '') ? $login : 'anyone';
 $usercheck = ($login == 'anyone') ? "LIKE '%'" : "= '$login'";
@@ -48,7 +48,7 @@ echo <<<EOM
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
@@ -79,7 +79,7 @@ if ($link){
                $row = @da_sql_fetch_array($search,$config);
                if ($row[id] == $row_id){
                        $admin = "$row[admin]";
-                       if (($admin != '-' && $HTTP_SERVER_VARS["PHP_AUTH_USER"] == $admin) || $admin == '-'){
+                       if (($admin != '-' && $_SERVER["PHP_AUTH_USER"] == $admin) || $admin == '-'){
                                $sql_servers = array();
                                if ($config[sql_extra_servers] != '')
                                        $sql_servers = explode(' ',$config[sql_extra_servers]);
@@ -137,7 +137,7 @@ EOM;
        </tr>
 
 <?php
-$auth_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
+$auth_user = $_SERVER["PHP_AUTH_USER"];
 if ($config[general_restrict_badusers_access] == 'yes'){
        $auth_user = da_sql_escape_string($auth_user);
        $extra_query = "AND admin == '$auth_user'";
@@ -145,15 +145,17 @@ if ($config[general_restrict_badusers_access] == 'yes'){
 $link = @da_sql_pconnect($config);
 if ($link){
        $search = @da_sql_query($link,$config,
-       "SELECT * FROM $config[sql_badusers_table]
-       WHERE UserName $usercheck $extra_query AND Date <= '$now_str'
-       AND Date >= '$prev_str' ORDER BY Date $order $limit;");
+       "SELECT " . da_sql_limit($limit,0,$config) . " * FROM $config[sql_badusers_table]
+       WHERE username $usercheck $extra_query AND incidentdate <= '$now_str'
+       AND incidentdate >= '$prev_str' " . da_sql_limit($limit,1,$config) .
+       " ORDER BY incidentdate $order " . da_sql_limit($limit,2,$config) . " ;");
        if ($search){
                while( $row = @da_sql_fetch_array($search,$config) ){
                        $num++;
                        $id = $row[id];
-                       $user = "$row[userName]";
-                       $date = "$row[date]";
+                       $user = "$row[username]";
+                       $User = urlencode($user);
+                       $date = "$row[incidentdate]";
                        $reason = "$row[reason]";
                        $admin = "$row[admin]";
                        if ($admin == $auth_user || $admin == '-')
@@ -167,7 +169,7 @@ if ($link){
                        echo <<<EOM
                        <tr align=center>
                                <td>$num</td>
-                               <td><a href="user_admin.php3?login=$user" title="Edit user $user">$user</a></td>
+                               <td><a href="user_admin.php3?login=$User" title="Edit user $user">$user</a></td>
                                <td>$date</td>
                                <td>$admin</td>
                                <td>$reason</td>
index 12c2c32..6a16eef 100644 (file)
@@ -1,5 +1,5 @@
 <?php
-$auth_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
+$auth_user = $_SERVER["PHP_AUTH_USER"];
 if ($auth_user){
        if (is_file("../html/buttons/$auth_user/buttons.html.php3"))
                include("../html/buttons/$auth_user/buttons.html.php3");
index 10349dc..62d0d1a 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 require('../conf/config.php3');
+require_once('../lib/xlat.php3');
 if (is_file("../lib/sql/drivers/$config[sql_type]/functions.php3"))
        include_once("../lib/sql/drivers/$config[sql_type]/functions.php3");
 else{
@@ -8,7 +9,7 @@ else{
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <b>Could not include SQL library functions. Aborting</b>
 </body>
@@ -24,7 +25,7 @@ echo <<<EOM
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
@@ -40,8 +41,10 @@ include("../html/user_toolbar.html.php3");
 $open_sessions = 0;
 
 $sql_extra_query = '';
-if ($config[sql_accounting_extra_query] != '')
-       $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config);
+if ($config[sql_accounting_extra_query] != ''){
+       $sql_extra_query = xlat($config[sql_accounting_extra_query],$login,$config);
+       $sql_extra_query = da_sql_escape_string($sql_extra_query);
+}
 
 print <<<EOM
 </table>
@@ -61,20 +64,78 @@ print <<<EOM
        <table border=0 width=100% cellpadding=12 cellspacing=0 bgcolor="#ffffd0" valign=top>
        <tr><td>
 EOM;
-   
-if ($clear_sessions == 1){
+if ($drop_conns == 1){
+       $method = 'snmp';
+       $nastype = 'cisco';
+       if ($config[general_sessionclear_method] != '')
+               $method = $config[general_sessionclear_method];
+       if ($config[general_nas_type] != '')
+               $nastype = $config[general_nas_type];
+       if ($config[general_ld_library_path] != '')
+               putenv("LD_LIBRARY_PATH=$config[general_ld_library_path]");
+       $nas_by_ip = array();
+       $meth_by_ip = array();
+       $nastype_by_ip = array();
+       foreach ($nas_list as $nas){
+               if ($nas[ip] != ''){
+                       $ip = $nas[ip];
+                       $nas_by_ip[$ip] = $nas[community];
+                       $meth_by_ip[$ip] = $nas[sessionclear_method];
+                       $nastype_by_ip[$ip] = $nas[nas_type];
+               }
+       }
+
        $link = @da_sql_pconnect($config);
        if ($link){
-               $res = @da_sql_query($link,$config,
-               "DELETE FROM $config[sql_accounting_table]
-               WHERE username='$login' AND acctstoptime = 0 $sql_extra_query;");
-               if ($res)
-                       echo "<b>Deleted open sessions from accounting table</b><br>\n";
+               $search = @da_sql_query($link,$config,
+               "SELECT nasipaddress,acctsessionid FROM $config[sql_accounting_table]
+               WHERE username = '$login' AND acctstoptime IS NULL;");
+               if ($search){
+                       while($row = @da_sql_fetch_array($search,$config)){
+                               $sessionid = $row[acctsessionid];
+                               $sessionid = hexdec($sessionid);
+                               $nas = $row[nasipaddress];
+                               $port = $row[nasportid];
+                               $meth = $meth_by_ip[$nas];
+                               $nastype = ($nastype_by_ip[$nas] != '') ? $nastype_by_ip[$nas] : $nastype;
+                               $comm = $nas_by_ip[$nas];
+                               if ($meth == '')
+                                       $meth = $method;
+                               if ($meth == 'snmp' && $comm != '')
+                                       exec("$config[general_sessionclear_bin] $nas snmp $nastype $login $sessionid $comm");
+                               if ($meth == 'telnet')
+                                       exec("$config[general_sessionclear_bin] $nas telnet $nastype $login $sessionid $port");
+                       }
+               }
                else
-                       echo "<b>Error deleting open sessions for user" . da_sql_error($link,$config) . "</b><br>\n";
-        }
+                       echo "<b>Database query failed: " . da_sql_error($link,$config) . "</b><br>\n";
+       }
        else
                echo "<b>Could not connect to SQL database</b><br>\n";
+}
+if ($clear_sessions == 1){
+       $sql_servers = array();
+       if ($config[sql_extra_servers] != '')
+               $sql_servers = explode(' ',$config[sql_extra_servers]);
+       $quer = '= 0';
+       if ($config[sql_type] == 'pg')
+               $quer = 'IS NULL';
+       $sql_servers[] = $config[sql_server];
+       foreach ($sql_servers as $server){
+               $link = @da_sql_host_connect($server,$config);
+               if ($link){
+                       $res = @da_sql_query($link,$config,
+                       "DELETE FROM $config[sql_accounting_table]
+                       WHERE username='$login' AND acctstoptime $quer $sql_extra_query;");
+                       if ($res)
+                               echo "<b>Deleted open sessions from accounting table on server $server</b><br>\n";
+                       else
+                               echo "<b>Error deleting open sessions for user" . da_sql_error($link,$config) . "</b><br>\n";
+               }
+               else
+                       echo "<b>Could not connect to SQL database</b><br>\n";
+       }
        echo <<<EOM
 </td></tr>
 </table>
@@ -97,7 +158,7 @@ else{
                }
                else
                        echo "<b>Database query failed: " . da_sql_error($link,$config) . "</b><br>\n";
-        }
+       }
        else
                echo "<b>Could not connect to SQL database</b><br>\n";
 }
@@ -115,6 +176,8 @@ Are you sure you want to clear all open user sessions?
        </table>
 <br>
 <input type=submit class=button value="Yes Clear" OnClick="this.form.clear_sessions.value=1">
+<br><br>
+<input type=submit class=button value="Yes Drop Connections" OnClick="this.form.drop_conns.value=1">
 </form>
 </td></tr>
 </table>
index d8fa823..8e27e24 100644 (file)
@@ -1,5 +1,8 @@
 <html>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<head>
+<link rel="stylesheet" href="style.css">
+</head>
+<body>
 <center><img src="images/title2.gif">
 <br><font size=+1><br>
 <b>A web based administration interface for the freeradius radius server</b>
index 938ed82..6387886 100644 (file)
@@ -1,6 +1,8 @@
 <?php
 require('../conf/config.php3');
 require('../lib/attrshow.php3');
+require('../lib/sql/nas_list.php3');
+require_once('../lib/xlat.php3');
 ?>
 <html>
 <?php
@@ -13,7 +15,7 @@ else{
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <b>Could not include SQL library functions. Aborting</b>
 </body>
@@ -23,8 +25,10 @@ EOM;
 }
 
 $now = time();
-if ($last == 0)
+if (!isset($last))
        $last = ($config[general_most_recent_fl]) ? $config[general_most_recent_fl] : 5;
+if (!is_numeric($last))
+       $last = 5;
 $start = $now - ($last*60);
 $now_str = date($config[sql_full_date_format],$now);
 $prev_str = date($config[sql_full_date_format],$start);
@@ -35,7 +39,7 @@ $prev_str = da_sql_escape_string($prev_str);
 $pagesize = ($pagesize) ? $pagesize : 10;
 if (!is_numeric($pagesize) && $pagesize != 'all')
        $pagesize = 10;
-$limit = ($pagesize == 'all') ? '' : "LIMIT $pagesize";
+$limit = ($pagesize == 'all') ? '' : "$pagesize";
 $selected[$pagesize] = 'selected';
 $order = ($order != '') ? $order : $config[general_accounting_info_order];
 if ($order != 'desc' && $order != 'asc')
@@ -50,6 +54,10 @@ if ($server != '' && $server != 'all'){
        $server_str = "AND nasipaddress = '$server'";
 }
 
+unset($da_name_cache);
+if (isset($_SESSION['da_name_cache']))
+       $da_name_cache = $_SESSION['da_name_cache'];
+
 ?>
 
 <head>
@@ -57,7 +65,7 @@ if ($server != '' && $server != 'all'){
 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $config[general_charset]?>">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
@@ -95,9 +103,11 @@ if ($acct_attrs['fl'][2] != '') echo "<th>" . $acct_attrs['fl'][2] . "</th>\n";
 if ($acct_attrs['fl'][7] != '') echo "<th>" . $acct_attrs['fl'][7] . "</th>\n";
 if ($acct_attrs['fl'][8] != '') echo "<th>" . $acct_attrs['fl'][8] . "</th>\n";
 if ($acct_attrs['fl'][9] != '') echo "<th>" . $acct_attrs['fl'][9] . "</th>\n";
-$sql_extra_query = '';
-if ($config[sql_accounting_extra_query] != '')
-       $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config);
+unset($sql_extra_query);
+if ($config[sql_accounting_extra_query] != ''){
+       $sql_extra_query = xlat($config[sql_accounting_extra_query],$login,$config);
+       $sql_extra_query = da_sql_escape_string($sql_extra_query);
+}
 ?>
        </tr>
 
@@ -105,13 +115,13 @@ if ($config[sql_accounting_extra_query] != '')
 $link = @da_sql_pconnect($config);
 if ($link){
        $search = @da_sql_query($link,$config,
-       "SELECT acctstoptime,username,nasipaddress,nasportid,acctterminatecause,callingstationid
+       "SELECT " . da_sql_limit($limit,0,$config) . " acctstoptime,username,nasipaddress,nasportid,acctterminatecause,callingstationid
        FROM $config[sql_accounting_table]
        WHERE acctstoptime <= '$now_str' AND acctstoptime >= '$prev_str'
        AND (acctterminatecause LIKE 'Login-Incorrect%' OR
        acctterminatecause LIKE 'Invalid-User%' OR
-       acctterminatecause LIKE 'Multiple-Logins%') $callerid_str $server_str $sql_extra_query
-       ORDER BY acctstoptime $order $limit;");
+       acctterminatecause LIKE 'Multiple-Logins%') $callerid_str $server_str $sql_extra_query " . da_sql_limit($limit,1,$config) .
+       " ORDER BY acctstoptime $order " . da_sql_limit($limit,2,$config) . " ;");
        if ($search){
                while( $row = @da_sql_fetch_array($search,$config) ){
                        $num++;
@@ -200,6 +210,8 @@ EOM;
 <?php
 foreach ($nas_list as $nas){
        $name = $nas[name];
+       if ($nas[ip] == '')
+               continue;
        $servers[$name] = $nas[ip];
 }
 ksort($servers);
index f3e90c8..f83ac7e 100644 (file)
@@ -10,7 +10,7 @@ $max = ($max_results) ? $max_results : 40;
 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $config[general_charset]?>">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
@@ -36,6 +36,7 @@ $max = ($max_results) ? $max_results : 40;
 
 <?php
 if ($find_user == 1){
+       unset($found_users);
        if (is_file("../lib/$config[general_lib_type]/find.php3"))
                include("../lib/$config[general_lib_type]/find.php3");
        if (isset($found_users)){
@@ -50,11 +51,12 @@ EOM;
                foreach ($found_users as $user){
                        if ($user == '')
                                $user = '-';
+                       $User = urlencode($user);
                        $num++;
                        $msg .= <<<EOM
                        <tr align=center>
                                <td>$num</td>
-                               <td><a href="user_admin.php3?login=$user" title="Edit user $user">$user</a></td>
+                               <td><a href="user_admin.php3?login=$User" title="Edit user $user">$user</a></td>
                        </tr>
 EOM;
                }
@@ -76,8 +78,9 @@ Search Criteria
 <?php
 echo <<<EOM
 <select name="search_IN" editable onChange="this.form.submit();">
+<option $selected[username] value="username">User Name
 <option $selected[name]  value="name">User Full Name
-<option $selected[ou] value="ou">User Department
+<option $selected[department] value="department">User Department
 <option $selected[radius] value="radius">User Radius Attribute
 EOM;
 ?>
index 172f4f1..41bb7e8 100644 (file)
@@ -10,7 +10,7 @@ if ($config[general_lib_type] != 'sql'){
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <b>This page is only available if you are using sql as general library type</b>
 </body>
@@ -19,6 +19,7 @@ EOM;
        exit();
 }
 
+unset($group_members);
 if (is_file("../lib/$config[general_lib_type]/group_info.php3")){
        include("../lib/$config[general_lib_type]/group_info.php3");
        if ($group_exists == 'no'){
@@ -27,7 +28,7 @@ if (is_file("../lib/$config[general_lib_type]/group_info.php3")){
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <form action="group_admin.php3" method=get>
 <b>Group Name&nbsp;&nbsp;</b>
@@ -48,7 +49,7 @@ EOM;
 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $config[general_charset]?>">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
@@ -88,7 +89,7 @@ if ($do_changes == 1){
        
    
    <form method=post>
-      <input type=hidden name=login value="<?php echo $login ?>">
+      <input type=hidden name=login value=<?php echo $login ?>>
       <input type=hidden name=do_changes value=0>
       <input type=hidden name=show value=0>
        <table border=1 bordercolordark=#ffffe0 bordercolorlight=#000000 width=100% cellpadding=2 cellspacing=0 bgcolor="#ffffe0" valign=top>
index bce1d1b..2c63a80 100644 (file)
@@ -11,7 +11,7 @@ if ($config[general_lib_type] != 'sql'){
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <b>This page is only available if you are using sql as general library type</b>
 </body>
@@ -22,6 +22,7 @@ EOM;
 
 require('../lib/attrshow.php3');
 require('../lib/defaults.php3');
+require("../lib/$config[general_lib_type]/group_info.php3");
 
 if ($config[general_lib_type] == 'sql' && $config[sql_use_operators] == 'true'){
        $colspan=2;
@@ -39,7 +40,7 @@ if ($config[general_lib_type] == 'sql' && $config[sql_use_operators] == 'true'){
 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $config[general_charset]?>">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
@@ -87,6 +88,22 @@ EOM;
        echo <<<EOM
        <tr>
                <td align=right colspan=$colspan bgcolor="#d0ddb0">
+               Available Groups
+               </td><td>
+EOM;
+               if (!isset($existing_groups))
+                       echo "<b>No groups available</b>\n";
+               else{
+                       echo "<select name=\"existing_groups\">\n";     
+                       foreach ($existing_groups as $group => $count)
+                               echo "<option value=\"$group\">$group\n";
+                       echo "</select>\n";
+               }
+       echo <<<EOM
+               </td>
+       </tr>
+       <tr>
+               <td align=right colspan=$colspan bgcolor="#d0ddb0">
                Group name
                </td><td>
                <input type=text name="login" value="$login" size=35>
index 54cca94..725797f 100644 (file)
        <table border=0 width=100% cellpadding=12 cellspacing=0 bgcolor="#ffffd0" valign=top>
        <tr><td>
 <br>
-<pre>
-
-<b>For now we just include the README file</b><br>
 
+<b>Please choose which file you wish to read:</b><br><br>
+<form name="readhelp" method=post>
+<select name=help_file>
 <?php
-readfile('../../README');
+$selected[$help_file] = 'selected';
+
+echo <<<EOM
+<option $selected[readme] value="readme">README File
+<option $selected[howto] value="howto">HOWTO File
+<option $selected[faq] value="faq">FAQ File
+EOM;
 ?>
+</select>
+<br><br>
+<input type=submit class=button value="Read File">
+</form>
 
+<pre>
+<?php
+$in_file = '';
+if ($help_file == 'readme')
+       $in_file = '../../README';
+else if ($help_file == 'howto')
+       $in_file = '../../doc/HOWTO';
+else if ($help_file == 'faq')
+       $in_file = '../../doc/FAQ';
+if ($in_file != '')
+       readfile("$in_file");
+?>
 </pre>
 <br>
 </td></tr>
index b05a435..fd0659a 100644 (file)
@@ -3,7 +3,7 @@
 <title>
 dialup administration</title>
 </head>
-       <frameset cols="122,*" border="0" frameborder="0" framespacing="0">
+       <frameset cols="130,*" border="0" frameborder="0" framespacing="0">
                <frame  name="buttons" src="buttons.php3" marginwidth="8"
                        marginheight="8" noresize >
                <frame  name="content" src="content.html" marginwidth="8"
index 39e437a..6461a7d 100644 (file)
@@ -4,7 +4,7 @@
 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $config[general_charset]?>">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <?php
 
 function check_day($day){
@@ -30,7 +30,7 @@ function check_day($day){
 
 $mapping = array(
        'Mo' => 'Monday',
-       'Tu' => 'Tusday',
+       'Tu' => 'Tuesday',
        'We' => 'Wednesday',
        'Th' => 'Thursday',
        'Fr' => 'Friday',
index 3378ff6..c4b3cfc 100644 (file)
@@ -8,7 +8,7 @@ else{
 <title>NAS Administration Page</title>
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <b>Could not include SQL library functions. Aborting</b>
 </body>
@@ -16,8 +16,25 @@ else{
 EOM;
        exit();
 }
+if ($config[general_restrict_nasadmin_access] == 'yes'){
+       $auth_user = $_SERVER["PHP_AUTH_USER"];
+       if ($auth_user == '' || $mappings[$auth_user][nasadmin] != 'yes'){
+               echo <<<EOM
+<title>NAS Administration Page</title>
+<link rel="stylesheet" href="style.css">
+</head>
+<body>
+<center>
+<b>Access is not allowed to this username.</b>
+</body>
+</html>
+EOM;
+               exit();
+       }
+}
 
-if ($clear_fields == 1)
+
+if ($clear_fields == 1 || ($do_it == 0 && $select_nas == 0))
        $selected_nas = $readonly = '';
 else
        $readonly = 'readonly';
@@ -28,7 +45,8 @@ if ($link){
                $selected_nas = da_sql_escape_string($selected_nas);
                switch ($action) {
                        case 'check_nas':
-                               if ($selected_nas == gethostbyname($selected_nas))
+                               require_once('../lib/functions.php3');
+                               if (!check_ip($selected_nas) && $selected_nas == gethostbyname($selected_nas))
                                        $msg = "<b>The NAS name <font color=red>is not</font> valid</b><br>\n";
                                else
                                        $msg = "<b>The NAS name <font color=green>is</font> valid</b><br>\n";
@@ -47,6 +65,14 @@ if ($link){
                                if ($nasname == '' || $nassecret == '' || $nasshortname == '')
                                        $msg = "<b>Error. Required fields are not set</b><br>\n";
                                else{
+                                       $nasshortname = da_sql_escape_string($nasshortname);
+                                       $nastype = da_sql_escape_string($nastype);
+                                       $nasportnum = da_sql_escape_string($nasportnum);
+                                       $nassecret = da_sql_escape_string($nassecret);
+                                       $nascommunity = da_sql_escape_string($nascommunity);
+                                       $nasdescription = da_sql_escape_string($nasdescription);
+                                       $nasname = da_sql_escape_string($nasname);
+
                                        $res = @da_sql_query($link,$config,
                                        "INSERT INTO $config[sql_nas_table]
                                        (nasname,shortname,type,ports,secret,community,description)
@@ -64,6 +90,14 @@ if ($link){
                                if ($nassecret == '' || $nasshortname == '')
                                        $msg = "<b>Error. Required fields are not set</b><br>\n";
                                else{
+                                       $nasshortname = da_sql_escape_string($nasshortname);
+                                       $nastype = da_sql_escape_string($nastype);
+                                       $nasportnum = da_sql_escape_string($nasportnum);
+                                       $nassecret = da_sql_escape_string($nassecret);
+                                       $nascommunity = da_sql_escape_string($nascommunity);
+                                       $nasdescription = da_sql_escape_string($nasdescription);
+                                       $nasname = da_sql_escape_string($nasname);
+
                                        $res = @da_sql_query($link,$config,
                                        "UPDATE $config[sql_nas_table] SET
                                        shortname = '$nasshortname',
@@ -84,21 +118,22 @@ if ($link){
        "SELECT * FROM $config[sql_nas_table] ORDER BY nasname;");
        if ($search){
                $num = 0;
-               unset($nas_list);
+               unset($my_nas_list);
                while($row = @da_sql_fetch_array($search,$config)){
                        $my_nas_name = $row['nasname'];
                        if ($my_nas_name != ''){
                                $num++;
-                               if ($clear_fields == 0 && $selected_nas == $my_nas_name)
+                               $my_nas_list[$my_nas_name]['name'] = $my_nas_name;
+                               $my_nas_list[$my_nas_name]['shortname'] = $row['shortname'];
+                               $my_nas_list[$my_nas_name]['type'] = $row['type'];
+                               if ($clear_fields == 0 && $selected_nas == $my_nas_name){
                                        $selected[$my_nas_name] = 'selected';
-                               $nas_list[$my_nas_name]['name'] = $my_nas_name;
-                               $nas_list[$my_nas_name]['shortname'] = $row['shortname'];
-                               $nas_list[$my_nas_name]['type'] = $row['type'];
-                               $selected[$nas_list[$my_nas_name]['type']] = 'selected';
-                               $nas_list[$my_nas_name]['ports'] = $row['ports'];
-                               $nas_list[$my_nas_name]['secret'] = $row['secret'];
-                               $nas_list[$my_nas_name]['community'] = $row['community'];
-                               $nas_list[$my_nas_name]['description'] = $row['description'];
+                                       $selected[$my_nas_list[$my_nas_name]['type']] = 'selected';
+                               }
+                               $my_nas_list[$my_nas_name]['ports'] = $row['ports'];
+                               $my_nas_list[$my_nas_name]['secret'] = $row['secret'];
+                               $my_nas_list[$my_nas_name]['community'] = $row['community'];
+                               $my_nas_list[$my_nas_name]['description'] = $row['description'];
                        }
                }
        }
@@ -114,7 +149,7 @@ else
 <title>NAS Administration Page</title>
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
@@ -152,7 +187,7 @@ NAS List
 <td>
 <select name=selected_nas size=5 OnChange="this.form.select_nas.value=1;this.form.submit()"> 
 <?php
-foreach ($nas_list as $member){
+foreach ($my_nas_list as $member){
        $name = $member[name];
        echo "<option $selected[$name] value=\"$name\">$name\n";
 }
@@ -161,7 +196,7 @@ foreach ($nas_list as $member){
 </td>
 </tr>
 <?php
-$array = $nas_list[$selected_nas];
+$array = $my_nas_list[$selected_nas];
 echo <<<EOM
 <tr>
 <td align=right bgcolor="#d0ddb0">
@@ -231,9 +266,9 @@ EOM;
 <br>
 <select name=action size=1>
 <?php
-if ($clear_fields == 1)
+if ($clear_fields == 1 || ($do_it == 0 && $select_nas == 0))
        echo "<option value=\"add_nas\">Add NAS\n";
-else
+if ($clear_fields == 0)
        echo <<<EOM
 <option value="change_nas">Change NAS Info
 <option value="del_nas">Delete Selected NAS
index 589f75b..7934552 100644 (file)
@@ -8,7 +8,7 @@ session_destroy();
 <title>Session Cache Destroy Page</title>
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <b>Session Cache Destroyed</b>
 </body>
index 722f84e..b17e314 100644 (file)
@@ -12,7 +12,7 @@ else{
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <b>Could not include SQL library functions. Aborting</b>
 </body>
@@ -20,13 +20,27 @@ else{
 EOM;
        exit();
 }
+if ($config[general_lib_type] != 'sql'){
+       echo <<<EOM
+<title>User Groups</title>
+<meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
+<link rel="stylesheet" href="style.css">
+</head>
+<body>
+<center>
+<b>This page is only available if you are using sql as general library type</b>
+</body>
+</html>
+EOM;
+       exit();
+}
 ?>
 <head>
 <title>User Groups</title>
 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $config[general_charset]?>">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
@@ -48,41 +62,31 @@ EOM;
 <tr bgcolor="black" valign=top><td colspan=2>
        <table border=0 width=100% cellpadding=12 cellspacing=0 bgcolor="#ffffd0" valign=top>
        <tr><td>
-<p>
+<font size=-2>Only groups with members are shown</font><p>
        <table border=1 bordercolordark=#ffffe0 bordercolorlight=#000000 width=100% cellpadding=2 cellspacing=0 bgcolor="#ffffe0" valign=top>
        <tr bgcolor="#d0ddb0">
        <th>#</th><th>group</th><th># of members</th>
        </tr>
 
 <?php
-$link = @da_sql_pconnect($config);
-if ($link){
-       $search = @da_sql_query($link,$config,
-       "SELECT COUNT(*) as counter,groupname,MAX(username) AS usersample FROM $config[sql_usergroup_table] GROUP BY groupname;");
-       if ($search){
-               if (@da_sql_num_rows($search,$config)){
-                       while( $row = @da_sql_fetch_array($search,$config) ){
-                               $num++;
-                               $group = $row[groupname];
-                               $num_members = $row[counter];
-                               if ($row[usersample] == "") $num_members--;
-                               echo <<<EOM
+unset($login);
+$num = 0;
+include_once("../lib/$config[general_lib_type]/group_info.php3");
+if (isset($existing_groups)){
+       foreach ($existing_groups as $group => $num_members){
+               $num++;
+               $Group = urlencode($group);
+               echo <<<EOM
                <tr align=center>
                        <td>$num</td>
-                       <td><a href="group_admin.php3?login=$group" title="Edit group $group">$group</a></td>
+                       <td><a href="group_admin.php3?login=$Group" title="Edit group $group">$group</a></td>
                        <td>$num_members</td>
                </tr>
 EOM;
-                       }
-               }
-               else
-                       echo "<b>Could not find any groups</b><br>\n";
        }
-       else
-               echo "<b>Database query failed: " . da_sql_error($link,$config) . "</b><br>\n";
 }
 else
-       echo "<b>Could not connect to SQL database</b><br>\n";
+       echo "<b>Could not find any groups</b><br>\n";
 ?>
        </table>
 </table>
index bade492..ca48d91 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 require('../conf/config.php3');
+require('../lib/sql/nas_list.php3');
+require_once('../lib/xlat.php3');
 ?>
 <html>
 <head>
@@ -7,11 +9,11 @@ require('../conf/config.php3');
 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $config[general_charset]?>">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 
 <?php
-require('../lib/functions.php3');
+require_once('../lib/functions.php3');
 
 if (is_file("../lib/sql/drivers/$config[sql_type]/functions.php3"))
        include_once("../lib/sql/drivers/$config[sql_type]/functions.php3");
@@ -24,6 +26,7 @@ EOM;
        exit();
 }
 
+$stats_num = array();
 
 $date = strftime('%A, %e %B %Y, %T %Z');
 $now = time();
@@ -81,6 +84,8 @@ $i = 1;
 $servers[all] = 'all';
 foreach ($nas_list as $nas){
        $name = $nas[name];
+       if ($nas[ip] == '')
+               continue;
        $servers[$name] = $nas[ip];
        $i++;
 }
@@ -91,7 +96,7 @@ if ($server != 'all' && $server != ''){
 }
 $sql_extra_query = '';
 if ($config[sql_accounting_extra_query] != '')
-       $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config);
+       $sql_extra_query = xlat($config[sql_accounting_extra_query],$login,$config);
 
 $link = @da_sql_pconnect($config);
 if ($link){
@@ -110,13 +115,13 @@ if ($link){
                        $row = @da_sql_fetch_array($search,$config);
                        $data[$day][1] = $row[res_1];
                        $data[sum][1] += $row[res_1];
-                       $num[1] = ($data[$day][1]) ? $num[1] + 1 : $num[1];
+                       $stats_num[1] = ($data[$day][1]) ? $stats_num[1] + 1 : $stats_num[1];
                        $data[$day][2] = $row[res_2];
                        $data[sum][2] += $row[res_2];
-                       $num[2] = ($data[$day][2]) ? $num[2] + 1 : $num[2];
+                       $stats_num[2] = ($data[$day][2]) ? $stats_num[2] + 1 : $stats_num[2];
                        $data[$day][3] = $row[res_3];
                        $data[sum][3] += $row[res_3];
-                       $num[3] = ($data[$day][3]) ? $num[3] + 1 : $num[3];
+                       $stats_num[3] = ($data[$day][3]) ? $stats_num[3] + 1 : $stats_num[3];
                }
                else
                        echo "<b>Database query failed: " . da_sql_error($link,$config) . "</b><br>\n";
@@ -125,13 +130,13 @@ if ($link){
 else
        echo "<b>Could not connect to SQL database</b><br>\n";
 
-$num[1] = ($num[1]) ? $num[1] : 1;
-$num[2] = ($num[2]) ? $num[2] : 1;
-$num[3] = ($num[3]) ? $num[3] : 1;
+$stats_num[1] = ($stats_num[1]) ? $stats_num[1] : 1;
+$stats_num[2] = ($stats_num[2]) ? $stats_num[2] : 1;
+$stats_num[3] = ($stats_num[3]) ? $stats_num[3] : 1;
 
-$data['avg'][1] = ceil($data['sum'][1] / $num[1]);
-$data['avg'][2] = ceil($data['sum'][2] / $num[2]);
-$data['avg'][3] = ceil($data['sum'][3] / $num[3]);
+$data['avg'][1] = ceil($data['sum'][1] / $stats_num[1]);
+$data['avg'][2] = ceil($data['sum'][2] / $stats_num[2]);
+$data['avg'][3] = ceil($data['sum'][3] / $stats_num[3]);
 
 $data['avg'][1] = $fun[$column[1]]($data['avg'][1]);
 $data['avg'][2] = $fun[$column[2]]($data['avg'][2]);
index 09c0faf..44f19d8 100644 (file)
@@ -29,4 +29,18 @@ body
        scrollbar-highlight-color:#fffff0;
        scrollbar-3dlight-color:#000000;
        scrollbar-darkshadow-color:#000000;
+       bgcolor:#80a040;
+       background-image: url(images/greenlines1.gif);
+}
+a:link {
+       color: #000000;
+}
+a:visited {
+       color:#000000;
+}
+a:hover {
+       color:#000000;
+}
+a:active {
+       color:#000000;
 }
index 81be558..f362519 100644 (file)
@@ -15,7 +15,7 @@ else{
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <b>Could not include SQL library functions. Aborting</b>
 </body>
@@ -31,7 +31,7 @@ $num = 0;
 $pagesize = ($pagesize) ? $pagesize : 10;
 if (!is_numeric($pagesize) && $pagesize != 'all')
        $pagesize = 10;
-$limit = ($pagesize == 'all') ? '' : "LIMIT $pagesize";
+$limit = ($pagesize == 'all') ? '' : "$pagesize";
 $selected[$pagesize] = 'selected';
 $order = ($order != '') ? $order : $config[general_accounting_info_order];
 if ($order != 'desc' && $order != 'asc')
@@ -40,6 +40,10 @@ $selected[$order] = 'selected';
 $now_str = da_sql_escape_string($now_str);
 $prev_str = da_sql_escape_string($prev_str);
 
+unset($da_name_cache);
+if (isset($_SESSION['da_name_cache']))
+       $da_name_cache = $_SESSION['da_name_cache'];
+
 
 echo <<<EOM
 <head>
@@ -47,7 +51,7 @@ echo <<<EOM
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
@@ -90,7 +94,7 @@ for($i=1;$i<=9;$i++){
 }
 $sql_extra_query = '';
 if ($config[sql_accounting_extra_query] != '')
-       $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config);
+       $sql_extra_query = xlat($config[sql_accounting_extra_query],$login,$config);
 ?>
        </tr>
 
@@ -98,9 +102,10 @@ if ($config[sql_accounting_extra_query] != '')
 $link = @da_sql_pconnect($config);
 if ($link){
        $search = @da_sql_query($link,$config,
-       "SELECT * FROM $config[sql_accounting_table]
+       "SELECT " . da_sql_limit($limit,0,$config) . " * FROM $config[sql_accounting_table]
        WHERE username = '$login' AND acctstarttime <= '$now_str'
-       AND acctstarttime >= '$prev_str' $sql_extra_query ORDER BY acctstarttime $order $limit;");
+       AND acctstarttime >= '$prev_str' $sql_extra_query " . da_sql_limit($limit,1,$config) .
+       " ORDER BY acctstarttime $order " . da_sql_limit($limit,2,$config). " ;");
        if ($search){
                while( $row = @da_sql_fetch_array($search,$config) ){
                        $tr_color='white';
index 9db3177..3c4e7ff 100644 (file)
@@ -16,7 +16,7 @@ if (is_file("../lib/$config[general_lib_type]/user_info.php3")){
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <form action="user_admin.php3" method=get>
 <b>User Name&nbsp;&nbsp;</b>
@@ -38,7 +38,7 @@ else{
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <b>Could not include SQL library functions. Aborting</b>
 </body>
@@ -214,9 +214,9 @@ if ($link){
        }
 
        $search = @da_sql_query($link,$config,
-       "SELECT * FROM $config[sql_accounting_table]
-       WHERE username = '$login' AND acctstoptime IS NULL
-       ORDER BY acctstarttime DESC LIMIT 1;");
+       "SELECT " . da_sql_limit(1,0,$config) . " * FROM $config[sql_accounting_table]
+       WHERE username = '$login' AND acctstoptime IS NULL " . da_sql_limit(1,1,$config) . "
+        ORDER BY acctstarttime DESC " . da_sql_limit(1,2,$config). " ;");
        if ($search){
                if (@da_sql_num_rows($search,$config)){
                        $logged_now = 1;
@@ -255,9 +255,9 @@ if ($link){
                echo "<b>Database query failed: " . da_sql_error($link,$config) . "</b><br>\n";
        if (! $logged_now){
                $search = @da_sql_query($link,$config,
-               "SELECT * FROM $config[sql_accounting_table]
-               WHERE username = '$login' AND acctsessiontime != '0'
-               ORDER BY acctstoptime DESC LIMIT 1;");
+               "SELECT " . da_sql_limit(1,0,$config) . " * FROM $config[sql_accounting_table]
+               WHERE username = '$login' AND acctsessiontime != '0' " . da_sql_limit(1,1,$config) . "
+                ORDER BY acctstoptime DESC " . da_sql_limit(1,2,$config). " ;");
                if ($search){
                        if (@da_sql_num_rows($search,$config)){
                                $row = @da_sql_fetch_array($search,$config);
@@ -320,3 +320,4 @@ EOM;
 }
 
 require('../html/user_admin.html.php3');
+?>
index f6da8e7..6edd647 100644 (file)
@@ -24,7 +24,7 @@ echo <<<EOM
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
@@ -80,7 +80,7 @@ EOM;
 }
 ?>
    <form method=post>
-      <input type=hidden name=login value="<?php print $login ?>">
+      <input type=hidden name=login value=<?php print $login ?>>
       <input type=hidden name=delete_user value="0">
        <table border=1 bordercolordark=#ffffe0 bordercolorlight=#000000 width=100% cellpadding=2 cellspacing=0 bgcolor="#ffffe0" valign=top>
 <tr>
index d8251d9..edd044b 100644 (file)
@@ -1,14 +1,19 @@
 <?php
 require('../conf/config.php3');
-if ($edit_group == 1){
-       header("Location: group_admin.php3?login=$group_to_edit");
-       exit;
-}
 require('../lib/attrshow.php3');
 require('../lib/defaults.php3');
+$extra_text = '';
 if ($user_type != 'group'){
        if (is_file("../lib/$config[general_lib_type]/user_info.php3"))
                include("../lib/$config[general_lib_type]/user_info.php3");
+       if ($config[general_lib_type] == 'sql' && $config[sql_show_all_groups] == 'true'){
+               $extra_text = "<br><font size=-2><i>(The groups that the user is a member of are highlated)</i></font>";
+               $saved_login = $login;
+               $login = '';
+               if (is_file("../lib/sql/group_info.php3"))
+                       include("../lib/sql/group_info.php3");
+               $login = $saved_login;
+       }
 }
 else{
        if (is_file("../lib/$config[general_lib_type]/group_info.php3"))
@@ -39,7 +44,7 @@ else
 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $config[general_charset]?>">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
@@ -82,6 +87,10 @@ if ($change == 1){
                        include("../lib/$config[general_lib_type]/change_passwd.php3");
                if (is_file("../lib/$config[general_lib_type]/user_info.php3"))
                        include("../lib/$config[general_lib_type]/user_info.php3");
+               if ($group_change && $config[general_lib_type] == 'sql' && $config[sql_show_all_groups] == 'true'){
+                       include("../lib/sql/group_change.php3");
+                       include("../lib/defaults.php3");
+               }
        }
        else{
                if (is_file("../lib/$config[general_lib_type]/group_info.php3"))
@@ -95,11 +104,12 @@ else if ($badusers == 1){
        
 ?>
    <form name="edituser" method=post>
-      <input type=hidden name=login value="<?php print $login ?>">
+      <input type=hidden name=login value=<?php print $login ?>>
       <input type=hidden name=user_type value=<?php print $user_type ?>>
       <input type=hidden name=change value="0">
       <input type=hidden name=add value="0">
       <input type=hidden name=badusers value="0">
+      <input type=hidden name=group_change value="0">
        <table border=1 bordercolordark=#ffffe0 bordercolorlight=#000000 width=100% cellpadding=2 cellspacing=0 bgcolor="#ffffe0" valign=top>
 <?php
 if ($user_type == 'group')
@@ -241,20 +251,25 @@ EOM;
 if (isset($member_groups)){
        echo <<<EOM
 <tr>
-<input type=hidden name=edit_group value=0>
 <td align=right colspan=$colspan bgcolor="#d0ddb0">
-Member of
+Member of $extra_text
 </td>
 <td>
-<select name="group_to_edit">
+<select size=2 name="edited_groups[]" multiple OnChange="this.form.group_change.value=1">
 EOM;
-       foreach ($member_groups as $group){
-               echo "<option value=\"$group\">$group\n";
+       if ($config[sql_show_all_groups] == 'true'){
+               foreach ($existing_groups as $group => $count){
+                       if ($member_groups[$group] == $group)
+                               echo "<option selected value=\"$group\">$group\n";
+                       else
+                               echo "<option value=\"$group\">$group\n";
+               }
+       }else{
+               foreach ($member_groups as $group)
+                       echo "<option value=\"$group\">$group\n";
        }
        echo <<<EOM
 </select>
-&nbsp;&nbsp;&nbsp;
-<input type=submit class=button value="Edit Group" OnClick="this.form.edit_group.value=1">
 </td>
 </tr>
 EOM;
index a79021d..f190c0b 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 require('../conf/config.php3');
 require('../lib/attrshow.php3');
+require('../lib/sql/nas_list.php3');
 if (!isset($usage_summary)){
        echo <<<EOM
 <html>
@@ -21,14 +22,14 @@ if ($config[general_decode_normal_attributes] == 'yes'){
        $k = init_decoder();
        $decode_normal = 1;
 }
-require('../lib/functions.php3');
+require_once('../lib/functions.php3');
 require("../lib/$config[general_lib_type]/functions.php3");
 
 if (is_file("../lib/sql/drivers/$config[sql_type]/functions.php3"))
        include_once("../lib/sql/drivers/$config[sql_type]/functions.php3");
 else{
        echo <<<EOM
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <b>Could not include SQL library functions. Aborting</b>
 </body>
@@ -40,8 +41,10 @@ EOM;
 $date = strftime('%A, %e %B %Y, %T %Z');
 
 $sql_extra_query = '';
-if ($config[sql_accounting_extra_query] != '')
-       $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config);
+if ($config[sql_accounting_extra_query] != ''){
+       $sql_extra_query = xlat($config[sql_accounting_extra_query],$login,$config);
+       $sql_extra_query = da_sql_escape_string($sql_extra_query);
+}
 
 $link = @da_sql_pconnect($config);
 $link2 = connect2db($config);
@@ -49,7 +52,10 @@ $tot_in = $tot_rem = 0;
 if ($link){
        $h = 21;
        $servers_num = 0;
+       if ($config[general_ld_library_path] != '')
+               putenv("LD_LIBRARY_PATH=$config[general_ld_library_path]");
        foreach($nas_list as $nas){
+               $j = 0;
                $num = 0;
 
                if ($server != ''){
@@ -60,46 +66,62 @@ if ($link){
                }
                else
                        $servers_num++;
+               if ($nas[ip] == '')
+                       continue;
                $name_data = $nas[ip];
                $community_data = $nas[community];
                $server_name[$servers_num] = $nas[name];
                $server_model[$servers_num] = $nas[model];
-               if ($config[general_ld_library_path] != '')
-                       putenv("LD_LIBRARY_PATH=$config[general_ld_library_path]");
                $extra = "";
-               if ($config[$finger_type] != 'database' && $config[general_finger_type] == 'snmp'){
-                       if ($config[$nas_type] == '')
-                               $nas_type = $config[general_nas_type];
-                       else
-                               $nas_type = $nas[type];
+               $finger_type = $config[general_finger_type];
+               if ($nas[finger_type] != '')
+                       $finger_type = $nas[finger_type];
+               if ($finger_type == 'snmp'){
+                       $nas_type = ($nas[type] != '') ? $nas[type] : $config[general_nas_type];
                        if ($nas_type == '')
                                $nas_type = 'cisco';
 
                        $users=exec("$config[general_snmpfinger_bin] $name_data $community_data $nas_type");
-                       if (strlen($users))
+                       if (strlen($users)){
                                $extra = "AND username IN ($users)";
+                               if ($config[general_strip_realms] == 'yes'){
+                                       if ($config[general_realm_format] == 'prefix')
+                                               $match = "'[^']+" . $config[general_realm_delimiter];
+                                       else
+                                               $match = $config[general_realm_delimiter] . "[^']+'";
+                                       $extra = preg_replace("/$match/","'",$extra);
+                               }
+                       }
+               }
+               $search = @da_sql_query($link,$config,
+               "SELECT COUNT(*) AS onlineusers FROM $config[sql_accounting_table] WHERE
+               acctstoptime IS NULL AND nasipaddress = '$name_data' $extra $sql_extra_query;");
+               if ($search){
+                       if (($row = @da_sql_fetch_array($search,$config)))
+                               $num = $row[onlineusers];
                }
                $search = @da_sql_query($link,$config,
                "SELECT DISTINCT username,acctstarttime,framedipaddress,callingstationid
                FROM $config[sql_accounting_table] WHERE
                acctstoptime IS NULL AND nasipaddress = '$name_data' $extra $sql_extra_query
-               GROUP BY username ORDER BY acctstarttime;");
+               GROUP BY username,acctstarttime,framedipaddress,callingstationid
+               ORDER BY acctstarttime;");
                if ($search){
                        $now = time();
                        while($row = @da_sql_fetch_array($search,$config)){
-                               $num++;
+                               $j++;
                                $h += 21;
                                $user = $row['username'];
-                               $finger_info[$servers_num][$num]['ip'] = $row['framedipaddress'];
-                               if ($finger_info[$servers_num][$num]['ip'] == '')
-                                       $finger_info[$servers_num][$num]['ip'] = '-';
+                               $finger_info[$servers_num][$j]['ip'] = $row['framedipaddress'];
+                               if ($finger_info[$servers_num][$j]['ip'] == '')
+                                       $finger_info[$servers_num][$j]['ip'] = '-';
                                $session_time = $row['acctstarttime'];
                                $session_time = date2timediv($session_time,$now);
-                               $finger_info[$servers_num][$num]['session_time'] = time2strclock($session_time);
-                               $finger_info[$servers_num][$num]['user'] = $user;
-                               $finger_info[$servers_num][$num]['callerid'] = $row['callingstationid'];
-                               if ($finger_info[$servers_num][$num]['callerid'] == '')
-                                       $finger_info[$servers_num][$num]['callerid'] = '-';
+                               $finger_info[$servers_num][$j]['session_time'] = time2strclock($session_time);
+                               $finger_info[$servers_num][$j]['user'] = $user;
+                               $finger_info[$servers_num][$j]['callerid'] = $row['callingstationid'];
+                               if ($finger_info[$servers_num][$j]['callerid'] == '')
+                                       $finger_info[$servers_num][$j]['callerid'] = '-';
                                if ($user_info["$user"] == ''){
                                        $user_info["$user"] = get_user_info($link2,$user,$config,$decode_normal,$k);
                                        if ($user_info["$user"] == '' || $user_info["$user"] == ' ')
@@ -108,6 +130,7 @@ if ($link){
                        }
                        $height[$servers_num] = $h;
                }
+               $server_counting[$servers_num] = $j;
                $server_loggedin[$servers_num] = $num;
                $server_rem[$servers_num] = ($config[$portnum]) ? ($config[$portnum] - $num) : 'unknown';
                $tot_in += $num;
@@ -123,7 +146,7 @@ if (isset($usage_summary)){
 }
 ?>
 
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
@@ -166,17 +189,18 @@ echo <<<EOM
        <th>name</th><th>duration</th>
        </tr>
 EOM;
-       for( $k = 1; $k <= $server_loggedin[$j]; $k++){
+       for( $k = 1; $k <= $server_counting[$j]; $k++){
                $user = $finger_info[$j][$k][user];
                if ($user == '')
                        $user = '&nbsp;';
+               $User = urlencode($user);
                $time = $finger_info[$j][$k][session_time];
                $ip = $finger_info[$j][$k][ip];
                $cid = $finger_info[$j][$k][callerid];
                $inf = $user_info[$user];
                echo <<<EOM
        <tr align=center>
-       <td>$k</td><td><a href="user_admin.php3?login=$user" title="Edit User $user">$user</a></td>
+       <td>$k</td><td><a href="user_admin.php3?login=$User" title="Edit User $user">$user</a></td>
 EOM;
 if ($acct_attrs['uf'][4] != '') echo "<td>$ip</td>\n";
 if ($acct_attrs['uf'][9] != '') echo "<td>$cid</td>\n";
index 03d8266..f5868cb 100644 (file)
@@ -8,7 +8,7 @@ require('../conf/config.php3');
 <title>Personal information page</title>
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
index 091b826..b40c0eb 100644 (file)
@@ -23,7 +23,7 @@ if ($config[general_lib_type] == 'sql' && $config[sql_use_operators] == 'true'){
 <meta http-equiv="Content-Type" content="text/html; charset=<?php echo $config[general_charset]?>">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 
 <?php
 include("password_generator.jsc");
index 233c19d..0e5ec31 100644 (file)
@@ -25,6 +25,8 @@ $week = $now - date('w') * 86400;
 $now_str = date("$config[sql_date_format]",$now + 86400);
 $week_str = date("$config[sql_date_format]",$week);
 $today = date("$config[sql_date_format]",$now);
+$open_conns = $daily_conns = $weekly_conns = 0;
+$weekly_used = $daily_used = $online_time = time2strclock(0);
 
 $link = @da_sql_pconnect($config);
 if ($link){
@@ -33,24 +35,43 @@ if ($link){
        username = '$login' AND acctstoptime >= '$week_str' AND
        acctstoptime <= '$now_str';");
        if ($search){
-               $row = @da_sql_fetch_array($search,$config);
-               $weekly_used = time2strclock($row[sum_sess_time]);
-               $weekly_conns = $row[counter];
+               if ($row = @da_sql_fetch_array($search,$config)){
+                       $weekly_used = time2strclock($row[sum_sess_time]);
+                       $weekly_conns = $row[counter];
+               }
        }
        $search = @da_sql_query($link,$config,
        "SELECT COUNT(*) AS counter,sum(acctsessiontime) AS sum_sess_time FROM $config[sql_accounting_table] WHERE
        username = '$login' AND acctstoptime >= '$today 00:00:00'
        AND acctstoptime <= '$today 23:59:59';");
        if ($search){
-               $row = @da_sql_fetch_array($search,$config);
-               $daily_used = time2strclock($row[sum_sess_time]);
-               $daily_conns = $row[counter];
+               if ($row = @da_sql_fetch_array($search,$config)){
+                       $daily_used = time2strclock($row[sum_sess_time]);
+                       $daily_conns = $row[counter];
+               }
        }
+       $search = @da_sql_query($link,$config,
+       "SELECT COUNT(*) AS counter, unix_timestamp() - unix_timestamp(acctstarttime) as diff FROM
+       $config[sql_accounting_table] WHERE acctstoptime is null AND username = '$login'
+       GROUP BY username;");
+       if ($search){
+               if ($row = @da_sql_fetch_array($search,$config)){
+                       $open_conns = $row[counter];
+                       $online_time = $row[diff];
+                       $weekly_used += $online_time;
+                       $daily_used += $online_time;
+                       $daily_conns += $open_conns;
+                       $weekly_conns += $open_conns;
+                       $online_time = time2strclock($online_time);
+               }
+       }
+       $weekly_used = time2strclock($weekly_used);
+       $daily_used = time2strclock($daily_used);
 }
 
 
 foreach($vars as $val){
        echo "$val\n";
 }
-echo "$weekly_used\n$weekly_conns\n$daily_used\n$daily_conns";
+echo "$weekly_used\n$weekly_conns\n$daily_used\n$daily_conns\n$open_conns\n$online_time";
 ?>
index d1b29db..556e1fe 100644 (file)
@@ -1,6 +1,8 @@
 <?php
 require('../conf/config.php3');
 require('../lib/functions.php3');
+require('../lib/sql/nas_list.php3');
+require_once('../lib/xlat.php3');
 ?>
 <html>
 <?php
@@ -13,7 +15,7 @@ else{
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <b>Could not include SQL library functions. Aborting</b>
 </body>
@@ -32,8 +34,10 @@ $start = da_sql_escape_string($start);
 $stop = da_sql_escape_string($stop);
 $pagesize = ($pagesize) ? $pagesize : 10;
 if (!is_numeric($pagesize) && $pagesize != 'all')
-       $pagesize = 10;
-$limit = ($pagesize == 'all') ? '' : "LIMIT $pagesize";
+       $pagezise = 10;
+if ($pagesize > 100)
+       $pagesize = 100;
+$limit = ($pagesize == 'all') ? '100' : "$pagesize";
 $selected[$pagesize] = 'selected';
 $order = ($order) ? $order : $config[general_accounting_info_order];
 if ($order != 'desc' && $order != 'asc')
@@ -52,8 +56,14 @@ $selected[$order] = 'selected';
 $selected[$sortby] = 'selected';
 
 $sql_extra_query = '';
-if ($config[sql_accounting_extra_query] != '')
-       $sql_extra_query = sql_xlat($config[sql_accounting_extra_query],$login,$config);
+if ($config[sql_accounting_extra_query] != ''){
+       $sql_extra_query = xlat($config[sql_accounting_extra_query],$login,$config);
+       $sql_extra_query = da_sql_escape_string($sql_extra_query);
+}
+
+unset($da_name_cache);
+if (isset($_SESSION['da_name_cache']))
+       $da_name_cache = $_SESSION['da_name_cache'];
 
 ?>
 
@@ -61,7 +71,7 @@ if ($config[sql_accounting_extra_query] != '')
 <title>User Statistics</title>
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
@@ -100,9 +110,9 @@ EOM;
 $link = @da_sql_pconnect($config);
 if ($link){
        $search = @da_sql_query($link,$config,
-       "SELECT * FROM $config[sql_total_accounting_table]
-       WHERE acctdate >= '$start' AND acctdate <= '$stop' $server_str $login_str $sql_extra_query
-       ORDER BY $order_attr $order $limit;");
+       "SELECT " . da_sql_limit($limit,0,$config) . " * FROM $config[sql_total_accounting_table]
+       WHERE acctdate >= '$start' AND acctdate <= '$stop' $server_str $login_str $sql_extra_query " . da_sql_limit($limit,1,$config)
+       . " ORDER BY $order_attr $order " . da_sql_limit($limit,2,$config) . " ;");
 
        if ($search){
                while( $row = @da_sql_fetch_array($search,$config) ){
@@ -110,8 +120,10 @@ if ($link){
                        $acct_login = $row[username];
                        if ($acct_login == '')
                                $acct_login = '-';
-                       else
-                               $acct_login = "<a href=\"user_admin.php3?login=$acct_login\" title=\"Edit user $acct_login\">$acct_login</a>";
+                       else{
+                               $Acct_login = urlencode($acct_login);
+                               $acct_login = "<a href=\"user_admin.php3?login=$Acct_login\" title=\"Edit user $acct_login\">$acct_login</a>";
+                       }
                        $acct_time = $row[conntotduration];
                        $acct_time = time2str($acct_time);
                        $acct_conn_num = $row[connnum];
@@ -194,6 +206,8 @@ EOM;
 <?php
 foreach ($nas_list as $nas){
        $name = $nas[name];
+       if ($nas[ip] == '')
+               continue;
        $servers[$name] = $nas[ip];
 }
 ksort($servers);
index 34ed715..60c3519 100644 (file)
@@ -13,7 +13,7 @@ echo <<<EOM
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 <link rel="stylesheet" href="style.css">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <center>
 <table border=0 width=550 cellpadding=0 cellspacing=0>
 <tr valign=top>
index 7a7b9db..2777723 100644 (file)
@@ -12,15 +12,15 @@ function myout(a) {
 }
 </script>
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <form action="user_admin.php3" method=get target="content">
 <table border=0 width=100 cellpadding=1 cellspacing=1>
 <tr><td align=center>
 <img src="images/logo2.gif" vspace=2>
 </td></tr>
 <?php
-if ($HTTP_SERVER_VARS["PHP_AUTH_USER"])
-       echo "<tr valign=top><td align=center><b>Logged in as " . $HTTP_SERVER_VARS["PHP_AUTH_USER"] . "...</b><br><br></td></tr>\n";
+if ($_SERVER["PHP_AUTH_USER"])
+       echo "<tr valign=top><td align=center><b>Logged in as " . $_SERVER["PHP_AUTH_USER"] . "...</b><br><br></td></tr>\n";
 ?>
 <tr bgcolor="black" valign=top><td>
 <table border=0 width=100% cellpadding=2 cellspacing=0>
index 0763565..c31d599 100644 (file)
@@ -1,12 +1,13 @@
 <?php
+$Login = urlencode($login);
 print <<<EOM
 <tr valign=top>
 <td align=center bgcolor="black" width=100>
-<a href="group_admin.php3?login=$login" title="Administer Group"><font color="white"><b>ADMIN</b></font></a></td>
+<a href="group_admin.php3?login=$Login" title="Administer Group"><font color="white"><b>ADMIN</b></font></a></td>
 <td align=center bgcolor="black" width=100>
-<a href="user_edit.php3?login=$login&user_type=group" title="Edit Group Dialup Settings"><font color="white"><b>EDIT</b></font></a></td>
+<a href="user_edit.php3?login=$Login&user_type=group" title="Edit Group Dialup Settings"><font color="white"><b>EDIT</b></font></a></td>
 <td align=center bgcolor="black" width=100>
-<a href="user_delete.php3?login=$login&user_type=group" title="Delete Group"><font color="white"><b>DELETE</b></font></a></td>
+<a href="user_delete.php3?login=$Login&user_type=group" title="Delete Group"><font color="white"><b>DELETE</b></font></a></td>
 </tr>
 EOM;
 ?>
index 2f1f85b..6309eed 100644 (file)
@@ -4,7 +4,7 @@ echo <<<EOM
 <title>user information for $cn</title>
 <meta http-equiv="Content-Type" content="text/html; charset=$config[general_charset]">
 </head>
-<body bgcolor="#80a040" background="images/greenlines1.gif" link="black" alink="black">
+<body>
 <link rel="stylesheet" href="style.css">
 EOM;
 if ($logged_now)
index 8ac6db5..892ee43 100644 (file)
@@ -1,27 +1,28 @@
 <?php
+$Login = urlencode($login);
 print <<<EOM
 <tr valign=top>
 <td align=center bgcolor="black" width=100>
-<a href="user_admin.php3?login=$login" title="Show User Information"><font color="white"><b>SHOW</b></font></a></td>
+<a href="user_admin.php3?login=$Login" title="Show User Information"><font color="white"><b>SHOW</b></font></a></td>
 <td align=center bgcolor="black" width=100>
-<a href="user_edit.php3?login=$login" title="Change User Dialup Settings"><font color="white"><b>EDIT</b></font></a></td>
+<a href="user_edit.php3?login=$Login" title="Change User Dialup Settings"><font color="white"><b>EDIT</b></font></a></td>
 <td align=center bgcolor="black" width=200 colspan=2>
-<a href="user_info.php3?login=$login" title="Change User Personal Information"><font color="white"><b>USER INFO</b></font></a></td>
+<a href="user_info.php3?login=$Login" title="Change User Personal Information"><font color="white"><b>USER INFO</b></font></a></td>
 </tr>
 <tr valign=top>
 <td align=center bgcolor="black" width=100>
-<a href="user_accounting.php3?login=$login" title="Show User Accounting Information"><font color="white"><b>ACCOUNTING</b></font></a></td>
+<a href="user_accounting.php3?login=$Login" title="Show User Accounting Information"><font color="white"><b>ACCOUNTING</b></font></a></td>
 <td align=center bgcolor="black" width=100>
-<a href="badusers.php3?login=$login" title="Show User Unauthorized Actions"><font color="white"><b>BADUSERS</b></font></a></td>
+<a href="badusers.php3?login=$Login" title="Show User Unauthorized Actions"><font color="white"><b>BADUSERS</b></font></a></td>
 <td align=center bgcolor="black" width=100>
-<a href="user_delete.php3?login=$login" title="Delete User"><font color="white"><b>DELETE</b></font></a></td>
+<a href="user_delete.php3?login=$Login" title="Delete User"><font color="white"><b>DELETE</b></font></a></td>
 <td align=center bgcolor="black" width=100>
-<a href="user_test.php3?login=$login" title="Test User"><font color="white"><b>TEST</b></font></a></td>
+<a href="user_test.php3?login=$Login" title="Test User"><font color="white"><b>TEST</b></font></a></td>
 </tr>
 <tr valign=top>
 <td align=center width=100></td>
 <td align=center bgcolor="black" width=200 colspan=2>
-<a href="clear_opensessions.php3?login=$login" title="Clear Open User Sessions"><font color="white"><b>OPEN SESSIONS</b></font></a></td>
+<a href="clear_opensessions.php3?login=$Login" title="Clear Open User Sessions"><font color="white"><b>OPEN SESSIONS</b></font></a></td>
 <td align=center width=100></td>
 </tr>
 EOM;
index bb2b0e3..de39327 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 #Read sql attribute map
+unset($sql_attrs);
+if (isset($_SESSION['sql_attrs']))
+       $sql_attrs = $_SESSION["sql_attrs"];
 if (!isset($sql_attrs)){
        $ARR = file($config[general_sql_attrs_file]);
        foreach($ARR as $val){
index 83bbde5..e68b17b 100644 (file)
@@ -10,8 +10,8 @@ $date=date($config[sql_full_date_format]);
 $lockmsg_name = $attrmap['Dialup-Lock-Msg'] . '0';
 $msg = $$lockmsg_name;
 $admin = '-';
-if ($HTTP_SERVER_VARS["PHP_AUTH_USER"] != '')
-       $admin = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
+if ($_SERVER["PHP_AUTH_USER"] != '')
+       $admin = $_SERVER["PHP_AUTH_USER"];
 if ($msg == '')
        echo "<b>Lock Message should not be empty</b><br>\n";
 else{
@@ -23,7 +23,7 @@ else{
                $link = @da_sql_host_connect($server,$config);
                if ($link){
                        $r = da_sql_query($link,$config,
-                       "INSERT INTO $config[sql_badusers_table] (username,date,admin,reason)
+                       "INSERT INTO $config[sql_badusers_table] (username,incidentdate,admin,reason)
                        VALUES ('$login','$date','$admin','$msg');");
                        if (!$r)
                                echo "<b>SQL Error:" . da_sql_error($link,$config) . "</b><br>\n";
index e837b60..98f90e7 100644 (file)
@@ -1,7 +1,12 @@
 <?php
+include_once('../lib/xlat.php3');
 #Read user_edit attribute map
+unset($show_attrs);
+if (isset($_SESSION['show_attrs']))
+       $show_attrs = $_SESSION['show_attrs'];
 if (!isset($show_attrs)){
-       $ARR = file($config[general_user_edit_attrs_file]);
+       $infile = xlat($config[general_user_edit_attrs_file],$login,$config);
+       $ARR = file($infile);
        foreach($ARR as $val){
                $val=chop($val);
                if (ereg('^[[:space:]]*#',$val) || ereg('^[[:space:]]*$',$val))
@@ -12,8 +17,12 @@ if (!isset($show_attrs)){
        if ($config[general_use_session] == 'yes')
                session_register('show_attrs');
 }
+unset($acct_attrs);
+if (isset($_SESSION['acct_attrs']))
+       $acct_attrs = $_SESSION['acct_attrs'];
 if (!isset($acct_attrs) && isset($config[general_accounting_attrs_file])){
-       $ARR = file($config[general_accounting_attrs_file]);
+       $infile = xlat($config[general_accounting_attrs_file],$login,$config);
+       $ARR = file($infile);
        foreach ($ARR as $val){
                $val=chop($val);
                if (ereg('^[[:space:]]*#',$val) || ereg('^[[:space:]]*$',$val))
index 6aec80c..c821fa2 100644 (file)
@@ -1,4 +1,8 @@
 <?php
+unset($text_default_vals);
+unset($default_vals);
+if (isset($_SESSION['text_default_vals']))
+       $text_default_vals = $_SESSION['text_default_vals'];
 if (!isset($text_default_vals)){
        $ARR=file("$config[general_default_file]");
        foreach($ARR as $val) {
index c0cd1ce..f3bda86 100644 (file)
@@ -35,7 +35,16 @@ function time2strclock($time)
        if (!$time)
                return "00:00:00";
 
-       $str["hour"] = $str["min"] = $str["sec"] = "00";
+       $str["days"] = $str["hour"] = $str["min"] = $str["sec"] = "00";
+
+       $d = $time/86400;
+       $d = floor($d);
+       if ($d){
+               if ($d < 10)
+                       $d = "0" . $d;
+               $str["days"] = "$d";
+               $time = $time % 86400;
+       }
        $h = $time/3600;
        $h = floor($h);
        if ($h){
@@ -59,7 +68,10 @@ function time2strclock($time)
        else
                $time = "00";
        $str["sec"] = "$time";
-       $ret = "$str[hour]:$str[min]:$str[sec]";
+       if ($str["days"] != "00")
+               $ret = "$str[days]:$str[hour]:$str[min]:$str[sec]";
+       else
+               $ret = "$str[hour]:$str[min]:$str[sec]";
 
        return $ret;
 }
@@ -110,4 +122,14 @@ function check_defaults($val,$op,$def)
 
        return 0;
 }
+
+function check_ip($ipaddr) {
+    if(ereg("^([0-9]{1,3})\x2E([0-9]{1,3})\x2E([0-9]{1,3})\x2E([0-9]{1,3})$", $ipaddr,$digit)) {
+         if(($digit[1] <= 255) && ($digit[2] <= 255) && ($digit[3] <= 255) && ($digit[4] <= 255)) {
+        return(1);
+      }
+    }
+    return(0);
+  }
+
 ?>
index 6469c86..c79b6c4 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 #Read ldap attribute map
+unset($attrmap);
+if (isset($_SESSION['attrmap']))
+       $attrmap = $_SESSION['attrmap'];
 if (!isset($attrmap)){
        $ARR = file("$config[general_ldap_attrmap]");
        foreach($ARR as $val){
index 3583098..9db4af2 100644 (file)
@@ -28,7 +28,7 @@ if ($config[ldap_default_dn] != ''){
                if ($regular_profile_attr != ''){
                        $get_attrs = array("$regular_profile_attr");
                        if ($config[ldap_filter] != '')
-                               $filter = ldap_xlat($config[ldap_filter],$login,$config);
+                               $filter = xlat($config[ldap_filter],$login,$config);
                        else
                                $filter = 'uid=' . $login;
                        if ($config[ldap_debug] == 'true')
index 5b9e4a3..3d24e7e 100644 (file)
@@ -2,6 +2,10 @@
 require_once('../lib/ldap/functions.php3');
 $ds=@ldap_connect("$config[ldap_server]");  // must be a valid ldap server!
 if ($ds) {
+       if (!is_numeric($max))
+               $max = 10;
+       if ($max > 500)
+               $max = 10;
        $r=@da_ldap_bind($ds,$config);
        if ($search_IN == 'name' || $search_IN == 'ou')
                $attr = ($search_IN == 'name') ? 'cn' : 'ou';
@@ -11,7 +15,7 @@ if ($ds) {
        }
        if ($config[ldap_debug] == 'true')
                print "<b>DEBUG(LDAP): Search Query: BASE='$config[ldap_base]',FILTER='$attr=*$search*'</b><br>\n";
-       $sr=@ldap_search($ds,"$config[ldap_base]", "$attr=*$search*",array('uid'),0,$max_results);
+       $sr=@ldap_search($ds,"$config[ldap_base]", "$attr=*$search*",array('uid'),0,$max);
        if (($info = @ldap_get_entries($ds, $sr))){
                for ($i = 0; $i < $info["count"]; $i++)
                        $found_users[] = $info[$i]['uid'][0];
index 6cb3ad5..e09f699 100644 (file)
@@ -1,24 +1,12 @@
 <?php
-function ldap_xlat($filter,$login,$config)
-{
-       $string = $filter;
-       if ($filter != ''){
-               $string = preg_replace('/%u/',$login,$string);
-               $string = preg_replace('/%U/',$HTTP_SERVER_VARS["PHP_AUTH_USER"],$string);
-               $string = preg_replace('/%ma/',$mappings[$http_user][accounting],$string);
-               $string = preg_replace('/%mu/',$mappings[$http_user][userdb],$string);
-       }
-
-       return $string;
-}
+require_once('../lib/xlat.php3');
 
 function da_ldap_bind($ds,$config)
 {
        if ($ds){
                if ($config[ldap_use_http_credentials] == 'yes'){
-                       global $HTTP_SERVER_VARS;
-                       $din = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
-                       $pass = $HTTP_SERVER_VARS["PHP_AUTH_PW"];
+                       $din = $_SERVER["PHP_AUTH_USER"];
+                       $pass = $_SERVER["PHP_AUTH_PW"];
                        if ($config[ldap_map_to_directory_manager] != '' &&
                        $din == $config[ldap_map_to_directory_manager] &&
                        $config[ldap_directory_manager] != '')
@@ -66,12 +54,12 @@ function get_user_info($ds,$user,$config,$decode_normal,$k)
                $attrs = array('cn');
                if ($config[ldap_userdn] == ''){
                        if ($config[ldap_filter] != '')
-                               $filter = ldap_xlat($config[ldap_filter],$login,$config);
+                               $filter = xlat($config[ldap_filter],$login,$config);
                        else
                                $filter = 'uid=' . $login;
                }
                else
-                       $filter = ldap_xlat($config[ldap_userdn],$login,$config);
+                       $filter = xlat($config[ldap_userdn],$login,$config);
                if ($config[ldap_debug] == 'true'){
                        if ($config[ldap_userdn] == '')
        print "<b>DEBUG(LDAP): Search Query: BASE='$config[ldap_base]',FILTER='$filter'</b><br>\n";
@@ -98,12 +86,12 @@ function get_user_dn($ds,$user,$config)
                $attrs = array('dn');
                if ($config[ldap_userdn] == ''){
                        if ($config[ldap_filter] != '')
-                               $filter = ldap_xlat($config[ldap_filter],$login,$config);
+                               $filter = xlat($config[ldap_filter],$login,$config);
                        else
                                $filter = 'uid=' . $login;
                }
                else
-                       $filter = ldap_xlat($config[ldap_userdn],$login,$config);
+                       $filter = xlat($config[ldap_userdn],$login,$config);
                if ($config[ldap_debug] == 'true'){
                        if ($config[ldap_userdn] == '')
        print "<b>DEBUG(LDAP): Search Query: BASE='$config[ldap_base]',FILTER='$filter'</b><br>\n";
index 45116b8..6939bd1 100644 (file)
@@ -23,6 +23,9 @@ $homephone = '-';
 $mobile = '-';
 $mail = '-';
 $mailalt = '-';
+$dn = '';
+$user_exists = 'no';
+unset($item_vals);
 
 if ($config[general_decode_normal_attributes] == 'yes')
        $decode_normal = 1;
@@ -32,12 +35,12 @@ if ($ds) {
        $r=@da_ldap_bind($ds,$config);
        if ($config[ldap_userdn] == ''){
                if ($config[ldap_filter] != '')
-                       $filter = ldap_xlat($config[ldap_filter],$login,$config);
+                       $filter = xlat($config[ldap_filter],$login,$config);
                else
                        $filter = 'uid=' . $login;
        }
        else
-               $filter = ldap_xlat($config[ldap_userdn],$login,$config);
+               $filter = xlat($config[ldap_userdn],$login,$config);
        if ($config[ldap_debug] == 'true'){
                if ($config[ldap_userdn] == '')
                        print "<b>DEBUG(LDAP): Search Query: BASE='$config[ldap_base]',FILTER='$filter'</b><br>\n";
@@ -55,7 +58,6 @@ if ($ds) {
        else{
                $user_exists = 'yes';
                $user_info = 1;
-               unset($item_vals);
                $k = init_decoder();
                $cn = ($info[0]['cn'][0]) ? $info[0]['cn'][0] : '-';
                if ($decode_normal)
diff --git a/dialup_admin/lib/missing.php3 b/dialup_admin/lib/missing.php3
new file mode 100644 (file)
index 0000000..af2bb8e
--- /dev/null
@@ -0,0 +1,13 @@
+function array_change_key_case($input,$case)
+{
+       $NEW_ARR = array();
+       foreach ($input as $val => $key){
+               if ($case == CASE_UPPER)
+                       $K = strtoupper($key);
+               else if ($case == CASE_LOWER)
+                       $K = strtolower($key);
+               $NEW_ARR[$K] = $val;
+       }
+
+       return $NEW_ARR;
+}
index b4c02ef..ae3a5cd 100644 (file)
@@ -1,12 +1,37 @@
 <?php
 #Read sql attribute map
-$ARR = file("$config[general_sql_attrmap]");
-foreach($ARR as $val){
-       $val=chop($val);
-       if (ereg('^[[:space:]]*#',$val) || ereg('^[[:space:]]*$',$val))
-               continue;
-       list($type,$key,$v)=split('[[:space:]]+',$val);
-       $attrmap["$key"]=$v;
-       $rev_attrmap["$v"] = $key;
-       $attr_type["$key"]=$type;
+unset($attrmap);
+unset($rev_attrmap);
+unset($attr_type);
+if (isset($_SESSION['attrmap'])){
+       #If attrmap is set then the rest will also be set
+        $attrmap = $_SESSION['attrmap'];
+       $rev_attrmap =$_SESSION['rev_attrmap'];
+       $attr_type = $_SESSION['attr_type'];
+}
+else{
+       $ARR = file("$config[general_sql_attrmap]");
+       foreach($ARR as $val){
+               $val=chop($val);
+               if (ereg('^[[:space:]]*#',$val) || ereg('^[[:space:]]*$',$val))
+                       continue;
+               list($type,$key,$v)=split('[[:space:]]+',$val);
+               $attrmap["$key"]=$v;
+               $rev_attrmap["$v"] = $key;
+               $attr_type["$key"]=$type;
+       }
+       if (isset($show_attrs)){
+               foreach($show_attrs as $key => $desc){
+                       if ($attrmap["$key"] == ''){
+                               $attrmap["$key"] = $key;
+                               $attr_type["key"] = 'replyItem';
+                               $rev_attrmap["$key"] = $key;
+                       }
+               }
+       }
+       if ($config[general_use_session] == 'yes'){
+               session_register('attrmap');
+               session_register('rev_attrmap');
+               session_register('attr_type');
+       }
 }
index 1c80c2b..a71e706 100644 (file)
@@ -46,14 +46,16 @@ if ($link){
                        if ($use_ops){
                                $op_val = $$op_name;
                                if ($op_val != ''){
+                                       $op_val = da_sql_escape_string($op_val);
                                        if (check_operator($op_val,$type) == -1){
                                                echo "<b>Invalid operator ($op_val) for attribute $key</b><br>\n";
                                                continue;
                                        }
-                                       $op_val1 = "'$op_val'";
                                        $op_val2 = ",'$op_val'";
                                }
                        }
+                       $sql_attr = da_sql_escape_string($sql_attr);
+                       $val = da_sql_escape_string($val);
        // if we have operators, the operator has changed and the corresponding value exists then update
                        if ($use_ops && isset($item_vals["$key"][operator][$j]) &&
                                $op_val != $item_vals["$key"][operator][$j] ){
@@ -81,6 +83,7 @@ if ($link){
                        else{
                                if (isset($item_vals["$key"][$j])){
                                        $old_val = $item_vals["$key"][$j];
+                                       $old_val = da_sql_escape_string($old_val);
                                        $res = @da_sql_query($link,$config,
                                        "UPDATE $table SET value = '$val' WHERE $query_key = '$login' AND
                                        attribute = '$sql_attr' AND value = '$old_val';");
index 856b17b..35fa1dc 100644 (file)
@@ -5,10 +5,10 @@ else{
        echo "<b>Could not include SQL library</b><br>\n";
        exit();
 }
-if ($config[sql_use_operator] == 'true'){
+if ($config[sql_use_operators] == 'true'){
        $text1 = ',op';
        $text2  = ",':='";
-       $text3 = "AND op = ':='";
+       $text3 = ", op = ':='";
 }
 else{
        $text1 = '';
@@ -20,6 +20,7 @@ if ($link){
        if (is_file("../lib/crypt/$config[general_encryption_method].php3")){
                include("../lib/crypt/$config[general_encryption_method].php3");
                $passwd = da_encrypt($passwd);
+               $passwd = da_sql_escape_string($passwd);
                $res = @da_sql_query($link,$config,
                        "SELECT value FROM $config[sql_check_table] WHERE username = '$login'
                        AND attribute = '$config[sql_password_attribute]';");
index c602d64..0539b99 100644 (file)
@@ -12,6 +12,7 @@ if ($config[sql_use_operators] == 'true'){
        $passwd_op = ",':='";
 }
 $da_abort=0;
+$op_val2 = '';
 $link = @da_sql_pconnect($config);
 if ($link){
        $Members = preg_split("/[\n\s]+/",$members,-1,PREG_SPLIT_NO_EMPTY);
@@ -26,15 +27,9 @@ if ($link){
                                $da_abort=1;
                        }
                }
-       } else {
-               $res = @da_sql_query($link,$config,
-               "INSERT INTO $config[sql_usergroup_table] (groupname)
-               VALUES ('$login');");
-               if (!$res || !@da_sql_affected_rows($link,$res,$config)){
-                       echo "<b>Unable to create group $login: " . da_sql_error($link,$config) . "</b><br>\n";
-                       $da_abort=1;
-               }
        }
+       else
+               echo "<b>Members list is empty!!</b><br>\n";
        if (!$da_abort){
                foreach($show_attrs as $key => $attr){
                        if ($attrmap["$key"] == 'none')
@@ -57,6 +52,7 @@ if ($link){
                        $op_name = $attrmap["$key"] . '_op';
                        $op_val = $$op_name;
                        if ($op_val != ''){
+                               $op_val = da_sql_escape_string($op_val);
                                if (check_operator($op_val,$type) == -1){
                                        echo "<b>Invalid operator ($op_val) for attribute $key</b><br>\n";
                                        coninue;
@@ -71,8 +67,8 @@ if ($link){
                        if (!$res || !@da_sql_affected_rows($link,$res,$config))
                                echo "<b>Query failed for attribute $key: " . da_sql_error($link,$config) . "</b><br>\n";
                }
+               echo "<b>Group created successfully</b><br>\n";
        }
-       echo "<b>Group created successfully</b><br>\n";
 }
 else
        echo "<b>Could not connect to SQL database</b><br>\n";
index ab6131d..1f3e876 100644 (file)
@@ -12,11 +12,13 @@ if ($config[sql_use_operators] == 'true'){
        $passwd_op = ",':='";
 }
 $da_abort=0;
+$op_val2 = '';
 $link = @da_sql_pconnect($config);
 if ($link){
        if (is_file("../lib/crypt/$config[general_encryption_method].php3")){
                include("../lib/crypt/$config[general_encryption_method].php3");
                $passwd = da_encrypt($passwd);
+               $passwd = da_sql_escape_string($passwd);
                $res = @da_sql_query($link,$config,
                "INSERT INTO $config[sql_check_table] (attribute,value,username $text)
                VALUES ('$config[sql_password_attribute]','$passwd','$login' $passwd_op);");
@@ -92,6 +94,7 @@ if ($link){
                                $op_name = $attrmap["$key"] . '_op';
                                $op_val = $$op_name;
                                if ($op_val != ''){
+                                       $op_val = da_sql_escape_string($op_val);
                                        if (check_operator($op_val,$type) == -1){
                                                echo "<b>Invalid operator ($op_val) for attribute $key</b><br>\n";
                                                coninue;
index f201ebe..8ade8a1 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 require('../lib/sql/attrmap.php3');
-if ($login != ''){
+if ($login != '' && $user_type != 'group'){
        if (is_file("../lib/sql/drivers/$config[sql_type]/functions.php3"))
                include_once("../lib/sql/drivers/$config[sql_type]/functions.php3");
        else{
@@ -27,8 +27,12 @@ if ($login != ''){
                        $res = @da_sql_query($link,$config,
                        "SELECT groupname FROM $config[sql_usergroup_table] WHERE username = '$login';");
                        if ($res){
-                               while(($row = @da_sql_fetch_array($res,$config)))
-                                       $member_groups[] = $row[groupname];
+                               while(($row = @da_sql_fetch_array($res,$config))){
+                                       $group = $row[groupname];
+                                       $member_groups[$group] = $group;
+                               }
+                               if (isset($member_groups))
+                                       ksort($member_groups);
                        }
                        if (isset($member_groups)){
                                $in = '(';
diff --git a/dialup_admin/lib/sql/drivers/dbx/functions.php3 b/dialup_admin/lib/sql/drivers/dbx/functions.php3
new file mode 100644 (file)
index 0000000..a968fd8
--- /dev/null
@@ -0,0 +1,146 @@
+<?php
+function da_sql_limit($limit,$point,$config)
+{
+       switch($point){
+               case 0:
+                       return '';
+               case 1:
+                       return '';
+               case 2:
+                       return "LIMIT $limit";
+       }
+}
+
+function da_sql_host_connect($server,$config)
+{
+       if ($config[sql_use_http_credentials] == 'yes'){
+               global $HTTP_SERVER_VARS;
+               $SQL_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
+               $SQL_passwd = $HTTP_SERVER_VARS["PHP_AUTH_PW"];
+       }
+       else{
+               $SQL_user = $config[sql_username];
+               $SQL_passwd = $config[sql_password];
+       }
+       // FIXME: This function is still Postgres specific. Needs to be configurable.
+       return @dbx_connect(DBX_PGSQL, "$server", "$config[sql_database]",
+                       "$SQL_user", "$SQL_passwd", DBX_PERSISTENT);
+}
+
+function da_sql_connect($config)
+{
+       if ($config[sql_use_http_credentials] == 'yes'){
+               global $HTTP_SERVER_VARS;
+               $SQL_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
+               $SQL_passwd = $HTTP_SERVER_VARS["PHP_AUTH_PW"];
+       }
+       else{
+               $SQL_user = $config[sql_username];
+               $SQL_passwd = $config[sql_password];
+       }
+       // FIXME: This function is still Postgres specific. Needs to be configurable.
+       return @dbx_connect(DBX_PGSQL, "$server", "$config[sql_database]",
+                       "$SQL_user", "$SQL_passwd");
+}
+
+function da_sql_pconnect($config)
+{
+       if ($config[sql_use_http_credentials] == 'yes'){
+               global $HTTP_SERVER_VARS;
+               $SQL_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
+               $SQL_passwd = $HTTP_SERVER_VARS["PHP_AUTH_PW"];
+       }
+       else{
+               $SQL_user = $config[sql_username];
+               $SQL_passwd = $config[sql_password];
+       }
+       // FIXME: This function is still Postgres specific. Needs to be configurable.
+       return @dbx_connect(DBX_PGSQL, "$server", "$config[sql_database]",
+                       "$SQL_user", "$SQL_passwd", DBX_PERSISTENT);
+}
+
+function da_sql_close($link,$config)
+{
+       @dbx_close($link);
+}
+
+function da_sql_escape_string($string)
+{
+       return addslashes($string);
+}
+
+function da_sql_query($link,$config,$query)
+{
+       if ($config[sql_debug] == 'true') {
+               print "<b>DEBUG(SQL,PG DRIVER): Query: <i>$query</i></b><br>\n";
+       }
+       return @dbx_query($link,$query);
+}
+
+function da_sql_num_rows($result,$config)
+{
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,PG DRIVER): Query Result: Num rows:: " . $result->rows . "</b><br>\n";
+       return $result->rows;
+}
+
+$dbx_global_record_counter = array() ;
+function da_sql_fetch_array($result,$config)
+{
+
+       global $dbx_global_record_counter;
+       if (!$dbx_global_record_counter[$result->handle]){
+               $dbx_global_record_counter[$result->handle] = 0;
+       }
+
+       if ($dbx_global_record_counter[$result->handle] <= $result->rows - 1 ){
+               return $result->data[$dbx_global_record_counter[$result->handle]++];
+       } elseif ($dbx_global_record_counter[$result->handle] > $result->rows - 1 ) {
+               $dbx_global_record_counter[$result->handle]++;
+               return NULL;
+       } else {
+               $dbx_global_record_counter[$result->handle]++;
+               return FALSE;
+       }
+}
+
+function da_sql_affected_rows($link,$result,$config)
+{
+       // FIXME: This function is still Postgres specific.
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,PG DRIVER): Query Result: Affected rows:: " . @pg_cmdtuples($result->handle) . "</b><br>\n";
+       return @pg_cmdtuples($result->handle);
+}
+
+function da_sql_list_fields($table,$link,$config)
+{
+       $res = @dbx_query($link,"SELECT * FROM ".$table." LIMIT 1 ;"); 
+       if ($res){
+               $fields[num] = $res->cols;
+       }
+       $res = @dbx_query($link,"SELECT * FROM ".$table." LIMIT 1 ;");
+       if ($res)
+               $fields[res] = $res->info[name];
+       else
+               return NULL;
+
+       return $fields;
+}
+
+function da_sql_num_fields($fields,$config)
+{
+       if ($fields)
+               return $fields[num];
+}
+
+function da_sql_field_name($fields,$num,$config)
+{
+       if ($fields)
+               return $fields[res][$num];
+}
+
+function da_sql_error($link,$config)
+{
+       return dbx_error($link);
+}
+?>
index 8f313c6..ce5e2c9 100644 (file)
@@ -1,4 +1,16 @@
 <?php
+function da_sql_limit($limit,$point,$config)
+{
+       switch($point){
+               case 0:
+                       return '';
+               case 1:
+                       return '';
+               case 3:
+                       return "LIMIT $limit";
+       }
+}
+
 function da_sql_host_connect($server,$config)
 {
        if ($config[sql_use_http_credentials] == 'yes'){
@@ -11,6 +23,10 @@ function da_sql_host_connect($server,$config)
                $SQL_passwd = $config[sql_password];
        }
 
+       if ($config[sql_connect_timeout] != 0)
+               @ini_set('mysql.connect_timeout',$config[sql_connect_timeout]);
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,MYSQL DRIVER): Connect: User=$SQL_user,Password=$SQL_passwd </b><br>\n";
        return @mysql_connect("$server:$config[sql_port]",$SQL_user,$SQL_passwd);
 }
 
@@ -28,6 +44,8 @@ function da_sql_connect($config)
 
        if ($config[sql_connect_timeout] != 0)
                @ini_set('mysql.connect_timeout',$config[sql_connect_timeout]);
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,MYSQL DRIVER): Connect: User=$SQL_user,Password=$SQL_passwd </b><br>\n";
        return @mysql_connect("$config[sql_server]:$config[sql_port]",$SQL_user,$SQL_passwd);
 }
 
@@ -45,6 +63,8 @@ function da_sql_pconnect($config)
 
        if ($config[sql_connect_timeout] != 0)
                @ini_set('mysql.connect_timeout',$config[sql_connect_timeout]);
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,MYSQL DRIVER): Connect: User=$SQL_user,Password=$SQL_passwd </b><br>\n";
        return @mysql_pconnect("$config[sql_server]:$config[sql_port]",$SQL_user,$SQL_passwd);
 }
 
diff --git a/dialup_admin/lib/sql/drivers/oracle/functions.php3 b/dialup_admin/lib/sql/drivers/oracle/functions.php3
new file mode 100644 (file)
index 0000000..1fabc3d
--- /dev/null
@@ -0,0 +1,147 @@
+<?php
+// $Id$
+function da_sql_limit($limit,$point,$config)
+{
+       switch($point){
+               case 0:
+                       return '';
+               case 1:
+                       return "AND ROWNUM <= $limit";
+               case 2:
+                       return '';
+       }
+}
+
+function da_sql_host_connect($server,$config)
+{
+       if ($config[sql_use_http_credentials] == 'yes'){
+               global $HTTP_SERVER_VARS;
+               $SQL_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
+               $SQL_passwd = $HTTP_SERVER_VARS["PHP_AUTH_PW"];
+       }
+       else{
+               $SQL_user = $config[sql_username];
+               $SQL_passwd = $config[sql_password];
+       }
+       $link = @ocilogon($SQL_user, $SQL_passwd, $config[sql_database]);
+        $res = @da_sql_query($link,$config,"ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='YYYY-MM-DD HH24:MI:SS.FF TZH:TZM'");
+       return $link;
+}
+
+function da_sql_connect($config)
+{
+       if ($config[sql_use_http_credentials] == 'yes'){
+               global $HTTP_SERVER_VARS;
+               $SQL_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
+               $SQL_passwd = $HTTP_SERVER_VARS["PHP_AUTH_PW"];
+       }
+       else{
+               $SQL_user = $config[sql_username];
+               $SQL_passwd = $config[sql_password];
+       }
+       $link = @ocilogon($SQL_user, $SQL_passwd, $config[sql_database]);
+        $res = @da_sql_query($link,$config,"ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='YYYY-MM-DD HH24:MI:SS.FF TZH:TZM'");
+       return $link;
+}
+
+function da_sql_pconnect($config)
+{
+       if ($config[sql_use_http_credentials] == 'yes'){
+               global $HTTP_SERVER_VARS;
+               $SQL_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
+               $SQL_passwd = $HTTP_SERVER_VARS["PHP_AUTH_PW"];
+       }
+       else{
+               $SQL_user = $config[sql_username];
+               $SQL_passwd = $config[sql_password];
+       }
+       $link = @ociplogon($SQL_user, $SQL_passwd, $config[sql_database]);
+        $res = @da_sql_query($link,$config,"ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT='YYYY-MM-DD HH24:MI:SS.FF TZH:TZM'");
+       return $link;
+}
+
+function da_sql_close($link,$config)
+{
+       @ociclose($link);
+}
+
+function da_sql_escape_string($string)
+{
+       return addslashes($string);
+}
+
+function da_sql_query($link,$config,$query)
+{
+       $trimmed_query = rtrim($query, ";");
+       if ($config[sql_debug] == 'true') {
+               print "<b>DEBUG(SQL,OCI DRIVER): Query: <i>$trimmed_query</i></b><br>\n";
+       }
+       $statement = OCIParse($link,$trimmed_query);
+       OCIExecute($statement);
+       return $statement;
+}
+
+function da_sql_num_rows($statement,$config)
+{
+       // Unfortunately we need to fetch the statement as ocirowcount doesn't work on SELECTs
+       $rows = OCIFetchStatement($statement,$res); 
+
+        if ($config[sql_debug] == 'true'){
+                print "<b>DEBUG(SQL,OCI DRIVER): Query Result: Num rows:: " . $rows . "</b><br>\n";
+        }
+       // Unfortunately we need to re-execute because the statement cursor is reset after OCIFetchStatement :-(
+       OCIExecute($statement); 
+        return $rows;
+}
+
+
+function da_sql_fetch_array($statement,$config)
+{
+       OCIFetchInto($statement, $temprow, OCI_ASSOC);
+       $row = array_change_key_case($temprow, CASE_LOWER);
+        if ($config[sql_debug] == 'true') {
+                print "<b>DEBUG(SQL,OCI DRIVER): Query Result: <pre>";
+                print_r($row);
+                print "</b></pre>\n";
+        }
+        return $row;
+}
+
+
+function da_sql_affected_rows($link,$statement,$config)
+{
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,OCI DRIVER): Query Result: Affected rows:: " . @ocirowcount($statement) . "</b><br>\n";
+       return @ocirowcount($statement);
+}
+
+function da_sql_list_fields($table,$link,$config)
+{
+        $res = @da_sql_query($link,$config,"SELECT * from $table WHERE ROWNUM <=1");
+        if ($res){
+               $fields[res]=Array();
+               for ($i = 1;$i<=ocinumcols($res);$i++) {
+                       array_push($fields[res],strtolower(OCIColumnName($res,$i)));
+               }
+                $fields[num]=@ocinumcols($res);
+        }else{
+                return NULL;
+        }
+        return $fields;
+}
+
+function da_sql_num_fields($fields,$config)
+{
+        return $fields[num];
+}
+
+function da_sql_field_name($fields,$num,$config)
+{
+       return $fields[res][$num];
+}
+
+function da_sql_error($link,$config)
+{
+       return ocierror($link);
+}
+?>
index ec20319..68ad17c 100644 (file)
@@ -1,4 +1,15 @@
 <?php
+function da_sql_limit($limit,$point,$config)
+{
+       switch($point){
+               case 0:
+                       return '';
+               case 1:
+                       return '';
+               case 2:
+                       return "LIMIT $limit";
+       }
+}
 function da_sql_host_connect($server,$config)
 {
        if ($config[sql_use_http_credentials] == 'yes'){
@@ -10,6 +21,8 @@ function da_sql_host_connect($server,$config)
                $SQL_user = $config[sql_username];
                $SQL_passwd = $config[sql_password];
        }
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,PG DRIVER): Connect: User=$SQL_user,Password=$SQL_passwd </b><br>\n";
        return @pg_connect("host=$server port=$config[sql_port]
                        dbname=$config[sql_database] user=$SQL_user
                        password=$SQL_passwd");
@@ -26,6 +39,8 @@ function da_sql_connect($config)
                $SQL_user = $config[sql_username];
                $SQL_passwd = $config[sql_password];
        }
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,PG DRIVER): Connect: User=$SQL_user,Password=$SQL_passwd </b><br>\n";
        return @pg_connect("host=$config[sql_server] port=$config[sql_port]
                        dbname=$config[sql_database] user=$SQL_user
                        password=$SQL_passwd");
@@ -42,6 +57,8 @@ function da_sql_pconnect($config)
                $SQL_user = $config[sql_username];
                $SQL_passwd = $config[sql_password];
        }
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,PG DRIVER): Connect: User=$SQL_user,Password=$SQL_passwd </b><br>\n";
        return @pg_pconnect("host=$config[sql_server] port=$config[sql_port]
                        dbname=$config[sql_database] user=$SQL_user
                        password=$SQL_passwd");
@@ -61,7 +78,7 @@ function da_sql_query($link,$config,$query)
 {
        if ($config[sql_debug] == 'true')
                print "<b>DEBUG(SQL,PG DRIVER): Query: <i>$query</i></b><br>\n";
-       return @pg_exec($link,$query);
+       return @pg_query($link,$query);
 }
 
 function da_sql_num_rows($result,$config)
@@ -93,7 +110,7 @@ function da_sql_affected_rows($link,$result,$config)
 
 function da_sql_list_fields($table,$link,$config)
 {
-       $res = @pg_exec($link,
+       $res = @pg_query($link,
                "select count(*) from pg_attribute where attnum > '0' and
                attrelid = (select oid from pg_class where relname='$table');");
        if ($res){
@@ -104,7 +121,7 @@ function da_sql_list_fields($table,$link,$config)
                        $fields[num] = $row[0];
                }
        }
-       $res = @pg_exec($link,
+       $res = @pg_query($link,
                "select attname from pg_attribute where attnum > '0' and
                attrelid = (select oid from pg_class where relname='$table');");
        if ($res)
diff --git a/dialup_admin/lib/sql/drivers/sqlrelay/functions.php3 b/dialup_admin/lib/sql/drivers/sqlrelay/functions.php3
new file mode 100644 (file)
index 0000000..8c5fd9d
--- /dev/null
@@ -0,0 +1,193 @@
+<?php
+function da_sql_limit($limit,$point,$config)
+{
+       switch($point){
+               case 0:
+                       return '';
+               case 1:
+                       return '';
+               case 2:
+                       return "LIMIT $limit";
+       }       
+}
+
+function da_sql_host_connect($server,$config)
+{
+       $retrytime = 0;
+
+       if ($config[sql_use_http_credentials] == 'yes'){
+               global $HTTP_SERVER_VARS;
+               $SQL_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
+               $SQL_passwd = $HTTP_SERVER_VARS["PHP_AUTH_PW"];
+       }
+       else{
+               $SQL_user = $config[sql_username];
+               $SQL_passwd = $config[sql_password];
+       }
+
+       if ($config[sql_connect_timeout] != 0)
+               $retrytime = $config[sql_connect_timeout];
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,SQLRELAY DRIVER): Connect: User=$SQL_user,Password=$SQL_passwd </b><br>\n";
+       $link[con] = @sqlrcon_alloc($server,$port,'',$SQL_user,$SQL_passwd,$retrytime,1);
+       if ($link[con]){
+               $link[cur] = @sqlrcur_alloc($link[con]);
+               if ($link[cur])
+                       return $link;
+               else
+                       return 0;
+       }
+       else
+               return 0;
+}
+
+function da_sql_connect($config)
+{
+       $retrytime = 0;
+
+       if ($config[sql_use_http_credentials] == 'yes'){
+               global $HTTP_SERVER_VARS;
+               $SQL_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
+               $SQL_passwd = $HTTP_SERVER_VARS["PHP_AUTH_PW"];
+       }
+       else{
+               $SQL_user = $config[sql_username];
+               $SQL_passwd = $config[sql_password];
+       }
+
+       if ($config[sql_connect_timeout] != 0)
+               $retrytime = $config[sql_connect_timeout];
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,SQLRELAY DRIVER): Connect: User=$SQL_user,Password=$SQL_passwd </b><br>\n";
+       $link[con] = @sqlrcon_alloc($config[sql_server],$config[sql_port],'',$SQL_user,$SQL_passwd,$retrytime,1);
+       if ($link[con]){
+               $link[cur] = @sqlrcur_alloc($link[con]);
+               if ($link[cur])
+                       return $link;
+               else
+                       return 0;
+       }
+       else
+               return 0;
+}
+
+function da_sql_pconnect($config)
+{
+       $retrytime = 0;
+
+
+       if ($config[sql_use_http_credentials] == 'yes'){
+               global $HTTP_SERVER_VARS;
+               $SQL_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
+               $SQL_passwd = $HTTP_SERVER_VARS["PHP_AUTH_PW"];
+       }
+       else{
+               $SQL_user = $config[sql_username];
+               $SQL_passwd = $config[sql_password];
+       }
+
+       if ($config[sql_connect_timeout] != 0)
+               $retrytime = $config[sql_connect_timeout];
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,SQLRELAY DRIVER): Connect: Host=$config[sql_server],Port=$config[sql_port],User=$SQL_user,Password=$SQL_passwd </b><br>\n";
+       $link[con] = sqlrcon_alloc($config[sql_server],$config[sql_port],'',$SQL_user,$SQL_passwd,$retrytime,1);
+       if ($link[con]){
+               sqlrcon_debugOn($link[con]);
+               $link[cur] = sqlrcur_alloc($link[con]);
+               if ($link[cur]){
+                       sqlrcur_setResultSetBufferSize($link[cur], 4);
+                       sqlrcur_lowerCaseColumnNames($link[cur]);
+                       return $link;
+               }
+               else
+                       return false;
+       }
+       else{
+               return false;
+       }
+}
+
+function da_sql_close($link,$config)
+{
+       if (sqlrcur_free($link[cur]))
+               return sqlrcon_free($link[con]);
+       else
+               return 0;
+}
+
+function da_sql_escape_string($string)
+{
+       return addslashes($string);
+}
+
+function da_sql_query($link,$config,$query)
+{
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,SQLRELAY DRIVER): Query: <i>$query</i></b><br>\n";
+       if (sqlrcur_sendQuery($link[cur],$query)){
+               sqlrcon_endSession($link[con]);
+               $link[count] = sqlrcur_rowCount($link[cur]);
+               return $link;
+       }
+       else{
+               return false;
+       }
+}
+
+function da_sql_num_rows($result,$config)
+{
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,SQLRELAY DRIVER): Query Result: Num rows:: " . @sqlrcur_rowCount($result[cur]) . "</b><br>\n";
+       return sqlrcur_rowCount($result[cur]);
+       return 0;
+}
+
+function da_sql_fetch_array($result,$config)
+{
+       static $counter = 0;
+       if ($counter < $result[count]){
+               $row = sqlrcur_getRowAssoc($result[cur],$counter);
+               $counter++;
+       }
+       else{
+               $counter = 0;
+               return false;
+       }
+       if ($config[sql_debug] == 'true'){
+               print "<b>DEBUG(SQL,SQLRELAY DRIVER): Query Result: <pre>";
+       }
+       return $row;
+}
+
+function da_sql_affected_rows($link,$result,$config)
+{
+       if ($config[sql_debug] == 'true')
+               print "<b>DEBUG(SQL,SQLRELAY DRIVER): Query Result: Affected rows:: " . @sqlrcur_affectedRows($result[cur]) . "</b><br>\n";
+       return sqlrcur_affectedRows($result[cur]);
+}
+
+function da_sql_list_fields($table,$link,$config)
+{
+       if (sqlrcur_sendQuery($link[cur],"SELECT * FROM $table WHERE  1 = 0;")){
+               sqlrcon_endSession($link[con]);
+               return $link[cur];
+       }
+       else
+               return false;
+}
+
+function da_sql_num_fields($fields,$config)
+{
+       return sqlrcur_colCount($fields);
+}
+
+function da_sql_field_name($fields,$num,$config)
+{
+       return sqlrcur_getColumnName($fields,$num);
+}
+
+function da_sql_error($link,$config)
+{
+       return sqlrcur_errorMessage($link[cur]);
+}
+?>
index 7440c37..9bbd8b1 100644 (file)
@@ -6,16 +6,21 @@ else{
        exit();
 }
 
+unset($found_users);
+
 $link = @da_sql_pconnect($config);
 if ($link){
        $search = da_sql_escape_string($search);
-       if (!is_numeric($max_results))
-               $max_results = 10;
-       if (($search_IN == 'name' || $search_IN == 'ou') && $config[sql_use_user_info_table] == 'true'){
-               $attr = ($search_IN == 'name') ? 'name' : 'department';
+       if (!is_numeric($max))
+               $max = 10;
+       if ($max > 500)
+               $max = 10;
+       if (($search_IN == 'name' || $search_IN == 'department' || $search_IN == 'username') && 
+                       $config[sql_use_user_info_table] == 'true'){
                $res = @da_sql_query($link,$config,
-               "SELECT username FROM $config[sql_user_info_table] WHERE
-               lower($attr) LIKE '%$search%' LIMIT $max_results;");
+               "SELECT " . da_sql_limit($max,0,$config) . " username FROM $config[sql_user_info_table] WHERE
+               lower($search_IN) LIKE '%$search%' " .
+               da_sql_limit($max,1,$config) . " " . da_sql_limit($max,2,$config) . " ;");
                if ($res){
                        while(($row = @da_sql_fetch_array($res,$config)))
                                $found_users[] = $row[username];
@@ -31,8 +36,10 @@ if ($link){
                }
                $table = ($attr_type[$radius_attr] == 'checkItem') ? $config[sql_check_table] : $config[sql_reply_table];
                $attr = $attrmap[$radius_attr];
+               $attr = da_sql_escape_string($attr);
                $res = @da_sql_query($link,$config,
-               "SELECT username FROM $table WHERE attribute = '$attr' AND value LIKE '%$search%' LIMIT $max_results;");
+               "SELECT " . da_sql_limit($max,0,$config) . " username FROM $table WHERE attribute = '$attr'
+               AND value LIKE '%$search%' " . da_sql_limit($max,1,$config) . " " . da_sql_limit($max,2,$config) . " ;");
                if ($res){
                        while(($row = @da_sql_fetch_array($res,$config)))
                                $found_users[] = $row[username];
index 98fdc66..7d6b613 100644 (file)
@@ -5,6 +5,7 @@ else{
        echo "<b>Could not include SQL library</b><br>\n";
        exit();
 }
+require_once('../lib/xlat.php3');
 
 function connect2db($config)
 {
@@ -31,16 +32,4 @@ function closedb($link,$config)
 {
        return 1;
 }
-function sql_xlat($filter,$login,$config)
-{
-       $string = $filter;
-       $http_user = $HTTP_SERVER_VARS["PHP_AUTH_USER"];
-       if ($filter != ''){
-               $string = preg_replace('/%u/',$login,$string);
-               $string = preg_replace('/%U/',$http_user,$string);
-               $string = preg_replace('/%m/',$mappings[$http_user],$string);
-       }
-
-       return $string;
-}
 ?>
diff --git a/dialup_admin/lib/sql/group_change.php3 b/dialup_admin/lib/sql/group_change.php3
new file mode 100644 (file)
index 0000000..eed00e7
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+if (is_file("../lib/sql/drivers/$config[sql_type]/functions.php3"))
+       include_once("../lib/sql/drivers/$config[sql_type]/functions.php3");
+else{
+       echo "<b>Could not include SQL library</b><br>\n";
+       exit();
+}
+$link = @da_sql_pconnect($config);
+if ($link){
+       if (isset($member_groups) && isset($edited_groups)){
+               $del_groups = array_diff($member_groups,$edited_groups);
+               if (isset($del_groups)){
+                       foreach ($del_groups as $del){
+                               $del = da_sql_escape_string($del);
+                               $res = @da_sql_query($link,$config,
+                       "DELETE FROM $config[sql_usergroup_table] WHERE username = '$login' AND groupname = '$del';");
+                               if (!$res)
+                                       echo "<b>Could not delete user $login from group $del: " . da_sql_error($link,$config) . "</b><br>\n";
+                               else
+                                       echo "<b>User $login deleted from group $del</b><br>\n";
+                       }
+               }
+               $new_groups = array_diff($edited_groups,$member_groups);
+               if (isset($new_groups)){
+                       foreach($new_groups as $new){
+                               $new = da_sql_escape_string($new);
+                               $res = @da_sql_query($link,$config,
+                               "INSERT INTO $config[sql_usergroup_table] (groupname,username)
+                               VALUES ('$new','$login');");
+                               if (!$res)
+                                       echo "<b>Error while adding user $login to group $login: " . da_sql_error($link,$config) . "</b><br>\n";
+                               else
+                                       echo "<b>User $login added to group $new</b><br>\n";
+                       }
+               }
+       }
+}
+else
+       echo "<b>Could not connect to SQL database</b><br>\n";
+?>
index fda77a6..58d2261 100644 (file)
@@ -14,28 +14,33 @@ if ($config[sql_use_operators] == 'true'){
        $use_op = 0;
 }
 $group_exists = 'no';
-unset($item_vals);
-unset($tmp);
-unset($group_members);
 $link = @da_sql_pconnect($config);
 if ($link){
-       $res = @da_sql_query($link,$config,
-       "SELECT attribute,value $op FROM $config[sql_groupcheck_table] WHERE groupname = '$login';");
-       if ($res){
-               if (@da_sql_num_rows($res,$config))
-                       $group_exists = 'yes';
-               while(($row = @da_sql_fetch_array($res,$config))){
-                       $attr = $row[attribute];
-                       $val = $row[value];
-                       if ($use_op){
-                               $oper = $row[op];
-                               $tmp["$attr"][operator][]="$oper";
+       if ($login == ''){
+               unset($existing_groups);
+
+               $res = @da_sql_query($link,$config,
+               "SELECT COUNT(*) as counter,groupname FROM $config[sql_usergroup_table]
+               GROUP BY groupname;");
+               if ($res){
+                       while(($row = @da_sql_fetch_array($res,$config))){
+                               $name = $row[groupname];
+                               $existing_groups["$name"] = $row[counter];
                        }
-                       $tmp["$attr"][]="$val";
-                       $tmp["$attr"][count]++;
+                       if (isset($existing_groups))
+                               ksort($existing_groups);
                }
+               else
+                       echo "<b>Database query failed: " . da_sql_error($link,$config) . "</b><br>\n";
+       }
+       else{
+               unset($item_vals);
+               unset($tmp);
+               unset($group_members);
+               unset($existing_groups);
+
                $res = @da_sql_query($link,$config,
-               "SELECT attribute,value $op FROM $config[sql_groupreply_table] WHERE groupname = '$login';");
+               "SELECT attribute,value $op FROM $config[sql_groupcheck_table] WHERE groupname = '$login';");
                if ($res){
                        if (@da_sql_num_rows($res,$config))
                                $group_exists = 'yes';
@@ -46,45 +51,60 @@ if ($link){
                                        $oper = $row[op];
                                        $tmp["$attr"][operator][]="$oper";
                                }
-                               $tmp["$attr"][] = "$val";
+                               $tmp["$attr"][]="$val";
                                $tmp["$attr"][count]++;
                        }
-               }
-               else
-                       echo "<b>Database query failed partially: " . da_sql_error($link,$config) . "</b><br>\n";
-               $res = @da_sql_query($link,$config,
-               "SELECT username FROM $config[sql_usergroup_table] WHERE groupname = '$login' ORDER BY username;");
-               if ($res){
-                       if (@da_sql_num_rows($res,$config))
-                               $group_exists = 'yes';
-                       while(($row = @da_sql_fetch_array($res,$config))){
-                               $member = $row[username];
-                               $group_members[] = "$member";
+                       $res = @da_sql_query($link,$config,
+                       "SELECT attribute,value $op FROM $config[sql_groupreply_table] WHERE groupname = '$login';");
+                       if ($res){
+                               if (@da_sql_num_rows($res,$config))
+                                       $group_exists = 'yes';
+                               while(($row = @da_sql_fetch_array($res,$config))){
+                                       $attr = $row[attribute];
+                                       $val = $row[value];
+                                       if ($use_op){
+                                               $oper = $row[op];
+                                               $tmp["$attr"][operator][]="$oper";
+                                       }
+                                       $tmp["$attr"][] = "$val";
+                                       $tmp["$attr"][count]++;
+                               }
                        }
-               }       
-               else
-                       echo "<b>Database query failed partially: " . da_sql_error($link,$config) . "</b><br>\n";
-               if (isset($tmp)){
-                       foreach(array_keys($tmp) as $val){
-                               if ($val == '')
-                                       continue;
-                               $key = $rev_attrmap["$val"];
-                               if ($key == ''){
-                                       $key = $val;
-                                       $attrmap["$key"] = $val;
-                                       $attr_type["$key"] = 'replyItem';
-                                       $rev_attrmap["$val"] = $key;
+                       else
+                               echo "<b>Database query failed partially: " . da_sql_error($link,$config) . "</b><br>\n";
+                       $res = @da_sql_query($link,$config,
+                       "SELECT username FROM $config[sql_usergroup_table] WHERE groupname = '$login' ORDER BY username;");
+                       if ($res){
+                               if (@da_sql_num_rows($res,$config))
+                                       $group_exists = 'yes';
+                               while(($row = @da_sql_fetch_array($res,$config))){
+                                       $member = $row[username];
+                                       $group_members[] = "$member";
+                               }
+                       }       
+                       else
+                               echo "<b>Database query failed partially: " . da_sql_error($link,$config) . "</b><br>\n";
+                       if (isset($tmp)){
+                               foreach(array_keys($tmp) as $val){
+                                       if ($val == '')
+                                               continue;
+                                       $key = $rev_attrmap["$val"];
+                                       if ($key == ''){
+                                               $key = $val;
+                                               $attrmap["$key"] = $val;
+                                               $attr_type["$key"] = 'replyItem';
+                                               $rev_attrmap["$val"] = $key;
+                                       }
+                                       $item_vals["$key"] = $tmp[$val];
+                                       $item_vals["$key"][count] = $tmp[$val][count];
+                                       if ($use_op)
+                                               $item_vals["$key"][operator] = $tmp[$val][operator];
                                }
-                               $item_vals["$key"] = $tmp[$val];
-                               $item_vals["$key"][count] = $tmp[$val][count];
-                               if ($use_op)
-                                       $item_vals["$key"][operator] = $tmp[$val][operator];
                        }
                }
-
+               else
+                       echo "<b>Database query failed: " . da_sql_error($link,$config) . "</b><br>\n";
        }
-       else
-               echo "<b>Database query failed: " . da_sql_error($link,$config) . "</b><br>\n";
 }
 else
        echo "<b>Could not connect to SQL database</b><br>\n";
diff --git a/dialup_admin/lib/sql/nas_list.php3 b/dialup_admin/lib/sql/nas_list.php3
new file mode 100644 (file)
index 0000000..a7aa428
--- /dev/null
@@ -0,0 +1,62 @@
+<?php
+require('../conf/config.php3');
+require_once('../lib/functions.php3');
+
+unset($da_name_cache);
+if (isset($_SESSION['da_name_cache']))
+       $da_name_cache = $_SESSION['da_name_cache'];
+if ($config[sql_nas_table] != ''){
+
+       if (is_file("../lib/sql/drivers/$config[sql_type]/functions.php3"))
+               include_once("../lib/sql/drivers/$config[sql_type]/functions.php3");
+       else{
+               echo "<b>Could not include SQL library</b><br>\n";
+               exit();
+       }
+       $link = @da_sql_pconnect($config);
+       if ($link){
+               $auth_user = $_SERVER["PHP_AUTH_USER"];
+               $extra = '';
+               if (isset($mappings[$auth_user][nasdb])){
+                       $NAS_ARR = array();
+                       $NAS_ARR = split(',',$mappings[$auth_user][nasdb]);
+                       $extra = 'WHERE nasname IN (';
+                       foreach ($NAS_ARR as $nas)
+                               $extra .= "'$nasname',";        
+                       unset($NAS_ARR);
+                       $extra = rtrim($extra,",");
+                       $extra .= ')';  
+               }
+               $search = @da_sql_query($link,$config,
+               "SELECT * FROM $config[sql_nas_table] $extra;");
+               if ($search){
+                       while($row = @da_sql_fetch_array($search,$config)){
+                               $num = 0;
+                               $my_nas_name = $row['nasname'];
+                               if ($my_nas_name != ''){
+                                       $nas_list[$my_nas_name]['name'] = $my_nas_name;
+                                       $nas_server = $da_name_cache[$my_nas_name];
+                                       if (!isset($nas_server)){
+                                               if (!check_ip($my_nas_name))
+                                                       $nas_server = @gethostbyname($my_nas_name);
+                                               else
+                                                       $nas_server = $my_nas_name;
+                                               if (!isset($da_name_cache) && $config[general_use_session] == 'yes'){
+                                                       $da_name_cache[$my_nas_name] = $nas_server;
+                                                       session_register('da_name_cache');
+                                               }
+                                       }
+                                       if ($nas_server != $my_nas_name || check_ip($nas_server))
+                                               $nas_list[$my_nas_name]['ip'] = $nas_server;
+                                       $nas_list[$my_nas_name]['port_num'] = $row['ports'];
+                                       $nas_list[$my_nas_name]['community'] = $row['community'];
+                                       $nas_list[$my_nas_name]['model'] = $row['description'];
+                               }
+                       }
+               }
+       }
+       else
+               echo "<b>Could not connect to SQL database</b><br>\n";
+}
+
+?>
index a2f8f11..582d059 100644 (file)
@@ -12,15 +12,13 @@ if ($action == 'checkpass'){
        if ($link){
                $res = @da_sql_query($link,$config,
                        "SELECT attribute,value FROM $config[sql_check_table] WHERE username = '$login'
-                       AND (attribute = 'User-Password' OR attribute = 'Crypt-Password');");
+                       AND attribute = '$config[sql_password_attribute]';");
                if ($res){
                        $row = @da_sql_fetch_array($res,$config);
                        if (is_file("../lib/crypt/$config[general_encryption_method].php3")){
                                include("../lib/crypt/$config[general_encryption_method].php3");
                                $enc_passwd = $row[value];
-                               if ($row[attribute] == 'Crypt-Password') {
-                                       $passwd = da_encrypt($passwd,$enc_passwd);
-                               }
+                               $passwd = da_encrypt($passwd,$enc_passwd);
                                if ($passwd == $enc_passwd)
                                        $msg = '<font color=blue><b>YES It is that</b></font>';
                                else
diff --git a/dialup_admin/lib/xlat.php3 b/dialup_admin/lib/xlat.php3
new file mode 100644 (file)
index 0000000..ac282ee
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+function xlat($filter,$login,$config)
+{
+       $string = $filter;
+       if ($filter != ''){
+               $string = preg_replace('/%u/',$login,$string);
+               $string = preg_replace('/%U/',$_SERVER["PHP_AUTH_USER"],$string);
+               $string = preg_replace('/%ma/',$mappings[$http_user][accounting],$string);
+               $string = preg_replace('/%mu/',$mappings[$http_user][userdb],$string);
+               $string = preg_replace('/%mn/',$mappings[$http_user][nasdb],$string);
+               $string = preg_replace('/%mN/',$mappings[$http_user][nasadmin],$string);
+       }
+
+       return $string;
+}
+?>
similarity index 80%
rename from dialup_admin/sql/badusers.sql
rename to dialup_admin/sql/mysql/badusers.sql
index c5011b9..c8b5032 100644 (file)
@@ -4,7 +4,7 @@
 CREATE TABLE badusers (
   id int(10) DEFAULT '0' NOT NULL auto_increment,
   UserName varchar(30),
-  Date datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
+  IncidentDate datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
   Reason varchar(200),
   Admin varchar(30) DEFAULT '-',
   PRIMARY KEY (id),
similarity index 91%
rename from dialup_admin/sql/userinfo.sql
rename to dialup_admin/sql/mysql/userinfo.sql
index aacb4d2..ba9d721 100644 (file)
@@ -12,5 +12,5 @@ CREATE TABLE userinfo (
   Mobile varchar(200),
   PRIMARY KEY (id),
   KEY UserName (UserName),
-  KEY Departmet (Department)
+  KEY Department (Department)
 );
diff --git a/dialup_admin/sql/oracle/badusers.sql b/dialup_admin/sql/oracle/badusers.sql
new file mode 100644 (file)
index 0000000..06b0820
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * $Id$
+ *
+ */
+
+/*
+ * Table structure for table 'radcheck'
+ */
+
+CREATE TABLE badusers (
+       id              INT PRIMARY KEY,
+       username        VARCHAR(30) DEFAULT '' NOT NULL,
+       incidentdate    TIMESTAMP WITH TIME ZONE DEFAULT sysdate NOT NULL,
+       reason          VARCHAR(128) DEFAULT '' NOT NULL,
+       admin           VARCHAR(128) DEFAULT '-' NOT NULL
+);
+CREATE SEQUENCE badusers_seq START WITH 1 INCREMENT BY 1;
+CREATE INDEX badusers_incidentdate_idx ON badusers (incidentdate);
+CREATE INDEX badusers_username_idx ON badusers (username);
+
+/* Trigger to emulate a serial # on the primary key */
+CREATE OR REPLACE TRIGGER badusers_serialnumber
+        BEFORE INSERT OR UPDATE OF id ON badusers
+        FOR EACH ROW
+        BEGIN
+                if ( :new.id = 0 or :new.id is null ) then
+                        SELECT badusers_seq.nextval into :new.id from dual;
+                end if;
+        END;
+/
+
diff --git a/dialup_admin/sql/oracle/mtotacct.sql b/dialup_admin/sql/oracle/mtotacct.sql
new file mode 100644 (file)
index 0000000..b623ece
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * $Id$
+ *
+ */
+
+
+/*
+ * Table structure for table 'mtotacct'
+ */
+CREATE TABLE mtotacct (
+       mtotacctid      INT PRIMARY KEY,
+       username        varchar(64) DEFAULT '' NOT NULL,
+       acctdate        DATE DEFAULT sysdate NOT NULL,
+       connnum         NUMERIC(12),
+       conntotduration NUMERIC(12),
+       connmaxduration NUMERIC(12),
+       connminduration NUMERIC(12),
+       inputoctets     NUMERIC(12),
+       outputoctets    NUMERIC(12),
+       nasipaddress    varchar(15) default NULL
+);
+
+CREATE INDEX mtotacct_acctdate_idx ON mtotacct (acctdate);
+CREATE INDEX mtotacct_nasipaddress_idx ON mtotacct (nasipaddress);
+CREATE INDEX mtotacct_username_idx ON mtotacct (username);
+CREATE INDEX mtotacct_userondate_idx ON mtotacct (username, acctdate);
+
+CREATE SEQUENCE mtotacct_seq START WITH 1 INCREMENT BY 1;
+
+/* Trigger to emulate a serial # on the primary key */
+CREATE OR REPLACE TRIGGER mtotacct_serialnumber
+        BEFORE INSERT OR UPDATE OF mtotacctid ON mtotacct
+        FOR EACH ROW
+        BEGIN
+                if ( :new.mtotacctid = 0 or :new.mtotacctid is null ) then
+                        SELECT mtotacct_seq.nextval into :new.mtotacctid from dual;
+                end if;
+        END;
+/
+
diff --git a/dialup_admin/sql/oracle/totacct.sql b/dialup_admin/sql/oracle/totacct.sql
new file mode 100644 (file)
index 0000000..144c2f4
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * $Id$
+ *
+ */
+
+
+/*
+ * Table structure for table 'totacct'
+ */
+CREATE TABLE totacct (
+        totacctid      INT PRIMARY KEY,
+        username        varchar(64) DEFAULT '' NOT NULL,
+        acctdate        DATE DEFAULT sysdate NOT NULL,
+        connnum         NUMERIC(12),
+        conntotduration NUMERIC(12),
+        connmaxduration NUMERIC(12),
+        connminduration NUMERIC(12),
+        inputoctets     NUMERIC(12),
+        outputoctets    NUMERIC(12),
+        nasipaddress    varchar(15) default NULL
+);
+CREATE INDEX totacct_acctdate_idx ON totacct (acctdate);
+CREATE INDEX totacct_nasipaddress_idx ON totacct (nasipaddress);
+CREATE INDEX totacct_nasondate_idx ON totacct (acctdate, nasipaddress);
+CREATE INDEX totacct_username_idx ON totacct (username);
+CREATE INDEX totacct_userondate_idx ON totacct (username, acctdate);
+
+CREATE SEQUENCE totacct_seq START WITH 1 INCREMENT BY 1;
+
+/* Trigger to emulate a serial # on the primary key */
+CREATE OR REPLACE TRIGGER totacct_serialnumber
+        BEFORE INSERT OR UPDATE OF totacctid ON totacct
+        FOR EACH ROW
+        BEGIN
+                if ( :new.totacctid = 0 or :new.totacctid is null ) then
+                        SELECT totacct_seq.nextval into :new.totacctid from dual;
+                end if;
+        END;
+/
+
diff --git a/dialup_admin/sql/oracle/userinfo.sql b/dialup_admin/sql/oracle/userinfo.sql
new file mode 100644 (file)
index 0000000..7ecd6cc
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * $Id$
+ *
+ */
+
+/*
+ * Table structure for table 'userinfo'
+ */
+
+CREATE TABLE userinfo (
+       id              INT PRIMARY KEY,
+       username        VARCHAR(128) DEFAULT '' NOT NULL,
+       name            VARCHAR(128) DEFAULT '' NOT NULL,
+       mail            VARCHAR(128) DEFAULT '' NOT NULL,
+       department      VARCHAR(128) DEFAULT '' NOT NULL,
+       workphone       VARCHAR(128) DEFAULT '' NOT NULL,
+       homephone       VARCHAR(128) DEFAULT '' NOT NULL,
+       mobile          VARCHAR(128) DEFAULT '' NOT NULL 
+);
+CREATE INDEX userinfo_department_idx ON userinfo (department);
+CREATE INDEX userinfo_username_idx ON userinfo (username);
+CREATE SEQUENCE userinfo_seq START WITH 1 INCREMENT BY 1;
+
+
+/* Trigger to emulate a serial # on the primary key */
+CREATE OR REPLACE TRIGGER userinfo_serialnumber
+        BEFORE INSERT OR UPDATE OF id ON userinfo
+        FOR EACH ROW
+        BEGIN
+                if ( :new.id = 0 or :new.id is null ) then
+                        SELECT userinfo_seq.nextval into :new.id from dual;
+                end if;
+        END;
+/
diff --git a/dialup_admin/sql/postgresql/badusers.sql b/dialup_admin/sql/postgresql/badusers.sql
new file mode 100644 (file)
index 0000000..93e5ca0
--- /dev/null
@@ -0,0 +1,13 @@
+SET search_path = public, pg_catalog;
+
+--Table structure for table 'badusers'
+--
+CREATE TABLE badusers (
+    id BIGSERIAL PRIMARY KEY,
+    username TEXT NOT NULL,
+    incidentdate timestamp with time zone DEFAULT 'now' NOT NULL,
+    reason TEXT,
+    admin TEXT DEFAULT '-'
+);
+CREATE INDEX badusers_incidentdate_idx ON badusers USING btree (incidentdate);
+CREATE INDEX badusers_username_idx ON badusers USING btree (username);
diff --git a/dialup_admin/sql/postgresql/mtotacct.sql b/dialup_admin/sql/postgresql/mtotacct.sql
new file mode 100644 (file)
index 0000000..f8502e1
--- /dev/null
@@ -0,0 +1,23 @@
+SET search_path = public, pg_catalog;
+
+--
+-- Table structure for table 'mtotacct'
+--
+CREATE TABLE mtotacct (
+    mtotacctid BIGSERIAL PRIMARY KEY,
+    username TEXT DEFAULT '' NOT NULL,
+    acctdate DATE DEFAULT 'now' NOT NULL,
+    connnum BIGINT,
+    conntotduration BIGINT,
+    connmaxduration BIGINT,
+    connminduration BIGINT,
+    inputoctets BIGINT,
+    outputoctets BIGINT,
+    nasipaddress INET
+);
+CREATE INDEX mtotacct_acctdate_idx ON mtotacct USING btree (acctdate);
+CREATE INDEX mtotacct_nasipaddress_idx ON mtotacct USING btree
+(nasipaddress);
+CREATE INDEX mtotacct_username_idx ON mtotacct USING btree (username);
+CREATE INDEX mtotacct_userondate_idx ON mtotacct USING btree (username,
+acctdate);
diff --git a/dialup_admin/sql/postgresql/totacct.sql b/dialup_admin/sql/postgresql/totacct.sql
new file mode 100644 (file)
index 0000000..373aae4
--- /dev/null
@@ -0,0 +1,24 @@
+SET search_path = public, pg_catalog;
+
+--
+-- Table structure for table 'totacct'
+--
+CREATE TABLE totacct (
+    totacctid bigSERIAL PRIMARY KEY,
+    username TEXT DEFAULT '' NOT NULL,
+    acctdate DATE DEFAULT 'now' NOT NULL,
+    connnum BIGINT,
+    conntotduration BIGINT,
+    connmaxduration BIGINT,
+    connminduration BIGINT,
+    inputoctets BIGINT,
+    outputoctets BIGINT,
+    nasipaddress INET
+);
+CREATE INDEX totacct_acctdate_idx ON totacct USING btree (acctdate);
+CREATE INDEX totacct_nasipaddress_idx ON totacct USING btree (nasipaddress);
+CREATE INDEX totacct_nasondate_idx ON totacct USING btree (acctdate,
+nasipaddress);
+CREATE INDEX totacct_username_idx ON totacct USING btree (username);
+CREATE INDEX totacct_userondate_idx ON totacct USING btree (username,
+acctdate);
diff --git a/dialup_admin/sql/postgresql/userinfo.sql b/dialup_admin/sql/postgresql/userinfo.sql
new file mode 100644 (file)
index 0000000..644bc95
--- /dev/null
@@ -0,0 +1,19 @@
+SET search_path = public, pg_catalog;
+
+--
+-- Table structure for table 'userinfo'
+--
+CREATE TABLE userinfo (
+    id SERIAL PRIMARY KEY,
+    username TEXT,
+    name TEXT,
+    mail TEXT,
+    department TEXT,
+    workphone TEXT,
+    homephone TEXT,
+    mobile TEXT
+);
+CREATE INDEX userinfo_department_idx ON userinfo USING btree (department);
+CREATE INDEX userinfo_username_idx ON userinfo USING btree (username);
+
+
index 6ac510c..b0a807d 100644 (file)
-FreeRADIUS 1.1.5 ; Date: 2007/03/05 13:13:43  , urgency=low
-       Feature improvements
-       * Added more dictionaries
-       * Dictionary files now MUST NOT be globally writable.
-       * Configuration files now MUST NOT be globally readable,
-         or globally writable.
-       * Be more aggressive about freeing memory on clean exit.
-         This helps track down run-time leaks.
-       * Updated rlm_python to something usable
-       * Added experimental sql "HPW" IPPools.
-
-       Bug fixes
-       * Corrected base64 decoding in rlm_pap
-       * Don't retransmit accounting packets.  The NAS should do this.
-       * Handle Client-Error in EAP-SIM.  This closes #419
-       * Port OpenSSL locking fixes from CVS head.  This makes PEAP
-         more stable on some systems.
-       * Require Message-Authenticator in Status-Server packets
-       * Correct Tunnel-Medium-Type VALUEs in dictionary.rfc2868
-       * Be more aggressibe about freeing memory on clean exit.
-         This isn't strictly a bug fix, but it makes it easier to
-         find memory leaks
-       * Increase buffer size for dynamic expansion, which allows
-         longer SQL qeuries.  (close: #405)
-       * Use correct line number when there's a parse error in one
-         of the configuration sections. (close #421)
-       * Terminate SSL sessions in EAP on error, rather than continuing
-         in some cases.
-       * Increase buffer size to allow parsing of long octet strings
-       * Fix string termination on xlat in rlm_perl
-
-FreeRADIUS 1.1.4 ; Date: 2007/01/14 00:37:15 , urgency=medium
-
-       Feature improvements
-       * Major enhancements to rlm_pap, that make "encryption_scheme"
-         a thing of the past.  See "man rlm_pap" for details.
-       * Added SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS flag to use
-         work-arounds that enable Windows Vista clients to work.
-       * Added preliminary code to support Firebird. (closes: #378)
-         Use at your own risk!
-       * Send MS-CHAP2-Success, which makes EAP-TTLS/MSCHAP work on more
-         platforms.  (closes: #402)
-       * Add a new "reply-name" directive in rlm_sqlcounter to define the
-         name of the reply attribute. (closes: #403)
-       * Added more dictionaries and attributes (closes: #408, among others)
-       * Print ntlm_auth failure reason in Module-Failure-Message
-         (closes: #398)
-       * radsqlrelay is able to get the DB password from a file instead
-         of command line. (closes: #395)
-
-       Bug fixes
-       * Fix a parse error in the digest module, where malformed
-         digest requests would result in the user being accepted.  Oops...
-       * VALUEs can only be defined for 'integer', to catch mistakes
-         with setting VALUEs for type 'string'.
-       * Better parsing of VALUE names, so that values starting with
-         a digit work correctly.
-       * Check return from malloc (closes: #407)
-       * Fix a double free() in rlm_eap_tls.c (closes: #404)
-       * Check return code of malloc() during initialization. (closes: #407)
-       * Fix a corner case where the proxy port isn't set either in
-         radiusd.conf or in proxy.conf.
-
-FreeRADIUS 1.1.3 ; Date: 2006/08/22 23:09:20, urgency=low
-
-       Feature improvements
-       * rlm_otp now talks to otpd for OTP verification, rather than
-         doing the work itself; this improves portability and security
-         (access to OTP token keys is now much more limited)
-       * More dictionary updates
-       * Added Oracle support to radsqlrelay
-       * Added experimental module sql_ippool.  See doc/rlm_sqlippool
-
-       Bug fixes
-       * Allow rlm_dbm to load empty check items (Bug #380)
-       * Better handling of Framed-MTU in EAP-TLS (Bug #383)
-       * Handle Access-Challenge verification properly
-       * Fixed configure/make error for Solaris (set HAVE_CLOSEFROM).
-       * Update libtool and ltdl to 1.5.22, to fix 'make install R=';
-         also improve integration by importing unmodified original
-         source (except a small patch to ltdl)
-
-FreeRADIUS 1.1.2 ; Date: 2006/06/23 04:57:51 , urgency=low
-
-       Feature improvements
-       * Allow tagged VSA's for Juniper.  Closes bugs #367 and #368.
-       * Allow Ascend "abinary" format to be specified as octets,
-        (e.g. Ascend-Data-Filter = 0x010203...)
-       * Added "cipher_list" configuration to the EAP-TLS module.
-         See "eap.conf" and "man 1 cipher" for details.
-       * Added "check_cert_issuer" configuration to the EAP-TLS module.
-         See "eap.conf" for details. (closes: #346)
-       * Added "suppress" configuration entry to rlm_detail,
-         to suppress certain attributes (e.g. User-Password).
-         This closes bug #359.
-       * More dictionary updates
-       * Write SSL errors to log file, rather than stderr.
-         This closes bug #347.
-       * Allow a core dump on uid change on Linux (closes: #361)
-
-       Bug fixes
-       * Return better error codes in SQL IODBC module.  Closes bug #341.
-       * Corrected list of EAP handlers.
-       * Initialize variable in rlm_ldap.c.  This fixes RedHat
-         bug #136468.
-       * Escape more ldap strings, so configuration entries
-         that have magic LDAP characters don't break LDAP.
-         This closes bug #360.
-       * Updated doc/rlm_ldap.  This closes bug #353.
-       * Updated redhat/freeradius.spec.  This closes bug #330.
-       * Don't forcibly over-write Auth-Type in the mschap module.
-         This prevents an earlier module from forcing reject.
-       * Use the correct module reference in the authenticate section,
-         where Auth-Type wasn't explicitely specified.
-       * If there are typos in a subsection in radiusd.conf, exit
-         after printing an error, rather than continuing.
-       * Print Ascend "abinary" format as text rather than octets
-         when we receive it.
-       * Silently drop packets with bad Message-Authenticators, as per RFC3579
-       * Unbreak ./configure --disable-static (closes: #350)
-       * Unbreak ./configure --prefix (closes: #354)
-
-FreeRADIUS 1.1.1 ; Date: 2006/03/17 19:50:34, urgency=low
-
-       Security fixes
-       * Additional state checking in the EAP-MSCHAPv2 module.
-         Bug found by Steffen Schuster.
-       
-       Feature improvements
-       * More dictionary updates
-       * Additional tests and fixes for Digest module from Phillipe Sultan.
-       * Add new "phone" response mode to rlm_otp/cryptocard.
-       * Put the eap sessions into a tree, so that looking them up is very
-         fast, and no longer O(n) in the number of sessions.
-       * Install the schema examples for a set of backends with the rest
-         of the documentation.
-       * Add support for xlat expansion of attributes from LDAP.
-
-       Bug fixes
-       * Fix rlm_perl crash. (closes: #348)
-       * Fix handling of CoA-Request packets (close #344).  Also correct
-         name of CoA packets.
-       * Fix an error on x86_64 machines when reading dictionaries.
-         (closes: #312)
-       * Fix compilation errors on FreeBSD and NetBSD because of rlm_otp
-         module. (closes: #314 #328)
-       * Workaround Cisco bug in State attribute handling in rlm_otp.
-       * Support LP64 for async mode in rlm_otp.
-       * Fix libtool problems on Debian with rlm_eap_peap and rlm_eap_ttls
-         modules. (closes: #75)
-       * Make "use_tunneled_reply" work properly for PEAP.
-       * Copy the whole string when getting a one-to-one-mapped attribute
-         from LDAP (closes: #261)
-       * Fix net-snmp's ucd-snmp compatibility mode.
-
-FreeRADIUS 1.1.0 ; Date: 2006/01/04 05:55:19, urgency=low
-
-       Feature improvements
-       * rlm_ldap has "set_auth_type" configuration option, which should
-         address some configuration problems when using it.
-       * Fix MIT Kerberos bug
-       * Modules can be load balanced, both in isolation and redundantly.
-         See doc/load-balance.txt for more information.
-       * rlm_perl is now marked "stable"
-       * N-tier certificate patch from Mohammed Petiwala.
-       * Copied dictionaries from the CVS head (many, many, more vendors)
-       * Enabled support for weird VSA formats, like Lucent and Starent.
-       * Support encrypted IP address and integers, for Juniper clients.
-       * Add PEAP machine authentication support in module "rlm_mschap".
-       * Support User-Password field encryption in digest mode.
-       * rlm_x99_token has become rlm_otp (with lots of changes).
-       * Add rlm_sqlcounter to the list of stable modules.
-       * Read MySQL specific options in sections [freeradius] and [client]
-         from file "my.cnf".
-       * Support the ${Cisco-AVPair[n]} syntax.
-       * Execute modules in {Pre,Post}-Proxy-Type stanzas.
-       * Add new options to radclient to run stress tests on the server.
-       * New module "rlm_sql_log" to postpone the storage of accounting data
-         in a SQL database. See rlm_sql_log(5) manpage.
-       * New program "radsqlrelay" which sends the SQL logfile according to
-         the SQL server's capabilities.
-
-       Bug fixes
-       * #306 (HUP when built with threads, but executed with -s)
-       * #285 (more attributes in dictionary.cisco.vpn3000)
-       * rlm_digest has a number of bug fixes to authentication types.
-       * Don't leak memory in module "rlm_sql".
-       * Update the dictionaries, so that VALUEs with the same name,
-         but different numbers, aren't allowed.
-       * Queue the request before looking for available threads.
-       * Don't free the check items after we received the proxy reply.
-       * Expand config variables in included files, too.
-       * Check the return value of accounting modules and don't proxy
-         invalid requests.
-       * In rlm_passwd, don't close a file stream more than once.
-       * Fix format string errors in rlm_sql.c, spotted by Primoz Bratanic.
-       * Walk the whole string in when escaping strings in rlm_ldap.
-       * Include crypt.h if it is available so we get a prototype for crypt(),
-         spotted by Konstantin Kubatkin.
-       * Removed (for almost all uses) length restrictions on vendor names
-         and VALUE names.
-       * Don't leak memory when proxying an Access-Challenge response.
-       * Make the sleep time user-defined, so radrelay can send more than
-         7 requests/s.
-       * Fix a memory leak in rlm_checkval.
-       * radclient doesn't resend countless times packets with invalid
-         signature.
-       * Fix segfault and mem leak in rlm_pam.
-
-FreeRADIUS 1.0.5 ; Date: 2005/09/04 16:23:00, urgency=medium
-
-       Security Fixes
-       * SQL injection attack in the module "rlm_sqlcounter".
-       * Buffer overflows in the module "rlm_sqlcounter".
-       * Expansion of variable %t may write 26 bytes beyond the buffer
-         bound. Primoz Bratanic is credited with the discovery of these
-         three bugs.
-
-       Bug fixes
-       * Don't de-reference a NULL pointer if the auth-type is unknown
-         in the function rad_check_password().
-       * Escape more characters in the LDAP queries.
-         Bug found by Suse engineers.
-       * In rlm_sql_unixodbc, don't call rad_malloc from sql_error(),
-         it leaks memory.
-       * Fix an off-by-one error in the module rlm_sql_unixodbc.
-         Bug found by Suse engineers.
-       * In rlm_sql, resize the buffer for the value of SQL-User-Name.
-       * Initialize memory for a new SQL socket in the module rlm_sql.
-       * Don't add too many attributes after running an external program.
-         Bug found by Suse engineers.
-       * Fix an off-by-one error in the function getthing().
-       * snprintf() and vsnprintf() replacements were not compiled if
-         the autoconf tests didn't find the functions.
-       * Don't use vsprintf() anymore, but the replacement for vsnprintf()
-         in libradius instead.
-       * The function decode_attribute() may write beyond buffer bounds.
-         Bug found by Suse engineers.
-       * Fix a memset() in the function request_enqueue() which was
-         begining at the wrong address. Bug found by Matthias Ruttman.
-       * Fix an off-by-one error in the function xlat_copy().
-         Bug found by Primoz Bratanic.
-       * Fix other off-by-one errors in module "rlm_unix", too.
-         Bug found by Allan Bazinet.
-       * Fix a 2-byte over-run read in function rad_decode().
-       * Update thread pool queue properly.
-       * Autonconf tests try first any user-specified directory,
-         otherwise they may pick up the wrong version.
-       * Delete the autoconf tests for the libldap dependancies.
-       * Install all the regular files under the "doc" directory.
-       * Distinguish between exit code <0 (failure) and >0 (reject)
-         in Exec-Program-Wait. Patch from Thor Spruyt.
-       * Make Expiration work.
-       * Clean up the code for opening a proxy socket.
-       * When finding a realm to proxy to, if all are dead, wake them
-         if wake_all_if_all_dead is true.
-       * In radwho, print the NAS-Port as unsigned int.
-       * Use extended regex instead of basic regex in rlm_attr_filter.
-       * Catch the case where someone deletes a directory that rlm_detail
-         is using.
-       * Use the variable $(LDFLAGS) when linking a module.
-       * Ignore the Stripped-User-Name when a realm has the "nostrip"
-         directive.
-       * Add support for NT-Password in rlm_pap.
-       * In rlm_sqlcounter, use the time left to the next reset if it's
-         inferior to the time left in the counter.
-       * Calculate Message-Authenticator correctly for Accounting-Request
-         and Accounting-Response.  Bug found by Paolo Rotela.
-       * Build on MAC OS X.  Still need --disable-shared, though.
-       * Fix bug #255 (crash with expired CRL's, etc.)
-       * Fix quote removal of the values from a SQL database.
-       * Reap the zombie process after a command run from "Exec-Program".
-       * Allow to cancel proxy of accounting with "Proxy-To-Realm := LOCAL".
-       * Don't copy VSA's to an Access-Reject packet.
-
-FreeRADIUS 1.0.4 ; Date: 2005/06/11 22:46:52, urgency=medium
-
-       * Fix installation problem.
-       * Increase a buffer size, so radrelay doesn't truncate values.
-       * Updates in the documentation. Patches from Thor Spruyt.
-
-FreeRADIUS 1.0.3 ; Date: 2005/06/03 17:15:11, urgency=high
-
-       Security Fixes
-       * Always escape the strings in the SQL module.
-       * Check buffer bound when input character needs escaping in
-         the SQL module. Bug found by Primoz Bratanic.
-
-       Bug fixes
-       * Return EAP-Fail in Access-Reject, rather than an empty Access-Reject
-       * Don't send Proxy-State from home server in TTLS.
-       * Fixes for forking external programs, so the server doesn't
-         suddenly stop processing requests, or stop forking programs.
-       * radzap now works, but it's command-line options have changed
-         completely, and it's a shell script.
-       * radwho has updated command-line options, and no longer reads
-         Unix "utmp" files.
+FreeRADIUS 2.0.0 ; $Date$, urgency=low
+       * Remove 'delete_blocked_requests' option.
+       * Fix fd leak in rlm_otp.
+       * Use Cleartext-Password for "known good" password in config items,
+         rather than "User-Password".  This should solve a lot of problems.
+       * Define Password-With-Header for LDAP-style "{crypt}...." passwords,
+         to avoid overloading User-Password.
+       * Permit per-socket list of clients in "listen" directives
+       * Faster client lookups, to permit scaling to 10^6 or more clients.
+       * Removed radrelay and radsqlrelay.  See "man radrelay.conf" for
+         details.
+       * Full IPv6 support.  The server can listen on IPv6 sockets,
+         and send/receive IPv6 packets.
+       * rlm_ns_mta_md5 is deprecated.  rlm_pap does everything it does,
+         and more.
+       * The command-line options "-i ipaddr" and "-p port" now work.
+       * rlm_unix no longer reads /etc/passwd (etc.) directly.  See
+         "man rlm_unix" for details.  Also see the "authorize" section
+          of "radiusd.conf".
+       * Configuration files now use binary trees, which means that
+         arbitrary amounts of information can be stored in them.
+       * Fixed xlat's for %{config:...}.  Dynamic expanstion now works
+         better, so %{config:section.subsection.%{User-Name}.item" works,
+         even if the User-Name contains periods.  This is a cheap way
+         of getting in-memory databases, as anything can be put into
+         the configuration files.
+       * Fix locking issues for radrelay.
+       * Add radsqlrelay, which works like radrelay, but reads data
+         from an SQL database.
+       * rlm_ldap now auto-discovers password headers.  See the "ldap"
+         subsection of "modules", in "radiusd.conf" for details.
+       * rlm_pap now auto-discovers password encryption/hash methods.
+         See "man rlm_pap" and the "authorize" section of "radiusd.conf".
+       * Don't call exit() if module instantiation files.
+       * "virtual" modules can now be used.  See the last bit of the
+         "instantiate" section in "radiusd.conf".
+       * Fix problems with Exec-Program-Wait & forking issues.
+       * Configuration files can now "$INCLUDE directory/", to automatically
+         load all files in that directory.  Use with caution!
+       * Fix for log_dest = stdout/stderr.
+       * New "policy" module, which has none of the limitations of the
+         "users" file.  See "man rlm_policy" for details.
+       * rlm_sql can now behave more like the "users" file.
+       * New rlm_caching module.
+       * Now uses autoconf 2.5x, and the various associated tools.
+       * Include ucd-snmp-config.h, fixing use of net-snmp's
+         ucd-snmp backwards compatibility mode.
+       * Modules can now be load-balanced.  See "doc/configurable_failover"
+       * Move the Login-Time,Current-Time,Expiration attribute handling
+         to new modules  rlm_logintime and rlm_expiration.
+       * Added %{mschap:NT-Hash <passwd>} and %{mschap: LM-Hash <passwd>},
+         and update rlm_pap to handle NT/LM-hashed passwords.
+       * New rlm_protocol_filter, which permits/denies requests containing
+         certain attributes.
+       * Don't escape printed strings during xlat's, to avoid the
+         infinite expansion of backslashes..
+       * Add Message-Authenticator to rlm_digest sample.
+       * Correct handling of post-auth REJECT stanza to include externally and
+         proxy-received rejections. (Bugzilla bug #149)
+       * Fix building SNMP support on Solaris 9, which needs -lkstat
        * Fix bug in calling checkrad script with NAS port > 9999999
        * Fix long-standing bug when both crypt and pthreads are in use
-       * Don't SEGV when rlm_sql gets 'NULL' value from request.
-       * Re-arrange code in radrelay to not duplicate accounting packets.
-       * In rlm_attr_rewrite, change the value when the attribute type
-         is different from string.
-
-FreeRADIUS 1.0.2 ; Date: 2005/02/13 01:03:20, urgency=medium
-
-       * Novell eDirectoty support.  Patch from Novell.
-       * localweb & Trapeze dictionary updates.
-       * EAP-SIM fixes.
-       * Make "Strip-User-Name = No" work.
-       * Don't declare zero-length arrays in rlm_passwd
-       * Bug fix to make udpfromto code work
-       * radrelay shouldn't dump core if it can't read a VP from the
-         detail file.
-       * Only initialize the random pool once.
-       * In rlm_sql, don't escape characters twice.
-       * Fix MD4 calculation on big-endian machines.
-       * In rlm_ldap, only claim Auth-Type if a plain text password is present.
-       * Treat Quintium VSAs like Cisco VSAs
-       * Locking fixes in threading code
-       * rlm_krb5 includes /usr/include/et for Fedora Core
-       * Fix post-auth REJECT stanza processing for rejections from external
-         processes or home RADIUS servers
-       * Fix building on gcc-4.0 by not trying to access static auth_port from
-         other files.
-       * Fix building SNMP support on Solaris 9, which needs -lkstat
-
-FreeRADIUS 1.0.1 ; Date: 2004/09/02 10:52:03 , urgency=high
 
+FreeRADIUS 1.0.1 ; Date: 2004/09/02 10:52:03, urgency=high
        Denial-of-Service Security Fix
        * Fix two remote crashes and a memory leak in RADIUS packet
          decoding.
 
-       Bug fixes
+       Bug fixes.
        * Fix premature "success" during EAP/TLS handshake.
        * Dictionary handling now complains about identically named
          values with different values, and rejects dictionary
@@ -339,11 +74,10 @@ FreeRADIUS 1.0.1 ; Date: 2004/09/02 10:52:03 , urgency=high
        * Update dictionaries to deal with the above change.
 
 FreeRADIUS 1.0.0 ; Date: 2004/07/17 06:31:32, urgency=low
-
        pre3 -> release
        * Fix LDAP dictionary map loading.
-       * Check login time allowance to packet timestampe where available.
-       * Compilation fix for machines withouth <pthread.h>.
+       * Check login time allowance to packet timestamp where available.
+       * Compilation fix for machines without <pthread.h>.
        * Man page improvements.
        * Grab latest config.sub and config.guess (2004-03-12).
 
@@ -700,7 +434,7 @@ FreeRADIUS 0.8 ; Date: 2002/11/18 15:37:24, urgency=low
          garbage it previously showed.
        * Cleaned up header files and function prototypes for the SQL
          sub-modules.
-
+       
 FreeRADIUS 0.7 ; Date: 2002/07/26 18:01:50 , urgency=high
 
        * Allow attributes of type 'date' to be sent in outgoing packets.
@@ -825,7 +559,7 @@ FreeRADIUS 0.6.0 ; Date: Date: 2002/07/03 14:16:33 , urgency=high
          'make install'
        * Fixed EAP module to use 16-bit integers, so that it will
          work on big-endian architectures.
-
+       
 FreeRADIUS 0.5.0 ; Date: 2002/03/14 22:18:22, urgency=medium
 
        * Many bug fixes.  For explicit details, see:
@@ -967,7 +701,7 @@ FreeRADIUS 0.3.0 ; urgency=low
        * Added support for Exec-Program to acct.  Bug found by
          <magmike@mail.ru>
        * Corrected rlm_files so that raddb/acct_users works
-       * When doing synchronous proxying, update proxy next try
+        * When doing synchronous proxying, update proxy next try
          entries, so that the server doesn't eat CPU time.
          Raghu <raghud@hereuare.com>
        * Add primitive dictionary.nomadix <CBoyd@apogeetelecom.com>
index 1ef0238..07e36c3 100644 (file)
--- a/doc/DIFFS
+++ b/doc/DIFFS
@@ -68,7 +68,7 @@ SECTION 1 - CREATING AND SENDING YOUR CHANGE
    4. Select e-mail destination. 
 
       If you are on the developers mailing list, send the patch there.
-      freeradius-devel@info.cistron.nl
+      freeradius-devel@lists.freeradius.org
 
       Otherwise, send the patch to 'patches@freeradius.org'
 
index ac1dee2..68f4898 100644 (file)
@@ -19,7 +19,7 @@ O.INTRODUCTION
 
 2.EXAMPLES
 
-  In the example below, when a request has been rejected, the
+  In the example below, when a request has been rejected, the 
   module my_ippool will not be run, only the module my_detail
   will be run.
   If the request is not rejected, the my_ippool module will be
@@ -41,3 +41,4 @@ O.INTRODUCTION
           my_sql_reject
       }
   }
+
index a722486..b3ea175 100644 (file)
@@ -11,10 +11,10 @@ RADIUS-SQL.schema
  
   There isn't a generic SQL schema, but there is one for some databases:
 
-    src/modules/rlm_sql/drivers/rlm_sql_mysql/db_mysql.sql
-    src/modules/rlm_sql/drivers/rlm_sql_postgresql/db_postgresql.sql
-    src/modules/rlm_sql/drivers/rlm_sql_freetds/db_mssql.sql
-    src/modules/rlm_sql/drivers/rlm_sql_oracle/db_oracle.sql
+    doc/examples/mysql.sql
+    doc/examples/postgresql.sql
+    doc/examples/mssql.sql
+    doc/examples/oracle.sql
 
 2.MYSQL
 
@@ -33,3 +33,4 @@ RADIUS-SQL.schema
   A good page for MySQL best practices is:
 
     http://www.onlamp.com/pub/a/onlamp/2002/07/11/MySQLtips.html
+
index 1232ad2..4df784e 100644 (file)
   ----                 ----            ------
   Simultaneous-Use     integer         Max. number of concurrent logins
   Fall-Through         integer         Yes/No
-  Exec-Program         string          program to execute after authentication
-  Exec-Program-Wait    string          ditto, but wait for program to finish
-                                       before sending back auth. reply
   Login-Time           string          Defines when user may login.
   Current-Time         string          Allows you to perform time-based
                                        checks when a request is received.
 
-  Exec-Program can take arguments. You can use variables in the
-  arguments, which are automatically expanded by the server.  See
-  'doc/variables.txt' for more information.
-
-  For example, use the following entry for someone who has BSMTP (queued
-  SMTP) service. "brunq" is the program that runs the SMTP queue.
-
-  robert       Service-Type = Framed-User
-               Exec-Program = "/usr/local/sbin/brunq -h %f delta",
-               Fall-Through = 1
-
-  The output from Exec-Program-Wait is parsed by the radius server. If
-  it looks like Attribute/Value pairs, they are decoded and added to the
-  reply sent to the NAS. This way, you can for example set Session-Timeout.
-
-  If Exec-Program-Wait returns a non-zero exit status, access will be
-  denied to the user. With a zero-exit status, access is granted.
-
   Login-Time defines the time span a user may login to the system. The
   format of a so-called time string is like the format used by UUCP.
   A time string may be a list of simple time strings separated by "|" or ",".
index 66bccd7..90702cf 100644 (file)
@@ -38,7 +38,7 @@ o Enable VSA's on the Ascend/Lucent MAX:
 
 o Enable OLD attributes in FreeRADIUS
 
-  One note on this, cicsos have an Ascend compatability mode that
+  One note on this, Ciscos have an Ascend compatibility mode that
   accepts only the OLD style Ascend attributes, just to make life more
   interesting.  :)
 
index 313b43d..5e5130e 100644 (file)
@@ -62,8 +62,8 @@ server to process the second module if the first one fails.  Any
 number of modules can be listed in a "redundant" section.  The server
 will process each in turn, until one of the modules succeeds.  It willthen stop processing the "redundant" list.
 
-  Rewriting results for single modules
-  ------------------------------------
+1. Rewriting results for single modules
+   ------------------------------------
 
   Normally, when a module fails, the entire section ("authorize",
 "accounting", etc.) stops being processed.  In some cases, we may want
@@ -100,8 +100,8 @@ with priority "1".  The normal configuration is "fail = return", which
 means "if the detail module fails, stop processing the accounting
 section".
 
-  Fail-over configuration entries
-  -------------------------------
+2. Fail-over configuration entries
+   -------------------------------
 
   Modules normally return on of the following codes as their result:
 
@@ -122,6 +122,10 @@ listed, with a value.  If the code is not listed, or a configurable
 fail-over section is not defined, then values that make sense for the
 requested "group" (group, redundant, load-balance, etc) are used.
 
+  The special code "default" can be used to set all return codes to
+the specified value.  This value will be used with a lower priority
+than ones that are explicitly set.
+
   The values for each code may be one of two things:
 
        Value           Meaning
@@ -142,8 +146,8 @@ modules will be "ok", because it has higher priority than "fail".
 to fail, so long as a later module succeeds.
 
 
-  More Complex Configurations
-  ---------------------------
+3. More Complex Configurations
+   ---------------------------
 
   The "authorize" section is normally a list of module names.  We can
 create sub-lists by using the section name "group".  The "redundant"
@@ -197,8 +201,120 @@ return code found by processing the list.
 "group" section.
 
 
-  The Gory Details
-  ----------------
+4. More Complex Configuration using "if" and "else"
+   ------------------------------------------------
+
+  As of version 2.0, the server allows "if"-style checking in the
+configuration sections.  The section is still processed as a list, so
+there is no looping or "goto" support.  But by using "if", the
+administrator can have branching paths of execution, where none was
+possible before.
+
+  For example, the following configuration says "run sql, if it
+returns notfound, run ldap1, else run ldap2".
+
+  authorize {
+       ...
+       sql
+       if notfound {
+               ldap1
+       }
+       else {
+               ldap2
+       }
+
+  Note that the parser is easily confused.  The words "if" and "else"
+MUST be the first entry on the line.  Using statements like "} else {"
+is forbidden, and will prevent the server from starting.  Putting
+brackets around the condition like "if (notfound)" won't work, either.
+
+  If you want to specify multiple conditions, put them in double
+quotes, and separate the conditions by a single '|' character, as
+follows:
+
+       if "notfound | ok | fail" {
+               ...
+       }
+
+  The reason for these limitations is that the "if" conditions are
+overloading module names, and therefore have to follow a similar
+syntax.  These limitations may be removed in a future release.
+
+  The conditions that can be checked are the names listed in section
+2, above.  Any other condition is not permitted.
+
+  
+  You can also use "elsif", as follows:
+
+       if notfound {
+               ldap1
+       }
+       elsif fail {
+               ldap2
+       }
+       else {
+               ldap3
+       }
+
+  Note that the condition being checked is the return code of the last
+module or group that was executed.  This may sometimes have odd
+side-effects:
+
+       sql
+       if notfound {
+               ldap1
+       }
+       if fail {
+               ldap2
+       }
+
+  In this case, the "ldap2" module will be executed if the "sql"
+modules returns "fail", OR if the "sql" module returns "notfound", and
+the "ldap2" module returns "fail".  For this reason, you should
+probably use "elsif" whenever you have two "if" statements right after
+one another.
+
+  The "if" checks can be nested to a depth of 30 or so, which should
+be sufficient for most configurations.
+
+
+5. Virtual Modules
+   ---------------
+
+  Some configurations may require using the same list of modules, in
+the same order, in multiple sections.  For those systems, the
+configuration can be simplified through the use of "virtual" modules.
+These modules are configured as named sub-sections of the
+"instantiate" section, as follows:
+
+       instantiate {
+               ...
+
+               redundant sql1_or_2 {
+                       sql1
+                       sql2
+               }
+       }
+
+  The name "sql1_or_2" can then be used in any other section, such as
+"authorize" or "accounting".  The result will be *exactly* as if that
+section was placed at the location of the "sql1_or_2" reference.
+
+  These virtual modules are full-fledged objects in and of themselves.
+One virtual module can refer to another virtual module, and they can
+contain "if" conditions, or any other configuration permitted in a
+section.
+
+
+7. Redundancy and Load-Balancing
+   -----------------------------
+
+  See doc/load-balance.txt for information on simple redundancy
+(fail-over) and load balancing.
+
+
+6. The Gory Details
+   ----------------
 
 The fundamental object is called a MODCALLABLE, because it is something that
 can be passed a specific radius request and returns one of the RLM_MODULE_*
@@ -272,6 +388,33 @@ authorize{...} GROUP as a whole returns RLM_MODULE_NOOP, which makes sense
 because to say the user was not found at all would be a lie, since preprocess
 apparently found him, or else it would have returned RLM_MODULE_NOTFOUND too.
 
+We could use the "default" code to simplify the above example a
+little.  The following two configurations are identical:
+
+...
+  files {
+    notfound = 1
+    noop     = 2
+    ok       = 3
+    updated  = 4
+    default  = return
+  }
+...
+
+When putting the "default" first, later definitions over-ride it's
+return code:
+
+...
+  files {
+    default  = return
+    notfound = 1
+    noop     = 2
+    ok       = 3
+    updated  = 4
+  }
+...
+
+
 [Take a deep breath - the worst is over]
 
 That RESULT preference/desirability stuff is pretty complex, but my hope is
diff --git a/doc/duplicate-users b/doc/duplicate-users
deleted file mode 100644 (file)
index 7b9338e..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-
-User Collision in FreeRadius
-----------------------------
-
-0.  INTRODUCTION
-
-    A.  What is it?
-
-        User collision is the ability to uniquely authenticate duplicate
-        usernames in radius. In addition, it provides resources to
-        correctly identify each duplicate user in the accounting logs.
-
-    B.  Who needs it and why?
-
-        Many ISPs are acquiring other ISPs in local or remote areas.  This
-        causes problems with centralizing services such as radius because
-        of the overlap in usernames between ISPs.
-
-        For example:
-
-        o  ISP A (with 10,000 users) acquires ISP B (with 1,000 users).
-        o  ISP A determines that 375 of ISP B's 1,000 usernames conflict
-           with usernames already in use at ISP A (eg 'foo' is valid
-           username on both ISPs)
-        o  ISP A, therefore, cannot merge its user files with ISP B and
-           centralize radius
-
-        Now, about now, many of you are thinking, "what about realms?"  
-        Well, realms are great, but, in general, it will require the end
-        user to add "@domain.com", which is a pain. It means ISP A has to
-        call 375 people and tell them to add that to their login name.
-
-        And now some of you are thinking, "why couldn't you add the realm
-        in the server based on some other attribute (such as NAS-IP or
-        Calling-Station)?"  The answer is, you could, but both of those
-        solutions are a pill to maintain.  For example, what if you want
-        to merge the huntgroups (and NASs) of ISP A and ISP B?  Then the
-        NAS-IP method falls apart.  And god forbid the user call from a
-        different number or change their line for Calling-Station.
-
-        So how to solve it?  Enter user collision code in radius...
-
-    C.  How does it work?
-
-        Currently, it only works when authenticating users via the
-        following methods in FreeRadius:
-
-        o  'users' file ( Auth-Types 'Local' and 'Crypt-Local' _ONLY_ )
-        o  cached password (and shadow) file users
-                               o  rlm_fastusers module (see README.rlm_fastusers)
-
-        That's it so far.  Perhaps other module authors will include it in
-        their code later, but that is for them to decide.
-
-        Btw, the reason user collision cannot be implemented (efficiently)
-        on a non-cached /etc/passwd file is because getpwnam() will always
-        return the first user it finds with a matching username.  Thus, if
-        you're going to use the /etc/passwd file, you MUST set 'cache =
-        yes' in your radiusd.conf.  Or, you could always just put
-        duplicate usernames in the 'users' files, but you should probably
-        be caching anyway if you want a speedy server :)
-
-1.  Authentication
-
-    It currently works by using the password of the user to uniquely
-    identify and auth- enticate them.
-
-    Example:
-
-    ISP A user 'foo' has password 'bar'
-    ISP B user 'foo' has password 'bleah'
-
-    If the user logs in with 'bar' as their password, their login will be
-    accepted and they will get the reply attributes associated with what
-    you've entered for the user 'foo' password 'bar' entry.
-
-    If the user logs in with 'bleah' as the password, again, they'll be
-    authenticated, but they will get the reply attributes associated with
-    user 'foo' password 'bleah'.
-
-    So, what happens if two users have the same password?  IT
-    BREAKS.  Well, ok, it doesn't "break", but every user with the
-    associated pass will get the same reply attributes, causing grief for
-    you.  THE CODE DOES NOT CHECK FOR THIS, THAT IS YOUR JOB!
-
-    NOTE:  Again, user collision authentication *depends* on the passwords
-    being distinct!
-
-    So the security minded among us are now agast.  I'm not much for this
-    method myself, but trust me, the corporate folks are gonna love it.  
-    And it's not inherently insecure as long as the passwords remain
-    different.
-
-2.  Accounting
-
-    Ok, so now, how can we tell in the accounting logs which user 'foo'
-    logged in?  Well, again, you have a little work to do.  The code
-    identifies the user via a unique value assigned to the 'Class' reply
-    attribute in the users file.
-
-    For example:
-
-    foo Auth-Type := Local, User-Password == "bar"
-    Class = 0x0001
-
-    foo Auth-Type := Local, User-Password == "bleah"
-    Class = 0x0002
-
-    Now, you'd add other attributes as well, but let's just start with
-    'Class' by itself as a reply.  When a user 'foo' logs in with password
-    'bar', the 'Class=0x0001' reply item gets sent back to the NAS they
-    dialed into.  The NAS then adds 'Class=0x0001' to the Accounting
-    'Start' packet it sends for that user, thus uniquely identifying *this*
-    'foo' in the your accounting logs.
-
-    If the user 'foo' logs in with password 'bleah', you will get
-    'Class=0x0002' in your accounting logs.
-
-    Now, again, you should note that it is *your job* to make sure the
-    'Class' values are different for each user.  If you don't, I can assure
-    you the phones will ring off the hook when bitchy users get their
-    bills.
-
-    Obviously, this method works only for users in your 'users' files.  
-
-    If you are using a cached passwd file, then the "Full name" field in
-    the passwd file you cached will be passed back to the NAS as the value
-    of 'Class'.
-
-    Example:
-
-    /etc/passwd  ->  test:x:500:500:0x1001:/dev/null:/dev/null
-
-    In this case, "0x1001" will be passed as the value for the 'Class'
-    attribute when the Auth-Accept packet gets sent back to the NAS, and
-    then you should see 'Class=0x1001' for that user in your accounting
-    logs.
-
-    Once again, it is your job to ensure that these Class values are unique
-    for each user.
-
-D.  *Does* it work?
-
-    As of 10-01-2000, it is *extremely alpha*.  If you find bugs, by all
-    means let met know at jeff@apex.net, but make sure you include
-    relavent sections of your 'users' file and debug output from the
-    server (radiusd -X).
-
-1.  USAGE
-
-               Set 'usercollide=yes' in your radiusd.conf and either restart or
-    kill -HUP radiusd.
-
-2.  CAVEATS
-
-    Currently does not work with all modules (ie, sql, ldap, etc).
-
-3.  ACKNOWLEDGEMENT
-
-    Jeff Carneal - Author
-    Alan DeKok - for telling me about the 'Class' attribute :)
-
diff --git a/doc/examples/iplanet.ldif b/doc/examples/iplanet.ldif
new file mode 100644 (file)
index 0000000..04773b7
--- /dev/null
@@ -0,0 +1,71 @@
+# This is a LDAPv3 schema for RADIUS attributes.
+# Converted for use with iPlanet/Sun Directory Servers 5.x by Arne Brutschy <abrutschy@xylon.de>
+#
+# Originally Tested on OpenLDAP 2.0.7
+# Posted by Javier Fernandez-Sanguino Pena <jfernandez@sgi.es>
+# LDAP v3 version by Jochen Friedrich <jochen@scram.de>
+# Updates by Adrian Pavlykevych <pam@polynet.lviv.ua>
+##############
+dn: cn=schema
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.1 NAME 'radiusArapFeatures' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.2 NAME 'radiusArapSecurity' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.3 NAME 'radiusArapZoneAccess' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.44 NAME 'radiusAuthType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.4 NAME 'radiusCallbackId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.5 NAME 'radiusCallbackNumber' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.6 NAME 'radiusCalledStationId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.7 NAME 'radiusCallingStationId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.8 NAME 'radiusClass' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.45 NAME 'radiusClientIPAddress' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.9 NAME 'radiusFilterId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.10 NAME 'radiusFramedAppleTalkLink' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.11 NAME 'radiusFramedAppleTalkNetwork' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.12 NAME 'radiusFramedAppleTalkZone' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.13 NAME 'radiusFramedCompression' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.14 NAME 'radiusFramedIPAddress' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.15 NAME 'radiusFramedIPNetmask' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.16 NAME 'radiusFramedIPXNetwork' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.17 NAME 'radiusFramedMTU' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.18 NAME 'radiusFramedProtocol' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.19 NAME 'radiusFramedRoute' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.20 NAME 'radiusFramedRouting' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.46 NAME 'radiusGroupName' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.47 NAME 'radiusHint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.48 NAME 'radiusHuntgroupName' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.21 NAME 'radiusIdleTimeout' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.22 NAME 'radiusLoginIPHost' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.23 NAME 'radiusLoginLATGroup' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.24 NAME 'radiusLoginLATNode' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.25 NAME 'radiusLoginLATPort' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.26 NAME 'radiusLoginLATService' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.27 NAME 'radiusLoginService' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.28 NAME 'radiusLoginTCPPort' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.29 NAME 'radiusPasswordRetry' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.30 NAME 'radiusPortLimit' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.49 NAME 'radiusProfileDn' DESC '' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.31 NAME 'radiusPrompt' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.50 NAME 'radiusProxyToRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.51 NAME 'radiusReplicateToRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.52 NAME 'radiusRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.32 NAME 'radiusServiceType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.33 NAME 'radiusSessionTimeout' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.34 NAME 'radiusTerminationAction' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.35 NAME 'radiusTunnelAssignmentId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.36 NAME 'radiusTunnelMediumType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.37 NAME 'radiusTunnelPassword' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.38 NAME 'radiusTunnelPreference' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.39 NAME 'radiusTunnelPrivateGroupId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.40 NAME 'radiusTunnelServerEndpoint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.41 NAME 'radiusTunnelType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.42 NAME 'radiusVSA' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.43 NAME 'radiusTunnelClientEndpoint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+#need to change asn1.id
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.53 NAME 'radiusSimultaneousUse' DESC '' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.54 NAME 'radiusLoginTime' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.55 NAME 'radiusUserCategory' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.56 NAME 'radiusStripUserName' DESC '' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.57 NAME 'dialupAccess' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.58 NAME 'radiusExpiration' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.59 NAME 'radiusCheckItem' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.60 NAME 'radiusReplyItem' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+objectClasses: ( 1.3.6.1.4.1.3317.4.3.2.1 NAME 'radiusprofile' DESC '' SUP top AUXILIARY MUST ( cn ) MAY ( radiusArapFeatures $ radiusArapSecurity $ radiusArapZoneAccess $ radiusAuthType $ radiusCallbackId $ radiusCallbackNumber $ radiusCalledStationId $ radiusCallingStationId $ radiusClass $ radiusClientIPAddress $ radiusFilterId $ radiusFramedAppleTalkLink $ radiusFramedAppleTalkNetwork $ radiusFramedAppleTalkZone $ radiusFramedCompression $ radiusFramedIPAddress $ radiusFramedIPNetmask $ radiusFramedIPXNetwork $ radiusFramedMTU $ radiusFramedProtocol $ radiusCheckItem $ radiusReplyItem $ radiusFramedRoute $ radiusFramedRouting $ radiusIdleTimeout $ radiusGroupName $ radiusHint $ radiusHuntgroupName $ radiusLoginIPHost $ radiusLoginLATGroup $ radiusLoginLATNode $ radiusLoginLATPort $ radiusLoginLATService $ radiusLoginService $ radiusLoginTCPPort $ radiusLoginTime $ radiusPasswordRetry $ radiusPortLimit $ radiusPrompt $ radiusProxyToRealm $ radiusRealm $ radiusReplicateToRealm $ radiusServiceType $ radiusSessionTimeout $ radiusStripUserName $ radiusTerminationAction $ radiusTunnelClientEndpoint $ radiusProfileDn $ radiusSimultaneousUse $ radiusTunnelAssignmentId $ radiusTunnelMediumType $ radiusTunnelPassword $ radiusTunnelPreference $ radiusTunnelPrivateGroupId $ radiusTunnelServerEndpoint $ radiusTunnelType $ radiusUserCategory $ radiusVSA $ radiusExpiration $ dialupAccess ) )
diff --git a/doc/examples/iplanet.schema b/doc/examples/iplanet.schema
new file mode 100644 (file)
index 0000000..0f68569
--- /dev/null
@@ -0,0 +1,76 @@
+# This is a LDAPv3 schema for RADIUS attributes.
+# Tested on Sun One Directory server 5.2
+# Created by Daniel Wilson (danielwilson_2k@yahoo.com)
+##############
+dn: cn=schema
+objectClass: top
+objectClass: ldapSubentry
+objectClass: subschema
+cn: schema
+#######################
+# aci to ensure that the standard schema attributes are visible to
+# all LDAP clients (anonymous access).
+#
+aci: (target="ldap:///cn=schema")(targetattr !="aci")(version 3.0;acl "anonymous, no acis"; allow (read, search, compare) userdn = "ldap:///anyone";
+#######################
+objectClasses: ( 1.3.6.1.4.1.3317.4.3.2.1 NAME 'radiusprofile' SUP top AUXILIARY DESC 'Free Radius schema for Directory Server 5.2' MUST (cn) MAY ( radiusArapFeatures $ radiusArapSecurity $ radiusArapZoneAccess $ radiusAuthType $ radiusCallbackId $ radiusCallbackNumber $ radiusCalledStationId $ radiusCallingStationId $ radiusClass $ radiusClientIPAddress $ radiusFilterId $ radiusFramedAppleTalkLink $ radiusFramedAppleTalkNetwork $ radiusFramedAppleTalkZone $ radiusFramedCompression $ radiusFramedIPAddress $ radiusFramedIPNetmask $ radiusFramedIPXNetwork $ radiusFramedMTU $ radiusFramedProtocol $ radiusCheckItem $ radiusReplyItem $ radiusFramedRoute $ radiusFramedRouting $ radiusIdleTimeout $ radiusGroupName $ radiusHint $ radiusHuntgroupName $ radiusLoginIPHost $ radiusLoginLATGroup $ radiusLoginLATNode $ radiusLoginLATPort $ radiusLoginLATService $ radiusLoginService $ radiusLoginTCPPort $ radiusLoginTime $ radiusPasswordRetry $ radiusPortLimit $ radiusPrompt $ radiusProxyToRealm $ radiusRealm $ radiusReplicateToRealm $ radiusServiceType $ radiusSessionTimeout $ radiusStripUserName $ radiusTerminationAction $ radiusTunnelClientEndpoint $ radiusProfileDn $ radiusSimultaneousUse $ radiusTunnelAssignmentId $ radiusTunnelMediumType $ radiusTunnelPassword $ radiusTunnelPreference $ radiusTunnelPrivateGroupId $ radiusTunnelServerEndpoint $ radiusTunnelType $ radiusUserCategory $ radiusVSA $ radiusExpiration $ dialupAccess) X-ORIGIN 'user defined')
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.1 NAME 'radiusArapFeatures' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined')
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.2 NAME 'radiusArapSecurity' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined')
+attributeTypes: ( 1.3.6.1.4.1.3317.4.3.1.3 NAME 'radiusArapZoneAccess' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined')
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.44 NAME 'radiusAuthType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.4 NAME 'radiusCallbackId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.5 NAME 'radiusCallbackNumber' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.6 NAME 'radiusCalledStationId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.7 NAME 'radiusCallingStationId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.8 NAME 'radiusClass' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.45 NAME 'radiusClientIPAddress' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.9 NAME 'radiusFilterId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.10 NAME 'radiusFramedAppleTalkLink' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.11 NAME 'radiusFramedAppleTalkNetwork' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.12 NAME 'radiusFramedAppleTalkZone' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.13 NAME 'radiusFramedCompression' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.14 NAME 'radiusFramedIPAddress' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.15 NAME 'radiusFramedIPNetmask' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.16 NAME 'radiusFramedIPXNetwork' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.17 NAME 'radiusFramedMTU' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.18 NAME 'radiusFramedProtocol' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.19 NAME 'radiusFramedRoute' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.20 NAME 'radiusFramedRouting' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.46 NAME 'radiusGroupName' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.47 NAME 'radiusHint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.48 NAME 'radiusHuntgroupName' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.21 NAME 'radiusIdleTimeout' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.22 NAME 'radiusLoginIPHost' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.23 NAME 'radiusLoginLATGroup' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.24 NAME 'radiusLoginLATNode' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.25 NAME 'radiusLoginLATPort' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.26 NAME 'radiusLoginLATService' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.27 NAME 'radiusLoginService' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.28 NAME 'radiusLoginTCPPort' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.29 NAME 'radiusPasswordRetry' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.30 NAME 'radiusPortLimit' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.49 NAME 'radiusProfileDn' DESC '' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.31 NAME 'radiusPrompt' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.50 NAME 'radiusProxyToRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.51 NAME 'radiusReplicateToRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.52 NAME 'radiusRealm' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.32 NAME 'radiusServiceType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.33 NAME 'radiusSessionTimeout' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.34 NAME 'radiusTerminationAction' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.35 NAME 'radiusTunnelAssignmentId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.36 NAME 'radiusTunnelMediumType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.37 NAME 'radiusTunnelPassword' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.38 NAME 'radiusTunnelPreference' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.39 NAME 'radiusTunnelPrivateGroupId' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.40 NAME 'radiusTunnelServerEndpoint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.41 NAME 'radiusTunnelType' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.42 NAME 'radiusVSA' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.43 NAME 'radiusTunnelClientEndpoint' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.53 NAME 'radiusSimultaneousUse' DESC '' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.54 NAME 'radiusLoginTime' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.55 NAME 'radiusUserCategory' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.56 NAME 'radiusStripUserName' DESC '' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.57 NAME 'dialupAccess' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.58 NAME 'radiusExpiration' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'user defined' )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.59 NAME 'radiusCheckItem' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+attributeTypes:  ( 1.3.6.1.4.1.3317.4.3.1.60 NAME 'radiusReplyItem' DESC '' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
index a151025..6273410 100644 (file)
@@ -1,4 +1,6 @@
 /***************************************************************************
+ * $Id$                   *
+ *                                                                        *
  * db_mssql.sql                                                           *
  *                                                                         *
  * Database schema for MSSQL server                                       *
@@ -17,6 +19,7 @@ CREATE TABLE [radacct] (
        [AcctSessionId] [varchar] (32) NOT NULL ,
        [AcctUniqueId] [varchar] (32) NOT NULL ,
        [UserName] [varchar] (64) NOT NULL ,
+       [GroupName] [varchar] (64) NOT NULL ,
        [Realm] [varchar] (64) NULL ,
        [NASIPAddress] [varchar] (15) NOT NULL ,
        [NASPortId] [varchar] (15) NULL ,
@@ -81,8 +84,8 @@ CREATE TABLE [radreply] (
 ) ON [PRIMARY]
 GO
 
-/****** Object:  Table [usergroup]    Script Date: 26.03.02 16:55:18 ******/
-CREATE TABLE [usergroup] (
+/****** Object:  Table [radusergroup]    Script Date: 26.03.02 16:55:18 ******/
+CREATE TABLE [radusergroup] (
        [id] [int] IDENTITY (1, 1) NOT NULL ,
        [UserName] [varchar] (64) NOT NULL ,
        [GroupName] [varchar] (64) NULL
@@ -164,10 +167,10 @@ ALTER TABLE [radreply] WITH NOCHECK ADD
        )  ON [PRIMARY]
 GO
 
-ALTER TABLE [usergroup] WITH NOCHECK ADD
-       CONSTRAINT [DF_usergroup_UserName] DEFAULT ('') FOR [UserName],
-       CONSTRAINT [DF_usergroup_GroupName] DEFAULT ('') FOR [GroupName],
-       CONSTRAINT [PK_usergroup] PRIMARY KEY  NONCLUSTERED
+ALTER TABLE [radusergroup] WITH NOCHECK ADD
+       CONSTRAINT [DF_radusergroup_UserName] DEFAULT ('') FOR [UserName],
+       CONSTRAINT [DF_radusergroup_GroupName] DEFAULT ('') FOR [GroupName],
+       CONSTRAINT [PK_radusergroup] PRIMARY KEY  NONCLUSTERED
        (
                [id]
        )  ON [PRIMARY]
@@ -206,5 +209,5 @@ GO
  CREATE  INDEX [UserName] ON [radreply]([UserName]) ON [PRIMARY]
 GO
 
- CREATE  INDEX [UserName] ON [usergroup]([UserName]) ON [PRIMARY]
+ CREATE  INDEX [UserName] ON [radusergroup]([UserName]) ON [PRIMARY]
 GO
index 0c630a0..d798e85 100644 (file)
@@ -1,4 +1,6 @@
 ###########################################################################
+# $Id$                 #
+#                                                                         #
 #  db_mysql.sql                     rlm_sql - FreeRADIUS SQL Module       #
 #                                                                         #
 #     Database schema for MySQL rlm_sql module                            #
@@ -17,6 +19,7 @@ CREATE TABLE radacct (
   AcctSessionId varchar(32) NOT NULL default '',
   AcctUniqueId varchar(32) NOT NULL default '',
   UserName varchar(64) NOT NULL default '',
+  GroupName varchar(64) NOT NULL default '',
   Realm varchar(64) default '',
   NASIPAddress varchar(15) NOT NULL default '',
   NASPortId varchar(15) default NULL,
@@ -105,10 +108,10 @@ CREATE TABLE radreply (
 
 
 #
-# Table structure for table 'usergroup'
+# Table structure for table 'radusergroup'
 #
 
-CREATE TABLE usergroup (
+CREATE TABLE radusergroup (
   UserName varchar(64) NOT NULL default '',
   GroupName varchar(64) NOT NULL default '',
   priority int(11) NOT NULL default '1',
diff --git a/doc/examples/openldap.schema b/doc/examples/openldap.schema
new file mode 100644 (file)
index 0000000..55d34f3
--- /dev/null
@@ -0,0 +1,587 @@
+# This is a LDAPv3 schema for RADIUS attributes.
+# Tested on OpenLDAP 2.0.7
+# Posted by Javier Fernandez-Sanguino Pena <jfernandez@sgi.es>
+# LDAP v3 version by Jochen Friedrich <jochen@scram.de>
+# Updates by Adrian Pavlykevych <pam@polynet.lviv.ua>
+##############
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.1
+      NAME 'radiusArapFeatures'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.2
+      NAME 'radiusArapSecurity'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.3
+      NAME 'radiusArapZoneAccess'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.44
+     NAME 'radiusAuthType'
+     DESC ''
+     EQUALITY caseIgnoreIA5Match
+     SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+     SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.4
+      NAME 'radiusCallbackId'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.5
+      NAME 'radiusCallbackNumber'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.6
+      NAME 'radiusCalledStationId'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.7
+      NAME 'radiusCallingStationId'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.8
+      NAME 'radiusClass'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.45
+     NAME 'radiusClientIPAddress'
+     DESC ''
+     EQUALITY caseIgnoreIA5Match
+     SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+     SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.9
+      NAME 'radiusFilterId'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.10
+      NAME 'radiusFramedAppleTalkLink'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.11
+      NAME 'radiusFramedAppleTalkNetwork'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.12
+      NAME 'radiusFramedAppleTalkZone'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.13
+      NAME 'radiusFramedCompression'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.14
+      NAME 'radiusFramedIPAddress'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.15
+      NAME 'radiusFramedIPNetmask'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.16
+      NAME 'radiusFramedIPXNetwork'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.17
+      NAME 'radiusFramedMTU'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.18
+      NAME 'radiusFramedProtocol'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.19
+      NAME 'radiusFramedRoute'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.20
+      NAME 'radiusFramedRouting'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.46
+      NAME 'radiusGroupName'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.47
+      NAME 'radiusHint'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.48
+      NAME 'radiusHuntgroupName'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.21
+      NAME 'radiusIdleTimeout'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.22
+      NAME 'radiusLoginIPHost'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.23
+      NAME 'radiusLoginLATGroup'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.24
+      NAME 'radiusLoginLATNode'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.25
+      NAME 'radiusLoginLATPort'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.26
+      NAME 'radiusLoginLATService'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.27
+      NAME 'radiusLoginService'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.28
+      NAME 'radiusLoginTCPPort'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.29
+      NAME 'radiusPasswordRetry'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.30
+      NAME 'radiusPortLimit'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.49
+      NAME 'radiusProfileDn'
+      DESC ''
+      EQUALITY distinguishedNameMatch
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.31
+      NAME 'radiusPrompt'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.50
+      NAME 'radiusProxyToRealm'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.51
+      NAME 'radiusReplicateToRealm'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.52
+      NAME 'radiusRealm'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.32
+      NAME 'radiusServiceType'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.33
+      NAME 'radiusSessionTimeout'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.34
+      NAME 'radiusTerminationAction'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.35
+      NAME 'radiusTunnelAssignmentId'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.36
+      NAME 'radiusTunnelMediumType'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.37
+      NAME 'radiusTunnelPassword'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.38
+      NAME 'radiusTunnelPreference'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.39
+      NAME 'radiusTunnelPrivateGroupId'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.40
+      NAME 'radiusTunnelServerEndpoint'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.41
+      NAME 'radiusTunnelType'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.42
+      NAME 'radiusVSA'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.43
+      NAME 'radiusTunnelClientEndpoint'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+
+#need to change asn1.id
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.53
+      NAME 'radiusSimultaneousUse'
+      DESC ''
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.54
+      NAME 'radiusLoginTime'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.55
+      NAME 'radiusUserCategory'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.56
+      NAME 'radiusStripUserName'
+      DESC ''
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.57
+      NAME 'dialupAccess'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.58
+      NAME 'radiusExpiration'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.59
+      NAME 'radiusCheckItem'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.60
+      NAME 'radiusReplyItem'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.61
+      NAME 'radiusNASIpAddress'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+      SINGLE-VALUE
+   )
+
+attributetype
+   ( 1.3.6.1.4.1.3317.4.3.1.62
+      NAME 'radiusReplyMessage'
+      DESC ''
+      EQUALITY caseIgnoreIA5Match
+      SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
+   )
+
+
+objectclass
+   ( 1.3.6.1.4.1.3317.4.3.2.1
+      NAME 'radiusprofile'
+      SUP top AUXILIARY
+      DESC ''
+      MUST cn
+      MAY ( radiusArapFeatures $ radiusArapSecurity $ radiusArapZoneAccess $
+            radiusAuthType $ radiusCallbackId $ radiusCallbackNumber $
+            radiusCalledStationId $ radiusCallingStationId $ radiusClass $
+            radiusClientIPAddress $ radiusFilterId $ radiusFramedAppleTalkLink $
+            radiusFramedAppleTalkNetwork $ radiusFramedAppleTalkZone $
+            radiusFramedCompression $ radiusFramedIPAddress $
+            radiusFramedIPNetmask $ radiusFramedIPXNetwork $
+            radiusFramedMTU $ radiusFramedProtocol $
+           radiusCheckItem $ radiusReplyItem $
+            radiusFramedRoute $ radiusFramedRouting $ radiusIdleTimeout $
+            radiusGroupName $ radiusHint $ radiusHuntgroupName $
+            radiusLoginIPHost $ radiusLoginLATGroup $ radiusLoginLATNode $
+            radiusLoginLATPort $ radiusLoginLATService $ radiusLoginService $
+            radiusLoginTCPPort $ radiusLoginTime $ radiusPasswordRetry $
+            radiusPortLimit $ radiusPrompt $ radiusProxyToRealm $
+            radiusRealm $ radiusReplicateToRealm $ radiusServiceType $
+            radiusSessionTimeout $ radiusStripUserName $
+            radiusTerminationAction $ radiusTunnelClientEndpoint $ radiusProfileDn $
+            radiusSimultaneousUse $ radiusTunnelAssignmentId $
+            radiusTunnelMediumType $ radiusTunnelPassword $ radiusTunnelPreference $
+            radiusTunnelPrivateGroupId $ radiusTunnelServerEndpoint $
+            radiusTunnelType $ radiusUserCategory $ radiusVSA $
+            radiusExpiration $ dialupAccess $ radiusNASIpAddress $
+            radiusReplyMessage )
+   )
+
+objectclass
+  ( 1.3.6.1.4.1.3317.4.3.2.2
+       NAME 'radiusObjectProfile'
+       SUP top STRUCTURAL
+       DESC 'A Container Objectclass to be used for creating radius profile object'
+       MUST cn
+       MAY ( uid $ userPassword $ description )
+  )
index 3d5082c..3910a83 100644 (file)
@@ -43,7 +43,8 @@ CREATE TABLE radacct (
        radacctid               INT PRIMARY KEY,
        acctsessionid           VARCHAR(32) NOT NULL,
        acctuniqueid            VARCHAR(32),
-       username                VARCHAR(32) NOT NULL,
+       username                VARCHAR(64) NOT NULL,
+       groupname               VARCHAR(32) NOT NULL,
        realm                   VARCHAR(30),
        nasipaddress            VARCHAR(15) NOT NULL,
        nasportid               VARCHAR(15),
@@ -154,22 +155,22 @@ CREATE OR REPLACE TRIGGER radreply_serialnumber
 /
 
 /*
- * Table structure for table 'usergroup'
+ * Table structure for table 'radusergroup'
  */
-CREATE TABLE usergroup (
+CREATE TABLE radusergroup (
        id              INT PRIMARY KEY,
        UserName        VARCHAR(30) UNIQUE NOT NULL,
        GroupName       VARCHAR(30)
 );
-CREATE SEQUENCE usergroup_seq START WITH 1 INCREMENT BY 1;
+CREATE SEQUENCE radusergroup_seq START WITH 1 INCREMENT BY 1;
 
 /* Trigger to emulate a serial # on the primary key */
-CREATE OR REPLACE TRIGGER usergroup_serialnumber
-       BEFORE INSERT OR UPDATE OF id ON usergroup
+CREATE OR REPLACE TRIGGER radusergroup_serialnumber
+       BEFORE INSERT OR UPDATE OF id ON radusergroup
        FOR EACH ROW
        BEGIN
                if ( :new.id = 0 or :new.id is null ) then
-                       SELECT usergroup_seq.nextval into :new.id from dual;
+                       SELECT radusergroup_seq.nextval into :new.id from dual;
                end if;
        END;
 /
index 2dc94aa..49c6f7b 100644 (file)
@@ -18,6 +18,7 @@ CREATE TABLE radacct (
        AcctSessionId           VARCHAR(32) NOT NULL,
        AcctUniqueId            VARCHAR(32) NOT NULL,
        UserName                VARCHAR(253),
+       GroupName               VARCHAR(253),
        Realm                   VARCHAR(64),
        NASIPAddress            INET NOT NULL,
        NASPortId               VARCHAR(15),
@@ -38,8 +39,7 @@ CREATE TABLE radacct (
        FramedProtocol          VARCHAR(32),
        FramedIPAddress         INET,
        AcctStartDelay          BIGINT,
-       AcctStopDelay           BIGINT,
-       XAscendSessionSvrKey    VARCHAR(10)
+       AcctStopDelay           BIGINT
 );
 -- This index may be usefull..
 -- CREATE UNIQUE INDEX radacct_whoson on radacct (AcctStartTime, nasipaddress);
@@ -129,18 +129,18 @@ create index radreply_UserName on radreply (UserName,Attribute);
 -- create index radreply_UserName_lower on radreply (lower(UserName),Attribute);
 
 /*
- * Table structure for table 'usergroup'
+ * Table structure for table 'radusergroup'
  */
-CREATE TABLE usergroup (
+CREATE TABLE radusergroup (
        UserName        VARCHAR(64) NOT NULL DEFAULT '',
        GroupName       VARCHAR(64) NOT NULL DEFAULT '',
        priority        INTEGER NOT NULL DEFAULT 0
 );
-create index usergroup_UserName on usergroup (UserName);
+create index radusergroup_UserName on radusergroup (UserName);
 /*
  * Use this index if you use case insensitive queries
  */
--- create index usergroup_UserName_lower on usergroup (lower(UserName));
+-- create index radusergroup_UserName_lower on radusergroup (lower(UserName));
 
 /*
  * Table structure for table 'realmgroup'
@@ -185,12 +185,14 @@ create index nas_nasname on nas (nasname);
 --
 
 CREATE TABLE radpostauth (
-       id              BIGSERIAL PRIMARY KEY,
-       username        VARCHAR(253) NOT NULL,
-       pass            VARCHAR(128),
-       reply           VARCHAR(32),
-       authdate        TIMESTAMP with time zone NOT NULL default 'now'
-) ;
+       id                      BIGSERIAL PRIMARY KEY,
+       username                VARCHAR(253) NOT NULL,
+       pass                    VARCHAR(128),
+       reply                   VARCHAR(32),
+       CalledStationId         VARCHAR(50),
+       CallingStationId        VARCHAR(50),
+       authdate                TIMESTAMP with time zone NOT NULL default 'now'
+);
 
 --
 -- Table structure for table 'radippool'
@@ -198,16 +200,21 @@ CREATE TABLE radpostauth (
 
 CREATE TABLE radippool (
        id                      BIGSERIAL PRIMARY KEY,
-       pool_name               text NOT NULL,
-       FramedIPAddress         INET,
-       NASIPAddress            text NOT NULL,
+       pool_name               varchar(64) NOT NULL,
+       FramedIPAddress         INET NOT NULL,
+       NASIPAddress            VARCHAR(16) NOT NULL default '',
+       pool_key                VARCHAR(64) NOT NULL default 0,
        CalledStationId         VARCHAR(64),
-       CallingStationId        text NOT NULL DEFAULT ''::text,
-       expiry_time             TIMESTAMP(0) without time zone NOT NULL,
-       username                text DEFAULT ''::text,
-       pool_key                VARCHAR(30) NOT NULL
+       CallingStationId        text NOT NULL default ''::text,
+       expiry_time             TIMESTAMP(0) without time zone NOT NULL default 'now'::timestamp(0),
+       username                text DEFAULT ''::text
 );
 
+CREATE INDEX radippool_poolname_ipaadr ON radippool USING btree (pool_name, framedipaddress);
+CREATE INDEX radippool_poolname_expire ON radippool USING btree (pool_name, expiry_time);
+CREATE INDEX radippool_nasipaddr_poolkey ON radippool USING btree (nasipaddress, pool_key);
+CREATE INDEX radippool_nasipaddr_calling ON radippool USING btree (nasipaddress, callingstationid);
+
 --
 -- Table structure for table 'dictionary'
 -- This is not currently used by FreeRADIUS
diff --git a/doc/examples/postgresql_update_radacct_group_trigger.sql b/doc/examples/postgresql_update_radacct_group_trigger.sql
new file mode 100644 (file)
index 0000000..b2f6967
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * $Id$
+ *
+ * OPTIONAL Postgresql trigger for FreeRADIUS
+ *
+ * This trigger updates fills in the groupname field (which doesnt come in Accounting packets)
+ * by querying the radusergroup table.
+ * This makes it easier to do group summary reports, however note that it does add some extra
+ * database load to 50% of your SQL accounting queries. If you dont care about group summary 
+ * reports then you dont need to install this.
+ *
+ */
+
+
+CREATE OR REPLACE FUNCTION upd_radgroups() RETURNS trigger AS'
+
+DECLARE
+        v_groupname varchar;
+
+BEGIN
+        SELECT INTO v_groupname groupname FROM radusergroup WHERE calledstationid = NEW.calledstationid AND username = NEW.username;
+        IF FOUND THEN
+                UPDATE radacct SET groupname = v_groupname WHERE radacctid = NEW.radacctid;
+        END IF;
+
+        RETURN NEW;
+END
+
+'LANGUAGE plpgsql;
+
+
+DROP TRIGGER upd_radgroups ON radacct;
+
+CREATE TRIGGER upd_radgroups AFTER INSERT ON radacct
+    FOR EACH ROW EXECUTE PROCEDURE upd_radgroups();
+
+
index 5496707..4a92671 100644 (file)
@@ -3,7 +3,7 @@ Dusty Doris
 dusty at doris dot cc
 01-09-2003
 
-This document decribes how to setup Freeradius on a Freebsd machine
+This document describes how to setup Freeradius on a Freebsd machine
 using LDAP as a backend.  This is by no means complete and your
 mileage may vary.  If you are having any problems with the setup of
 your freeradius installation, please read the documentation that comes
@@ -1075,7 +1075,7 @@ The next module is files, which is commonly know as the users file.  The users
 file will start with either a username to determine how to authorize a specific 
 user, or a DEFAULT setting.  In each line it will define what items must be 
 present for there to be a match in the form of attribute == value.  If all the 
-required attributes are matched, then attributes specified with attribte := 
+required attributes are matched, then attributes specified with attribute := 
 value will be set for that user.  If no match is found the users file will 
 continue to be processed until there is a match.  The last DEFAULT setting will 
 be set as a catch-all, in case there is no previous match.  If a match is made, 
index 0151258..72906aa 100644 (file)
@@ -81,7 +81,7 @@ then log to the detail file"
        ==========================
 
   If you want to do redundancy and load-balancing among three
-modules, the configuration is complex:
+modules, the configuration is quite complex:
 
 ...
   load-balance {
@@ -147,5 +147,58 @@ one picked for load-balancing is down, load-balance among the
 remaining two.  If that one is down, pick the one remaining 'live'
 server".
 
+  The "redundant-load-balance" section can contain any number of
+modules.
+
+
+  Interaction with "if" and "else"
+  --------------------------------
+
+  It's best to have "if" and "else" blocks contain "load-balance" or
+"redundant-load-balance" sections, rather than the other way around.
+The "else" and "elsif" sections cannot appear inside of a
+"load-balance" or "redundant-load-balance" section, because the "else"
+condition would be chose as one of the modules for load-balancing,
+which is not what you want.
+
+  It's OK to have a plain "if" block inside of a "load-balance" or
+"redundant-load-balance" section.  In that case, the "if" condition
+checks the return code of the module or group that executed just
+before the "load-balance" section.  It does *not* check the return
+code of the previous module in the section.
+
+  The following table illustrates which sections can be sub-sections
+of others.  If an entry for a row/column is empty, then that
+combination is not allowed.
+
+           x = allowed
+           i = allowed if immediately after an 'if or 'elsif'
+
+
+   Allowed:    group   redundant  l-b  r-l-b   if    else  elsif
+
+Container:
+
+  group          x        x        x      x     x     i     i
+
+  if             x        x        x      x     x     i     i
+
+  else           i        i        i      i     i     i     i
+
+  elsif          i        i        i      i     i     i     i
+
+  l-b            x        x        x      x     x
+
+  r-l-b          x        x        x      x     x
+
+  redundant      x        x        x      x
+
+
+  e.g. "redundant" can contain "load-balance", but not "if", "else",
+or "eslif".  "if" can contain any other section, but if it contains
+"else" or "elsif", they have to have be listed after a second "if"
+section, inside of the first "if".
+
+
 ----------------------------------------------------------------------
 $Id$
diff --git a/doc/radrelay b/doc/radrelay
deleted file mode 100644 (file)
index 1df1963..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-
-             Accounting replication with radrelay.
-
-
-0. INTRODUCTION
-
-   Often people run multiple radius servers; at least one primary and
-   one backup server. When the primary goes down, most NASes detect that
-   and switch to the backup server.
-
-   That will cause your accounting packets to go the the backup
-   server - and some NASes don't even switch back to the primary
-   server when it comes back up.
-
-   That means you miss accounting records or must jump through hoops
-   to combine the different detail files from multiple servers. It
-   also means that the session database ("radutmp", used for radwho
-   and simultaneous use detection) gets out of sync.
-
-1. REPLICATION
-
-   Radrelay is a program that does the equivalent of tail(1) on a
-   accounting detail file. Each time the server writes a packet
-   to this file, radrelay reads it and sends it to a remote radius
-   server. If all works well, radrelay gets replies from the remote
-   server as it should. When it reaches end-of-file, it locks the
-   file, renames it to <filename>.work, and waits for all it's
-   accounting requests to get answered. As soon as they are
-   answered, <filename.work> is deleted.
-
-   When radrelay starts up it first checks for <filename.work>
-   before it starts processing the standard detail file. This
-   ensures that no packets get lost.
-
-   Even if the primary server is down for a day, or if the secondary
-   server crashes and reboots, radrelay will buffer the accounting
-   packets and send them to the remote accounting server.
-
-   Radrelay checks the "Client-IP-Address" attribute in each record,
-   and if it's the same as the remote server it will not replicate
-   that record to prevent loops. That means you can point radrelay
-   to the primary server on the backup host, and to the backup server
-   on the primary host, to have complete records on both.
-
-2. USAGE
-
-   First, you should make radiusd log to an extra, single detail file.
-   This is probably done easiest by adding an extra instance of the
-   detail module to your radiusd.conf.
-
-   For example:
-
-   detail detail1 {
-       detailfile = %A/%{Client-IP-Address}/detail-%Y%m
-       detailperm = 0600
-       dirperm = 0755
-   }
-   detail detail2 {
-       detailfile = ${radacctdir}/detail-combined
-       detailperm = 0600
-       dirperm = 0755
-       locking = yes
-   }
-
-   [...]
-
-   accounting {
-        [...]
-       detail1
-        detail2
-        [...]
-   }
-
-   In the above example, the instance detail1 of the detail module
-   represents your original detail logging. detail2 will create a
-   detail file dedicated only to radrelay. Note the use of "locking = yes",
-   this is _very very_ important when using the detail module in combination
-   with radrelay. It's used to keep both the detail module and radrelay
-   playing nice with each other.
-
-   Next, you need to fire up radrelay.
-
-   For example:
-
-   radrelay -S secret_file <server> detail-combined
-
-   The use of -S is recommended over -s due to the fact that your secret
-   won't show up with ps. You should also make sure your secret file is not
-   world readable.
-
-   If the server you are relaying to is included in your 'clients.conf' file
-   using the '-n [shortname]' commandline option is probably easiest. This
-   means you won't have to give the remote server address or the shared
-   secret when you start radrelay.
-
-   You should never logrotate your detail file, radrelay will take care of
-   this for you.
-
-3. REPLICATION AND PROXYING
-
-   If you have a primary and a backup server with identical configs
-   that both proxy for certain realms to other radius servers, the
-   remote server might end up with duplicate accounting info - the
-   accounting packet is received by the backup server, proxied to
-   the remote server and replicated to the primary server, then the
-   primary server proxies the same packet to the remote radius server
-   again because it doesn't know that that was already done.
-
-   To prevent this scenario, FreeRADIUS writes an extra attribute
-   to the detail file if it has proxied the accounting packet, the
-   vendor-specific attribute 'Freeradius-Proxied-To'. It contains the
-   address of the remote radius server. Radrelay replicates this
-   attribute just like any other to the primary server. If the
-   primary server wants to proxy an accounting packet to a remote
-   radius server, it first checks the packet to see if the
-   'Freeradius-Proxied-To' attribute is present. If it is, and it
-   contains the IP address of the remote radius server, it knows
-   that it doesn't need to proxy this packet to the remote server
-   once more. Problem solved!
-
-4. NOTES
-
-   Only attributes that are defined in the dictionary are replicated.
-   Unknown attributes are simply ignored.
-
-   Radrelay doesn't re-read its config files on a SIGHUP. It uses
-   two config files - the dictionary (which can consist of multiple
-   files ofcourse if you use $INCLUDE) and possibly the secret file.
-   If you modify one of those files you need to restart radrelay.
-
-5. CREDITS
-   Original   - Miquel van Smoorenburg <miquels@cistron.nl>
-               Written for the Cistron radius project.
-   2002-06-09 - Simon Ekstrand <simon@routemeister.net>
-               Ported to the FreeRADIUS project.
-
index c659d30..4d8fd43 100644 (file)
@@ -7,19 +7,26 @@
 include ../../Make.inc
 
 RFC    = rfc2548.txt rfc2865.txt rfc2866.txt rfc2867.txt rfc2868.txt \
-         rfc2869.txt rfc3162.txt
+         rfc2869.txt rfc3162.txt rfc3576.txt rfc3579.txt rfc3580.txt \
+         rfc4590.txt
 
 all:
 
 html: refs
        ./rewrite.pl $(RFC)
+       ./per-rfc.pl $(RFC)
        @touch .rewrite
 
+index.html: html
+       ./update.sh
+
 refs: $(RFC)
        ./genref.pl $(RFC) > refs
+       @echo 'rfc2865 Class' >> refs
+       @echo 'rfc2865 State' >> refs
 
 clean:
-       rm -f refs rfc*.html *~ .rewrite index.html
+       rm -f refs *rfc*.html *~ .rewrite index.html
 
 install:
        $(INSTALL) -d -m 755 $(R)$(docdir)/rfc
index 7852a2f..8f15be2 100644 (file)
@@ -2,16 +2,15 @@
 <HTML>
 <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-   <title>RADIUS Attribute List</title>
+   <meta name="GENERATOR" content="Perl">
+   <title>rfc4590.html</title>
 </head>
-<body bgcolor="#ffffff" >
+<body>
 
-<H1>RADIUS Attribute List</H1>
+<H2>RADIUS Attribute List</H2>
 
-This is a list of RADIUS attributes, automatically generated from the
-relevant RFC's.  Any errors or omissions are unintentional.
+<H3>A</H3>
 
-<H2>A</H2>
 <UL>
 <A HREF="rfc2869.html#ARAP-Challenge-Response">ARAP-Challenge-Response</A><BR>
 <A HREF="rfc2869.html#ARAP-Features">ARAP-Features</A><BR>
@@ -44,9 +43,8 @@ relevant RFC's.  Any errors or omissions are unintentional.
 <A HREF="rfc2867.html#Acct-Tunnel-Packets-Lost">Acct-Tunnel-Packets-Lost</A><BR>
 </UL>
 
-<H2>B</H2>
+<H3>C</H3>
 
-<H2>C</H2>
 <UL>
 <A HREF="rfc2865.html#CHAP-Challenge">CHAP-Challenge</A><BR>
 <A HREF="rfc2865.html#CHAP-Password">CHAP-Password</A><BR>
@@ -54,21 +52,48 @@ relevant RFC's.  Any errors or omissions are unintentional.
 <A HREF="rfc2865.html#Callback-Number">Callback-Number</A><BR>
 <A HREF="rfc2865.html#Called-Station-Id">Called-Station-Id</A><BR>
 <A HREF="rfc2865.html#Calling-Station-Id">Calling-Station-Id</A><BR>
+<A HREF="rfc3576.html#Change-of-Authorization">Change-of-Authorization</A><BR>
 <A HREF="rfc2865.html#Class">Class</A><BR>
 <A HREF="rfc2869.html#Configuration-Token">Configuration-Token</A><BR>
 <A HREF="rfc2869.html#Connect-Info">Connect-Info</A><BR>
 </UL>
 
-<H2>D</H2>
+<H3>D</H3>
+
+<UL>
+<A HREF="rfc4590.html#Digest-AKA-Auts">Digest-AKA-Auts</A><BR>
+<A HREF="rfc4590.html#Digest-Algorithm">Digest-Algorithm</A><BR>
+<A HREF="rfc4590.html#Digest-Auth-Param">Digest-Auth-Param</A><BR>
+<A HREF="rfc4590.html#Digest-CNonce">Digest-CNonce</A><BR>
+<A HREF="rfc4590.html#Digest-Domain">Digest-Domain</A><BR>
+<A HREF="rfc4590.html#Digest-Entity-Body-Hash">Digest-Entity-Body-Hash</A><BR>
+<A HREF="rfc4590.html#Digest-HA1">Digest-HA1</A><BR>
+<A HREF="rfc4590.html#Digest-Method">Digest-Method</A><BR>
+<A HREF="rfc4590.html#Digest-Nextnonce">Digest-Nextnonce</A><BR>
+<A HREF="rfc4590.html#Digest-Nonce">Digest-Nonce</A><BR>
+<A HREF="rfc4590.html#Digest-Nonce-Count">Digest-Nonce-Count</A><BR>
+<A HREF="rfc4590.html#Digest-Opaque">Digest-Opaque</A><BR>
+<A HREF="rfc4590.html#Digest-Qop">Digest-Qop</A><BR>
+<A HREF="rfc4590.html#Digest-Realm">Digest-Realm</A><BR>
+<A HREF="rfc4590.html#Digest-Response">Digest-Response</A><BR>
+<A HREF="rfc4590.html#Digest-Response-Auth">Digest-Response-Auth</A><BR>
+<A HREF="rfc4590.html#Digest-Stale">Digest-Stale</A><BR>
+<A HREF="rfc4590.html#Digest-URI">Digest-URI</A><BR>
+<A HREF="rfc4590.html#Digest-Username">Digest-Username</A><BR>
+</UL>
+
+<H3>E</H3>
 
-<H2>E</H2>
 <UL>
 <A HREF="rfc2869.html#EAP-Message">EAP-Message</A><BR>
+<A HREF="rfc3576.html#Error-Cause">Error-Cause</A><BR>
 <A HREF="rfc2869.html#Event-Timestamp">Event-Timestamp</A><BR>
 </UL>
 
-<H2>F</H2>
+<H3>F</H3>
+
 <UL>
+<A HREF="rfc3580.html#Filter-ID">Filter-ID</A><BR>
 <A HREF="rfc2865.html#Filter-Id">Filter-Id</A><BR>
 <A HREF="rfc2865.html#Framed-AppleTalk-Link">Framed-AppleTalk-Link</A><BR>
 <A HREF="rfc2865.html#Framed-AppleTalk-Network">Framed-AppleTalk-Network</A><BR>
@@ -76,11 +101,11 @@ relevant RFC's.  Any errors or omissions are unintentional.
 <A HREF="rfc2865.html#Framed-Compression">Framed-Compression</A><BR>
 <A HREF="rfc2865.html#Framed-IP-Address">Framed-IP-Address</A><BR>
 <A HREF="rfc2865.html#Framed-IP-Netmask">Framed-IP-Netmask</A><BR>
+<A HREF="rfc2865.html#Framed-IPX-Network">Framed-IPX-Network</A><BR>
 <A HREF="rfc3162.html#Framed-IPv6-Pool">Framed-IPv6-Pool</A><BR>
 <A HREF="rfc3162.html#Framed-IPv6-Prefix">Framed-IPv6-Prefix</A><BR>
 <A HREF="rfc3162.html#Framed-IPv6-Route">Framed-IPv6-Route</A><BR>
 <A HREF="rfc3162.html#Framed-Interface-Id">Framed-Interface-Id</A><BR>
-<A HREF="rfc2865.html#Framed-IPX-Network">Framed-IPX-Network</A><BR>
 <A HREF="rfc2865.html#Framed-MTU">Framed-MTU</A><BR>
 <A HREF="rfc2869.html#Framed-Pool">Framed-Pool</A><BR>
 <A HREF="rfc2865.html#Framed-Protocol">Framed-Protocol</A><BR>
@@ -88,23 +113,20 @@ relevant RFC's.  Any errors or omissions are unintentional.
 <A HREF="rfc2865.html#Framed-Routing">Framed-Routing</A><BR>
 </UL>
 
-<H2>G</H2>
-
-<H2>H</H2>
+<H3>I</H3>
 
-<H2>I</H2>
 <UL>
 <A HREF="rfc2865.html#Idle-Timeout">Idle-Timeout</A><BR>
 </UL>
 
-<H2>J</H2>
+<H3>K</H3>
 
-<H2>K</H2>
 <UL>
 <A HREF="rfc2865.html#Keep-Alives">Keep-Alives</A><BR>
 </UL>
 
-<H2>L</H2>
+<H3>L</H3>
+
 <UL>
 <A HREF="rfc2865.html#Login-IP-Host">Login-IP-Host</A><BR>
 <A HREF="rfc3162.html#Login-IPv6-Host">Login-IPv6-Host</A><BR>
@@ -116,7 +138,8 @@ relevant RFC's.  Any errors or omissions are unintentional.
 <A HREF="rfc2865.html#Login-TCP-Port">Login-TCP-Port</A><BR>
 </UL>
 
-<H2>M</H2>
+<H3>M</H3>
+
 <UL>
 <A HREF="rfc2548.html#MS-ARAP-Challenge">MS-ARAP-Challenge</A><BR>
 <A HREF="rfc2548.html#MS-ARAP-Password-Change-Reason">MS-ARAP-Password-Change-Reason</A><BR>
@@ -151,10 +174,10 @@ relevant RFC's.  Any errors or omissions are unintentional.
 <A HREF="rfc2548.html#MS-Secondary-DNS-Server">MS-Secondary-DNS-Server</A><BR>
 <A HREF="rfc2548.html#MS-Secondary-NBNS-Server">MS-Secondary-NBNS-Server</A><BR>
 <A HREF="rfc2869.html#Message-Authenticator">Message-Authenticator</A><BR>
-<A HREF="rfc2869.html#Message-Authenticator">Message-Authenticator</A><BR>
 </UL>
 
-<H2>N</H2>
+<H3>N</H3>
+
 <UL>
 <A HREF="rfc2865.html#NAS-IP-Address">NAS-IP-Address</A><BR>
 <A HREF="rfc3162.html#NAS-IPv6-Address">NAS-IPv6-Address</A><BR>
@@ -164,33 +187,32 @@ relevant RFC's.  Any errors or omissions are unintentional.
 <A HREF="rfc2865.html#NAS-Port-Type">NAS-Port-Type</A><BR>
 </UL>
 
-<H2>O</H2>
+<H3>P</H3>
 
-<H2>P</H2>
 <UL>
 <A HREF="rfc2869.html#Password-Retry">Password-Retry</A><BR>
 <A HREF="rfc2865.html#Port-Limit">Port-Limit</A><BR>
-<A HREF="rfc2869.html#Prompt">Prompt</A><BR>
 <A HREF="rfc2865.html#Proxy-State">Proxy-State</A><BR>
 </UL>
 
-<H2>Q</H2>
+<H3>R</H3>
 
-<H2>R</H2>
 <UL>
 <A HREF="rfc2865.html#Reply-Message">Reply-Message</A><BR>
 </UL>
 
-<H2>S</H2>
+<H3>S</H3>
+
 <UL>
+<A HREF="rfc4590.html#SIP-AOR">SIP-AOR</A><BR>
 <A HREF="rfc2865.html#Service-Type">Service-Type</A><BR>
 <A HREF="rfc2865.html#Session-Timeout">Session-Timeout</A><BR>
 <A HREF="rfc2865.html#State">State</A><BR>
 </UL>
 
-<H2>T</H2>
+<H3>T</H3>
+
 <UL>
-<A HREF="rfc2809.html#Telephone-number">Telephone-number</A><BR>
 <A HREF="rfc2865.html#Termination-Action">Termination-Action</A><BR>
 <A HREF="rfc2868.html#Tunnel-Assignment-ID">Tunnel-Assignment-ID</A><BR>
 <A HREF="rfc2868.html#Tunnel-Client-Auth-ID">Tunnel-Client-Auth-ID</A><BR>
@@ -199,7 +221,6 @@ relevant RFC's.  Any errors or omissions are unintentional.
 <A HREF="rfc2867.html#Tunnel-Link-Start">Tunnel-Link-Start</A><BR>
 <A HREF="rfc2867.html#Tunnel-Link-Stop">Tunnel-Link-Stop</A><BR>
 <A HREF="rfc2868.html#Tunnel-Medium-Type">Tunnel-Medium-Type</A><BR>
-<A HREF="rfc2868.html#Tunnel-Medium-Type">Tunnel-Medium-Type</A><BR>
 <A HREF="rfc2868.html#Tunnel-Password">Tunnel-Password</A><BR>
 <A HREF="rfc2868.html#Tunnel-Preference">Tunnel-Preference</A><BR>
 <A HREF="rfc2868.html#Tunnel-Private-Group-ID">Tunnel-Private-Group-ID</A><BR>
@@ -211,21 +232,16 @@ relevant RFC's.  Any errors or omissions are unintentional.
 <A HREF="rfc2868.html#Tunnel-Type">Tunnel-Type</A><BR>
 </UL>
 
-<H2>U</H2>
+<H3>U</H3>
+
 <UL>
 <A HREF="rfc2865.html#User-Name">User-Name</A><BR>
 <A HREF="rfc2865.html#User-Password">User-Password</A><BR>
 </UL>
 
-<H2>V</H2>
+<H3>V</H3>
+
 <UL>
 <A HREF="rfc2865.html#Vendor-Specific">Vendor-Specific</A><BR>
 </UL>
-
-<H2>W</H2>
-<H2>X</H2>
-<H2>Y</H2>
-<H2>Z</H2>
-
-</body>
-</html>
+</BODY>
index 6ab0ab1..61486ee 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 foreach $file (@ARGV) {
     open FILE, "<$file" || die "Error opening $file: $!\n";
 
@@ -10,7 +10,14 @@ foreach $file (@ARGV) {
 
        chop;
        split;
+
+       next if ($_[1] =~ /,/);
+
+       next if (defined($file{$_[1]}));
+
        print $ref, "\t", $_[1], "\n";
+
+       $file{$_[1]} = $ref;
     }
 
     close FILE;
diff --git a/doc/rfc/per-rfc.pl b/doc/rfc/per-rfc.pl
new file mode 100755 (executable)
index 0000000..7705afd
--- /dev/null
@@ -0,0 +1,65 @@
+#!/usr/bin/env perl
+
+#
+#   Read in the references, and put into an associative array
+#
+open FILE, "<refs" || die "Error opening refs: $!\n";
+while (<FILE>) {
+    chop;
+    split;
+    
+    $refs{$_[1]} = $_[0];
+    $defs{$_[0]}{$_[1]}++;
+}
+close FILE;
+
+#
+#  now loop over the input RFC's.
+#
+foreach $file (@ARGV) {
+    $def=$file;
+    $def =~ s/\.txt//;
+
+    $attribute = "zzzzz";
+
+    # get the current reference
+    $ref = $file;
+    $ref =~ s/\..*//g;
+    $rfc = $ref;
+    $ref = "attributes-$ref";
+
+    open OUTPUT, ">$ref.html" || die "Error creating $ref.html: $!\n";
+
+    #
+    #  Print out the HTML header
+    #
+    print OUTPUT <<EOF;
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<HTML>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="GENERATOR" content="Perl">
+   <title>$rfc Index of Attributes</title>
+</head>
+<body>
+<h1>$rfc Attribute List</h1>
+EOF
+
+  $letter = "@";
+
+  foreach $key (sort keys %{$defs{$def}}) {
+    if (substr($key,0,1) ne $letter) {
+      print OUTPUT "</UL>\n" if ($letter ne "@");
+      $letter = substr($key,0,1);
+      print OUTPUT "\n<H3>$letter</H3>\n\n";
+      print OUTPUT "<UL>\n";
+    }
+    
+    print OUTPUT "<A HREF=\"$refs{$key}.html#$key\">$key</A><BR />\n";
+
+  }
+
+  print OUTPUT "</UL>\n";
+  print OUTPUT "</BODY>\n";
+  close OUTPUT;
+}
index 78d7be1..73039c7 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 #
 #   Read in the references, and put into an associative array
@@ -64,13 +64,13 @@ EOF
        #
        #  Attribute name header.
        #
-       if (/^\d+\./) {
+       if (/^\d+\./ && !/\d$/) {
            split;
 
            if ($refs{$_[1]} ne "") {
                $attribute = $_[1];
                
-               print OUTPUT "<A NAME=\"$attribute\"><H2>$_[0] $attribute</H2></a>\n";
+               print OUTPUT "<A NAME=\"$attribute\"><H2>$_</H2></a>\n";
                
            } else {
                print OUTPUT "<H2>$_</H2>\n";
@@ -122,7 +122,7 @@ EOF
 #
 #  And finally, create the index.
 #
-open OUTPUT, ">index.html" || die "Error creating index.html: $!\n";
+open OUTPUT, ">attributes.html" || die "Error creating attributes.html: $!\n";
 
 #
 #  Print out the HTML header
@@ -144,12 +144,16 @@ $letter = "@";
 
 foreach $key (sort keys %refs) {
     if (substr($key,0,1) ne $letter) {
+       print OUTPUT "</UL>\n" if ($letter ne "@");
        $letter = substr($key,0,1);
        print OUTPUT "\n<H3>$letter</H3>\n\n";
+        print OUTPUT "<UL>\n";
     }
     
     print OUTPUT "<A HREF=\"$refs{$key}.html#$key\">$key</A><BR>\n";
 }
 
+print OUTPUT "</UL>\n";
+
 print OUTPUT "</BODY>\n";
 close OUTPUT;
diff --git a/doc/rfc/rfc2607.txt b/doc/rfc/rfc2607.txt
new file mode 100644 (file)
index 0000000..2d34c5b
--- /dev/null
@@ -0,0 +1,843 @@
+
+
+
+
+
+
+Network Working Group                                           B. Aboba
+Request for Comments: 2607                         Microsoft Corporation
+Category: Informational                                    J. Vollbrecht
+                                                    Merit Networks, Inc.
+                                                               June 1999
+
+
+          Proxy Chaining and Policy Implementation in Roaming
+
+Status of this Memo
+
+   This memo provides information for the Internet community.  It does
+   not specify an Internet standard of any kind.  Distribution of this
+   memo is unlimited.
+
+Copyright Notice
+
+   Copyright (C) The Internet Society (1999).  All Rights Reserved.
+
+1.  Abstract
+
+   This document describes how proxy chaining and policy implementation
+   can be supported in roaming systems. The mechanisms described in this
+   document are in current use.
+
+   However, as noted in the security considerations section, the
+   techniques outlined in this document are vulnerable to attack from
+   external parties as well as susceptible to fraud perpetrated by the
+   roaming partners themselves. As a result, such methods are not
+   suitable for wide-scale deployment on the Internet.
+
+2.  Terminology
+
+   This document frequently uses the following terms:
+
+   Network Access Server
+      The Network Access Server (NAS) is the device that clients contact
+      in order to get access to the network.
+
+   RADIUS server
+      This is a server which provides for authentication/authorization
+      via the protocol described in [3], and for accounting as described
+      in [4].
+
+
+
+
+
+
+
+
+Aboba & Vollbrecht           Informational                      [Page 1]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+   RADIUS proxy
+      In order to provide for the routing of RADIUS authentication and
+      accounting requests, a RADIUS proxy can be employed. To the NAS,
+      the RADIUS proxy appears to act as a RADIUS server, and to the
+      RADIUS server, the proxy appears to act as a RADIUS client.
+
+   Network Access Identifier
+      In order to provide for the routing of RADIUS authentication and
+      accounting requests, the userID field used in PPP (known as the
+      Network Access Identifier or NAI) and in the subsequent RADIUS
+      authentication and accounting requests, can contain structure.
+      This structure provides a means by which the RADIUS proxy will
+      locate the RADIUS server that is to receive the request. The NAI
+      is defined in [6].
+
+   Roaming relationships
+      Roaming relationships include relationships between companies and
+      ISPs, relationships among peer ISPs within a roaming association,
+      and relationships between an ISP and a roaming consortia.
+      Together, the set of relationships forming a path between a local
+      ISP's authentication proxy and the home authentication server is
+      known as the roaming relationship path.
+
+3.  Requirements language
+
+   In this document, the key words "MAY", "MUST, "MUST NOT", "optional",
+   "recommended", "SHOULD", and "SHOULD NOT", are to be interpreted as
+   described in [5].
+
+4.  Introduction
+
+   Today, as described in [1], proxy chaining is widely deployed for the
+   purposes of providing roaming services. In such systems,
+   authentication/authorization and accounting packets are routed
+   between a NAS device and a home server through a series of proxies.
+   Consultation of the home server is required for password-based
+   authentication, since the home server maintains the password database
+   and thus it is necessary for the NAS to communicate with the home
+   authentication server in order to verify the user's identity.
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba & Vollbrecht           Informational                      [Page 2]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+4.1.  Advantages of proxy chaining
+
+   Proxies serve a number of functions in roaming, including:
+
+   Scalability improvement
+   Authentication forwarding
+   Capabilities adjustment
+   Policy implementation
+   Accounting reliability improvement
+   Atomic operation
+
+   Scalability improvement
+      In large scale roaming systems, it is necessary to provide for
+      scalable management of keys used for integrity protection and
+      authentication.
+
+      Proxy chaining enables implementation of hierarchical
+      forwarding within roaming systems, which improves scalability
+      in roaming consortia based on authentication protocols without
+      automated key management.  Since RADIUS as described in [3]
+      requires a shared secret for each client-server pair, a
+      consortium of 100 roaming partners would require 4950 shared
+      secrets if each partner were to contact each other directly,
+      one for each partner pair.  However, were the partners to
+      route authentication requests through a central proxy, only
+      100 shared secrets would be needed, one for each partner. The
+      reduction in the number of partner pairs also brings with it
+      other benefits, such as a reduction in the number of bilateral
+      agreements and accounting and auditing overhead.  Thus,
+      hierarchical routing might be desirable even if an
+      authentiation protocol supporting automated key exchange were
+      available.
+
+   Capabilities adjustment
+      As part of the authentication exchange with the home server,
+      the NAS receives authorization parameters describing the
+      service to be provided to the roaming user.  Since RADIUS,
+      described in [3], does not support capabilities negotiation,
+      it is possible that the authorization parameters sent by the
+      home server will not match those required by the NAS. For
+      example, a static IP address could be specified that would not
+      be routable by the NAS. As a result, capbilities adjustment is
+      performed by proxies in order to enable communication between
+      NASes and home servers with very different feature sets.
+
+
+
+
+
+
+
+Aboba & Vollbrecht           Informational                      [Page 3]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+      As part of capabilities adjustment, proxies can edit
+      attributes within the Access-Accept in order to ensure
+      compatibility with the NAS.  Such editing may include
+      addition, deletion, or modification of attributes. In
+      addition, in some cases it may be desirable for a proxy to
+      edit attributes within an Access-Request in order to clean up
+      or even hide information destined for the home server.  Note
+      that if the proxy edits attributes within the Access-Accept,
+      then it is possible that the service provided to the user may
+      not be the same as that requested by the home server. This
+      creates the possibility of disputes arising from inappropriate
+      capabilities adjustment.
+
+      Note that were roaming to be implemented based on an
+      authentication/authorization protocol with built-in capability
+      negotiation, proxy-based capabilities adjustment would
+      probably not be necessary.
+
+   Authentication forwarding
+      Since roaming associations frequently implement hierarchical
+      forwarding in order to improve scalability, in order for a NAS
+      and home server to communicate, authentication and accounting
+      packets are forwarded by one or more proxies. The path
+      travelled by these packets, known as the roaming relationship
+      path, is determined from the Network Access Identifier (NAI),
+      described in [6]. Since most NAS devices do not implement
+      forwarding logic, a proxy is needed to enable forwarding of
+      authentication and accounting packets. For reasons that are
+      described in the security section, in proxy systems it is
+      desirable for accounting and authentication packets to follow
+      the same path.
+
+      Note: The way a proxy learns the mapping between NAI and the
+      home server is  beyond  the  scope  of this document. This
+      mapping can be accomplished by static configuration in the
+      proxy, or by some currently undefined protocol that provides
+      for dynamic mapping. For the purposes of this document, it is
+      assumed that such a mapping capability exists in the proxy.
+
+   Policy implementation
+      In roaming systems it is often desirable to be able to
+      implement policy. For example, a given partner may only be
+      entitled to use of a given NAS during certain times of the
+      day. In order to implement such policies, proxies may be
+      implemented at the interface between administrative domains
+      and programmed to modify authentication/authorization packets
+      forwarded between the NAS and the home server. As a result,
+      from a security point of view, a proxy implementing policy
+
+
+
+Aboba & Vollbrecht           Informational                      [Page 4]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+      operates as a "man in the middle."
+
+   Accounting reliability improvement
+      In roaming systems based on proxy chaining, it is necessary
+      for accounting information to be forwarded between the NAS and
+      the home server. Thus roaming is inherently an interdomain
+      application.
+
+      This represents a problem since the RADIUS accounting
+      protocol, described in [4] is not designed for use on an
+      Internet scale.  Given that in roaming accounting packets
+      travel between administrative domains, packets will often pass
+      through network access points (NAPs) where packet loss may be
+      substantial. This can result in unacceptable rates of
+      accounting data loss.
+
+      For example, in a proxy chaining system involving four
+      systems, a one percent failure rate on each hop can result in
+      loss of 3.9 percent of all accounting transactions. Placement
+      of an accounting proxy near the NAS may improve reliability by
+      enabling enabling persistent storage of accounting records and
+      long duration retry.
+
+   Atomic operation
+      In order to ensure consistency among all parties required to
+      process accounting data, it can be desirable to assure that
+      transmission of accounting data is handled as an atomic
+      operation. This implies that all parties on the roaming
+      relationship path will receive and acknowledge the receipt of
+      the accounting data for the operation to complete. Proxies can
+      be used to ensure atomic delivery of accounting data by
+      arranging for delivery of the accounting data in a serial
+      fashion, as discussed in section 5.2.
+
+5.  Proxy chaining
+
+   An example of a proxy chaining system is shown below.
+
+         (request)          (request)          (request)
+     NAS ----------> Proxy1 ----------> Proxy2 ----------> Home
+         (reply)            (reply)            (reply)     Server
+         <---------         <---------         <---------
+
+   In the above diagram, the NAS generates a request and sends it to
+   Proxy1.  Proxy1 forwards the request to Proxy2 and Proxy2 forwards
+   the request to the Home Server.  The Home Server generates a reply
+   and sends it to Proxy2.  Proxy2 receives the reply, matches it with
+   the request it had sent, and forwards a reply to Proxy1. Proxy1
+
+
+
+Aboba & Vollbrecht           Informational                      [Page 5]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+   matches the reply with the request it sent earlier and forwards a
+   reply to the NAS.  This model applies to all requests, including
+   Access Requests and Accounting Requests.
+
+   Except for the two cases described below, a proxy server such as
+   Proxy2 in the diagram above SHOULD NOT send a Reply packet to Proxy1
+   without first having received a Reply packet initiated by the Home
+   Server.  The two exceptions are when the proxy is enforcing policy as
+   described in section 5.1 and when the proxy is acting as an
+   accounting store (as in store and forward), as described in section
+   5.2.
+
+   The RADIUS protocol described in [3] does not provide for end-to-end
+   security services, including integrity or replay protection,
+   authentication or confidentiality. As noted in the security
+   considerations section, this omission results in several security
+   problems within proxy chaining systems.
+
+5.1.  Policy implementation
+
+   Proxies are frequently used to implement policy in roaming
+   situations.  Proxies implementing policy MAY reply directly to
+   Access-Requests without forwarding the request. When replying
+   directly to an Access-Request, the proxy MUST reply either with an
+   Access-Reject or an Access-Challenge packet. A proxy MUST NOT reply
+   directly with an Access-Accept.  An example of this would be when the
+   proxy refuses all connections from a particular realm during prime
+   time. In this case the home server will never receive th Access-
+   Request.  This situation is shown below:
+
+         (request)          (request)
+     NAS ----------> Proxy1 ----------> Proxy2             Home
+         (reply)            (reply)                        Server
+         <---------         <---------
+
+   A proxy MAY also decide to Reject a Request that has been accepted by
+   the home server.  This could be based on the set of attributes
+   returned by the home server.  In this case the Proxy SHOULD send an
+   Access-Reject to the NAS and an Accounting-Request with Acct-Status-
+   Type=Proxy-Stop (6) to the home server.  This lets the home server
+   know that the session it approved has been denied downstream by the
+   proxy.  However, a proxy MUST NOT send an Access-Accept after
+   receiving an Access-Reject from a proxy or from the home server.
+
+
+
+
+
+
+
+
+Aboba & Vollbrecht           Informational                      [Page 6]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+         (Access-Req)       (Access-Req)       (Access-Req)
+     NAS ----------> Proxy1 ----------> Proxy2 ---------->     Home
+         (Access-Reject)    (Access-Accept)    (Access-Accept) Server
+         <---------         <---------         <---------
+                            (AcctPxStop)       (AcctPxStop)
+                            ---------->        ---------->
+
+5.2.  Accounting behavior
+
+   As described above, a proxy MUST NOT reply directly with an Access-
+   Accept, and MUST NOT reply with an Access-Accept when it has received
+   an Access-Reject from another proxy or Home Server. As a result, in
+   all cases where an accounting record is to be generated (accepted
+   sessions), no direct replies have occurred, and the Access-Request
+   and Access-Accept have passed through the same set of systems.
+
+   In order to allow proxies to match incoming Accounting-Requests with
+   previously handled Access-Requests and Access-Accepts, a proxy SHOULD
+   route the Accounting-Request along the same realm path travelled in
+   authentication/authorization.  Note that this does not imply that
+   accounting packets will necessarily travel the identical path,
+   machine by machine, as did authentication/authorization packets.
+   This is because it is conceivable that a proxy may have gone down,
+   and as a result the Accounting-request may need to be forwarded to an
+   alternate server. It is also conceivable that
+   authentication/authorization and accounting may be handled by
+   different servers within a realm.
+
+   The Class attribute can be used to match Accounting Requests with
+   prior Access Requests.  It can also be used to match session log
+   records between the home Server, proxies, and NAS. This matching can
+   be accomplished either in real-time (in the case that authentication
+   and accounting packets follow the same path, machine by machine), or
+   after the fact.
+
+   Home servers SHOULD insert a unique session identifier in the Class
+   attribute in an Access-Accept and Access-Challenge.  Proxies and
+   NASes MUST forward the unmodified Class attribute.  The NAS MUST
+   include the Class attribute in subsequent requests, in particular for
+   Accounting-Requests. The sequence of events is shown below:
+
+
+
+
+
+
+
+
+
+
+
+Aboba & Vollbrecht           Informational                      [Page 7]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+                      Authentication/Authorization
+
+      -------->         -------->          --------->
+ NAS            Proxy1              Proxy2             Home (add class)
+     <-class--          <-class-           <-class--
+
+
+                               Accounting
+
+     (Accounting-req)   (Accounting-req)  (Accounting-req)
+         w/class           w/class            w/class
+  NAS ----------> Proxy1 ----------> Proxy2 ---------->       Home
+      (Accounting-reply) (Accounting-reply)(Accounting-reply) Server
+      <---------         <---------         <---------
+
+   Since there is no need to implement policy in accounting, a proxy
+   MUST forward all Accounting Requests to the next server on the path.
+   The proxy MUST guarantee that the Accounting Request is received by
+   the End Server and all intermediate servers.  The proxy may do this
+   either by: 1) forwarding the Accounting Request and not sending a
+   Reply until it receives the matching Reply from the upstream server,
+   or 2) acting as a store point which takes responsibility for
+   reforwarding the Accounting Request until it receives a Reply.
+
+   Note that when the proxy does not send a reply until it receives a
+   matching reply, this ensures that Accounting Start and Stop messages
+   are received and can be logged by all servers along the roaming
+   relationship path. If one of the servers is not available, then the
+   operation will fail. As a result the entire accounting transaction
+   will either succeed or fail as a unit, and thus can be said to be
+   atomic.
+
+   Where store and forward is implemented, it is possible that one or
+   more servers along the roaming relationship path will not receive the
+   accounting data while others will. The accounting operation will not
+   succeed or fail as a unit, and is therefore not atomic.  As a result,
+   it may not be possible for the roaming partners to reconcile their
+   audit logs, opening new opportunities for fraud.  Where store and
+   forward is implemented, forwarding of Accounting Requests SHOULD be
+   done as they are received so the downstream servers will receive them
+   in a timely way.
+
+   Note that there are cases where a proxy will need to forward an
+   Accounting packet to more than one system. For example, in order to
+   allow for proper accounting in the case of a NAS that is shutting
+   down, the proxy can send an Accounting-Request with Acct-Status-
+   Type=Accounting-Off (8) to all realms that it forwards to.  In turn,
+   these proxies will also flood the packet to their connected realms.
+
+
+
+Aboba & Vollbrecht           Informational                      [Page 8]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+6.  References
+
+   [1]  Aboba, B., Lu J., Alsop J., Ding J. and W. Wang, "Review of
+        Roaming Implementations", RFC 2194, September 1997.
+
+   [2]  Aboba, B. and G. Zorn, "Criteria for Evaluating Roaming
+        Protocols", RFC 2477, January 1999.
+
+   [3]  Rigney, C., Rubens, A., Simpson, W. and S. Willens, "Remote
+        Authentication Dial In User Service (RADIUS)", RFC 2138, April
+        1997.
+
+   [4]  Rigney, C., "RADIUS  Accounting", RFC 2139, April 1997.
+
+   [5]  Bradner, S., "Key words for use in RFCs to Indicate Requirement
+        Levels", BCP 14, RFC 2119, March 1997.
+
+   [6]  Aboba, B. and M. Beadles, "The Network Access Identifier", RFC
+        2486, January 1999.
+
+7.  Security Considerations
+
+   The RADIUS protocol described in [3] was designed for intra-domain
+   use, where the NAS, proxy, and home server exist within a single
+   administrative domain, and proxies may be considered a trusted
+   component. However, in roaming the NAS, proxies, and home server will
+   typically be managed by different administrative entities. As a
+   result, roaming is inherently an inter-domain application, and
+   proxies cannot necessarily be trusted.  This results in a number of
+   security threats, including:
+
+      Message editing
+      Attribute editing
+      Theft of passwords
+      Theft and modification of accounting data
+      Replay attacks
+      Connection hijacking
+      Fraudulent accounting
+
+7.1.  Message editing
+
+   Through the use of shared secrets it is possible for proxies
+   operating in different domains to establish a trust relationship.
+   However, if only hop-by-hop security is available then untrusted
+   proxies are capable of perpetrating a number of man-in-the-middle
+   attacks.  These include modification of messages.
+
+
+
+
+
+Aboba & Vollbrecht           Informational                      [Page 9]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+   For example, an Access-Accept could be substituted for an Access-
+   Reject, and without end-to-end integrity protection, there is no way
+   for the NAS to detect this. On the home server, this will result in
+   an accounting log entry for a session that was not authorized.
+   However, if the proxy does not forward accounting packets or session
+   records to the home server, then the home server will not be able to
+   detect the discrepancy until a bill is received and audited.
+
+   Note that a proxy can also send an Access-Reject to the NAS after
+   receiving an Access-Accept from the home server. This will result in
+   an authentication log entry without a corresponding accounting log
+   entry.  Without the proxy sending an Accounting-Request with Acct-
+   Status-Type=Proxy-Stop (6) to the home server, then there will be no
+   way for the home server to determine whether the discrepancy is due
+   to policy implementation or loss of accounting packets.  Thus the use
+   of Acct-Status-Type=Proxy-Stop can be of value in debugging roaming
+   systems.
+
+   It should be noted that even if end-to-end security were to be
+   available, a number of sticky questions would remain. While the end-
+   points would be able to detect that the message from the home server
+   had been modified by an intermediary, the question arises as to what
+   action should be taken. While the modified packet could be silently
+   discarded, this could affect the ability of the home server to .
+   accept an Acct-Status-Type=Proxy-Stop message from an intermediate
+   proxy. Since this message would not be signed by the NAS, it may need
+   to be dropped by the home server.
+
+   This is similar to the problem that IPSEC-capable systems face in
+   making use of ICMP messages from systems with whom they do not have a
+   security association. The problem is more difficult here, since in
+   RADIUS retransmission is driven by the NAS.  Therefore the home
+   server does not receive acknowledgement for Access-Accepts and thus
+   would have no way of knowing that its response has not been honored.
+
+7.2.  Attribute editing
+
+   RADIUS as defined in [3] does not provide for end-to-end security or
+   capabilities negotiation. As a result there is no way for a home
+   server to securely negotiate a mutually acceptable configuration with
+   the NAS or proxies. As a result, a number of attribute editing
+   attacks are possible.
+
+   For example, EAP attributes might be removed or modified so as to
+   cause a client to authenticate with EAP MD5 or PAP, instead of a
+   stronger authentication method. Alternatively, tunnel attributes
+   might be removed or modified so as to remove encryption, redirect the
+   tunnel to a rogue tunnel server, or otherwise lessen the security
+
+
+
+Aboba & Vollbrecht           Informational                     [Page 10]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+   provided to the client.  The mismatch between requested and received
+   services may only be detectable after the fact by comparing the
+   Access-Accept attributes against the attributes included in the
+   Accounting-Request. However, without end-to-end security services, it
+   is possible for a rogue proxy to cover its tracks.
+
+   Due to the complexity of proxy configuration, such attacks need not
+   involve malice, but can occur due to mis-configuration or
+   implementation deficiencies.  Today several proxy implementations
+   remove attributes that they do not understand, or can be set up to
+   replace attribute sets sent in the Access-Accept with sets of
+   attributes appropriate for a particular NAS.
+
+   In practice, it is not possible to define a set of guidelines for
+   attribute editing, since the requirements are very often
+   implementation-specific. At the same time, protection against
+   inappropriate attribute editing is necessary to guard against attacks
+   and provide assurance that users are provisioned as directed by the
+   home server.
+
+   Since it is not possible to determine beforehand whether a given
+   attribute is editable or not, a mechanism needs to be provided to
+   allow senders to indicate which attributes are editable and which are
+   not, and for the receivers to detect modifications of "non-editable"
+   attributes.  Through implementation of end-to-end security it may be
+   possible to detect unauthorized addition, deletion, or modification
+   of integrity-protected attributes. However, it would still possible
+   for a rogue proxy to add, delete or modify attributes that are not
+   integrity-protected. If such attributes influence subsequent charges,
+   then the possibility of fraud would remain.
+
+7.3.  Theft of passwords
+
+   RADIUS as defined in [3] does not provide for end-to-end
+   confidentiality. As a result, where clients authenticate using PAP,
+   each proxy along the path between the local NAS and the home server
+   will have access to the cleartext password. In many circumstances,
+   this represents an unacceptable security risk.
+
+7.4.  Theft and modification of accounting data
+
+   Typically in roaming systems, accounting packets are provided to all
+   the participants along the roaming relationship path, in order to
+   allow them to audit subsequent invoices. RADIUS as described in [3]
+   does not provide for end-to-end security services, including
+   integrity protection or confidentiality. Without end-to-end integrity
+   protection, it is possible for proxies to modify accounting packets
+   or session records.  Without end-to-end confidentiality, accounting
+
+
+
+Aboba & Vollbrecht           Informational                     [Page 11]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+   data will be accessible to proxies.  However, if the objective is
+   merely to prevent snooping of accounting data on the wire, then IPSEC
+   ESP can be used.
+
+7.5.  Replay attacks
+
+   In this attack, a man in the middle or rogue proxy collects CHAP-
+   Challenge and CHAP-Response attributes, and later replays them. If
+   this attack is performed in collaboration with an unscrupulous ISP,
+   it can be used to subsequently submit fraudulent accounting records
+   for payment.  The system performing the replay need not necessarily
+   be the one that initially captured the CHAP Challenge/Response pair.
+
+   While RADIUS as described in [3] is vulnerable to replay attacks,
+   without roaming the threat is restricted to proxies operating in the
+   home server's domain. With roaming, such an attack can be mounted by
+   any proxy capable of reaching the home server.
+
+7.6.  Connection hijacking
+
+   In this form of attack, the attacker attempts to inject packets into
+   the conversation between the NAS and the home server. RADIUS as
+   described in [3] is vulnerable to such attacks since only Access-
+   Reply and Access-Challenge packets are authenticated.
+
+7.7.  Fraudulent accounting
+
+   In this form of attack, a local proxy transmits fraudulent accounting
+   packets or session records in an effort to collect fees to which they
+   are not entitled. This includes submission of packets or session
+   records for non-existent sessions. Since in RADIUS as described in
+   [3], there is no end-to-end security, a rogue proxy may insert or
+   edit packets without fear of detection.
+
+   In order to detect submissions of accounting packets or session
+   records for non-existent sessions, parties receiving accounting
+   packets or session records would be prudent to reconcile them with
+   the authentication logs. Such reconciliation is only typically
+   possible when the party acts as an authentication proxy for all
+   sessions for which an accounting record will subsequently be
+   submitted.
+
+   In order to make reconciliation easier, home servers involved in
+   roaming include a Class attribute in the Access-Accept.  The Class
+   attribute uniquely identifies a session, so as to allow an
+   authentication log entry to be matched with a corresponding
+   accounting packet or session record.
+
+
+
+
+Aboba & Vollbrecht           Informational                     [Page 12]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+   If reconciliation is put in place and all accounting log entries
+   without a corresponding authentication are rejected, then the
+   attacker will need to have obtained a valid user password prior to
+   submitting accounting packets or session records on non-existent
+   sessions. While use of end-to-end security can defeat unauthorized
+   injection or editing of accounting or authentication packets by
+   intermediate proxies, other attacks remain feasible. For example,
+   unless replay protection is put in place, it is still feasible for an
+   intermediate proxy to resubmit authentication or accounting packets
+   or session records. In addition, end-to-end security does not provide
+   protection against attacks by the local proxy, since this is
+   typically where end-to-end security will be initiated. To detect such
+   attacks, other measures need to be put in place, such as systems for
+   detecting unusual activity of ISP or user accounts, or for
+   determining whether a user or ISP account is within their credit
+   limit.
+
+   Note that implementation of the store and forward approach to proxy
+   accounting makes it possible for some systems in the roaming
+   relationship path to receive accounting records that other systems do
+   not get. This can result in audit discrepancies. About the best that
+   is achievable in such cases is to verify that the accounting data is
+   missing by checking against the authentication logs.
+
+8.  Acknowledgments
+
+   Thanks to Pat Calhoun of Sun Microsystems, Mark Beadles of
+   CompuServe, Aydin Edguer of Morningstar, Bill Bulley of Merit, and
+   Steven P. Crain of Shore.Net for useful discussions of this problem
+   space.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba & Vollbrecht           Informational                     [Page 13]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+9.  Authors' Addresses
+
+   Bernard Aboba
+   Microsoft Corporation
+   One Microsoft Way
+   Redmond, WA 98052
+
+   Phone: 425-936-6605
+   EMail: bernarda@microsoft.com
+
+
+   John R. Vollbrecht
+   Merit Network, Inc.
+   4251 Plymouth Rd.
+   Ann Arbor, MI 48105-2785
+
+   Phone: 313-763-1206
+   EMail: jrv@merit.edu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba & Vollbrecht           Informational                     [Page 14]
+\f
+RFC 2607          Proxy Chaining and Policy in Roaming         June 1999
+
+
+10.  Full Copyright Statement
+
+   Copyright (C) The Internet Society (1999).  All Rights Reserved.
+
+   This document and translations of it may be copied and furnished to
+   others, and derivative works that comment on or otherwise explain it
+   or assist in its implementation may be prepared, copied, published
+   and distributed, in whole or in part, without restriction of any
+   kind, provided that the above copyright notice and this paragraph are
+   included on all such copies and derivative works.  However, this
+   document itself may not be modified in any way, such as by removing
+   the copyright notice or references to the Internet Society or other
+   Internet organizations, except as needed for the purpose of
+   developing Internet standards in which case the procedures for
+   copyrights defined in the Internet Standards process must be
+   followed, or as required to translate it into languages other than
+   English.
+
+   The limited permissions granted above are perpetual and will not be
+   revoked by the Internet Society or its successors or assigns.
+
+   This document and the information contained herein is provided on an
+   "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+   TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+   BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+   HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Acknowledgement
+
+   Funding for the RFC Editor function is currently provided by the
+   Internet Society.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba & Vollbrecht           Informational                     [Page 15]
+\f
diff --git a/doc/rfc/rfc3748.txt b/doc/rfc/rfc3748.txt
new file mode 100644 (file)
index 0000000..75600c1
--- /dev/null
@@ -0,0 +1,3755 @@
+
+
+
+
+
+
+Network Working Group                                           B. Aboba
+Request for Comments: 3748                                     Microsoft
+Obsoletes: 2284                                                 L. Blunk
+Category: Standards Track                             Merit Network, Inc
+                                                           J. Vollbrecht
+                                               Vollbrecht Consulting LLC
+                                                              J. Carlson
+                                                                     Sun
+                                                       H. Levkowetz, Ed.
+                                                             ipUnplugged
+                                                               June 2004
+
+
+                Extensible Authentication Protocol (EAP)
+
+Status of this Memo
+
+   This document specifies an Internet standards track protocol for the
+   Internet community, and requests discussion and suggestions for
+   improvements.  Please refer to the current edition of the "Internet
+   Official Protocol Standards" (STD 1) for the standardization state
+   and status of this protocol.  Distribution of this memo is unlimited.
+
+Copyright Notice
+
+   Copyright (C) The Internet Society (2004).
+
+Abstract
+
+   This document defines the Extensible Authentication Protocol (EAP),
+   an authentication framework which supports multiple authentication
+   methods.  EAP typically runs directly over data link layers such as
+   Point-to-Point Protocol (PPP) or IEEE 802, without requiring IP.  EAP
+   provides its own support for duplicate elimination and
+   retransmission, but is reliant on lower layer ordering guarantees.
+   Fragmentation is not supported within EAP itself; however, individual
+   EAP methods may support this.
+
+   This document obsoletes RFC 2284.  A summary of the changes between
+   this document and RFC 2284 is available in Appendix A.
+
+
+
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                     [Page 1]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+Table of Contents
+
+   1.   Introduction. . . . . . . . . . . . . . . . . . . . . . . . .  3
+        1.1.  Specification of Requirements . . . . . . . . . . . . .  4
+        1.2.  Terminology . . . . . . . . . . . . . . . . . . . . . .  4
+        1.3.  Applicability . . . . . . . . . . . . . . . . . . . . .  6
+   2.   Extensible Authentication Protocol (EAP). . . . . . . . . . .  7
+        2.1.  Support for Sequences . . . . . . . . . . . . . . . . .  9
+        2.2.  EAP Multiplexing Model. . . . . . . . . . . . . . . . . 10
+        2.3.  Pass-Through Behavior . . . . . . . . . . . . . . . . . 12
+        2.4.  Peer-to-Peer Operation. . . . . . . . . . . . . . . . . 14
+   3.   Lower Layer Behavior. . . . . . . . . . . . . . . . . . . . . 15
+        3.1.  Lower Layer Requirements. . . . . . . . . . . . . . . . 15
+        3.2.  EAP Usage Within PPP. . . . . . . . . . . . . . . . . . 18
+              3.2.1. PPP Configuration Option Format. . . . . . . . . 18
+        3.3.  EAP Usage Within IEEE 802 . . . . . . . . . . . . . . . 19
+        3.4.  Lower Layer Indications . . . . . . . . . . . . . . . . 19
+   4.   EAP Packet Format . . . . . . . . . . . . . . . . . . . . . . 20
+        4.1.  Request and Response. . . . . . . . . . . . . . . . . . 21
+        4.2.  Success and Failure . . . . . . . . . . . . . . . . . . 23
+        4.3.  Retransmission Behavior . . . . . . . . . . . . . . . . 26
+   5.   Initial EAP Request/Response Types. . . . . . . . . . . . . . 27
+        5.1.  Identity. . . . . . . . . . . . . . . . . . . . . . . . 28
+        5.2.  Notification. . . . . . . . . . . . . . . . . . . . . . 29
+        5.3.  Nak . . . . . . . . . . . . . . . . . . . . . . . . . . 31
+              5.3.1. Legacy Nak . . . . . . . . . . . . . . . . . . . 31
+              5.3.2. Expanded Nak . . . . . . . . . . . . . . . . . . 32
+        5.4.  MD5-Challenge . . . . . . . . . . . . . . . . . . . . . 35
+        5.5.  One-Time Password (OTP) . . . . . . . . . . . . . . . . 36
+        5.6.  Generic Token Card (GTC). . . . . . . . . . . . . . . . 37
+        5.7.  Expanded Types. . . . . . . . . . . . . . . . . . . . . 38
+        5.8.  Experimental. . . . . . . . . . . . . . . . . . . . . . 40
+   6.   IANA Considerations . . . . . . . . . . . . . . . . . . . . . 40
+        6.1.  Packet Codes. . . . . . . . . . . . . . . . . . . . . . 41
+        6.2.  Method Types. . . . . . . . . . . . . . . . . . . . . . 41
+   7.   Security Considerations . . . . . . . . . . . . . . . . . . . 42
+        7.1.  Threat Model. . . . . . . . . . . . . . . . . . . . . . 42
+        7.2.  Security Claims . . . . . . . . . . . . . . . . . . . . 43
+              7.2.1. Security Claims Terminology for EAP Methods. . . 44
+        7.3.  Identity Protection . . . . . . . . . . . . . . . . . . 46
+        7.4.  Man-in-the-Middle Attacks . . . . . . . . . . . . . . . 47
+        7.5.  Packet Modification Attacks . . . . . . . . . . . . . . 48
+        7.6.  Dictionary Attacks. . . . . . . . . . . . . . . . . . . 49
+        7.7.  Connection to an Untrusted Network. . . . . . . . . . . 49
+        7.8.  Negotiation Attacks . . . . . . . . . . . . . . . . . . 50
+        7.9.  Implementation Idiosyncrasies . . . . . . . . . . . . . 50
+        7.10. Key Derivation. . . . . . . . . . . . . . . . . . . . . 51
+        7.11. Weak Ciphersuites . . . . . . . . . . . . . . . . . . . 53
+
+
+
+Aboba, et al.               Standards Track                     [Page 2]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+        7.12. Link Layer. . . . . . . . . . . . . . . . . . . . . . . 53
+        7.13. Separation of Authenticator and Backend Authentication
+              Server. . . . . . . . . . . . . . . . . . . . . . . . . 54
+        7.14. Cleartext Passwords . . . . . . . . . . . . . . . . . . 55
+        7.15. Channel Binding . . . . . . . . . . . . . . . . . . . . 55
+        7.16. Protected Result Indications. . . . . . . . . . . . . . 56
+   8.   Acknowledgements. . . . . . . . . . . . . . . . . . . . . . . 58
+   9.   References. . . . . . . . . . . . . . . . . . . . . . . . . . 59
+        9.1.  Normative References. . . . . . . . . . . . . . . . . . 59
+        9.2.  Informative References. . . . . . . . . . . . . . . . . 60
+   Appendix A. Changes from RFC 2284. . . . . . . . . . . . . . . . . 64
+   Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 66
+   Full Copyright Statement . . . . . . . . . . . . . . . . . . . . . 67
+
+1.  Introduction
+
+   This document defines the Extensible Authentication Protocol (EAP),
+   an authentication framework which supports multiple authentication
+   methods.  EAP typically runs directly over data link layers such as
+   Point-to-Point Protocol (PPP) or IEEE 802, without requiring IP.  EAP
+   provides its own support for duplicate elimination and
+   retransmission, but is reliant on lower layer ordering guarantees.
+   Fragmentation is not supported within EAP itself; however, individual
+   EAP methods may support this.
+
+   EAP may be used on dedicated links, as well as switched circuits, and
+   wired as well as wireless links.  To date, EAP has been implemented
+   with hosts and routers that connect via switched circuits or dial-up
+   lines using PPP [RFC1661].  It has also been implemented with
+   switches and access points using IEEE 802 [IEEE-802].  EAP
+   encapsulation on IEEE 802 wired media is described in [IEEE-802.1X],
+   and encapsulation on IEEE wireless LANs in [IEEE-802.11i].
+
+   One of the advantages of the EAP architecture is its flexibility.
+   EAP is used to select a specific authentication mechanism, typically
+   after the authenticator requests more information in order to
+   determine the specific authentication method to be used.  Rather than
+   requiring the authenticator to be updated to support each new
+   authentication method, EAP permits the use of a backend
+   authentication server, which may implement some or all authentication
+   methods, with the authenticator acting as a pass-through for some or
+   all methods and peers.
+
+   Within this document, authenticator requirements apply regardless of
+   whether the authenticator is operating as a pass-through or not.
+   Where the requirement is meant to apply to either the authenticator
+   or backend authentication server, depending on where the EAP
+   authentication is terminated, the term "EAP server" will be used.
+
+
+
+Aboba, et al.               Standards Track                     [Page 3]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+1.1.  Specification of Requirements
+
+   In this document, several words are used to signify the requirements
+   of the specification.  The key words "MUST", "MUST NOT", "REQUIRED",
+   "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY",
+   and "OPTIONAL" in this document are to be interpreted as described in
+   [RFC2119].
+
+1.2.  Terminology
+
+   This document frequently uses the following terms:
+
+   authenticator
+      The end of the link initiating EAP authentication.  The term
+      authenticator is used in [IEEE-802.1X], and has the same meaning
+      in this document.
+
+   peer
+      The end of the link that responds to the authenticator.  In
+      [IEEE-802.1X], this end is known as the Supplicant.
+
+   Supplicant
+      The end of the link that responds to the authenticator in [IEEE-
+      802.1X].  In this document, this end of the link is called the
+      peer.
+
+   backend authentication server
+      A backend authentication server is an entity that provides an
+      authentication service to an authenticator.  When used, this
+      server typically executes EAP methods for the authenticator.  This
+      terminology is also used in [IEEE-802.1X].
+
+   AAA
+      Authentication, Authorization, and Accounting.  AAA protocols with
+      EAP support include RADIUS [RFC3579] and Diameter [DIAM-EAP].  In
+      this document, the terms "AAA server" and "backend authentication
+      server" are used interchangeably.
+
+   Displayable Message
+      This is interpreted to be a human readable string of characters.
+      The message encoding MUST follow the UTF-8 transformation format
+      [RFC2279].
+
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                     [Page 4]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   EAP server
+      The entity that terminates the EAP authentication method with the
+      peer.  In the case where no backend authentication server is used,
+      the EAP server is part of the authenticator.  In the case where
+      the authenticator operates in pass-through mode, the EAP server is
+      located on the backend authentication server.
+
+   Silently Discard
+      This means the implementation discards the packet without further
+      processing.  The implementation SHOULD provide the capability of
+      logging the event, including the contents of the silently
+      discarded packet, and SHOULD record the event in a statistics
+      counter.
+
+   Successful Authentication
+      In the context of this document, "successful authentication" is an
+      exchange of EAP messages, as a result of which the authenticator
+      decides to allow access by the peer, and the peer decides to use
+      this access.  The authenticator's decision typically involves both
+      authentication and authorization aspects; the peer may
+      successfully authenticate to the authenticator, but access may be
+      denied by the authenticator due to policy reasons.
+
+   Message Integrity Check (MIC)
+      A keyed hash function used for authentication and integrity
+      protection of data.  This is usually called a Message
+      Authentication Code (MAC), but IEEE 802 specifications (and this
+      document) use the acronym MIC to avoid confusion with Medium
+      Access Control.
+
+   Cryptographic Separation
+      Two keys (x and y) are "cryptographically separate" if an
+      adversary that knows all messages exchanged in the protocol cannot
+      compute x from y or y from x without "breaking" some cryptographic
+      assumption.  In particular, this definition allows that the
+      adversary has the knowledge of all nonces sent in cleartext, as
+      well as all predictable counter values used in the protocol.
+      Breaking a cryptographic assumption would typically require
+      inverting a one-way function or predicting the outcome of a
+      cryptographic pseudo-random number generator without knowledge of
+      the secret state.  In other words, if the keys are
+      cryptographically separate, there is no shortcut to compute x from
+      y or y from x, but the work an adversary must do to perform this
+      computation is equivalent to performing an exhaustive search for
+      the secret state value.
+
+
+
+
+
+
+Aboba, et al.               Standards Track                     [Page 5]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   Master Session Key (MSK)
+      Keying material that is derived between the EAP peer and server
+      and exported by the EAP method.  The MSK is at least 64 octets in
+      length.  In existing implementations, a AAA server acting as an
+      EAP server transports the MSK to the authenticator.
+
+   Extended Master Session Key (EMSK)
+      Additional keying material derived between the EAP client and
+      server that is exported by the EAP method.  The EMSK is at least
+      64 octets in length.  The EMSK is not shared with the
+      authenticator or any other third party.  The EMSK is reserved for
+      future uses that are not defined yet.
+
+   Result indications
+      A method provides result indications if after the method's last
+      message is sent and received:
+
+      1) The peer is aware of whether it has authenticated the server,
+         as well as whether the server has authenticated it.
+
+      2) The server is aware of whether it has authenticated the peer,
+         as well as whether the peer has authenticated it.
+
+   In the case where successful authentication is sufficient to
+   authorize access, then the peer and authenticator will also know if
+   the other party is willing to provide or accept access.  This may not
+   always be the case.  An authenticated peer may be denied access due
+   to lack of authorization (e.g., session limit) or other reasons.
+   Since the EAP exchange is run between the peer and the server, other
+   nodes (such as AAA proxies) may also affect the authorization
+   decision.  This is discussed in more detail in Section 7.16.
+
+1.3.  Applicability
+
+   EAP was designed for use in network access authentication, where IP
+   layer connectivity may not be available.  Use of EAP for other
+   purposes, such as bulk data transport, is NOT RECOMMENDED.
+
+   Since EAP does not require IP connectivity, it provides just enough
+   support for the reliable transport of authentication protocols, and
+   no more.
+
+   EAP is a lock-step protocol which only supports a single packet in
+   flight.  As a result, EAP cannot efficiently transport bulk data,
+   unlike transport protocols such as TCP [RFC793] or SCTP [RFC2960].
+
+
+
+
+
+
+Aboba, et al.               Standards Track                     [Page 6]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   While EAP provides support for retransmission, it assumes ordering
+   guarantees provided by the lower layer, so out of order reception is
+   not supported.
+
+   Since EAP does not support fragmentation and reassembly, EAP
+   authentication methods generating payloads larger than the minimum
+   EAP MTU need to provide fragmentation support.
+
+   While authentication methods such as EAP-TLS [RFC2716] provide
+   support for fragmentation and reassembly, the EAP methods defined in
+   this document do not.  As a result, if the EAP packet size exceeds
+   the EAP MTU of the link, these methods will encounter difficulties.
+
+   EAP authentication is initiated by the server (authenticator),
+   whereas many authentication protocols are initiated by the client
+   (peer).  As a result, it may be necessary for an authentication
+   algorithm to add one or two additional messages (at most one
+   roundtrip) in order to run over EAP.
+
+   Where certificate-based authentication is supported, the number of
+   additional roundtrips may be much larger due to fragmentation of
+   certificate chains.  In general, a fragmented EAP packet will require
+   as many round-trips to send as there are fragments.  For example, a
+   certificate chain 14960 octets in size would require ten round-trips
+   to send with a 1496 octet EAP MTU.
+
+   Where EAP runs over a lower layer in which significant packet loss is
+   experienced, or where the connection between the authenticator and
+   authentication server experiences significant packet loss, EAP
+   methods requiring many round-trips can experience difficulties.  In
+   these situations, use of EAP methods with fewer roundtrips is
+   advisable.
+
+2.  Extensible Authentication Protocol (EAP)
+
+   The EAP authentication exchange proceeds as follows:
+
+   [1] The authenticator sends a Request to authenticate the peer.  The
+       Request has a Type field to indicate what is being requested.
+       Examples of Request Types include Identity, MD5-challenge, etc.
+       The MD5-challenge Type corresponds closely to the CHAP
+       authentication protocol [RFC1994].  Typically, the authenticator
+       will send an initial Identity Request; however, an initial
+       Identity Request is not required, and MAY be bypassed.  For
+       example, the identity may not be required where it is determined
+       by the port to which the peer has connected (leased lines,
+
+
+
+
+
+Aboba, et al.               Standards Track                     [Page 7]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+       dedicated switch or dial-up ports), or where the identity is
+       obtained in another fashion (via calling station identity or MAC
+       address, in the Name field of the MD5-Challenge Response, etc.).
+
+   [2] The peer sends a Response packet in reply to a valid Request.  As
+       with the Request packet, the Response packet contains a Type
+       field, which corresponds to the Type field of the Request.
+
+   [3] The authenticator sends an additional Request packet, and the
+       peer replies with a Response.  The sequence of Requests and
+       Responses continues as long as needed.  EAP is a 'lock step'
+       protocol, so that other than the initial Request, a new Request
+       cannot be sent prior to receiving a valid Response.  The
+       authenticator is responsible for retransmitting requests as
+       described in Section 4.1.  After a suitable number of
+       retransmissions, the authenticator SHOULD end the EAP
+       conversation.  The authenticator MUST NOT send a Success or
+       Failure packet when retransmitting or when it fails to get a
+       response from the peer.
+
+   [4] The conversation continues until the authenticator cannot
+       authenticate the peer (unacceptable Responses to one or more
+       Requests), in which case the authenticator implementation MUST
+       transmit an EAP Failure (Code 4).  Alternatively, the
+       authentication conversation can continue until the authenticator
+       determines that successful authentication has occurred, in which
+       case the authenticator MUST transmit an EAP Success (Code 3).
+
+   Advantages:
+
+   o  The EAP protocol can support multiple authentication mechanisms
+      without having to pre-negotiate a particular one.
+
+   o  Network Access Server (NAS) devices (e.g., a switch or access
+      point) do not have to understand each authentication method and
+      MAY act as a pass-through agent for a backend authentication
+      server.  Support for pass-through is optional.  An authenticator
+      MAY authenticate local peers, while at the same time acting as a
+      pass-through for non-local peers and authentication methods it
+      does not implement locally.
+
+   o  Separation of the authenticator from the backend authentication
+      server simplifies credentials management and policy decision
+      making.
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                     [Page 8]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   Disadvantages:
+
+   o  For use in PPP, EAP requires the addition of a new authentication
+      Type to PPP LCP and thus PPP implementations will need to be
+      modified to use it.  It also strays from the previous PPP
+      authentication model of negotiating a specific authentication
+      mechanism during LCP.  Similarly, switch or access point
+      implementations need to support [IEEE-802.1X] in order to use EAP.
+
+   o  Where the authenticator is separate from the backend
+      authentication server, this complicates the security analysis and,
+      if needed, key distribution.
+
+2.1.  Support for Sequences
+
+   An EAP conversation MAY utilize a sequence of methods.  A common
+   example of this is an Identity request followed by a single EAP
+   authentication method such as an MD5-Challenge.  However, the peer
+   and authenticator MUST utilize only one authentication method (Type 4
+   or greater) within an EAP conversation, after which the authenticator
+   MUST send a Success or Failure packet.
+
+   Once a peer has sent a Response of the same Type as the initial
+   Request, an authenticator MUST NOT send a Request of a different Type
+   prior to completion of the final round of a given method (with the
+   exception of a Notification-Request) and MUST NOT send a Request for
+   an additional method of any Type after completion of the initial
+   authentication method; a peer receiving such Requests MUST treat them
+   as invalid, and silently discard them.  As a result, Identity Requery
+   is not supported.
+
+   A peer MUST NOT send a Nak (legacy or expanded) in reply to a Request
+   after an initial non-Nak Response has been sent.  Since spoofed EAP
+   Request packets may be sent by an attacker, an authenticator
+   receiving an unexpected Nak SHOULD discard it and log the event.
+
+   Multiple authentication methods within an EAP conversation are not
+   supported due to their vulnerability to man-in-the-middle attacks
+   (see Section 7.4) and incompatibility with existing implementations.
+
+   Where a single EAP authentication method is utilized, but other
+   methods are run within it (a "tunneled" method), the prohibition
+   against multiple authentication methods does not apply.  Such
+   "tunneled" methods appear as a single authentication method to EAP.
+   Backward compatibility can be provided, since a peer not supporting a
+   "tunneled" method can reply to the initial EAP-Request with a Nak
+
+
+
+
+
+Aboba, et al.               Standards Track                     [Page 9]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   (legacy or expanded).  To address security vulnerabilities,
+   "tunneled" methods MUST support protection against man-in-the-middle
+   attacks.
+
+2.2.  EAP Multiplexing Model
+
+   Conceptually, EAP implementations consist of the following
+   components:
+
+   [a] Lower layer.  The lower layer is responsible for transmitting and
+       receiving EAP frames between the peer and authenticator.  EAP has
+       been run over a variety of lower layers including PPP, wired IEEE
+       802 LANs [IEEE-802.1X], IEEE 802.11 wireless LANs [IEEE-802.11],
+       UDP (L2TP [RFC2661] and IKEv2 [IKEv2]), and TCP [PIC].  Lower
+       layer behavior is discussed in Section 3.
+
+   [b] EAP layer.  The EAP layer receives and transmits EAP packets via
+       the lower layer, implements duplicate detection and
+       retransmission, and delivers and receives EAP messages to and
+       from the EAP peer and authenticator layers.
+
+   [c] EAP peer and authenticator layers.  Based on the Code field, the
+       EAP layer demultiplexes incoming EAP packets to the EAP peer and
+       authenticator layers.  Typically, an EAP implementation on a
+       given host will support either peer or authenticator
+       functionality, but it is possible for a host to act as both an
+       EAP peer and authenticator.  In such an implementation both EAP
+       peer and authenticator layers will be present.
+
+   [d] EAP method layers.  EAP methods implement the authentication
+       algorithms and receive and transmit EAP messages via the EAP peer
+       and authenticator layers.  Since fragmentation support is not
+       provided by EAP itself, this is the responsibility of EAP
+       methods, which are discussed in Section 5.
+
+   The EAP multiplexing model is illustrated in Figure 1 below.  Note
+   that there is no requirement that an implementation conform to this
+   model, as long as the on-the-wire behavior is consistent with it.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 10]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+         +-+-+-+-+-+-+-+-+-+-+-+-+  +-+-+-+-+-+-+-+-+-+-+-+-+
+         |           |           |  |           |           |
+         | EAP method| EAP method|  | EAP method| EAP method|
+         | Type = X  | Type = Y  |  | Type = X  | Type = Y  |
+         |       V   |           |  |       ^   |           |
+         +-+-+-+-!-+-+-+-+-+-+-+-+  +-+-+-+-!-+-+-+-+-+-+-+-+
+         |       !               |  |       !               |
+         |  EAP  ! Peer layer    |  |  EAP  ! Auth. layer   |
+         |       !               |  |       !               |
+         +-+-+-+-!-+-+-+-+-+-+-+-+  +-+-+-+-!-+-+-+-+-+-+-+-+
+         |       !               |  |       !               |
+         |  EAP  ! layer         |  |  EAP  ! layer         |
+         |       !               |  |       !               |
+         +-+-+-+-!-+-+-+-+-+-+-+-+  +-+-+-+-!-+-+-+-+-+-+-+-+
+         |       !               |  |       !               |
+         | Lower ! layer         |  | Lower ! layer         |
+         |       !               |  |       !               |
+         +-+-+-+-!-+-+-+-+-+-+-+-+  +-+-+-+-!-+-+-+-+-+-+-+-+
+                 !                          !
+                 !   Peer                   ! Authenticator
+                 +------------>-------------+
+
+                     Figure 1: EAP Multiplexing Model
+
+   Within EAP, the Code field functions much like a protocol number in
+   IP.  It is assumed that the EAP layer demultiplexes incoming EAP
+   packets according to the Code field.  Received EAP packets with
+   Code=1 (Request), 3 (Success), and 4 (Failure) are delivered by the
+   EAP layer to the EAP peer layer, if implemented.  EAP packets with
+   Code=2 (Response) are delivered to the EAP authenticator layer, if
+   implemented.
+
+   Within EAP, the Type field functions much like a port number in UDP
+   or TCP.  It is assumed that the EAP peer and authenticator layers
+   demultiplex incoming EAP packets according to their Type, and deliver
+   them only to the EAP method corresponding to that Type.  An EAP
+   method implementation on a host may register to receive packets from
+   the peer or authenticator layers, or both, depending on which role(s)
+   it supports.
+
+   Since EAP authentication methods may wish to access the Identity,
+   implementations SHOULD make the Identity Request and Response
+   accessible to authentication methods (Types 4 or greater), in
+   addition to the Identity method.  The Identity Type is discussed in
+   Section 5.1.
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 11]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   A Notification Response is only used as confirmation that the peer
+   received the Notification Request, not that it has processed it, or
+   displayed the message to the user.  It cannot be assumed that the
+   contents of the Notification Request or Response are available to
+   another method.  The Notification Type is discussed in Section 5.2.
+
+   Nak (Type 3) or Expanded Nak (Type 254) are utilized for the purposes
+   of method negotiation.  Peers respond to an initial EAP Request for
+   an unacceptable Type with a Nak Response (Type 3) or Expanded Nak
+   Response (Type 254).  It cannot be assumed that the contents of the
+   Nak Response(s) are available to another method.  The Nak Type(s) are
+   discussed in Section 5.3.
+
+   EAP packets with Codes of Success or Failure do not include a Type
+   field, and are not delivered to an EAP method.  Success and Failure
+   are discussed in Section 4.2.
+
+   Given these considerations, the Success, Failure, Nak Response(s),
+   and Notification Request/Response messages MUST NOT be used to carry
+   data destined for delivery to other EAP methods.
+
+2.3.  Pass-Through Behavior
+
+   When operating as a "pass-through authenticator", an authenticator
+   performs checks on the Code, Identifier, and Length fields as
+   described in Section 4.1.  It forwards EAP packets received from the
+   peer and destined to its authenticator layer to the backend
+   authentication server; packets received from the backend
+   authentication server destined to the peer are forwarded to it.
+
+   A host receiving an EAP packet may only do one of three things with
+   it: act on it, drop it, or forward it.  The forwarding decision is
+   typically based only on examination of the Code, Identifier, and
+   Length fields.  A pass-through authenticator implementation MUST be
+   capable of forwarding EAP packets received from the peer with Code=2
+   (Response) to the backend authentication server. It also MUST be
+   capable of receiving EAP packets from the backend authentication
+   server and forwarding EAP packets of Code=1 (Request), Code=3
+   (Success), and Code=4 (Failure) to the peer.
+
+   Unless the authenticator implements one or more authentication
+   methods locally which support the authenticator role, the EAP method
+   layer header fields (Type, Type-Data) are not examined as part of the
+   forwarding decision.  Where the authenticator supports local
+   authentication methods, it MAY examine the Type field to determine
+   whether to act on the packet itself or forward it.  Compliant pass-
+   through authenticator implementations MUST by default forward EAP
+   packets of any Type.
+
+
+
+Aboba, et al.               Standards Track                    [Page 12]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   EAP packets received with Code=1 (Request), Code=3 (Success), and
+   Code=4 (Failure) are demultiplexed by the EAP layer and delivered to
+   the peer layer.  Therefore, unless a host implements an EAP peer
+   layer, these packets will be silently discarded.  Similarly, EAP
+   packets received with Code=2 (Response) are demultiplexed by the EAP
+   layer and delivered to the authenticator layer.  Therefore, unless a
+   host implements an EAP authenticator layer, these packets will be
+   silently discarded.  The behavior of a "pass-through peer" is
+   undefined within this specification, and is unsupported by AAA
+   protocols such as RADIUS [RFC3579] and Diameter [DIAM-EAP].
+
+   The forwarding model is illustrated in Figure 2.
+
+        Peer         Pass-through Authenticator   Authentication
+                                                      Server
+
+   +-+-+-+-+-+-+                                   +-+-+-+-+-+-+
+   |           |                                   |           |
+   |EAP method |                                   |EAP method |
+   |     V     |                                   |     ^     |
+   +-+-+-!-+-+-+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+   +-+-+-!-+-+-+
+   |     !     |   |EAP  |  EAP  |             |   |     !     |
+   |     !     |   |Peer |  Auth.| EAP Auth.   |   |     !     |
+   |EAP  ! peer|   |     | +-----------+       |   |EAP  !Auth.|
+   |     !     |   |     | !     |     !       |   |     !     |
+   +-+-+-!-+-+-+   +-+-+-+-!-+-+-+-+-+-!-+-+-+-+   +-+-+-!-+-+-+
+   |     !     |   |       !     |     !       |   |     !     |
+   |EAP  !layer|   |   EAP !layer| EAP !layer  |   |EAP  !layer|
+   |     !     |   |       !     |     !       |   |     !     |
+   +-+-+-!-+-+-+   +-+-+-+-!-+-+-+-+-+-!-+-+-+-+   +-+-+-!-+-+-+
+   |     !     |   |       !     |     !       |   |     !     |
+   |Lower!layer|   |  Lower!layer| AAA ! /IP   |   | AAA ! /IP |
+   |     !     |   |       !     |     !       |   |     !     |
+   +-+-+-!-+-+-+   +-+-+-+-!-+-+-+-+-+-!-+-+-+-+   +-+-+-!-+-+-+
+         !                 !           !                 !
+         !                 !           !                 !
+         +-------->--------+           +--------->-------+
+
+
+                   Figure 2: Pass-through Authenticator
+
+   For sessions in which the authenticator acts as a pass-through, it
+   MUST determine the outcome of the authentication solely based on the
+   Accept/Reject indication sent by the backend authentication server;
+   the outcome MUST NOT be determined by the contents of an EAP packet
+   sent along with the Accept/Reject indication, or the absence of such
+   an encapsulated EAP packet.
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 13]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+2.4.  Peer-to-Peer Operation
+
+   Since EAP is a peer-to-peer protocol, an independent and simultaneous
+   authentication may take place in the reverse direction (depending on
+   the capabilities of the lower layer).  Both ends of the link may act
+   as authenticators and peers at the same time.  In this case, it is
+   necessary for both ends to implement EAP authenticator and peer
+   layers.  In addition, the EAP method implementations on both peers
+   must support both authenticator and peer functionality.
+
+   Although EAP supports peer-to-peer operation, some EAP
+   implementations, methods, AAA protocols, and link layers may not
+   support this.  Some EAP methods may support asymmetric
+   authentication, with one type of credential being required for the
+   peer and another type for the authenticator.  Hosts supporting peer-
+   to-peer operation with such a method would need to be provisioned
+   with both types of credentials.
+
+   For example, EAP-TLS [RFC2716] is a client-server protocol in which
+   distinct certificate profiles are typically utilized for the client
+   and server.  This implies that a host supporting peer-to-peer
+   authentication with EAP-TLS would need to implement both the EAP peer
+   and authenticator layers, support both peer and authenticator roles
+   in the EAP-TLS implementation, and provision certificates appropriate
+   for each role.
+
+   AAA protocols such as RADIUS/EAP [RFC3579] and Diameter EAP [DIAM-
+   EAP] only support "pass-through authenticator" operation.  As noted
+   in [RFC3579] Section 2.6.2, a RADIUS server responds to an Access-
+   Request encapsulating an EAP-Request, Success, or Failure packet with
+   an Access-Reject.  There is therefore no support for "pass-through
+   peer" operation.
+
+   Even where a method is used which supports mutual authentication and
+   result indications, several considerations may dictate that two EAP
+   authentications (one in each direction) are required.  These include:
+
+   [1] Support for bi-directional session key derivation in the lower
+       layer.  Lower layers such as IEEE 802.11 may only support uni-
+       directional derivation and transport of transient session keys.
+       For example, the group-key handshake defined in [IEEE-802.11i] is
+       uni-directional, since in IEEE 802.11 infrastructure mode, only
+       the Access Point (AP) sends multicast/broadcast traffic.  In IEEE
+       802.11 ad hoc mode, where either peer may send
+       multicast/broadcast traffic, two uni-directional group-key
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 14]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+       exchanges are required.  Due to limitations of the design, this
+       also implies the need for unicast key derivations and EAP method
+       exchanges to occur in each direction.
+
+   [2] Support for tie-breaking in the lower layer.  Lower layers such
+       as IEEE 802.11 ad hoc do not support "tie breaking" wherein two
+       hosts initiating authentication with each other will only go
+       forward with a single authentication.  This implies that even if
+       802.11 were to support a bi-directional group-key handshake, then
+       two authentications, one in each direction, might still occur.
+
+   [3] Peer policy satisfaction.  EAP methods may support result
+       indications, enabling the peer to indicate to the EAP server
+       within the method that it successfully authenticated the EAP
+       server, as well as for the server to indicate that it has
+       authenticated the peer.  However, a pass-through authenticator
+       will not be aware that the peer has accepted the credentials
+       offered by the EAP server, unless this information is provided to
+       the authenticator via the AAA protocol.  The authenticator SHOULD
+       interpret the receipt of a key attribute within an Accept packet
+       as an indication that the peer has successfully authenticated the
+       server.
+
+   However, it is possible that the EAP peer's access policy was not
+   satisfied during the initial EAP exchange, even though mutual
+   authentication occurred.  For example, the EAP authenticator may not
+   have demonstrated authorization to act in both peer and authenticator
+   roles.  As a result, the peer may require an additional
+   authentication in the reverse direction, even if the peer provided an
+   indication that the EAP server had successfully authenticated to it.
+
+3.  Lower Layer Behavior
+
+3.1.  Lower Layer Requirements
+
+   EAP makes the following assumptions about lower layers:
+
+   [1] Unreliable transport.  In EAP, the authenticator retransmits
+       Requests that have not yet received Responses so that EAP does
+       not assume that lower layers are reliable.  Since EAP defines its
+       own retransmission behavior, it is possible (though undesirable)
+       for retransmission to occur both in the lower layer and the EAP
+       layer when EAP is run over a reliable lower layer.
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 15]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   Note that EAP Success and Failure packets are not retransmitted.
+   Without a reliable lower layer, and with a non-negligible error rate,
+   these packets can be lost, resulting in timeouts.  It is therefore
+   desirable for implementations to improve their resilience to loss of
+   EAP Success or Failure packets, as described in Section 4.2.
+
+   [2] Lower layer error detection.  While EAP does not assume that the
+       lower layer is reliable, it does rely on lower layer error
+       detection (e.g., CRC, Checksum, MIC, etc.).  EAP methods may not
+       include a MIC, or if they do, it may not be computed over all the
+       fields in the EAP packet, such as the Code, Identifier, Length,
+       or Type fields.  As a result, without lower layer error
+       detection, undetected errors could creep into the EAP layer or
+       EAP method layer header fields, resulting in authentication
+       failures.
+
+       For example, EAP TLS [RFC2716], which computes its MIC over the
+       Type-Data field only, regards MIC validation failures as a fatal
+       error.  Without lower layer error detection, this method, and
+       others like it, will not perform reliably.
+
+   [3] Lower layer security.  EAP does not require lower layers to
+       provide security services such as per-packet confidentiality,
+       authentication, integrity, and replay protection.  However, where
+       these security services are available, EAP methods supporting Key
+       Derivation (see Section 7.2.1) can be used to provide dynamic
+       keying material.  This makes it possible to bind the EAP
+       authentication to subsequent data and protect against data
+       modification, spoofing, or replay.  See Section 7.1 for details.
+
+   [4] Minimum MTU.  EAP is capable of functioning on lower layers that
+       provide an EAP MTU size of 1020 octets or greater.
+
+       EAP does not support path MTU discovery, and fragmentation and
+       reassembly is not supported by EAP, nor by the methods defined in
+       this specification: Identity (1), Notification (2), Nak Response
+       (3), MD5-Challenge (4), One Time Password (5), Generic Token Card
+       (6), and expanded Nak Response (254) Types.
+
+       Typically, the EAP peer obtains information on the EAP MTU from
+       the lower layers and sets the EAP frame size to an appropriate
+       value.  Where the authenticator operates in pass-through mode,
+       the authentication server does not have a direct way of
+       determining the EAP MTU, and therefore relies on the
+       authenticator to provide it with this information, such as via
+       the Framed-MTU attribute, as described in [RFC3579], Section 2.4.
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 16]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+       While methods such as EAP-TLS [RFC2716] support fragmentation and
+       reassembly, EAP methods originally designed for use within PPP
+       where a 1500 octet MTU is guaranteed for control frames (see
+       [RFC1661], Section 6.1) may lack fragmentation and reassembly
+       features.
+
+       EAP methods can assume a minimum EAP MTU of 1020 octets in the
+       absence of other information.  EAP methods SHOULD include support
+       for fragmentation and reassembly if their payloads can be larger
+       than this minimum EAP MTU.
+
+       EAP is a lock-step protocol, which implies a certain inefficiency
+       when handling fragmentation and reassembly.  Therefore, if the
+       lower layer supports fragmentation and reassembly (such as where
+       EAP is transported over IP), it may be preferable for
+       fragmentation and reassembly to occur in the lower layer rather
+       than in EAP.  This can be accomplished by providing an
+       artificially large EAP MTU to EAP, causing fragmentation and
+       reassembly to be handled within the lower layer.
+
+   [5] Possible duplication.  Where the lower layer is reliable, it will
+       provide the EAP layer with a non-duplicated stream of packets.
+       However,  while it is desirable that lower layers provide for
+       non-duplication, this is not a requirement.  The Identifier field
+       provides both the peer and authenticator with the ability to
+       detect duplicates.
+
+   [6] Ordering guarantees.  EAP does not require the Identifier to be
+       monotonically increasing, and so is reliant on lower layer
+       ordering guarantees for correct operation.  EAP was originally
+       defined to run on PPP, and [RFC1661] Section 1 has an ordering
+       requirement:
+
+           "The Point-to-Point Protocol is designed for simple links
+           which transport packets between two peers.  These links
+           provide full-duplex simultaneous bi-directional operation,
+           and are assumed to deliver packets in order."
+
+       Lower layer transports for EAP MUST preserve ordering between a
+       source and destination at a given priority level (the ordering
+       guarantee provided by [IEEE-802]).
+
+       Reordering, if it occurs, will typically result in an EAP
+       authentication failure, causing EAP authentication to be re-run.
+       In an environment in which reordering is likely, it is therefore
+       expected that EAP authentication failures will be common.  It is
+       RECOMMENDED that EAP only be run over lower layers that provide
+       ordering guarantees; running EAP over raw IP or UDP transport is
+
+
+
+Aboba, et al.               Standards Track                    [Page 17]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+       NOT RECOMMENDED.  Encapsulation of EAP within RADIUS [RFC3579]
+       satisfies ordering requirements, since RADIUS is a "lockstep"
+       protocol that delivers packets in order.
+
+3.2.  EAP Usage Within PPP
+
+   In order to establish communications over a point-to-point link, each
+   end of the PPP link first sends LCP packets to configure the data
+   link during the Link Establishment phase.  After the link has been
+   established, PPP provides for an optional Authentication phase before
+   proceeding to the Network-Layer Protocol phase.
+
+   By default, authentication is not mandatory.  If authentication of
+   the link is desired, an implementation MUST specify the
+   Authentication Protocol Configuration Option during the Link
+   Establishment phase.
+
+   If the identity of the peer has been established in the
+   Authentication phase, the server can use that identity in the
+   selection of options for the following network layer negotiations.
+
+   When implemented within PPP, EAP does not select a specific
+   authentication mechanism at the PPP Link Control Phase, but rather
+   postpones this until the Authentication Phase.  This allows the
+   authenticator to request more information before determining the
+   specific authentication mechanism.  This also permits the use of a
+   "backend" server which actually implements the various mechanisms
+   while the PPP authenticator merely passes through the authentication
+   exchange.  The PPP Link Establishment and Authentication phases, and
+   the Authentication Protocol Configuration Option, are defined in The
+   Point-to-Point Protocol (PPP) [RFC1661].
+
+3.2.1.  PPP Configuration Option Format
+
+   A summary of the PPP Authentication Protocol Configuration Option
+   format to negotiate EAP follows.  The fields are transmitted from
+   left to right.
+
+   Exactly one EAP packet is encapsulated in the Information field of a
+   PPP Data Link Layer frame where the protocol field indicates type hex
+   C227 (PPP EAP).
+
+
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 18]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+    0                   1                   2                   3
+    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     Type      |    Length     |     Authentication Protocol   |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+   Type
+
+      3
+
+   Length
+
+      4
+
+   Authentication Protocol
+
+      C227 (Hex) for Extensible Authentication Protocol (EAP)
+
+3.3.  EAP Usage Within IEEE 802
+
+   The encapsulation of EAP over IEEE 802 is defined in [IEEE-802.1X].
+   The IEEE 802 encapsulation of EAP does not involve PPP, and IEEE
+   802.1X does not include support for link or network layer
+   negotiations.  As a result, within IEEE 802.1X, it is not possible to
+   negotiate non-EAP authentication mechanisms, such as PAP or CHAP
+   [RFC1994].
+
+3.4.  Lower Layer Indications
+
+   The reliability and security of lower layer indications is dependent
+   on the lower layer.  Since EAP is media independent, the presence or
+   absence of lower layer security is not taken into account in the
+   processing of EAP messages.
+
+   To improve reliability, if a peer receives a lower layer success
+   indication as defined in Section 7.2, it MAY conclude that a Success
+   packet has been lost, and behave as if it had actually received a
+   Success packet.  This includes choosing to ignore the Success in some
+   circumstances as described in Section 4.2.
+
+   A discussion of some reliability and security issues with lower layer
+   indications in PPP, IEEE 802 wired networks, and IEEE 802.11 wireless
+   LANs can be found in the Security Considerations, Section 7.12.
+
+   After EAP authentication is complete, the peer will typically
+   transmit and receive data via the authenticator.  It is desirable to
+   provide assurance that the entities transmitting data are the same
+   ones that successfully completed EAP authentication.  To accomplish
+
+
+
+Aboba, et al.               Standards Track                    [Page 19]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   this, it is necessary for the lower layer to provide per-packet
+   integrity, authentication and replay protection, and to bind these
+   per-packet services to the keys derived during EAP authentication.
+   Otherwise, it is possible for subsequent data traffic to be modified,
+   spoofed, or replayed.
+
+   Where keying material for the lower layer ciphersuite is itself
+   provided by EAP, ciphersuite negotiation and key activation are
+   controlled by the lower layer.  In PPP, ciphersuites are negotiated
+   within ECP so that it is not possible to use keys derived from EAP
+   authentication until the completion of ECP.  Therefore, an initial
+   EAP exchange cannot be protected by a PPP ciphersuite, although EAP
+   re-authentication can be protected.
+
+   In IEEE 802 media, initial key activation also typically occurs after
+   completion of EAP authentication.  Therefore an initial EAP exchange
+   typically cannot be protected by the lower layer ciphersuite,
+   although an EAP re-authentication or pre-authentication exchange can
+   be protected.
+
+4.  EAP Packet Format
+
+   A summary of the EAP packet format is shown below.  The fields are
+   transmitted from left to right.
+
+    0                   1                   2                   3
+    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     Code      |  Identifier   |            Length             |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |    Data ...
+   +-+-+-+-+
+
+   Code
+
+      The Code field is one octet and identifies the Type of EAP packet.
+      EAP Codes are assigned as follows:
+
+         1       Request
+         2       Response
+         3       Success
+         4       Failure
+
+      Since EAP only defines Codes 1-4, EAP packets with other codes
+      MUST be silently discarded by both authenticators and peers.
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 20]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   Identifier
+
+      The Identifier field is one octet and aids in matching Responses
+      with Requests.
+
+   Length
+
+      The Length field is two octets and indicates the length, in
+      octets, of the EAP packet including the Code, Identifier, Length,
+      and Data fields.  Octets outside the range of the Length field
+      should be treated as Data Link Layer padding and MUST be ignored
+      upon reception.  A message with the Length field set to a value
+      larger than the number of received octets MUST be silently
+      discarded.
+
+   Data
+
+      The Data field is zero or more octets.  The format of the Data
+      field is determined by the Code field.
+
+4.1.  Request and Response
+
+   Description
+
+      The Request packet (Code field set to 1) is sent by the
+      authenticator to the peer.  Each Request has a Type field which
+      serves to indicate what is being requested.  Additional Request
+      packets MUST be sent until a valid Response packet is received, an
+      optional retry counter expires, or a lower layer failure
+      indication is received.
+
+      Retransmitted Requests MUST be sent with the same Identifier value
+      in order to distinguish them from new Requests.  The content of
+      the data field is dependent on the Request Type.  The peer MUST
+      send a Response packet in reply to a valid Request packet.
+      Responses MUST only be sent in reply to a valid Request and never
+      be retransmitted on a timer.
+
+      If a peer receives a valid duplicate Request for which it has
+      already sent a Response, it MUST resend its original Response
+      without reprocessing the Request.  Requests MUST be processed in
+      the order that they are received, and MUST be processed to their
+      completion before inspecting the next Request.
+
+   A summary of the Request and Response packet format follows.  The
+   fields are transmitted from left to right.
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 21]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+    0                   1                   2                   3
+    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     Code      |  Identifier   |            Length             |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     Type      |  Type-Data ...
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+
+   Code
+
+      1 for Request
+      2 for Response
+
+   Identifier
+
+      The Identifier field is one octet.  The Identifier field MUST be
+      the same if a Request packet is retransmitted due to a timeout
+      while waiting for a Response.  Any new (non-retransmission)
+      Requests MUST modify the Identifier field.
+
+      The Identifier field of the Response MUST match that of the
+      currently outstanding Request.  An authenticator receiving a
+      Response whose Identifier value does not match that of the
+      currently outstanding Request MUST silently discard the Response.
+
+      In order to avoid confusion between new Requests and
+      retransmissions, the Identifier value chosen for each new Request
+      need only be different from the previous Request, but need not be
+      unique within the conversation.  One way to achieve this is to
+      start the Identifier at an initial value and increment it for each
+      new Request.  Initializing the first Identifier with a random
+      number rather than starting from zero is recommended, since it
+      makes sequence attacks somewhat more difficult.
+
+      Since the Identifier space is unique to each session,
+      authenticators are not restricted to only 256 simultaneous
+      authentication conversations.  Similarly, with re-authentication,
+      an EAP conversation might continue over a long period of time, and
+      is not limited to only 256 roundtrips.
+
+   Implementation Note: The authenticator is responsible for
+   retransmitting Request messages.  If the Request message is obtained
+   from elsewhere (such as from a backend authentication server), then
+   the authenticator will need to save a copy of the Request in order to
+   accomplish this.  The peer is responsible for detecting and handling
+   duplicate Request messages before processing them in any way,
+   including passing them on to an outside party.  The authenticator is
+   also responsible for discarding Response messages with a non-matching
+
+
+
+Aboba, et al.               Standards Track                    [Page 22]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   Identifier value before acting on them in any way, including passing
+   them on to the backend authentication server for verification.  Since
+   the authenticator can retransmit before receiving a Response from the
+   peer, the authenticator can receive multiple Responses, each with a
+   matching Identifier.  Until a new Request is received by the
+   authenticator, the Identifier value is not updated, so that the
+   authenticator forwards Responses to the backend authentication
+   server, one at a time.
+
+   Length
+
+      The Length field is two octets and indicates the length of the EAP
+      packet including the Code, Identifier, Length, Type, and Type-Data
+      fields.  Octets outside the range of the Length field should be
+      treated as Data Link Layer padding and MUST be ignored upon
+      reception.  A message with the Length field set to a value larger
+      than the number of received octets MUST be silently discarded.
+
+   Type
+
+      The Type field is one octet.  This field indicates the Type of
+      Request or Response.  A single Type MUST be specified for each EAP
+      Request or Response.  An initial specification of Types follows in
+      Section 5 of this document.
+
+      The Type field of a Response MUST either match that of the
+      Request, or correspond to a legacy or Expanded Nak (see Section
+      5.3) indicating that a Request Type is unacceptable to the peer.
+      A peer MUST NOT send a Nak (legacy or expanded) in response to a
+      Request, after an initial non-Nak Response has been sent.  An EAP
+      server receiving a Response not meeting these requirements MUST
+      silently discard it.
+
+   Type-Data
+
+      The Type-Data field varies with the Type of Request and the
+      associated Response.
+
+4.2.  Success and Failure
+
+   The Success packet is sent by the authenticator to the peer after
+   completion of an EAP authentication method (Type 4 or greater) to
+   indicate that the peer has authenticated successfully to the
+   authenticator.  The authenticator MUST transmit an EAP packet with
+   the Code field set to 3 (Success).  If the authenticator cannot
+   authenticate the peer (unacceptable Responses to one or more
+   Requests), then after unsuccessful completion of the EAP method in
+   progress, the implementation MUST transmit an EAP packet with the
+
+
+
+Aboba, et al.               Standards Track                    [Page 23]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   Code field set to 4 (Failure).  An authenticator MAY wish to issue
+   multiple Requests before sending a Failure response in order to allow
+   for human typing mistakes.  Success and Failure packets MUST NOT
+   contain additional data.
+
+   Success and Failure packets MUST NOT be sent by an EAP authenticator
+   if the specification of the given method does not explicitly permit
+   the method to finish at that point.  A peer EAP implementation
+   receiving a Success or Failure packet where sending one is not
+   explicitly permitted MUST silently discard it.  By default, an EAP
+   peer MUST silently discard a "canned" Success packet (a Success
+   packet sent immediately upon connection).  This ensures that a rogue
+   authenticator will not be able to bypass mutual authentication by
+   sending a Success packet prior to conclusion of the EAP method
+   conversation.
+
+   Implementation Note: Because the Success and Failure packets are not
+   acknowledged, they are not retransmitted by the authenticator, and
+   may be potentially lost.  A peer MUST allow for this circumstance as
+   described in this note.  See also Section 3.4 for guidance on the
+   processing of lower layer success and failure indications.
+
+   As described in Section 2.1, only a single EAP authentication method
+   is allowed within an EAP conversation.  EAP methods may implement
+   result indications.  After the authenticator sends a failure result
+   indication to the peer, regardless of the response from the peer, it
+   MUST subsequently send a Failure packet.  After the authenticator
+   sends a success result indication to the peer and receives a success
+   result indication from the peer, it MUST subsequently send a Success
+   packet.
+
+   On the peer, once the method completes unsuccessfully (that is,
+   either the authenticator sends a failure result indication, or the
+   peer decides that it does not want to continue the conversation,
+   possibly after sending a failure result indication), the peer MUST
+   terminate the conversation and indicate failure to the lower layer.
+   The peer MUST silently discard Success packets and MAY silently
+   discard Failure packets.  As a result, loss of a Failure packet need
+   not result in a timeout.
+
+   On the peer, after success result indications have been exchanged by
+   both sides, a Failure packet MUST be silently discarded.  The peer
+   MAY, in the event that an EAP Success is not received, conclude that
+   the EAP Success packet was lost and that authentication concluded
+   successfully.
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 24]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   If the authenticator has not sent a result indication, and the peer
+   is willing to continue the conversation, the peer waits for a Success
+   or Failure packet once the method completes, and MUST NOT silently
+   discard either of them.  In the event that neither a Success nor
+   Failure packet is received, the peer SHOULD terminate the
+   conversation to avoid lengthy timeouts in case the lost packet was an
+   EAP Failure.
+
+   If the peer attempts to authenticate to the authenticator and fails
+   to do so, the authenticator MUST send a Failure packet and MUST NOT
+   grant access by sending a Success packet.  However, an authenticator
+   MAY omit having the peer authenticate to it in situations where
+   limited access is offered (e.g., guest access).  In this case, the
+   authenticator MUST send a Success packet.
+
+   Where the peer authenticates successfully to the authenticator, but
+   the authenticator does not send a result indication, the
+   authenticator MAY deny access by sending a Failure packet where the
+   peer is not currently authorized for network access.
+
+   A summary of the Success and Failure packet format is shown below.
+   The fields are transmitted from left to right.
+
+    0                   1                   2                   3
+    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     Code      |  Identifier   |            Length             |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+   Code
+
+      3 for Success
+      4 for Failure
+
+   Identifier
+
+      The Identifier field is one octet and aids in matching replies to
+      Responses.  The Identifier field MUST match the Identifier field
+      of the Response packet that it is sent in response to.
+
+   Length
+
+      4
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 25]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+4.3.  Retransmission Behavior
+
+   Because the authentication process will often involve user input,
+   some care must be taken when deciding upon retransmission strategies
+   and authentication timeouts.  By default, where EAP is run over an
+   unreliable lower layer, the EAP retransmission timer SHOULD be
+   dynamically estimated.  A maximum of 3-5 retransmissions is
+   suggested.
+
+   When run over a reliable lower layer (e.g., EAP over ISAKMP/TCP, as
+   within [PIC]), the authenticator retransmission timer SHOULD be set
+   to an infinite value, so that retransmissions do not occur at the EAP
+   layer.  The peer may still maintain a timeout value so as to avoid
+   waiting indefinitely for a Request.
+
+   Where the authentication process requires user input, the measured
+   round trip times may be determined by user responsiveness rather than
+   network characteristics, so that dynamic RTO estimation may not be
+   helpful.  Instead, the retransmission timer SHOULD be set so as to
+   provide sufficient time for the user to respond, with longer timeouts
+   required in certain cases, such as where Token Cards (see Section
+   5.6) are involved.
+
+   In order to provide the EAP authenticator with guidance as to the
+   appropriate timeout value, a hint can be communicated to the
+   authenticator by the backend authentication server (such as via the
+   RADIUS Session-Timeout attribute).
+
+   In order to dynamically estimate the EAP retransmission timer, the
+   algorithms for the estimation of SRTT, RTTVAR, and RTO described in
+   [RFC2988] are RECOMMENDED, including use of Karn's algorithm, with
+   the following potential modifications:
+
+   [a] In order to avoid synchronization behaviors that can occur with
+       fixed timers among distributed systems, the retransmission timer
+       is calculated with a jitter by using the RTO value and randomly
+       adding a value drawn between -RTOmin/2 and RTOmin/2.  Alternative
+       calculations to create jitter MAY be used.  These MUST be
+       pseudo-random.  For a discussion of pseudo-random number
+       generation, see [RFC1750].
+
+   [b] When EAP is transported over a single link (as opposed to over
+       the Internet), smaller values of RTOinitial, RTOmin, and RTOmax
+       MAY be used.  Recommended values are RTOinitial=1 second,
+       RTOmin=200ms, and RTOmax=20 seconds.
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 26]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   [c] When EAP is transported over a single link (as opposed to over
+       the Internet), estimates MAY be done on a per-authenticator
+       basis, rather than a per-session basis.  This enables the
+       retransmission estimate to make the most use of information on
+       link-layer behavior.
+
+   [d] An EAP implementation MAY clear SRTT and RTTVAR after backing off
+       the timer multiple times, as it is likely that the current SRTT
+       and RTTVAR are bogus in this situation.  Once SRTT and RTTVAR are
+       cleared, they should be initialized with the next RTT sample
+       taken as described in [RFC2988] equation 2.2.
+
+5.  Initial EAP Request/Response Types
+
+   This section defines the initial set of EAP Types used in Request/
+   Response exchanges.  More Types may be defined in future documents.
+   The Type field is one octet and identifies the structure of an EAP
+   Request or Response packet.  The first 3 Types are considered special
+   case Types.
+
+   The remaining Types define authentication exchanges.  Nak (Type 3) or
+   Expanded Nak (Type 254) are valid only for Response packets, they
+   MUST NOT be sent in a Request.
+
+   All EAP implementations MUST support Types 1-4, which are defined in
+   this document, and SHOULD support Type 254.  Implementations MAY
+   support other Types defined here or in future RFCs.
+
+             1       Identity
+             2       Notification
+             3       Nak (Response only)
+             4       MD5-Challenge
+             5       One Time Password (OTP)
+             6       Generic Token Card (GTC)
+           254       Expanded Types
+           255       Experimental use
+
+   EAP methods MAY support authentication based on shared secrets.  If
+   the shared secret is a passphrase entered by the user,
+   implementations MAY support entering passphrases with non-ASCII
+   characters.  In this case, the input should be processed using an
+   appropriate stringprep [RFC3454] profile, and encoded in octets using
+   UTF-8 encoding [RFC2279].  A preliminary version of a possible
+   stringprep profile is described in [SASLPREP].
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 27]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+5.1.  Identity
+
+   Description
+
+      The Identity Type is used to query the identity of the peer.
+      Generally, the authenticator will issue this as the initial
+      Request.  An optional displayable message MAY be included to
+      prompt the peer in the case where there is an expectation of
+      interaction with a user.  A Response of Type 1 (Identity) SHOULD
+      be sent in Response to a Request with a Type of 1 (Identity).
+
+      Some EAP implementations piggy-back various options into the
+      Identity Request after a NUL-character.  By default, an EAP
+      implementation SHOULD NOT assume that an Identity Request or
+      Response can be larger than 1020 octets.
+
+      It is RECOMMENDED that the Identity Response be used primarily for
+      routing purposes and selecting which EAP method to use.  EAP
+      Methods SHOULD include a method-specific mechanism for obtaining
+      the identity, so that they do not have to rely on the Identity
+      Response.  Identity Requests and Responses are sent in cleartext,
+      so an attacker may snoop on the identity, or even modify or spoof
+      identity exchanges.  To address these threats, it is preferable
+      for an EAP method to include an identity exchange that supports
+      per-packet authentication, integrity and replay protection, and
+      confidentiality.  The Identity Response may not be the appropriate
+      identity for the method; it may have been truncated or obfuscated
+      so as to provide privacy, or it may have been decorated for
+      routing purposes.  Where the peer is configured to only accept
+      authentication methods supporting protected identity exchanges,
+      the peer MAY provide an abbreviated Identity Response (such as
+      omitting the peer-name portion of the NAI [RFC2486]).  For further
+      discussion of identity protection, see Section 7.3.
+
+   Implementation Note: The peer MAY obtain the Identity via user input.
+   It is suggested that the authenticator retry the Identity Request in
+   the case of an invalid Identity or authentication failure to allow
+   for potential typos on the part of the user.  It is suggested that
+   the Identity Request be retried a minimum of 3 times before
+   terminating the authentication.  The Notification Request MAY be used
+   to indicate an invalid authentication attempt prior to transmitting a
+   new Identity Request (optionally, the failure MAY be indicated within
+   the message of the new Identity Request itself).
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 28]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   Type
+
+      1
+
+   Type-Data
+
+      This field MAY contain a displayable message in the Request,
+      containing UTF-8 encoded ISO 10646 characters [RFC2279].  Where
+      the Request contains a null, only the portion of the field prior
+      to the null is displayed.  If the Identity is unknown, the
+      Identity Response field should be zero bytes in length.  The
+      Identity Response field MUST NOT be null terminated.  In all
+      cases, the length of the Type-Data field is derived from the
+      Length field of the Request/Response packet.
+
+   Security Claims (see Section 7.2):
+
+      Auth. mechanism:           None
+      Ciphersuite negotiation:   No
+      Mutual authentication:     No
+      Integrity protection:      No
+      Replay protection:         No
+      Confidentiality:           No
+      Key derivation:            No
+      Key strength:              N/A
+      Dictionary attack prot.:   N/A
+      Fast reconnect:            No
+      Crypt. binding:            N/A
+      Session independence:      N/A
+      Fragmentation:             No
+      Channel binding:           No
+
+5.2.  Notification
+
+   Description
+
+      The Notification Type is optionally used to convey a displayable
+      message from the authenticator to the peer.  An authenticator MAY
+      send a Notification Request to the peer at any time when there is
+      no outstanding Request, prior to completion of an EAP
+      authentication method.  The peer MUST respond to a Notification
+      Request with a Notification Response unless the EAP authentication
+      method specification prohibits the use of Notification messages.
+      In any case, a Nak Response MUST NOT be sent in response to a
+      Notification Request.  Note that the default maximum length of a
+      Notification Request is 1020 octets.  By default, this leaves at
+      most 1015 octets for the human readable message.
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 29]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+      An EAP method MAY indicate within its specification that
+      Notification messages must not be sent during that method.  In
+      this case, the peer MUST silently discard Notification Requests
+      from the point where an initial Request for that Type is answered
+      with a Response of the same Type.
+
+      The peer SHOULD display this message to the user or log it if it
+      cannot be displayed.  The Notification Type is intended to provide
+      an acknowledged notification of some imperative nature, but it is
+      not an error indication, and therefore does not change the state
+      of the peer.  Examples include a password with an expiration time
+      that is about to expire, an OTP sequence integer which is nearing
+      0, an authentication failure warning, etc.  In most circumstances,
+      Notification should not be required.
+
+   Type
+
+      2
+
+   Type-Data
+
+      The Type-Data field in the Request contains a displayable message
+      greater than zero octets in length, containing UTF-8 encoded ISO
+      10646 characters [RFC2279].  The length of the message is
+      determined by the Length field of the Request packet.  The message
+      MUST NOT be null terminated.  A Response MUST be sent in reply to
+      the Request with a Type field of 2 (Notification).  The Type-Data
+      field of the Response is zero octets in length.  The Response
+      should be sent immediately (independent of how the message is
+      displayed or logged).
+
+   Security Claims (see Section 7.2):
+
+      Auth. mechanism:           None
+      Ciphersuite negotiation:   No
+      Mutual authentication:     No
+      Integrity protection:      No
+      Replay protection:         No
+      Confidentiality:           No
+      Key derivation:            No
+      Key strength:              N/A
+      Dictionary attack prot.:   N/A
+      Fast reconnect:            No
+      Crypt. binding:            N/A
+      Session independence:      N/A
+      Fragmentation:             No
+      Channel binding:           No
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 30]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+5.3.  Nak
+
+5.3.1.  Legacy Nak
+
+   Description
+
+      The legacy Nak Type is valid only in Response messages.  It is
+      sent in reply to a Request where the desired authentication Type
+      is unacceptable.  Authentication Types are numbered 4 and above.
+      The Response contains one or more authentication Types desired by
+      the Peer.  Type zero (0) is used to indicate that the sender has
+      no viable alternatives, and therefore the authenticator SHOULD NOT
+      send another Request after receiving a Nak Response containing a
+      zero value.
+
+      Since the legacy Nak Type is valid only in Responses and has very
+      limited functionality, it MUST NOT be used as a general purpose
+      error indication, such as for communication of error messages, or
+      negotiation of parameters specific to a particular EAP method.
+
+   Code
+
+      2 for Response.
+
+   Identifier
+
+      The Identifier field is one octet and aids in matching Responses
+      with Requests.  The Identifier field of a legacy Nak Response MUST
+      match the Identifier field of the Request packet that it is sent
+      in response to.
+
+   Length
+
+      >=6
+
+   Type
+
+      3
+
+   Type-Data
+
+      Where a peer receives a Request for an unacceptable authentication
+      Type (4-253,255), or a peer lacking support for Expanded Types
+      receives a Request for Type 254, a Nak Response (Type 3) MUST be
+      sent.  The Type-Data field of the Nak Response (Type 3) MUST
+      contain one or more octets indicating the desired authentication
+      Type(s), one octet per Type, or the value zero (0) to indicate no
+      proposed alternative.  A peer supporting Expanded Types that
+
+
+
+Aboba, et al.               Standards Track                    [Page 31]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+      receives a Request for an unacceptable authentication Type (4-253,
+      255) MAY include the value 254 in the Nak Response (Type 3) to
+      indicate the desire for an Expanded authentication Type. If the
+      authenticator can accommodate this preference, it will respond
+      with an Expanded Type Request (Type 254).
+
+   Security Claims (see Section 7.2):
+
+      Auth. mechanism:           None
+      Ciphersuite negotiation:   No
+      Mutual authentication:     No
+      Integrity protection:      No
+      Replay protection:         No
+      Confidentiality:           No
+      Key derivation:            No
+      Key strength:              N/A
+      Dictionary attack prot.:   N/A
+      Fast reconnect:            No
+      Crypt. binding:            N/A
+      Session independence:      N/A
+      Fragmentation:             No
+      Channel binding:           No
+
+
+5.3.2.  Expanded Nak
+
+   Description
+
+      The Expanded Nak Type is valid only in Response messages.  It MUST
+      be sent only in reply to a Request of Type 254 (Expanded Type)
+      where the authentication Type is unacceptable.  The Expanded Nak
+      Type uses the Expanded Type format itself, and the Response
+      contains one or more authentication Types desired by the peer, all
+      in Expanded Type format.  Type zero (0) is used to indicate that
+      the sender has no viable alternatives.  The general format of the
+      Expanded Type is described in Section 5.7.
+
+      Since the Expanded Nak Type is valid only in Responses and has
+      very limited functionality, it MUST NOT be used as a general
+      purpose error indication, such as for communication of error
+      messages, or negotiation of parameters specific to a particular
+      EAP method.
+
+   Code
+
+      2 for Response.
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 32]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   Identifier
+
+      The Identifier field is one octet and aids in matching Responses
+      with Requests.  The Identifier field of an Expanded Nak Response
+      MUST match the Identifier field of the Request packet that it is
+      sent in response to.
+
+   Length
+
+      >=20
+
+   Type
+
+      254
+
+   Vendor-Id
+
+      0 (IETF)
+
+   Vendor-Type
+
+      3 (Nak)
+
+   Vendor-Data
+
+      The Expanded Nak Type is only sent when the Request contains an
+      Expanded Type (254) as defined in Section 5.7.  The Vendor-Data
+      field of the Nak Response MUST contain one or more authentication
+      Types (4 or greater), all in expanded format, 8 octets per Type,
+      or the value zero (0), also in Expanded Type format, to indicate
+      no proposed alternative.  The desired authentication Types may
+      include a mixture of Vendor-Specific and IETF Types.  For example,
+      an Expanded Nak Response indicating a preference for OTP (Type 5),
+      and an MIT (Vendor-Id=20) Expanded Type of 6 would appear as
+      follows:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 33]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+    0                   1                   2                   3
+    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     2         |  Identifier   |           Length=28           |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |   Type=254    |                0 (IETF)                       |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                                3 (Nak)                        |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |   Type=254    |                0 (IETF)                       |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                                5 (OTP)                        |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |   Type=254    |                20 (MIT)                       |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                                6                              |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+   An Expanded Nak Response indicating a no desired alternative would
+   appear as follows:
+
+    0                   1                   2                   3
+    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     2         |  Identifier   |           Length=20           |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |   Type=254    |                0 (IETF)                       |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                                3 (Nak)                        |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |   Type=254    |                0 (IETF)                       |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                                0 (No alternative)             |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+   Security Claims (see Section 7.2):
+
+      Auth. mechanism:           None
+      Ciphersuite negotiation:   No
+      Mutual authentication:     No
+      Integrity protection:      No
+      Replay protection:         No
+      Confidentiality:           No
+      Key derivation:            No
+      Key strength:              N/A
+      Dictionary attack prot.:   N/A
+      Fast reconnect:            No
+      Crypt. binding:            N/A
+
+
+
+Aboba, et al.               Standards Track                    [Page 34]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+      Session independence:      N/A
+      Fragmentation:             No
+      Channel binding:           No
+
+
+5.4.  MD5-Challenge
+
+   Description
+
+      The MD5-Challenge Type is analogous to the PPP CHAP protocol
+      [RFC1994] (with MD5 as the specified algorithm).  The Request
+      contains a "challenge" message to the peer.  A Response MUST be
+      sent in reply to the Request.  The Response MAY be either of Type
+      4 (MD5-Challenge), Nak (Type 3), or Expanded Nak (Type 254).  The
+      Nak reply indicates the peer's desired authentication Type(s).
+      EAP peer and EAP server implementations MUST support the MD5-
+      Challenge mechanism.  An authenticator that supports only pass-
+      through MUST allow communication with a backend authentication
+      server that is capable of supporting MD5-Challenge, although the
+      EAP authenticator implementation need not support MD5-Challenge
+      itself.  However, if the EAP authenticator can be configured to
+      authenticate peers locally (e.g., not operate in pass-through),
+      then the requirement for support of the MD5-Challenge mechanism
+      applies.
+
+      Note that the use of the Identifier field in the MD5-Challenge
+      Type is different from that described in [RFC1994].  EAP allows
+      for retransmission of MD5-Challenge Request packets, while
+      [RFC1994] states that both the Identifier and Challenge fields
+      MUST change each time a Challenge (the CHAP equivalent of the
+      MD5-Challenge Request packet) is sent.
+
+      Note: [RFC1994] treats the shared secret as an octet string, and
+      does not specify how it is entered into the system (or if it is
+      handled by the user at all).  EAP MD5-Challenge implementations
+      MAY support entering passphrases with non-ASCII characters.  See
+      Section 5 for instructions how the input should be processed and
+      encoded into octets.
+
+   Type
+
+      4
+
+   Type-Data
+
+      The contents of the Type-Data field is summarized below.  For
+      reference on the use of these fields, see the PPP Challenge
+      Handshake Authentication Protocol [RFC1994].
+
+
+
+Aboba, et al.               Standards Track                    [Page 35]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+    0                   1                   2                   3
+    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |  Value-Size   |  Value ...
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |  Name ...
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+   Security Claims (see Section 7.2):
+
+      Auth. mechanism:           Password or pre-shared key.
+      Ciphersuite negotiation:   No
+      Mutual authentication:     No
+      Integrity protection:      No
+      Replay protection:         No
+      Confidentiality:           No
+      Key derivation:            No
+      Key strength:              N/A
+      Dictionary attack prot.:   No
+      Fast reconnect:            No
+      Crypt. binding:            N/A
+      Session independence:      N/A
+      Fragmentation:             No
+      Channel binding:           No
+
+5.5.  One-Time Password (OTP)
+
+   Description
+
+      The One-Time Password system is defined in "A One-Time Password
+      System" [RFC2289] and "OTP Extended Responses" [RFC2243].  The
+      Request contains an OTP challenge in the format described in
+      [RFC2289].  A Response MUST be sent in reply to the Request.  The
+      Response MUST be of Type 5 (OTP), Nak (Type 3), or Expanded Nak
+      (Type 254).  The Nak Response indicates the peer's desired
+      authentication Type(s).  The EAP OTP method is intended for use
+      with the One-Time Password system only, and MUST NOT be used to
+      provide support for cleartext passwords.
+
+   Type
+
+      5
+
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 36]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   Type-Data
+
+      The Type-Data field contains the OTP "challenge" as a displayable
+      message in the Request.  In the Response, this field is used for
+      the 6 words from the OTP dictionary [RFC2289].  The messages MUST
+      NOT be null terminated.  The length of the field is derived from
+      the Length field of the Request/Reply packet.
+
+      Note: [RFC2289] does not specify how the secret pass-phrase is
+      entered by the user, or how the pass-phrase is converted into
+      octets.  EAP OTP implementations MAY support entering passphrases
+      with non-ASCII characters.  See Section 5 for instructions on how
+      the input should be processed and encoded into octets.
+
+   Security Claims (see Section 7.2):
+
+      Auth. mechanism:           One-Time Password
+      Ciphersuite negotiation:   No
+      Mutual authentication:     No
+      Integrity protection:      No
+      Replay protection:         Yes
+      Confidentiality:           No
+      Key derivation:            No
+      Key strength:              N/A
+      Dictionary attack prot.:   No
+      Fast reconnect:            No
+      Crypt. binding:            N/A
+      Session independence:      N/A
+      Fragmentation:             No
+      Channel binding:           No
+
+
+5.6.  Generic Token Card (GTC)
+
+   Description
+
+      The Generic Token Card Type is defined for use with various Token
+      Card implementations which require user input.  The Request
+      contains a displayable message and the Response contains the Token
+      Card information necessary for authentication.  Typically, this
+      would be information read by a user from the Token card device and
+      entered as ASCII text.  A Response MUST be sent in reply to the
+      Request.  The Response MUST be of Type 6 (GTC), Nak (Type 3), or
+      Expanded Nak (Type 254).  The Nak Response indicates the peer's
+      desired authentication Type(s).  The EAP GTC method is intended
+      for use with the Token Cards supporting challenge/response
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 37]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+      authentication and MUST NOT be used to provide support for
+      cleartext passwords in the absence of a protected tunnel with
+      server authentication.
+
+   Type
+
+      6
+
+   Type-Data
+
+      The Type-Data field in the Request contains a displayable message
+      greater than zero octets in length.  The length of the message is
+      determined by the Length field of the Request packet.  The message
+      MUST NOT be null terminated.  A Response MUST be sent in reply to
+      the Request with a Type field of 6 (Generic Token Card).  The
+      Response contains data from the Token Card required for
+      authentication.  The length of the data is determined by the
+      Length field of the Response packet.
+
+      EAP GTC implementations MAY support entering a response with non-
+      ASCII characters.  See Section 5 for instructions how the input
+      should be processed and encoded into octets.
+
+   Security Claims (see Section 7.2):
+
+      Auth. mechanism:           Hardware token.
+      Ciphersuite negotiation:   No
+      Mutual authentication:     No
+      Integrity protection:      No
+      Replay protection:         No
+      Confidentiality:           No
+      Key derivation:            No
+      Key strength:              N/A
+      Dictionary attack prot.:   No
+      Fast reconnect:            No
+      Crypt. binding:            N/A
+      Session independence:      N/A
+      Fragmentation:             No
+      Channel binding:           No
+
+
+5.7.  Expanded Types
+
+   Description
+
+      Since many of the existing uses of EAP are vendor-specific, the
+      Expanded method Type is available to allow vendors to support
+      their own Expanded Types not suitable for general usage.
+
+
+
+Aboba, et al.               Standards Track                    [Page 38]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+      The Expanded Type is also used to expand the global Method Type
+      space beyond the original 255 values.  A Vendor-Id of 0 maps the
+      original 255 possible Types onto a space of 2^32-1 possible Types.
+      (Type 0 is only used in a Nak Response to indicate no acceptable
+      alternative).
+
+      An implementation that supports the Expanded attribute MUST treat
+      EAP Types that are less than 256 equivalently, whether they appear
+      as a single octet or as the 32-bit Vendor-Type within an Expanded
+      Type where Vendor-Id is 0.  Peers not equipped to interpret the
+      Expanded Type MUST send a Nak as described in Section 5.3.1, and
+      negotiate a more suitable authentication method.
+
+      A summary of the Expanded Type format is shown below.  The fields
+      are transmitted from left to right.
+
+    0                   1                   2                   3
+    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     Type      |               Vendor-Id                       |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                          Vendor-Type                          |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |              Vendor data...
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+   Type
+
+      254 for Expanded Type
+
+   Vendor-Id
+
+      The Vendor-Id is 3 octets and represents the SMI Network
+      Management Private Enterprise Code of the Vendor in network byte
+      order, as allocated by IANA.  A Vendor-Id of zero is reserved for
+      use by the IETF in providing an expanded global EAP Type space.
+
+   Vendor-Type
+
+      The Vendor-Type field is four octets and represents the vendor-
+      specific method Type.
+
+      If the Vendor-Id is zero, the Vendor-Type field is an extension
+      and superset of the existing namespace for EAP Types.  The first
+      256 Types are reserved for compatibility with single-octet EAP
+      Types that have already been assigned or may be assigned in the
+      future.  Thus, EAP Types from 0 through 255 are semantically
+      identical, whether they appear as single octet EAP Types or as
+
+
+
+Aboba, et al.               Standards Track                    [Page 39]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+      Vendor-Types when Vendor-Id is zero.  There is one exception to
+      this rule: Expanded Nak and Legacy Nak packets share the same
+      Type, but must be treated differently because they have a
+      different format.
+
+   Vendor-Data
+
+      The Vendor-Data field is defined by the vendor.  Where a Vendor-Id
+      of zero is present, the Vendor-Data field will be used for
+      transporting the contents of EAP methods of Types defined by the
+      IETF.
+
+5.8.  Experimental
+
+   Description
+
+      The Experimental Type has no fixed format or content.  It is
+      intended for use when experimenting with new EAP Types.  This Type
+      is intended for experimental and testing purposes.  No guarantee
+      is made for interoperability between peers using this Type, as
+      outlined in [RFC3692].
+
+   Type
+
+      255
+
+   Type-Data
+
+      Undefined
+
+6.  IANA Considerations
+
+   This section provides guidance to the Internet Assigned Numbers
+   Authority (IANA) regarding registration of values related to the EAP
+   protocol, in accordance with BCP 26, [RFC2434].
+
+   There are two name spaces in EAP that require registration: Packet
+   Codes and method Types.
+
+   EAP is not intended as a general-purpose protocol, and allocations
+   SHOULD NOT be made for purposes unrelated to authentication.
+
+   The following terms are used here with the meanings defined in BCP
+   26: "name space", "assigned value", "registration".
+
+   The following policies are used here with the meanings defined in BCP
+   26: "Private Use", "First Come First Served", "Expert Review",
+   "Specification Required", "IETF Consensus", "Standards Action".
+
+
+
+Aboba, et al.               Standards Track                    [Page 40]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   For registration requests where a Designated Expert should be
+   consulted, the responsible IESG area director should appoint the
+   Designated Expert.  The intention is that any allocation will be
+   accompanied by a published RFC.  But in order to allow for the
+   allocation of values prior to the RFC being approved for publication,
+   the Designated Expert can approve allocations once it seems clear
+   that an RFC will be published.  The Designated expert will post a
+   request to the EAP WG mailing list (or a successor designated by the
+   Area Director) for comment and review, including an Internet-Draft.
+   Before a period of 30 days has passed, the Designated Expert will
+   either approve or deny the registration request and publish a notice
+   of the decision to the EAP WG mailing list or its successor, as well
+   as informing IANA.  A denial notice must be justified by an
+   explanation, and in the cases where it is possible, concrete
+   suggestions on how the request can be modified so as to become
+   acceptable should be provided.
+
+6.1.  Packet Codes
+
+   Packet Codes have a range from 1 to 255, of which 1-4 have been
+   allocated.  Because a new Packet Code has considerable impact on
+   interoperability, a new Packet Code requires Standards Action, and
+   should be allocated starting at 5.
+
+6.2.  Method Types
+
+   The original EAP method Type space has a range from 1 to 255, and is
+   the scarcest resource in EAP, and thus must be allocated with care.
+   Method Types 1-45 have been allocated, with 20 available for re-use.
+   Method Types 20 and 46-191 may be allocated on the advice of a
+   Designated Expert, with Specification Required.
+
+   Allocation of blocks of method Types (more than one for a given
+   purpose) should require IETF Consensus.  EAP Type Values 192-253 are
+   reserved and allocation requires Standards Action.
+
+   Method Type 254 is allocated for the Expanded Type.  Where the
+   Vendor-Id field is non-zero, the Expanded Type is used for functions
+   specific only to one vendor's implementation of EAP, where no
+   interoperability is deemed useful.  When used with a Vendor-Id of
+   zero, method Type 254 can also be used to provide for an expanded
+   IETF method Type space.  Method Type values 256-4294967295 may be
+   allocated after Type values 1-191 have been allocated, on the advice
+   of a Designated Expert, with Specification Required.
+
+   Method Type 255 is allocated for Experimental use, such as testing of
+   new EAP methods before a permanent Type is allocated.
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 41]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+7.  Security Considerations
+
+   This section defines a generic threat model as well as the EAP method
+   security claims mitigating those threats.
+
+   It is expected that the generic threat model and corresponding
+   security claims will used to define EAP method requirements for use
+   in specific environments.  An example of such a requirements analysis
+   is provided in [IEEE-802.11i-req].  A security claims section is
+   required in EAP method specifications, so that EAP methods can be
+   evaluated against the requirements.
+
+7.1.  Threat Model
+
+   EAP was developed for use with PPP [RFC1661] and was later adapted
+   for use in wired IEEE 802 networks [IEEE-802] in [IEEE-802.1X].
+   Subsequently, EAP has been proposed for use on wireless LAN networks
+   and over the Internet.  In all these situations, it is possible for
+   an attacker to gain access to links over which EAP packets are
+   transmitted.  For example, attacks on telephone infrastructure are
+   documented in [DECEPTION].
+
+   An attacker with access to the link may carry out a number of
+   attacks, including:
+
+   [1]  An attacker may try to discover user identities by snooping
+        authentication traffic.
+
+   [2]  An attacker may try to modify or spoof EAP packets.
+
+   [3]  An attacker may launch denial of service attacks by spoofing
+        lower layer indications or Success/Failure packets, by replaying
+        EAP packets, or by generating packets with overlapping
+        Identifiers.
+
+   [4]  An attacker may attempt to recover the pass-phrase by mounting
+        an offline dictionary attack.
+
+   [5]  An attacker may attempt to convince the peer to connect to an
+        untrusted network by mounting a man-in-the-middle attack.
+
+   [6]  An attacker may attempt to disrupt the EAP negotiation in order
+        cause a weak authentication method to be selected.
+
+   [7]  An attacker may attempt to recover keys by taking advantage of
+        weak key derivation techniques used within EAP methods.
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 42]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   [8]  An attacker may attempt to take advantage of weak ciphersuites
+        subsequently used after the EAP conversation is complete.
+
+   [9]  An attacker may attempt to perform downgrading attacks on lower
+        layer ciphersuite negotiation in order to ensure that a weaker
+        ciphersuite is used subsequently to EAP authentication.
+
+   [10] An attacker acting as an authenticator may provide incorrect
+        information to the EAP peer and/or server via out-of-band
+        mechanisms (such as via a AAA or lower layer protocol).  This
+        includes impersonating another authenticator, or providing
+        inconsistent information to the peer and EAP server.
+
+   Depending on the lower layer, these attacks may be carried out
+   without requiring physical proximity.  Where EAP is used over
+   wireless networks, EAP packets may be forwarded by authenticators
+   (e.g., pre-authentication) so that the attacker need not be within
+   the coverage area of an authenticator in order to carry out an attack
+   on it or its peers.  Where EAP is used over the Internet, attacks may
+   be carried out at an even greater distance.
+
+7.2.  Security Claims
+
+   In order to clearly articulate the security provided by an EAP
+   method, EAP method specifications MUST include a Security Claims
+   section, including the following declarations:
+
+   [a] Mechanism.  This is a statement of the authentication technology:
+       certificates, pre-shared keys, passwords, token cards, etc.
+
+   [b] Security claims.  This is a statement of the claimed security
+       properties of the method, using terms defined in Section 7.2.1:
+       mutual authentication, integrity protection, replay protection,
+       confidentiality, key derivation, dictionary attack resistance,
+       fast reconnect, cryptographic binding.  The Security Claims
+       section of an EAP method specification SHOULD provide
+       justification for the claims that are made.  This can be
+       accomplished by including a proof in an Appendix, or including a
+       reference to a proof.
+
+   [c] Key strength.  If the method derives keys, then the effective key
+       strength MUST be estimated.  This estimate is meant for potential
+       users of the method to determine if the keys produced are strong
+       enough for the intended application.
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 43]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+       The effective key strength SHOULD be stated as a number of bits,
+       defined as follows: If the effective key strength is N bits, the
+       best currently known methods to recover the key (with non-
+       negligible probability) require, on average, an effort comparable
+       to 2^(N-1) operations of a typical block cipher.  The statement
+       SHOULD be accompanied by a short rationale, explaining how this
+       number was derived.  This explanation SHOULD include the
+       parameters required to achieve the stated key strength based on
+       current knowledge of the algorithms.
+
+       (Note: Although it is difficult to define what "comparable
+       effort" and "typical block cipher" exactly mean, reasonable
+       approximations are sufficient here.  Refer to e.g. [SILVERMAN]
+       for more discussion.)
+
+       The key strength depends on the methods used to derive the keys.
+       For instance, if keys are derived from a shared secret (such as a
+       password or a long-term secret), and possibly some public
+       information such as nonces, the effective key strength is limited
+       by the strength of the long-term secret (assuming that the
+       derivation procedure is computationally simple).  To take another
+       example, when using public key algorithms, the strength of the
+       symmetric key depends on the strength of the public keys used.
+
+   [d] Description of key hierarchy.  EAP methods deriving keys MUST
+       either provide a reference to a key hierarchy specification, or
+       describe how Master Session Keys (MSKs) and Extended Master
+       Session Keys (EMSKs) are to be derived.
+
+   [e] Indication of vulnerabilities.  In addition to the security
+       claims that are made, the specification MUST indicate which of
+       the security claims detailed in Section 7.2.1 are NOT being made.
+
+7.2.1.  Security Claims Terminology for EAP Methods
+
+   These terms are used to describe the security properties of EAP
+   methods:
+
+   Protected ciphersuite negotiation
+      This refers to the ability of an EAP method to negotiate the
+      ciphersuite used to protect the EAP conversation, as well as to
+      integrity protect the negotiation.  It does not refer to the
+      ability to negotiate the ciphersuite used to protect data.
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 44]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   Mutual authentication
+      This refers to an EAP method in which, within an interlocked
+      exchange, the authenticator authenticates the peer and the peer
+      authenticates the authenticator.  Two independent one-way methods,
+      running in opposite directions do not provide mutual
+      authentication as defined here.
+
+   Integrity protection
+      This refers to providing data origin authentication and protection
+      against unauthorized modification of information for EAP packets
+      (including EAP Requests and Responses).  When making this claim, a
+      method specification MUST describe the EAP packets and fields
+      within the EAP packet that are protected.
+
+   Replay protection
+      This refers to protection against replay of an EAP method or its
+      messages, including success and failure result indications.
+
+   Confidentiality
+      This refers to encryption of EAP messages, including EAP Requests
+      and Responses, and success and failure result indications.  A
+      method making this claim MUST support identity protection (see
+      Section 7.3).
+
+   Key derivation
+      This refers to the ability of the EAP method to derive exportable
+      keying material, such as the Master Session Key (MSK), and
+      Extended Master Session Key (EMSK).  The MSK is used only for
+      further key derivation, not directly for protection of the EAP
+      conversation or subsequent data.  Use of the EMSK is reserved.
+
+   Key strength
+      If the effective key strength is N bits, the best currently known
+      methods to recover the key (with non-negligible probability)
+      require, on average, an effort comparable to 2^(N-1) operations of
+      a typical block cipher.
+
+   Dictionary attack resistance
+      Where password authentication is used, passwords are commonly
+      selected from a small set (as compared to a set of N-bit keys),
+      which raises a concern about dictionary attacks.  A method may be
+      said to provide protection against dictionary attacks if, when it
+      uses a password as a secret, the method does not allow an offline
+      attack that has a work factor based on the number of passwords in
+      an attacker's dictionary.
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 45]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   Fast reconnect
+      The ability, in the case where a security association has been
+      previously established, to create a new or refreshed security
+      association more efficiently or in a smaller number of round-
+      trips.
+
+   Cryptographic binding
+      The demonstration of the EAP peer to the EAP server that a single
+      entity has acted as the EAP peer for all methods executed within a
+      tunnel method.  Binding MAY also imply that the EAP server
+      demonstrates to the peer that a single entity has acted as the EAP
+      server for all methods executed within a tunnel method.  If
+      executed correctly, binding serves to mitigate man-in-the-middle
+      vulnerabilities.
+
+   Session independence
+      The demonstration that passive attacks (such as capture of the EAP
+      conversation) or active attacks (including compromise of the MSK
+      or EMSK) does not enable compromise of subsequent or prior MSKs or
+      EMSKs.
+
+   Fragmentation
+      This refers to whether an EAP method supports fragmentation and
+      reassembly.  As noted in Section 3.1, EAP methods should support
+      fragmentation and reassembly if EAP packets can exceed the minimum
+      MTU of 1020 octets.
+
+   Channel binding
+      The communication within an EAP method of integrity-protected
+      channel properties such as endpoint identifiers which can be
+      compared to values communicated via out of band mechanisms (such
+      as via a AAA or lower layer protocol).
+
+   Note: This list of security claims is not exhaustive.  Additional
+   properties, such as additional denial-of-service protection, may be
+   relevant as well.
+
+7.3.  Identity Protection
+
+   An Identity exchange is optional within the EAP conversation.
+   Therefore, it is possible to omit the Identity exchange entirely, or
+   to use a method-specific identity exchange once a protected channel
+   has been established.
+
+   However, where roaming is supported as described in [RFC2607], it may
+   be necessary to locate the appropriate backend authentication server
+   before the authentication conversation can proceed.  The realm
+   portion of the Network Access Identifier (NAI) [RFC2486] is typically
+
+
+
+Aboba, et al.               Standards Track                    [Page 46]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   included within the EAP-Response/Identity in order to enable the
+   authentication exchange to be routed to the appropriate backend
+   authentication server.  Therefore, while the peer-name portion of the
+   NAI may be omitted in the EAP-Response/Identity where proxies or
+   relays are present, the realm portion may be required.
+
+   It is possible for the identity in the identity response to be
+   different from the identity authenticated by the EAP method.  This
+   may be intentional in the case of identity privacy.  An EAP method
+   SHOULD use the authenticated identity when making access control
+   decisions.
+
+7.4.  Man-in-the-Middle Attacks
+
+   Where EAP is tunneled within another protocol that omits peer
+   authentication, there exists a potential vulnerability to a man-in-
+   the-middle attack.  For details, see [BINDING] and [MITM].
+
+   As noted in Section 2.1, EAP does not permit untunneled sequences of
+   authentication methods.  Were a sequence of EAP authentication
+   methods to be permitted, the peer might not have proof that a single
+   entity has acted as the authenticator for all EAP methods within the
+   sequence.  For example, an authenticator might terminate one EAP
+   method, then forward the next method in the sequence to another party
+   without the peer's knowledge or consent.  Similarly, the
+   authenticator might not have proof that a single entity has acted as
+   the peer for all EAP methods within the sequence.
+
+   Tunneling EAP within another protocol enables an attack by a rogue
+   EAP authenticator tunneling EAP to a legitimate server.  Where the
+   tunneling protocol is used for key establishment but does not require
+   peer authentication, an attacker convincing a legitimate peer to
+   connect to it will be able to tunnel EAP packets to a legitimate
+   server, successfully authenticating and obtaining the key.  This
+   allows the attacker to successfully establish itself as a man-in-
+   the-middle, gaining access to the network, as well as the ability to
+   decrypt data traffic between the legitimate peer and server.
+
+   This attack may be mitigated by the following measures:
+
+   [a] Requiring mutual authentication within EAP tunneling mechanisms.
+
+   [b] Requiring cryptographic binding between the EAP tunneling
+       protocol and the tunneled EAP methods.  Where cryptographic
+       binding is supported, a mechanism is also needed to protect
+       against downgrade attacks that would bypass it.  For further
+       details on cryptographic binding, see [BINDING].
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 47]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   [c] Limiting the EAP methods authorized for use without protection,
+       based on peer and authenticator policy.
+
+   [d] Avoiding the use of tunnels when a single, strong method is
+       available.
+
+7.5.  Packet Modification Attacks
+
+   While EAP methods may support per-packet data origin authentication,
+   integrity, and replay protection, support is not provided within the
+   EAP layer.
+
+   Since the Identifier is only a single octet, it is easy to guess,
+   allowing an attacker to successfully inject or replay EAP packets.
+   An attacker may also modify EAP headers (Code, Identifier, Length,
+   Type) within EAP packets where the header is unprotected.  This could
+   cause packets to be inappropriately discarded or misinterpreted.
+
+   To protect EAP packets against modification, spoofing, or replay,
+   methods supporting protected ciphersuite negotiation, mutual
+   authentication, and key derivation, as well as integrity and replay
+   protection, are recommended.  See Section 7.2.1 for definitions of
+   these security claims.
+
+   Method-specific MICs may be used to provide protection.  If a per-
+   packet MIC is employed within an EAP method, then peers,
+   authentication servers, and authenticators not operating in pass-
+   through mode MUST validate the MIC.  MIC validation failures SHOULD
+   be logged.  Whether a MIC validation failure is considered a fatal
+   error or not is determined by the EAP method specification.
+
+   It is RECOMMENDED that methods providing integrity protection of EAP
+   packets include coverage of all the EAP header fields, including the
+   Code, Identifier, Length, Type, and Type-Data fields.
+
+   Since EAP messages of Types Identity, Notification, and Nak do not
+   include their own MIC, it may be desirable for the EAP method MIC to
+   cover information contained within these messages, as well as the
+   header of each EAP message.
+
+   To provide protection, EAP also may be encapsulated within a
+   protected channel created by protocols such as ISAKMP [RFC2408], as
+   is done in [IKEv2] or within TLS [RFC2246].  However, as noted in
+   Section 7.4, EAP tunneling may result in a man-in-the-middle
+   vulnerability.
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 48]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   Existing EAP methods define message integrity checks (MICs) that
+   cover more than one EAP packet.  For example, EAP-TLS [RFC2716]
+   defines a MIC over a TLS record that could be split into multiple
+   fragments; within the FINISHED message, the MIC is computed over
+   previous messages.  Where the MIC covers more than one EAP packet, a
+   MIC validation failure is typically considered a fatal error.
+
+   Within EAP-TLS [RFC2716], a MIC validation failure is treated as a
+   fatal error, since that is what is specified in TLS [RFC2246].
+   However, it is also possible to develop EAP methods that support
+   per-packet MICs, and respond to verification failures by silently
+   discarding the offending packet.
+
+   In this document, descriptions of EAP message handling assume that
+   per-packet MIC validation, where it occurs, is effectively performed
+   as though it occurs before sending any responses or changing the
+   state of the host which received the packet.
+
+7.6.  Dictionary Attacks
+
+   Password authentication algorithms such as EAP-MD5, MS-CHAPv1
+   [RFC2433], and Kerberos V [RFC1510] are known to be vulnerable to
+   dictionary attacks.  MS-CHAPv1 vulnerabilities are documented in
+   [PPTPv1]; MS-CHAPv2 vulnerabilities are documented in [PPTPv2];
+   Kerberos vulnerabilities are described in [KRBATTACK], [KRBLIM], and
+   [KERB4WEAK].
+
+   In order to protect against dictionary attacks, authentication
+   methods resistant to dictionary attacks (as defined in Section 7.2.1)
+   are recommended.
+
+   If an authentication algorithm is used that is known to be vulnerable
+   to dictionary attacks, then the conversation may be tunneled within a
+   protected channel in order to provide additional protection.
+   However, as noted in Section 7.4, EAP tunneling may result in a man-
+   in-the-middle vulnerability, and therefore dictionary attack
+   resistant methods are preferred.
+
+7.7.  Connection to an Untrusted Network
+
+   With EAP methods supporting one-way authentication, such as EAP-MD5,
+   the peer does not authenticate the authenticator, making the peer
+   vulnerable to attack by a rogue authenticator.  Methods supporting
+   mutual authentication (as defined in Section 7.2.1) address this
+   vulnerability.
+
+   In EAP there is no requirement that authentication be full duplex or
+   that the same protocol be used in both directions.  It is perfectly
+
+
+
+Aboba, et al.               Standards Track                    [Page 49]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   acceptable for different protocols to be used in each direction.
+   This will, of course, depend on the specific protocols negotiated.
+   However, in general, completing a single unitary mutual
+   authentication is preferable to two one-way authentications, one in
+   each direction.  This is because separate authentications that are
+   not bound cryptographically so as to demonstrate they are part of the
+   same session are subject to man-in-the-middle attacks, as discussed
+   in Section 7.4.
+
+7.8.  Negotiation Attacks
+
+   In a negotiation attack, the attacker attempts to convince the peer
+   and authenticator to negotiate a less secure EAP method.  EAP does
+   not provide protection for Nak Response packets, although it is
+   possible for a method to include coverage of Nak Responses within a
+   method-specific MIC.
+
+   Within or associated with each authenticator, it is not anticipated
+   that a particular named peer will support a choice of methods.  This
+   would make the peer vulnerable to attacks that negotiate the least
+   secure method from among a set.  Instead, for each named peer, there
+   SHOULD be an indication of exactly one method used to authenticate
+   that peer name.  If a peer needs to make use of different
+   authentication methods under different circumstances, then distinct
+   identities SHOULD be employed, each of which identifies exactly one
+   authentication method.
+
+7.9.  Implementation Idiosyncrasies
+
+   The interaction of EAP with lower layers such as PPP and IEEE 802 are
+   highly implementation dependent.
+
+   For example, upon failure of authentication, some PPP implementations
+   do not terminate the link, instead limiting traffic in Network-Layer
+   Protocols to a filtered subset, which in turn allows the peer the
+   opportunity to update secrets or send mail to the network
+   administrator indicating a problem.  Similarly, while an
+   authentication failure will result in denied access to the controlled
+   port in [IEEE-802.1X], limited traffic may be permitted on the
+   uncontrolled port.
+
+   In EAP there is no provision for retries of failed authentication.
+   However, in PPP the LCP state machine can renegotiate the
+   authentication protocol at any time, thus allowing a new attempt.
+   Similarly, in IEEE 802.1X the Supplicant or Authenticator can re-
+   authenticate at any time.  It is recommended that any counters used
+   for authentication failure not be reset until after successful
+   authentication, or subsequent termination of the failed link.
+
+
+
+Aboba, et al.               Standards Track                    [Page 50]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+7.10.  Key Derivation
+
+   It is possible for the peer and EAP server to mutually authenticate
+   and derive keys.  In order to provide keying material for use in a
+   subsequently negotiated ciphersuite, an EAP method supporting key
+   derivation MUST export a Master Session Key (MSK) of at least 64
+   octets, and an Extended Master Session Key (EMSK) of at least 64
+   octets.  EAP Methods deriving keys MUST provide for mutual
+   authentication between the EAP peer and the EAP Server.
+
+   The MSK and EMSK MUST NOT be used directly to protect data; however,
+   they are of sufficient size to enable derivation of a AAA-Key
+   subsequently used to derive Transient Session Keys (TSKs) for use
+   with the selected ciphersuite.  Each ciphersuite is responsible for
+   specifying how to derive the TSKs from the AAA-Key.
+
+   The AAA-Key is derived from the keying material exported by the EAP
+   method (MSK and EMSK).  This derivation occurs on the AAA server.  In
+   many existing protocols that use EAP, the AAA-Key and MSK are
+   equivalent, but more complicated mechanisms are possible (see
+   [KEYFRAME] for details).
+
+   EAP methods SHOULD ensure the freshness of the MSK and EMSK, even in
+   cases where one party may not have a high quality random number
+   generator.  A RECOMMENDED method is for each party to provide a nonce
+   of at least 128 bits, used in the derivation of the MSK and EMSK.
+
+   EAP methods export the MSK and EMSK, but not Transient Session Keys
+   so as to allow EAP methods to be ciphersuite and media independent.
+   Keying material exported by EAP methods MUST be independent of the
+   ciphersuite negotiated to protect data.
+
+   Depending on the lower layer, EAP methods may run before or after
+   ciphersuite negotiation, so that the selected ciphersuite may not be
+   known to the EAP method.  By providing keying material usable with
+   any ciphersuite, EAP methods can used with a wide range of
+   ciphersuites and media.
+
+   In order to preserve algorithm independence, EAP methods deriving
+   keys SHOULD support (and document) the protected negotiation of the
+   ciphersuite used to protect the EAP conversation between the peer and
+   server.  This is distinct from the ciphersuite negotiated between the
+   peer and authenticator, used to protect data.
+
+   The strength of Transient Session Keys (TSKs) used to protect data is
+   ultimately dependent on the strength of keys generated by the EAP
+   method.  If an EAP method cannot produce keying material of
+   sufficient strength, then the TSKs may be subject to a brute force
+
+
+
+Aboba, et al.               Standards Track                    [Page 51]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   attack.  In order to enable deployments requiring strong keys, EAP
+   methods supporting key derivation SHOULD be capable of generating an
+   MSK and EMSK, each with an effective key strength of at least 128
+   bits.
+
+   Methods supporting key derivation MUST demonstrate cryptographic
+   separation between the MSK and EMSK branches of the EAP key
+   hierarchy.  Without violating a fundamental cryptographic assumption
+   (such as the non-invertibility of a one-way function), an attacker
+   recovering the MSK or EMSK MUST NOT be able to recover the other
+   quantity with a level of effort less than brute force.
+
+   Non-overlapping substrings of the MSK MUST be cryptographically
+   separate from each other, as defined in Section 7.2.1.  That is,
+   knowledge of one substring MUST NOT help in recovering some other
+   substring without breaking some hard cryptographic assumption.  This
+   is required because some existing ciphersuites form TSKs by simply
+   splitting the AAA-Key to pieces of appropriate length.  Likewise,
+   non-overlapping substrings of the EMSK MUST be cryptographically
+   separate from each other, and from substrings of the MSK.
+
+   The EMSK is reserved for future use and MUST remain on the EAP peer
+   and EAP server where it is derived; it MUST NOT be transported to, or
+   shared with, additional parties, or used to derive any other keys.
+   (This restriction will be relaxed in a future document that specifies
+   how the EMSK can be used.)
+
+   Since EAP does not provide for explicit key lifetime negotiation, EAP
+   peers, authenticators, and authentication servers MUST be prepared
+   for situations in which one of the parties discards the key state,
+   which remains valid on another party.
+
+   This specification does not provide detailed guidance on how EAP
+   methods derive the MSK and EMSK, how the AAA-Key is derived from the
+   MSK and/or EMSK, or how the TSKs are derived from the AAA-Key.
+
+   The development and validation of key derivation algorithms is
+   difficult, and as a result, EAP methods SHOULD re-use well
+   established and analyzed mechanisms for key derivation (such as those
+   specified in IKE [RFC2409] or TLS [RFC2246]), rather than inventing
+   new ones. EAP methods SHOULD also utilize well established and
+   analyzed mechanisms for MSK and EMSK derivation.  Further details on
+   EAP Key Derivation are provided within [KEYFRAME].
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 52]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+7.11.  Weak Ciphersuites
+
+   If after the initial EAP authentication, data packets are sent
+   without per-packet authentication, integrity, and replay protection,
+   an attacker with access to the media can inject packets, "flip bits"
+   within existing packets, replay packets, or even hijack the session
+   completely.  Without per-packet confidentiality, it is possible to
+   snoop data packets.
+
+   To protect against data modification, spoofing, or snooping, it is
+   recommended that EAP methods supporting mutual authentication and key
+   derivation (as defined by Section 7.2.1) be used, along with lower
+   layers providing per-packet confidentiality, authentication,
+   integrity, and replay protection.
+
+   Additionally, if the lower layer performs ciphersuite negotiation, it
+   should be understood that EAP does not provide by itself integrity
+   protection of that negotiation.  Therefore, in order to avoid
+   downgrading attacks which would lead to weaker ciphersuites being
+   used, clients implementing lower layer ciphersuite negotiation SHOULD
+   protect against negotiation downgrading.
+
+   This can be done by enabling users to configure which ciphersuites
+   are acceptable as a matter of security policy, or the ciphersuite
+   negotiation MAY be authenticated using keying material derived from
+   the EAP authentication and a MIC algorithm agreed upon in advance by
+   lower-layer peers.
+
+7.12.  Link Layer
+
+   There are reliability and security issues with link layer indications
+   in PPP, IEEE 802 LANs, and IEEE 802.11 wireless LANs:
+
+   [a] PPP.  In PPP, link layer indications such as LCP-Terminate (a
+       link failure indication) and NCP (a link success indication) are
+       not authenticated or integrity protected.  They can therefore be
+       spoofed by an attacker with access to the link.
+
+   [b] IEEE 802.  IEEE 802.1X EAPOL-Start and EAPOL-Logoff frames are
+       not authenticated or integrity protected.  They can therefore be
+       spoofed by an attacker with access to the link.
+
+   [c] IEEE 802.11.  In IEEE 802.11, link layer indications include
+       Disassociate and Deauthenticate frames (link failure
+       indications), and the first message of the 4-way handshake (link
+       success indication).  These messages are not authenticated or
+       integrity protected, and although they are not forwardable, they
+       are spoofable by an attacker within range.
+
+
+
+Aboba, et al.               Standards Track                    [Page 53]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   In IEEE 802.11, IEEE 802.1X data frames may be sent as Class 3
+   unicast data frames, and are therefore forwardable.  This implies
+   that while EAPOL-Start and EAPOL-Logoff messages may be authenticated
+   and integrity protected, they can be spoofed by an authenticated
+   attacker far from the target when "pre-authentication" is enabled.
+
+   In IEEE 802.11, a "link down" indication is an unreliable indication
+   of link failure, since wireless signal strength can come and go and
+   may be influenced by radio frequency interference generated by an
+   attacker.  To avoid unnecessary resets, it is advisable to damp these
+   indications, rather than passing them directly to the EAP.  Since EAP
+   supports retransmission, it is robust against transient connectivity
+   losses.
+
+7.13.  Separation of Authenticator and Backend Authentication Server
+
+   It is possible for the EAP peer and EAP server to mutually
+   authenticate and derive a AAA-Key for a ciphersuite used to protect
+   subsequent data traffic.  This does not present an issue on the peer,
+   since the peer and EAP client reside on the same machine; all that is
+   required is for the client to derive the AAA-Key from the MSK and
+   EMSK exported by the EAP method, and to subsequently pass a Transient
+   Session Key (TSK) to the ciphersuite module.
+
+   However, in the case where the authenticator and authentication
+   server reside on different machines, there are several implications
+   for security.
+
+   [a] Authentication will occur between the peer and the authentication
+       server, not between the peer and the authenticator.  This means
+       that it is not possible for the peer to validate the identity of
+       the authenticator that it is speaking to, using EAP alone.
+
+   [b] As discussed in [RFC3579], the authenticator is dependent on the
+       AAA protocol in order to know the outcome of an authentication
+       conversation, and does not look at the encapsulated EAP packet
+       (if one is present) to determine the outcome.  In practice, this
+       implies that the AAA protocol spoken between the authenticator
+       and authentication server MUST support per-packet authentication,
+       integrity, and replay protection.
+
+   [c] After completion of the EAP conversation, where lower layer
+       security services such as per-packet confidentiality,
+       authentication, integrity, and replay protection will be enabled,
+       a secure association protocol SHOULD be run between the peer and
+       authenticator in order to provide mutual authentication between
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 54]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+       the peer and authenticator, guarantee liveness of transient
+       session keys, provide protected ciphersuite and capabilities
+       negotiation for subsequent data, and synchronize key usage.
+
+   [d] A AAA-Key derived from the MSK and/or EMSK negotiated between the
+       peer and authentication server MAY be transmitted to the
+       authenticator.  Therefore, a mechanism needs to be provided to
+       transmit the AAA-Key from the authentication server to the
+       authenticator that needs it.  The specification of the AAA-key
+       derivation, transport, and wrapping mechanisms is outside the
+       scope of this document.  Further details on AAA-Key Derivation
+       are provided within [KEYFRAME].
+
+7.14.  Cleartext Passwords
+
+   This specification does not define a mechanism for cleartext password
+   authentication.  The omission is intentional.  Use of cleartext
+   passwords would allow the password to be captured by an attacker with
+   access to a link over which EAP packets are transmitted.
+
+   Since protocols encapsulating EAP, such as RADIUS [RFC3579], may not
+   provide confidentiality, EAP packets may be subsequently encapsulated
+   for transport over the Internet where they may be captured by an
+   attacker.
+
+   As a result, cleartext passwords cannot be securely used within EAP,
+   except where encapsulated within a protected tunnel with server
+   authentication.  Some of the same risks apply to EAP methods without
+   dictionary attack resistance, as defined in Section 7.2.1.  For
+   details, see Section 7.6.
+
+7.15.  Channel Binding
+
+   It is possible for a compromised or poorly implemented EAP
+   authenticator to communicate incorrect information to the EAP peer
+   and/or server.  This may enable an authenticator to impersonate
+   another authenticator or communicate incorrect information via out-
+   of-band mechanisms (such as via a AAA or lower layer protocol).
+
+   Where EAP is used in pass-through mode, the EAP peer typically does
+   not verify the identity of the pass-through authenticator, it only
+   verifies that the pass-through authenticator is trusted by the EAP
+   server.  This creates a potential security vulnerability.
+
+   Section 4.3.7 of [RFC3579] describes how an EAP pass-through
+   authenticator acting as a AAA client can be detected if it attempts
+   to impersonate another authenticator (such by sending incorrect NAS-
+   Identifier [RFC2865], NAS-IP-Address [RFC2865] or NAS-IPv6-Address
+
+
+
+Aboba, et al.               Standards Track                    [Page 55]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   [RFC3162] attributes via the AAA protocol).  However, it is possible
+   for a pass-through authenticator acting as a AAA client to provide
+   correct information to the AAA server while communicating misleading
+   information to the EAP peer via a lower layer protocol.
+
+   For example, it is possible for a compromised authenticator to
+   utilize another authenticator's Called-Station-Id or NAS-Identifier
+   in communicating with the EAP peer via a lower layer protocol, or for
+   a pass-through authenticator acting as a AAA client to provide an
+   incorrect peer Calling-Station-Id [RFC2865][RFC3580] to the AAA
+   server via the AAA protocol.
+
+   In order to address this vulnerability, EAP methods may support a
+   protected exchange of channel properties such as endpoint
+   identifiers, including (but not limited to): Called-Station-Id
+   [RFC2865][RFC3580], Calling-Station-Id [RFC2865][RFC3580], NAS-
+   Identifier [RFC2865], NAS-IP-Address [RFC2865], and NAS-IPv6-Address
+   [RFC3162].
+
+   Using such a protected exchange, it is possible to match the channel
+   properties provided by the authenticator via out-of-band mechanisms
+   against those exchanged within the EAP method.  Where discrepancies
+   are found, these SHOULD be logged; additional actions MAY also be
+   taken, such as denying access.
+
+7.16.  Protected Result Indications
+
+   Within EAP, Success and Failure packets are neither acknowledged nor
+   integrity protected.  Result indications improve resilience to loss
+   of Success and Failure packets when EAP is run over lower layers
+   which do not support retransmission or synchronization of the
+   authentication state.  In media such as IEEE 802.11, which provides
+   for retransmission, as well as synchronization of authentication
+   state via the 4-way handshake defined in [IEEE-802.11i], additional
+   resilience is typically of marginal benefit.
+
+   Depending on the method and circumstances, result indications can be
+   spoofable by an attacker.  A method is said to provide protected
+   result indications if it supports result indications, as well as the
+   "integrity protection" and "replay protection" claims.  A method
+   supporting protected result indications MUST indicate which result
+   indications are protected, and which are not.
+
+   Protected result indications are not required to protect against
+   rogue authenticators.  Within a mutually authenticating method,
+   requiring that the server authenticate to the peer before the peer
+   will accept a Success packet prevents an attacker from acting as a
+   rogue authenticator.
+
+
+
+Aboba, et al.               Standards Track                    [Page 56]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   However, it is possible for an attacker to forge a Success packet
+   after the server has authenticated to the peer, but before the peer
+   has authenticated to the server.  If the peer were to accept the
+   forged Success packet and attempt to access the network when it had
+   not yet successfully authenticated to the server, a denial of service
+   attack could be mounted against the peer.  After such an attack, if
+   the lower layer supports failure indications, the authenticator can
+   synchronize state with the peer by providing a lower layer failure
+   indication.  See Section 7.12 for details.
+
+   If a server were to authenticate the peer and send a Success packet
+   prior to determining whether the peer has authenticated the
+   authenticator, an idle timeout can occur if the authenticator is not
+   authenticated by the peer.  Where supported by the lower layer, an
+   authenticator sensing the absence of the peer can free resources.
+
+   In a method supporting result indications, a peer that has
+   authenticated the server does not consider the authentication
+   successful until it receives an indication that the server
+   successfully authenticated it.  Similarly, a server that has
+   successfully authenticated the peer does not consider the
+   authentication successful until it receives an indication that the
+   peer has authenticated the server.
+
+   In order to avoid synchronization problems, prior to sending a
+   success result indication, it is desirable for the sender to verify
+   that sufficient authorization exists for granting access, though, as
+   discussed below, this is not always possible.
+
+   While result indications may enable synchronization of the
+   authentication result between the peer and server, this does not
+   guarantee that the peer and authenticator will be synchronized in
+   terms of their authorization or that timeouts will not occur.  For
+   example, the EAP server may not be aware of an authorization decision
+   made by a AAA proxy; the AAA server may check authorization only
+   after authentication has completed successfully, to discover that
+   authorization cannot be granted, or the AAA server may grant access
+   but the authenticator may be unable to provide it due to a temporary
+   lack of resources.  In these situations, synchronization may only be
+   achieved via lower layer result indications.
+
+   Success indications may be explicit or implicit.  For example, where
+   a method supports error messages, an implicit success indication may
+   be defined as the reception of a specific message without a preceding
+   error message.  Failures are typically indicated explicitly.  As
+   described in Section 4.2, a peer silently discards a Failure packet
+   received at a point where the method does not explicitly permit this
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 57]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   to be sent.  For example, a method providing its own error messages
+   might require the peer to receive an error message prior to accepting
+   a Failure packet.
+
+   Per-packet authentication, integrity, and replay protection of result
+   indications protects against spoofing.  Since protected result
+   indications require use of a key for per-packet authentication and
+   integrity protection, methods supporting protected result indications
+   MUST also support the "key derivation", "mutual authentication",
+   "integrity protection", and "replay protection" claims.
+
+   Protected result indications address some denial-of-service
+   vulnerabilities due to spoofing of Success and Failure packets,
+   though not all.  EAP methods can typically provide protected result
+   indications only in some circumstances.  For example, errors can
+   occur prior to key derivation, and so it may not be possible to
+   protect all failure indications.  It is also possible that result
+   indications may not be supported in both directions or that
+   synchronization may not be achieved in all modes of operation.
+
+   For example, within EAP-TLS [RFC2716], in the client authentication
+   handshake, the server authenticates the peer, but does not receive a
+   protected indication of whether the peer has authenticated it.  In
+   contrast, the peer authenticates the server and is aware of whether
+   the server has authenticated it.  In the session resumption
+   handshake, the peer authenticates the server, but does not receive a
+   protected indication of whether the server has authenticated it.  In
+   this mode, the server authenticates the peer and is aware of whether
+   the peer has authenticated it.
+
+8.  Acknowledgements
+
+   This protocol derives much of its inspiration from Dave Carrel's AHA
+   document, as well as the PPP CHAP protocol [RFC1994].  Valuable
+   feedback was provided by Yoshihiro Ohba of Toshiba America Research,
+   Jari Arkko of Ericsson, Sachin Seth of Microsoft, Glen Zorn of Cisco
+   Systems, Jesse Walker of Intel, Bill Arbaugh, Nick Petroni and Bryan
+   Payne of the University of Maryland, Steve Bellovin of AT&T Research,
+   Paul Funk of Funk Software, Pasi Eronen of Nokia, Joseph Salowey of
+   Cisco, Paul Congdon of HP, and members of the EAP working group.
+
+   The use of Security Claims sections for EAP methods, as required by
+   Section 7.2 and specified for each EAP method described in this
+   document, was inspired by Glen Zorn through [EAP-EVAL].
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 58]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+9.  References
+
+9.1.  Normative References
+
+   [RFC1661]          Simpson, W., "The Point-to-Point Protocol (PPP)",
+                      STD 51, RFC 1661, July 1994.
+
+   [RFC1994]          Simpson, W., "PPP Challenge Handshake
+                      Authentication Protocol (CHAP)", RFC 1994, August
+                      1996.
+
+   [RFC2119]          Bradner, S., "Key words for use in RFCs to
+                      Indicate Requirement Levels", BCP 14, RFC 2119,
+                      March 1997.
+
+   [RFC2243]          Metz, C., "OTP Extended Responses", RFC 2243,
+                      November 1997.
+
+   [RFC2279]          Yergeau, F., "UTF-8, a transformation format of
+                      ISO 10646", RFC 2279, January 1998.
+
+   [RFC2289]          Haller, N., Metz, C., Nesser, P. and M. Straw, "A
+                      One-Time Password System", RFC 2289, February
+                      1998.
+
+   [RFC2434]          Narten, T. and H. Alvestrand, "Guidelines for
+                      Writing an IANA Considerations Section in RFCs",
+                      BCP 26, RFC 2434, October 1998.
+
+   [RFC2988]          Paxson, V. and M. Allman, "Computing TCP's
+                      Retransmission Timer", RFC 2988, November 2000.
+
+   [IEEE-802]         Institute of Electrical and Electronics Engineers,
+                      "Local and Metropolitan Area Networks: Overview
+                      and Architecture", IEEE Standard 802, 1990.
+
+   [IEEE-802.1X]      Institute of Electrical and Electronics Engineers,
+                      "Local and Metropolitan Area Networks: Port-Based
+                      Network Access Control", IEEE Standard 802.1X,
+                      September 2001.
+
+
+
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 59]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+9.2.  Informative References
+
+   [RFC793]           Postel, J., "Transmission Control Protocol", STD
+                      7, RFC 793, September 1981.
+
+   [RFC1510]          Kohl, J. and B. Neuman, "The Kerberos Network
+                      Authentication Service (V5)", RFC 1510, September
+                      1993.
+
+   [RFC1750]          Eastlake, D., Crocker, S. and J. Schiller,
+                      "Randomness Recommendations for Security", RFC
+                      1750, December 1994.
+
+   [RFC2246]          Dierks, T., Allen, C., Treese, W., Karlton, P.,
+                      Freier, A. and P. Kocher, "The TLS Protocol
+                      Version 1.0", RFC 2246, January 1999.
+
+   [RFC2284]          Blunk, L. and J. Vollbrecht, "PPP Extensible
+                      Authentication Protocol (EAP)", RFC 2284, March
+                      1998.
+
+   [RFC2486]          Aboba, B. and M. Beadles, "The Network Access
+                      Identifier", RFC 2486, January 1999.
+
+   [RFC2408]          Maughan, D., Schneider, M. and M. Schertler,
+                      "Internet Security Association and Key Management
+                      Protocol (ISAKMP)", RFC 2408, November 1998.
+
+   [RFC2409]          Harkins, D. and D. Carrel, "The Internet Key
+                      Exchange (IKE)", RFC 2409, November 1998.
+
+   [RFC2433]          Zorn, G. and S. Cobb, "Microsoft PPP CHAP
+                      Extensions", RFC 2433, October 1998.
+
+   [RFC2607]          Aboba, B. and J. Vollbrecht, "Proxy Chaining and
+                      Policy Implementation in Roaming", RFC 2607, June
+                      1999.
+
+   [RFC2661]          Townsley, W., Valencia, A., Rubens, A., Pall, G.,
+                      Zorn, G. and B. Palter, "Layer Two Tunneling
+                      Protocol "L2TP"", RFC 2661, August 1999.
+
+   [RFC2716]          Aboba, B. and D. Simon, "PPP EAP TLS
+                      Authentication Protocol", RFC 2716, October 1999.
+
+   [RFC2865]          Rigney, C., Willens, S., Rubens, A. and W.
+                      Simpson, "Remote Authentication Dial In User
+                      Service (RADIUS)", RFC 2865, June 2000.
+
+
+
+Aboba, et al.               Standards Track                    [Page 60]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   [RFC2960]          Stewart, R., Xie, Q., Morneault, K., Sharp, C.,
+                      Schwarzbauer, H., Taylor, T., Rytina, I., Kalla,
+                      M., Zhang, L. and V. Paxson, "Stream Control
+                      Transmission Protocol", RFC 2960, October 2000.
+
+   [RFC3162]          Aboba, B., Zorn, G. and D. Mitton, "RADIUS and
+                      IPv6", RFC 3162, August 2001.
+
+   [RFC3454]          Hoffman, P. and M. Blanchet, "Preparation of
+                      Internationalized Strings ("stringprep")", RFC
+                      3454, December 2002.
+
+   [RFC3579]          Aboba, B. and P. Calhoun, "RADIUS (Remote
+                      Authentication Dial In User Service) Support For
+                      Extensible Authentication Protocol (EAP)", RFC
+                      3579, September 2003.
+
+   [RFC3580]          Congdon, P., Aboba, B., Smith, A., Zorn, G. and J.
+                      Roese, "IEEE 802.1X Remote Authentication Dial In
+                      User Service (RADIUS) Usage Guidelines", RFC 3580,
+                      September 2003.
+
+   [RFC3692]          Narten, T., "Assigning Experimental and Testing
+                      Numbers Considered Useful", BCP 82, RFC 3692,
+                      January 2004.
+
+   [DECEPTION]        Slatalla, M. and J. Quittner, "Masters of
+                      Deception", Harper-Collins, New York, 1995.
+
+   [KRBATTACK]        Wu, T., "A Real-World Analysis of Kerberos
+                      Password Security", Proceedings of the 1999 ISOC
+                      Network and Distributed System Security Symposium,
+                      http://www.isoc.org/isoc/conferences/ndss/99/
+                      proceedings/papers/wu.pdf.
+
+   [KRBLIM]           Bellovin, S. and M. Merrit, "Limitations of the
+                      Kerberos authentication system", Proceedings of
+                      the 1991 Winter USENIX Conference, pp. 253-267,
+                      1991.
+
+   [KERB4WEAK]        Dole, B., Lodin, S. and E. Spafford, "Misplaced
+                      trust:  Kerberos 4 session keys", Proceedings of
+                      the Internet Society Network and Distributed
+                      System Security Symposium, pp. 60-70, March 1997.
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 61]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   [PIC]              Aboba, B., Krawczyk, H. and Y. Sheffer, "PIC, A
+                      Pre-IKE Credential Provisioning Protocol", Work in
+                      Progress, October 2002.
+
+   [IKEv2]            Kaufman, C., "Internet Key Exchange (IKEv2)
+                      Protocol", Work in Progress, January 2004.
+
+   [PPTPv1]           Schneier, B. and Mudge, "Cryptanalysis of
+                      Microsoft's Point-to- Point Tunneling Protocol",
+                      Proceedings of the 5th ACM Conference on
+                      Communications and Computer Security, ACM Press,
+                      November 1998.
+
+   [IEEE-802.11]      Institute of Electrical and Electronics Engineers,
+                      "Wireless LAN Medium Access Control (MAC) and
+                      Physical Layer (PHY) Specifications", IEEE
+                      Standard 802.11, 1999.
+
+   [SILVERMAN]        Silverman, Robert D., "A Cost-Based Security
+                      Analysis of Symmetric and Asymmetric Key Lengths",
+                      RSA Laboratories Bulletin 13, April 2000 (Revised
+                      November 2001),
+                      http://www.rsasecurity.com/rsalabs/bulletins/
+                      bulletin13.html.
+
+   [KEYFRAME]         Aboba, B., "EAP Key Management Framework", Work in
+                      Progress, October 2003.
+
+   [SASLPREP]         Zeilenga, K., "SASLprep: Stringprep profile for
+                      user names and passwords", Work in Progress, March
+                      2004.
+
+   [IEEE-802.11i]     Institute of Electrical and Electronics Engineers,
+                      "Unapproved Draft Supplement to Standard for
+                      Telecommunications and Information Exchange
+                      Between Systems - LAN/MAN Specific Requirements -
+                      Part 11: Wireless LAN Medium Access Control (MAC)
+                      and Physical Layer (PHY) Specifications:
+                      Specification for Enhanced Security", IEEE Draft
+                      802.11i (work in progress), 2003.
+
+   [DIAM-EAP]         Eronen, P., Hiller, T. and G. Zorn, "Diameter
+                      Extensible Authentication Protocol (EAP)
+                      Application", Work in Progress, February 2004.
+
+   [EAP-EVAL]         Zorn, G., "Specifying Security Claims for EAP
+                      Authentication Types", Work in Progress, October
+                      2002.
+
+
+
+Aboba, et al.               Standards Track                    [Page 62]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   [BINDING]          Puthenkulam, J., "The Compound Authentication
+                      Binding Problem", Work in Progress, October 2003.
+
+   [MITM]             Asokan, N., Niemi, V. and K. Nyberg, "Man-in-the-
+                      Middle in Tunneled Authentication Protocols", IACR
+                      ePrint Archive Report 2002/163, October 2002,
+                      <http://eprint.iacr.org/2002/163>.
+
+   [IEEE-802.11i-req] Stanley, D., "EAP Method Requirements for Wireless
+                      LANs", Work in Progress, February 2004.
+
+   [PPTPv2]           Schneier, B. and Mudge, "Cryptanalysis of
+                      Microsoft's PPTP Authentication Extensions (MS-
+                      CHAPv2)", CQRE 99, Springer-Verlag, 1999, pp.
+                      192-203.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 63]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+Appendix A. Changes from RFC 2284
+
+   This section lists the major changes between [RFC2284] and this
+   document.  Minor changes, including style, grammar, spelling, and
+   editorial changes are not mentioned here.
+
+   o  The Terminology section (Section 1.2) has been expanded, defining
+      more concepts and giving more exact definitions.
+
+   o  The concepts of Mutual Authentication, Key Derivation, and Result
+      Indications are introduced and discussed throughout the document
+      where appropriate.
+
+   o In Section 2, it is explicitly specified that more than one
+      exchange of Request and Response packets may occur as part of the
+      EAP authentication exchange.  How this may be used and how it may
+      not be used is specified in detail in Section 2.1.
+
+   o  Also in Section 2, some requirements have been made explicit for
+      the authenticator when acting in pass-through mode.
+
+   o  An EAP multiplexing model (Section 2.2) has been added to
+      illustrate a typical implementation of EAP.  There is no
+      requirement that an implementation conform to this model, as long
+      as the on-the-wire behavior is consistent with it.
+
+   o  As EAP is now in use with a variety of lower layers, not just PPP
+      for which it was first designed, Section 3 on lower layer behavior
+      has been added.
+
+   o  In the description of the EAP Request and Response interaction
+      (Section 4.1), both the behavior on receiving duplicate requests,
+      and when packets should be silently discarded has been more
+      exactly specified.  The implementation notes in this section have
+      been substantially expanded.
+
+   o  In Section 4.2, it has been clarified that Success and Failure
+      packets must not contain additional data, and the implementation
+      note has been expanded.  A subsection giving requirements on
+      processing of success and failure packets has been added.
+
+   o  Section 5 on EAP Request/Response Types lists two new Type values:
+      the Expanded Type (Section 5.7), which is used to expand the Type
+      value number space, and the Experimental Type.  In the Expanded
+      Type number space, the new Expanded Nak (Section 5.3.2) Type has
+      been added.  Clarifications have been made in the description of
+      most of the existing Types.  Security claims summaries have been
+      added for authentication methods.
+
+
+
+Aboba, et al.               Standards Track                    [Page 64]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+   o  In Sections 5, 5.1, and 5.2, a requirement has been added such
+      that fields with displayable messages should contain UTF-8 encoded
+      ISO 10646 characters.
+
+   o  It is now required in Section 5.1 that if the Type-Data field of
+      an Identity Request contains a NUL-character, only the part before
+      the null is displayed.  RFC 2284 prohibits the null termination of
+      the Type-Data field of Identity messages.  This rule has been
+      relaxed for Identity Request messages and the Identity Request
+      Type-Data field may now be null terminated.
+
+   o  In Section 5.5, support for OTP Extended Responses [RFC2243] has
+      been added to EAP OTP.
+
+   o  An IANA Considerations section (Section 6) has been added, giving
+      registration policies for the numbering spaces defined for EAP.
+
+   o  The Security Considerations (Section 7) have been greatly
+      expanded, giving a much more comprehensive coverage of possible
+      threats and other security considerations.
+
+   o  In Section 7.5, text has been added on method-specific behavior,
+      providing guidance on how EAP method-specific integrity checks
+      should be processed.  Where possible, it is desirable for a
+      method-specific MIC to be computed over the entire EAP packet,
+      including the EAP layer header (Code, Identifier, Length) and EAP
+      method layer header (Type, Type-Data).
+
+   o  In Section 7.14 the security risks involved in use of cleartext
+      passwords with EAP are described.
+
+   o  In Section 7.15 text has been added relating to detection of rogue
+      NAS behavior.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 65]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+Authors' Addresses
+
+   Bernard Aboba
+   Microsoft Corporation
+   One Microsoft Way
+   Redmond, WA  98052
+   USA
+
+   Phone: +1 425 706 6605
+   Fax:   +1 425 936 6605
+   EMail: bernarda@microsoft.com
+
+   Larry J. Blunk
+   Merit Network, Inc
+   4251 Plymouth Rd., Suite 2000
+   Ann Arbor, MI  48105-2785
+   USA
+
+   Phone: +1 734-647-9563
+   Fax:   +1 734-647-3185
+   EMail: ljb@merit.edu
+
+   John R. Vollbrecht
+   Vollbrecht Consulting LLC
+   9682 Alice Hill Drive
+   Dexter, MI  48130
+   USA
+
+   EMail: jrv@umich.edu
+
+   James Carlson
+   Sun Microsystems, Inc
+   1 Network Drive
+   Burlington, MA  01803-2757
+   USA
+
+   Phone: +1 781 442 2084
+   Fax:   +1 781 442 1677
+   EMail: james.d.carlson@sun.com
+
+   Henrik Levkowetz
+   ipUnplugged AB
+   Arenavagen 33
+   Stockholm  S-121 28
+   SWEDEN
+
+   Phone: +46 708 32 16 08
+   EMail: henrik@levkowetz.com
+
+
+
+Aboba, et al.               Standards Track                    [Page 66]
+\f
+RFC 3748                          EAP                          June 2004
+
+
+Full Copyright Statement
+
+   Copyright (C) The Internet Society (2004).  This document is subject
+   to the rights, licenses and restrictions contained in BCP 78, and
+   except as set forth therein, the authors retain all their rights.
+
+   This document and the information contained herein are provided on an
+   "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+   OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+   ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+   INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+   INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+   The IETF takes no position regarding the validity or scope of any
+   Intellectual Property Rights or other rights that might be claimed to
+   pertain to the implementation or use of the technology described in
+   this document or the extent to which any license under such rights
+   might or might not be available; nor does it represent that it has
+   made any independent effort to identify any such rights.  Information
+   on the procedures with respect to rights in RFC documents can be
+   found in BCP 78 and BCP 79.
+
+   Copies of IPR disclosures made to the IETF Secretariat and any
+   assurances of licenses to be made available, or the result of an
+   attempt made to obtain a general license or permission for the use of
+   such proprietary rights by implementers or users of this
+   specification can be obtained from the IETF on-line IPR repository at
+   http://www.ietf.org/ipr.
+
+   The IETF invites any interested party to bring to its attention any
+   copyrights, patents or patent applications, or other proprietary
+   rights that may cover technology that may be required to implement
+   this standard.  Please address the information to the IETF at ietf-
+   ipr@ietf.org.
+
+Acknowledgement
+
+   Funding for the RFC Editor function is currently provided by the
+   Internet Society.
+
+
+
+
+
+
+
+
+
+Aboba, et al.               Standards Track                    [Page 67]
+\f
diff --git a/doc/rfc/rfc4590.txt b/doc/rfc/rfc4590.txt
new file mode 100644 (file)
index 0000000..fad3d22
--- /dev/null
@@ -0,0 +1,1795 @@
+
+
+
+
+
+
+Network Working Group                                         B. Sterman
+Request for Comments: 4590                               Kayote Networks
+Category: Standards Track                                  D. Sadolevsky
+                                                          SecureOL, Inc.
+                                                             D. Schwartz
+                                                         Kayote Networks
+                                                             D. Williams
+                                                           Cisco Systems
+                                                                 W. Beck
+                                                     Deutsche Telekom AG
+                                                               July 2006
+
+
+               RADIUS Extension for Digest Authentication
+
+Status of This Memo
+
+   This document specifies an Internet standards track protocol for the
+   Internet community, and requests discussion and suggestions for
+   improvements.  Please refer to the current edition of the "Internet
+   Official Protocol Standards" (STD 1) for the standardization state
+   and status of this protocol.  Distribution of this memo is unlimited.
+
+Copyright Notice
+
+   Copyright (C) The Internet Society (2006).
+
+Abstract
+
+   This document defines an extension to the Remote Authentication
+   Dial-In User Service (RADIUS) protocol to enable support of Digest
+   Authentication, for use with HTTP-style protocols like the Session
+   Initiation Protocol (SIP) and HTTP.
+
+Table of Contents
+
+1. Introduction ....................................................2
+   1.1. Terminology ................................................2
+   1.2. Motivation .................................................3
+   1.3. Overview ...................................................4
+2. Detailed Description ............................................6
+   2.1. RADIUS Client Behavior .....................................6
+        2.1.1. Credential Selection ................................6
+        2.1.2. Constructing an Access-Request ......................6
+        2.1.3. Constructing an Authentication-Info Header ..........7
+        2.1.4. Failed Authentication ...............................8
+        2.1.5. Obtaining Nonces ....................................9
+   2.2. RADIUS Server Behavior .....................................9
+
+
+
+Sterman, et al.             Standards Track                     [Page 1]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+        2.2.1. General Attribute Checks ............................9
+        2.2.2. Authentication .....................................10
+        2.2.3. Constructing the Reply .............................11
+3. New RADIUS Attributes ..........................................12
+   3.1. Digest-Response attribute .................................12
+   3.2. Digest-Realm Attribute ....................................13
+   3.3. Digest-Nonce Attribute ....................................13
+   3.4. Digest-Response-Auth Attribute ............................14
+   3.5. Digest-Nextnonce Attribute ................................14
+   3.6. Digest-Method Attribute ...................................14
+   3.7. Digest-URI Attribute ......................................15
+   3.8. Digest-Qop Attribute ......................................15
+   3.9. Digest-Algorithm Attribute ................................16
+   3.10. Digest-Entity-Body-Hash Attribute ........................16
+   3.11. Digest-CNonce Attribute ..................................17
+   3.12. Digest-Nonce-Count Attribute .............................17
+   3.13. Digest-Username Attribute ................................17
+   3.14. Digest-Opaque Attribute ..................................18
+   3.15. Digest-Auth-Param Attribute ..............................18
+   3.16. Digest-AKA-Auts Attribute ................................19
+   3.17. Digest-Domain Attribute ..................................19
+   3.18. Digest-Stale Attribute ...................................20
+   3.19. Digest-HA1 Attribute .....................................20
+   3.20. SIP-AOR Attribute ........................................21
+4. Diameter Compatibility .........................................21
+5. Table of Attributes ............................................22
+6. Examples .......................................................23
+7. IANA Considerations ............................................27
+8. Security Considerations ........................................27
+   8.1. Denial of Service .........................................28
+   8.2. Confidentiality and Data Integrity ........................28
+9. Acknowledgements ...............................................29
+10. References ....................................................29
+   10.1. Normative References .....................................29
+   10.2. Informative References ...................................30
+
+1.  Introduction
+
+1.1.  Terminology
+
+   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+   "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+   document are to be interpreted as described in [RFC2119].
+
+   The use of normative requirement key words in this document shall
+   apply only to RADIUS client and RADIUS server implementations that
+   include the features described in this document.  This document
+   creates no normative requirements for existing implementations.
+
+
+
+Sterman, et al.             Standards Track                     [Page 2]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   HTTP-style protocol
+         The term 'HTTP-style' denotes any protocol that uses HTTP-like
+         headers and uses HTTP Digest Authentication as described in
+         [RFC2617].  Examples are HTTP and the Session Initiation
+         Protocol (SIP).
+
+   NAS
+         Network Access Server, the RADIUS client.
+
+   nonce
+         An unpredictable value used to prevent replay attacks.  The
+         nonce generator may use cryptographic mechanisms to produce
+         nonces it can recognize without maintaining state.
+
+   protection space
+         HTTP-style protocols differ in their definition of the
+         protection space.  For HTTP, it is defined as the combination
+         of realm and canonical root URL of the requested resource for
+         which the use is authorized by the RADIUS server.  In the case
+         of SIP, the realm string alone defines the protection space.
+
+   SIP UA
+         SIP User Agent, an Internet endpoint that uses the Session
+         Initiation Protocol.
+
+   SIP UAS
+         SIP User Agent Server, a logical entity that generates a
+         response to a SIP (Session Initiation Protocol) request.
+
+1.2.  Motivation
+
+   The HTTP Digest Authentication mechanism, defined in [RFC2617], was
+   subsequently adapted for use with SIP [RFC3261].  Due to the
+   limitations and weaknesses of Digest Authentication (see [RFC2617],
+   section 4), additional authentication and encryption mechanisms are
+   defined in SIP [RFC3261], including Transport Layer Security (TLS)
+   [RFC4346] and Secure MIME (S/MIME) [RFC3851].  However, Digest
+   Authentication support is mandatory in SIP implementations, and
+   Digest Authentication is the preferred way for a SIP UA to
+   authenticate itself to a proxy server.  Digest Authentication is used
+   in other protocols as well.
+
+   To simplify the provisioning of users, there is a need to support
+   this authentication mechanism within Authentication, Authorization,
+   and Accounting (AAA) protocols such as RADIUS [RFC2865] and Diameter
+   [RFC3588].
+
+
+
+
+
+Sterman, et al.             Standards Track                     [Page 3]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   This document defines an extension to the RADIUS protocol to enable
+   support of Digest Authentication for use with SIP, HTTP, and other
+   HTTP-style protocols using this authentication method.  Support for
+   Digest mechanisms such as Authentication and Key Agreement (AKA)
+   [RFC3310] is also supported.  A companion document [SIP-APP] defines
+   support for Digest Authentication within Diameter.
+
+1.3.  Overview
+
+   HTTP Digest is a challenge-response protocol used to authenticate a
+   client's request to access some resource on a server.  Figure 1 shows
+   a single HTTP Digest transaction.
+
+                                 HTTP/SIP..
+                  +------------+  (1)     +------------+
+                  |            |--------->|            |
+                  | HTTP-style |  (2)     | HTTP-style |
+                  | client     |<---------| server     |
+                  |            |  (3)     |            |
+                  |            |--------->|            |
+                  |            |  (4)     |            |
+                  |            |<---------|            |
+                  +------------+          +------------+
+
+                 Figure 1: Digest operation without RADIUS
+
+   If the client sends a request without any credentials (1), the server
+   will reply with an error response (2) containing a nonce.  The client
+   creates a cryptographic digest from parts of the request, from the
+   nonce it received from the server, and from a shared secret.  The
+   client re-transmits the request (3) to the server, but now includes
+   the digest within the packet.  The server does the same digest
+   calculation as the client and compares the result with the digest it
+   received in (3).  If the digest values are identical, the server
+   grants access to the resource and sends a positive response to the
+   client (4).  If the digest values differ, the server sends a negative
+   response to the client (4).
+
+   Instead of maintaining a local user database, the server could use
+   RADIUS to access a centralized user database.  However, RADIUS
+   [RFC2865] does not include support for HTTP Digest Authentication.
+   The RADIUS client cannot use the User-Password attribute, since it
+   does not receive a password from the HTTP-style client.  The
+   CHAP-Challenge and CHAP-Password attributes described in [RFC1994]
+   are also not suitable since the CHAP algorithm is not compatible with
+   HTTP Digest.
+
+
+
+
+
+Sterman, et al.             Standards Track                     [Page 4]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   This document defines new attributes that enable the RADIUS server to
+   perform the digest calculation defined in [RFC2617], providing
+   support for Digest Authentication as a native authentication
+   mechanism within RADIUS.
+
+   The nonces required by the digest algorithm are generated by the
+   RADIUS server.  Generating them in the RADIUS client would save a
+   round-trip, but introduce security and operational issues.  Some
+   digest algorithms -- e.g., AKA [RFC3310] -- would not work.
+
+   Figure 2 depicts a scenario in which the HTTP-style server defers
+   authentication to a RADIUS server.  Entities A and B communicate
+   using HTTP or SIP, while entities B and C communicate using RADIUS.
+
+                        HTTP/SIP           RADIUS
+
+               +-----+    (1)    +-----+           +-----+
+               |     |==========>|     |    (2)    |     |
+               |     |           |     |---------->|     |
+               |     |           |     |    (3)    |     |
+               |     |    (4)    |     |<----------|     |
+               |     |<==========|     |           |     |
+               |     |    (5)    |     |           |     |
+               |     |==========>|     |           |     |
+               |  A  |           |  B  |    (6)    |  C  |
+               |     |           |     |---------->|     |
+               |     |           |     |    (7)    |     |
+               |     |           |     |<----------|     |
+               |     |    (8)    |     |           |     |
+               |     |<==========|     |           |     |
+               +-----+           +-----+           +-----+
+
+               ====> HTTP/SIP
+               ----> RADIUS
+
+                    Figure 2: HTTP Digest over RADIUS
+
+   The entities have the following roles:
+
+   A: HTTP client / SIP UA
+
+   B: {HTTP server / HTTP proxy server / SIP proxy server / SIP UAS}
+      acting also as a RADIUS NAS
+
+   C: RADIUS server
+
+
+
+
+
+
+Sterman, et al.             Standards Track                     [Page 5]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   The following messages are sent in this scenario:
+
+   A sends B an HTTP/SIP request without an authorization header (step
+   1).  B sends an Access-Request packet with the newly defined
+   Digest-Method and Digest-URI attributes but without a Digest-Nonce
+   attribute to the RADIUS server, C (step 2).  C chooses a nonce and
+   responds with an Access-Challenge (step 3).  This Access-Challenge
+   contains Digest attributes, from which B takes values to construct an
+   HTTP/SIP "(Proxy) Authorization required" response.  B sends this
+   response to A (step 4).  A resends its request with its credentials
+   (step 5).  B sends an Access-Request to C (step 6).  C checks the
+   credentials and replies with Access-Accept or Access-Reject (step 7).
+   Depending on C's result, B processes A's request or rejects it with a
+   "(Proxy) Authorization required" response (step 8).
+
+2.  Detailed Description
+
+2.1.  RADIUS Client Behavior
+
+   The attributes described in this document are sent in cleartext.
+   Therefore, were a RADIUS client to accept secure connections (HTTPS
+   or SIPS) from HTTP-style clients, this could result in information
+   intentionally protected by HTTP-style clients being sent in the clear
+   during RADIUS exchange.
+
+2.1.1.  Credential Selection
+
+   On reception of an HTTP-style request message, the RADIUS client
+   checks whether it is authorized to authenticate the request.  Where
+   an HTTP-style request traverses several proxies and each of the
+   proxies requests to authenticate the HTTP-style client, the request
+   at the HTTP-style server may contain multiple credential sets.
+
+   The RADIUS client can use the 'realm' directive in HTTP to determine
+   which credentials are applicable.  Where none of the realms are of
+   interest, the RADIUS client MUST behave as though no relevant
+   credentials were sent.  In all situations, the RADIUS client MUST
+   send zero or exactly one credential to the RADIUS server.  The RADIUS
+   client MUST choose the credential of the (Proxy-)Authorization header
+   if the realm directive matches its locally configured realm.
+
+2.1.2.  Constructing an Access-Request
+
+   If a matching (Proxy-)Authorization header is present and contains
+   HTTP Digest information, the RADIUS client checks the 'nonce'
+   parameter.
+
+
+
+
+
+Sterman, et al.             Standards Track                     [Page 6]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   If the RADIUS client recognizes the nonce, it takes the header
+   directives and puts them into a RADIUS Access-Request packet.  It
+   puts the 'response' directive into a Digest-Response attribute and
+   the realm, nonce, digest-uri, qop, algorithm, cnonce, nc, username,
+   and opaque directives into the respective Digest-Realm, Digest-Nonce,
+   Digest-URI, Digest-Qop, Digest-Algorithm, Digest-CNonce,
+   Digest-Nonce-Count, Digest-Username, and Digest-Opaque attributes.
+   The RADIUS client puts the request method into the Digest-Method
+   attribute.
+
+   Due to syntactic requirements, HTTP-style protocols have to escape
+   with backslash all quote and backslash characters in contents of HTTP
+   Digest directives.  When translating directives into RADIUS
+   attributes, the RADIUS client only removes the surrounding quotes
+   where present.  See Section 3 for an example.
+
+   If the Quality of Protection (qop) directive's value is 'auth-int',
+   the RADIUS client calculates H(entity-body) as described in
+   [RFC2617], Section 3.2.1, and puts the result in a
+   Digest-Entity-Body-Hash attribute.
+
+   The RADIUS client adds a Message-Authenticator attribute, defined in
+   [RFC3579], and sends the Access-Request packet to the RADIUS server.
+
+   The RADIUS server processes the packet and responds with an
+   Access-Accept or an Access-Reject.
+
+2.1.3.  Constructing an Authentication-Info Header
+
+   After having received an Access-Accept from the RADIUS server, the
+   RADIUS client constructs an Authentication-Info header:
+
+   o  If the Access-Accept packet contains a Digest-Response-Auth
+      attribute, the RADIUS client checks the Digest-Qop attribute:
+
+      *  If the Digest-Qop attribute's value is 'auth' or not specified,
+         the RADIUS client puts the Digest-Response-Auth attribute's
+         content into the Authentication-Info header's 'rspauth'
+         directive of the HTTP-style response.
+
+      *  If the Digest-Qop attribute's value is 'auth-int', the RADIUS
+         client ignores the Access-Accept packet and behaves as if it
+         had received an Access-Reject packet (Digest-Response-Auth
+         can't be correct as the RADIUS server does not know the
+         contents of the HTTP-style response's body).
+
+
+
+
+
+
+Sterman, et al.             Standards Track                     [Page 7]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   o  If the Access-Accept packet contains a Digest-HA1 attribute, the
+      RADIUS client checks the 'qop' and 'algorithm' directives in the
+      Authorization header of the HTTP-style request it wants to
+      authorize:
+
+      *  If the 'qop' directive is missing or its value is 'auth', the
+         RADIUS client ignores the Digest-HA1 attribute.  It does not
+         include an Authentication-Info header in its HTTP-style
+         response.
+
+      *  If the 'qop' directive's value is 'auth-int' and at least one
+         of the following conditions is true, the RADIUS client
+         calculates the contents of the HTTP-style response's 'rspauth'
+         directive:
+
+         +  The algorithm directive's value is 'MD5-sess' or
+            'AKAv1-MD5-sess'.
+
+         +  IP Security (IPsec) is configured to protect traffic between
+            the RADIUS client and RADIUS server with IPsec (see
+            Section 8).
+
+         It creates the HTTP-style response message and calculates the
+         hash of this message's body.  It uses the result and the
+         Digest-URI attribute's value of the corresponding
+         Access-Request packet to perform the H(A2) calculation.  It
+         takes the Digest-Nonce, Digest-Nonce-Count, Digest-CNonce, and
+         Digest-Qop values of the corresponding Access-Request and the
+         Digest-HA1 attribute's value to finish the computation of the
+         'rspauth' value.
+
+   o  If the Access-Accept packet contains neither a
+      Digest-Response-Auth nor a Digest-HA1 attribute, the RADIUS client
+      will not create an Authentication-Info header for its HTTP-style
+      response.
+
+   When the RADIUS server provides a Digest-Nextnonce attribute in the
+   Access-Accept packet, the RADIUS client puts the contents of this
+   attribute into a 'nextnonce' directive.  Now it can send an
+   HTTP-style response.
+
+2.1.4.  Failed Authentication
+
+   If the RADIUS client did receive an HTTP-style request without a
+   (Proxy-)Authorization header matching its locally configured realm
+   value, it obtains a new nonce and sends an error response (401 or
+   407) containing a (Proxy-)Authenticate header.
+
+
+
+
+Sterman, et al.             Standards Track                     [Page 8]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   If the RADIUS client receives an Access-Challenge packet in response
+   to an Access-Request containing a Digest-Nonce attribute, the RADIUS
+   server did not accept the nonce.  If a Digest-Stale attribute is
+   present in the Access-Challenge and has a value of 'true' (without
+   surrounding quotes), the RADIUS client sends an error response (401
+   or 407) containing a WWW-/Proxy-Authenticate header with the
+   directive 'stale' and the digest directives derived from the Digest-*
+   attributes.
+
+   If the RADIUS client receives an Access-Reject from the RADIUS
+   server, it sends an error response to the HTTP-style request it has
+   received.  If the RADIUS client does not receive a response, it
+   retransmits or fails over to another RADIUS server as described in
+   [RFC2865].
+
+2.1.5.  Obtaining Nonces
+
+   The RADIUS client has two ways to obtain nonces: it has received one
+   in a Digest-Nextnonce attribute of a previously received
+   Access-Accept packet or it asks the RADIUS server for one.  To do the
+   latter, it sends an Access-Request containing a Digest-Method and a
+   Digest-URI attribute but without a Digest-Nonce attribute.  It adds a
+   Message-Authenticator (see [RFC3579]) attribute to the Access-Request
+   packet.  The RADIUS server chooses a nonce and responds with an
+   Access-Challenge containing a Digest-Nonce attribute.
+
+   The RADIUS client constructs a (Proxy-)Authenticate header using the
+   received Digest-Nonce and Digest-Realm attributes to fill the nonce
+   and realm directives.  The RADIUS server can send Digest-Qop,
+   Digest-Algorithm, Digest-Domain, and Digest-Opaque attributes in the
+   Access-Challenge carrying the nonce.  If these attributes are
+   present, the client MUST use them.
+
+2.2.  RADIUS Server Behavior
+
+   If the RADIUS server receives an Access-Request packet with a
+   Digest-Method and a Digest-URI attribute but without a Digest-Nonce
+   attribute, it chooses a nonce.  It puts the nonce into a Digest-Nonce
+   attribute and sends it in an Access-Challenge packet to the RADIUS
+   client.  The RADIUS server MUST add Digest-Realm,
+   Message-Authenticator (see [RFC3579]), SHOULD add Digest-Algorithm
+   and one or more Digest-Qop, and MAY add Digest-Domain or
+   Digest-Opaque attributes to the Access-Challenge packet.
+
+2.2.1.  General Attribute Checks
+
+   If the RADIUS server receives an Access-Request packet containing a
+   Digest-Response attribute, it looks for the following attributes:
+
+
+
+Sterman, et al.             Standards Track                     [Page 9]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   Digest-Realm, Digest-Nonce, Digest-Method, Digest-URI, Digest-Qop,
+   Digest-Algorithm, and Digest-Username.  Depending on the content of
+   Digest-Algorithm and Digest-Qop, it looks for
+   Digest-Entity-Body-Hash, Digest-CNonce, and Digest-AKA-Auts, too.
+   See [RFC2617] and [RFC3310] for details.  If the Digest-Algorithm
+   attribute is missing, 'MD5' is assumed.  If the RADIUS server has
+   issued a Digest-Opaque attribute along with the nonce, the
+   Access-Request MUST have a matching Digest-Opaque attribute.
+
+   If mandatory attributes are missing, it MUST respond with an
+   Access-Reject packet.
+
+   The RADIUS server removes '\' characters that escape quote and '\'
+   characters from the text values it has received in the Digest-*
+   attributes.
+
+   If the mandatory attributes are present, the RADIUS server MUST check
+   if the RADIUS client is authorized to serve users of the realm
+   mentioned in the Digest-Realm attribute.  If the RADIUS client is not
+   authorized, the RADIUS server MUST send an Access-Reject.  The RADIUS
+   server SHOULD log the event so as to notify the operator, and MAY
+   take additional action such as sending an Access-Reject in response
+   to all future requests from this client, until this behavior is reset
+   by management action.
+
+   The RADIUS server determines the age of the nonce in Digest-Nonce by
+   using an embedded time-stamp or by looking it up in a local table.
+   The RADIUS server MUST check the integrity of the nonce if it embeds
+   the time-stamp in the nonce.  Section 2.2.2 describes how the server
+   handles old nonces.
+
+2.2.2.  Authentication
+
+   If the Access-Request message has passed the checks described above,
+   the RADIUS server calculates the digest response as described in
+   [RFC2617].  To look up the password, the RADIUS server uses the
+   RADIUS User-Name attribute.  The RADIUS server MUST check if the user
+   identified by the User-Name attribute
+
+   o  is authorized to access the protection space and
+
+   o  is authorized to use the URI included in the SIP-AOR attribute, if
+      this attribute is present.
+
+   If any of those checks fails, the RADIUS server MUST send an
+   Access-Reject.
+
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 10]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   Correlation between User-Name and SIP-AOR AVP values is required just
+   to avoid that any user can register or misuse a SIP-AOR allocated to
+   a different user.
+
+   All values required for the digest calculation are taken from the
+   Digest attributes described in this document.  If the calculated
+   digest response equals the value received in the Digest-Response
+   attribute, the authentication was successful.
+
+   If the response values match, but the RADIUS server considers the
+   nonce in the Digest-Nonce attribute as too old, it sends an
+   Access-Challenge packet containing a new nonce and a Digest-Stale
+   attribute with a value of 'true' (without surrounding quotes).
+
+   If the response values don't match, the RADIUS server responds with
+   an Access-Reject.
+
+2.2.3.  Constructing the Reply
+
+   If the authentication was successful, the RADIUS server adds an
+   attribute to the Access-Accept packet that can be used by the RADIUS
+   client to construct an Authentication-Info header:
+
+   o  If the Digest-Qop attribute's value is 'auth' or unspecified, the
+      RADIUS server SHOULD put a Digest-Response-Auth attribute into the
+      Access-Accept packet.
+
+   o  If the Digest-Qop attribute's value is 'auth-int' and at least one
+      of the following conditions is true, the RADIUS server SHOULD put
+      a Digest-HA1 attribute into the Access-Accept packet:
+
+      *  The Digest-Algorithm attribute's value is 'MD5-sess' or
+         'AKAv1-MD5-sess'.
+
+      *  IPsec is configured to protect traffic between the RADIUS
+         client and RADIUS server with IPsec (see Section 8).
+
+   In all other cases, Digest-Response-Auth or Digest-HA1 MUST NOT be
+   sent.
+
+   RADIUS servers MAY construct a Digest-Nextnonce attribute and add it
+   to the Access-Accept packet.  This is useful to limit the lifetime of
+   a nonce and to save a round-trip in future requests (see nextnonce
+   discussion in [RFC2617], section 3.2.3).  The RADIUS server adds a
+   Message-Authenticator attribute (see [RFC3579]) and sends the
+   Access-Accept packet to the RADIUS client.
+
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 11]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   If the RADIUS server does not accept the nonce received in an
+   Access-Request packet but authentication was successful, the RADIUS
+   server MUST send an Access-Challenge packet containing a Digest-Stale
+   attribute set to 'true' (without surrounding quotes).  The RADIUS
+   server MUST add Message-Authenticator (see [RFC3579]), Digest-Nonce,
+   Digest-Realm, SHOULD add Digest-Algorithm and one or more Digest-Qop
+   and MAY add Digest-Domain, Digest-Opaque attributes to the
+   Access-Challenge packet.
+
+3.  New RADIUS Attributes
+
+   If not stated otherwise, the attributes have the following format:
+
+   0                   1                   2
+   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |     Type      |  Length       | Text ...
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+   Quote and backslash characters in Digest-* attributes representing
+   HTTP-style directives with a quoted-string syntax are escaped.  The
+   surrounding quotes are removed.  They are syntactical delimiters that
+   are redundant in RADIUS.  For example, the directive
+
+   realm="the \"example\" value"
+
+   is represented as follows:
+
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   | Digest-Realm  |       23      | the \"example\" value |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+3.1.  Digest-Response attribute
+
+   Description
+         If this attribute is present in an Access-Request message, a
+         RADIUS server implementing this specification MUST treat the
+         Access-Request as a request for Digest Authentication.  When a
+         RADIUS client receives a (Proxy-)Authorization header, it puts
+         the request-digest value into a Digest-Response attribute.
+         This attribute (which enables the user to prove possession of
+         the password) MUST only be used in Access-Requests.
+   Type
+         103 for Digest-Response.
+   Length
+         >= 3
+
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 12]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   Text
+         When using HTTP Digest, the text field is 32 octets long and
+         contains a hexadecimal representation of a 16-octet digest
+         value as it was calculated by the authenticated client.  Other
+         digest algorithms MAY define different digest lengths.  The
+         text field MUST be copied from request-digest of
+         digest-response ([RFC2617]) without surrounding quotes.
+
+3.2.  Digest-Realm Attribute
+
+   Description
+         This attribute describes a protection space component of the
+         RADIUS server.  HTTP-style protocols differ in their definition
+         of the protection space.  See [RFC2617], Section 1.2, for
+         details.  It MUST only be used in Access-Request and
+         Access-Challenge packets.
+   Type
+         104 for Digest-Realm
+   Length
+         >=3
+   Text
+         In Access-Requests, the RADIUS client takes the value of the
+         realm directive (realm-value according to [RFC2617]) without
+         surrounding quotes from the HTTP-style request it wants to
+         authenticate.  In Access-Challenge packets, the RADIUS server
+         puts the expected realm value into this attribute.
+
+3.3.  Digest-Nonce Attribute
+
+   Description
+
+         This attribute holds a nonce to be used in the HTTP Digest
+         calculation.  If the Access-Request had a Digest-Method and a
+         Digest-URI but no Digest-Nonce attribute, the RADIUS server
+         MUST put a Digest-Nonce attribute into its Access-Challenge
+         packet.  This attribute MUST only be used in Access-Request and
+         Access-Challenge packets.
+   Type
+         105 for Digest-Nonce
+   Length
+         >=3
+   Text
+         In Access-Requests, the RADIUS client takes the value of the
+         nonce directive (nonce-value in [RFC2617]) without surrounding
+         quotes from the HTTP-style request it wants to authenticate.
+         In Access-Challenge packets, the attribute contains the nonce
+         selected by the RADIUS server.
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 13]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+3.4.  Digest-Response-Auth Attribute
+
+   Description
+         This attribute enables the RADIUS server to prove possession of
+         the password.  If the previously received Digest-Qop attribute
+         was 'auth-int' (without surrounding quotes), the RADIUS server
+         MUST send a Digest-HA1 attribute instead of a
+         Digest-Response-Auth attribute.  The Digest-Response-Auth
+         attribute MUST only be used in Access-Accept packets.  The
+         RADIUS client puts the attribute value without surrounding
+         quotes into the rspauth directive of the Authentication-Info
+         header.
+   Type
+         106 for Digest-Response-Auth.
+   Length
+         >= 3
+   Text
+         The RADIUS server calculates a digest according to section
+         3.2.3 of [RFC2617] and copies the result into this attribute.
+         Digest algorithms other than the one defined in [RFC2617] MAY
+         define digest lengths other than 32.
+
+3.5.  Digest-Nextnonce Attribute
+
+   This attribute holds a nonce to be used in the HTTP Digest
+   calculation.
+
+   Description
+
+         The RADIUS server MAY put a Digest-Nextnonce attribute into an
+         Access-Accept packet.  If this attribute is present, the RADIUS
+         client MUST put the contents of this attribute into the
+         nextnonce directive of an Authentication-Info header in its
+         HTTP-style response.  This attribute MUST only be used in
+         Access-Accept packets.
+   Type
+         107 for Digest-Nextnonce
+   Length
+         >=3
+   Text
+         It is recommended that this text be base64 or hexadecimal data.
+
+3.6.  Digest-Method Attribute
+
+   Description
+         This attribute holds the method value to be used in the HTTP
+         Digest calculation.  This attribute MUST only be used in
+         Access-Request packets.
+
+
+
+Sterman, et al.             Standards Track                    [Page 14]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   Type
+         108 for Digest-Method
+   Length
+         >=3
+   Text
+         In Access-Requests, the RADIUS client takes the value of the
+         request method from the HTTP-style request it wants to
+         authenticate.
+
+3.7.  Digest-URI Attribute
+
+   Description
+         This attribute is used to transport the contents of the
+         digest-uri directive or the URI of the HTTP-style request.  It
+         MUST only be used in Access-Request packets.
+   Type
+         109 for Digest-URI
+   Length
+         >=3
+   Text
+         If the HTTP-style request has an Authorization header, the
+         RADIUS client puts the value of the "uri" directive found in
+         the HTTP-style request Authorization header (known as
+         "digest-uri-value" in section 3.2.2 of [RFC2617]) without
+         surrounding quotes into this attribute.  If there is no
+         Authorization header, the RADIUS client takes the value of the
+         request URI from the HTTP-style request it wants to
+         authenticate.
+
+3.8.  Digest-Qop Attribute
+
+   Description
+         This attribute holds the Quality of Protection parameter that
+         influences the HTTP Digest calculation.  This attribute MUST
+         only be used in Access-Request and Access-Challenge packets.  A
+         RADIUS client SHOULD insert one of the Digest-Qop attributes it
+         has received in a previous Access-Challenge packet.  RADIUS
+         servers SHOULD insert at least one Digest-Qop attribute in an
+         Access-Challenge packet.  Digest-Qop is optional in order to
+         preserve backward compatibility with a minimal implementation
+         of [RFC2069].
+   Type
+         110 for Digest-Qop
+   Length
+         >=3
+   Text
+         In Access-Requests, the RADIUS client takes the value of the
+         qop directive (qop-value as described in [RFC2617]) from the
+
+
+
+Sterman, et al.             Standards Track                    [Page 15]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+         HTTP-style request it wants to authenticate.  In
+         Access-Challenge packets, the RADIUS server puts a desired
+         qop-value into this attribute.  If the RADIUS server supports
+         more than one "quality of protection" value, it puts each
+         qop-value into a separate Digest-Qop attribute.
+
+3.9.  Digest-Algorithm Attribute
+
+   Description
+         This attribute holds the algorithm parameter that influences
+         the HTTP Digest calculation.  It MUST only be used in
+         Access-Request and Access-Challenge packets.  If this attribute
+         is missing, MD5 is assumed.
+   Type
+         111 for Digest-Algorithm
+   Length
+         >=3
+   Text
+         In Access-Requests, the RADIUS client takes the value of the
+         algorithm directive (as described in [RFC2617], section 3.2.1)
+         from the HTTP-style request it wants to authenticate.  In
+         Access-Challenge packets, the RADIUS server SHOULD put the
+         desired algorithm into this attribute.
+
+3.10.  Digest-Entity-Body-Hash Attribute
+
+   Description
+         When using the qop-level 'auth-int', a hash of the HTTP-style
+         message body's contents is required for digest calculation.
+         Instead of sending the complete body of the message, only its
+         hash value is sent.  This hash value can be used directly in
+         the digest calculation.
+
+         The clarifications described in section 22.4 of [RFC3261] about
+         the hash of empty entity bodies apply to the
+         Digest-Entity-Body-Hash attribute.  This attribute MUST only be
+         sent in Access-Request packets.
+   Type
+         112 for Digest-Entity-Body-Hash
+   Length
+         >=3
+   Text
+         The attribute holds the hexadecimal representation of
+         H(entity-body).  This hash is required by certain
+         authentication mechanisms, such as HTTP Digest with quality of
+         protection set to "auth-int".  RADIUS clients MUST use this
+         attribute to transport the hash of the entity body when HTTP
+         Digest is the authentication mechanism and the RADIUS server
+
+
+
+Sterman, et al.             Standards Track                    [Page 16]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+         requires that the integrity of the entity body (e.g., qop
+         parameter set to "auth-int") be verified.  Extensions to this
+         document may define support for authentication mechanisms other
+         than HTTP Digest.
+
+3.11.  Digest-CNonce Attribute
+
+   Description
+         This attribute holds the client nonce parameter that is used in
+         the HTTP Digest calculation.  It MUST only be used in
+         Access-Request packets.
+   Type
+         113 for Digest-CNonce
+   Length
+         >=3
+   Text
+         This attribute includes the value of the cnonce-value [RFC2617]
+         without surrounding quotes, taken from the HTTP-style request.
+
+3.12.  Digest-Nonce-Count Attribute
+
+   Description
+         This attribute includes the nonce count parameter that is used
+         to detect replay attacks.  The attribute MUST only be used in
+         Access-Request packets.
+
+   Type
+         114 for Digest-Nonce-Count
+   Length
+         10
+   Text
+         In Access-Requests, the RADIUS client takes the value of the nc
+         directive (nc-value according to [RFC2617]) without surrounding
+         quotes from the HTTP-style request it wants to authenticate.
+
+3.13.  Digest-Username Attribute
+
+   Description
+         This attribute holds the user name used in the HTTP Digest
+         calculation.  The RADIUS server MUST use this attribute only
+         for the purposes of calculating the digest.  In order to
+         determine the appropriate user credentials, the RADIUS server
+         MUST use the User-Name (1) attribute, and MUST NOT use the
+         Digest-Username attribute.  This attribute MUST only be used in
+         Access-Request packets.
+   Type
+         115 for Digest-Username
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 17]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   Length
+         >= 3
+   Text
+         In Access-Requests, the RADIUS client takes the value of the
+         username directive (username-value according to [RFC2617])
+         without surrounding quotes from the HTTP-style request it wants
+         to authenticate.
+
+3.14.  Digest-Opaque Attribute
+
+   Description
+         This attribute holds the opaque parameter that is passed to the
+         HTTP-style client.  The HTTP-style client will pass this value
+         back to the server (i.e., the RADIUS client) without
+         modification.  This attribute MUST only be used in
+         Access-Request and Access-Challenge packets.
+   Type
+         116 for Digest-Opaque
+   Length
+         >=3
+   Text
+         In Access-Requests, the RADIUS client takes the value of the
+         opaque directive (opaque-value according to [RFC2617]) without
+         surrounding quotes from the HTTP-style request it wants to
+         authenticate and puts it into this attribute.  In
+         Access-Challenge packets, the RADIUS server MAY include this
+         attribute.
+
+3.15.  Digest-Auth-Param Attribute
+
+   Description
+         This attribute is a placeholder for future extensions and
+         corresponds to the "auth-param" parameter defined in section
+         3.2.1 of [RFC2617].  The Digest-Auth-Param is the mechanism
+         whereby the RADIUS client and RADIUS server can exchange
+         auth-param extension parameters contained within Digest headers
+         that are not understood by the RADIUS client and for which
+         there are no corresponding stand-alone attributes.
+
+         Unlike the previously listed Digest-* attributes, the
+         Digest-Auth-Param contains not only the value but also the
+         parameter name, since the parameter name is unknown to the
+         RADIUS client.  If the Digest header contains several unknown
+         parameters, then the RADIUS implementation MUST repeat this
+         attribute and each instance MUST contain one different unknown
+         Digest parameter/value combination.  This attribute MUST ONLY
+         be used in Access-Request, Access-Challenge, or Access-Accept
+         packets.
+
+
+
+Sterman, et al.             Standards Track                    [Page 18]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   Type
+         117 for Digest-Auth-Param
+   Length
+         >=3
+   Text
+         The text consists of the whole parameter, including its name
+         and the equal sign ('=') and quotes.
+
+3.16.  Digest-AKA-Auts Attribute
+
+   Description
+         This attribute holds the auts parameter that is used in the
+         Digest AKA ([RFC3310]) calculation.  It is only used if the
+         algorithm of the digest-response denotes a version of AKA
+         Digest [RFC3310].  This attribute MUST only be used in
+         Access-Request packets.
+   Type
+         118 for Digest-AKA-Auts
+   Length
+         >=3
+   Text
+         In Access-Requests, the RADIUS client takes the value of the
+         auts directive (auts-param according to section 3.4 of
+         [RFC3310]) without surrounding quotes from the HTTP-style
+         request it wants to authenticate.
+
+3.17.  Digest-Domain Attribute
+
+   Description
+         When a RADIUS client has asked for a nonce, the RADIUS server
+         MAY send one or more Digest-Domain attributes in its
+         Access-Challenge packet.  The RADIUS client puts them into the
+         quoted, space-separated list of URIs of the 'domain' directive
+         of a WWW-Authenticate header.  Together with Digest-Realm, the
+         URIs in the list define the protection space (see [RFC2617],
+         section 3.2.1) for some HTTP-style protocols.  This attribute
+         MUST only be used in Access-Challenge packets.
+   Type
+         119 for Digest-Domain
+   Length
+         3
+   Text
+         This attribute consists of a single URI that defines a
+         protection space component.
+
+
+
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 19]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+3.18.  Digest-Stale Attribute
+
+   Description
+         This attribute is sent by a RADIUS server in order to notify
+         the RADIUS client whether it has accepted a nonce.  If the
+         nonce presented by the RADIUS client was stale, the value is
+         'true' and is 'false' otherwise.  The RADIUS client puts the
+         content of this attribute into a 'stale' directive of the
+         WWW-Authenticate header in the HTTP-style response to the
+         request it wants to authenticate.  The attribute MUST only be
+         used in Access-Challenge packets.
+   Type
+         120 for Digest-Stale
+   Length
+         3
+   Text
+         The attribute has either the value 'true' or 'false' (both
+         values without surrounding quotes).
+
+3.19.  Digest-HA1 Attribute
+
+   Description
+         This attribute is used to allow the generation of an
+         Authentication-Info header, even if the HTTP-style response's
+         body is required for the calculation of the rspauth value.  It
+         SHOULD be used in Access-Accept packets if the required quality
+         of protection ('qop') is 'auth-int'.
+
+         This attribute MUST NOT be sent if the qop parameter was not
+         specified or has a value of 'auth' (in this case, use
+         Digest-Response-Auth instead).
+
+         The Digest-HA1 attribute MUST only be sent by the RADIUS server
+         or processed by the RADIUS client if at least one of the
+         following conditions is true:
+
+         +  The Digest-Algorithm attribute's value is 'MD5-sess' or
+            'AKAv1-MD5-sess'.
+
+         +  IPsec is configured to protect traffic between RADIUS client
+            and RADIUS server with IPsec (see Section 8).
+
+         This attribute MUST only be used in Access-Accept packets.
+   Type
+         121 for Digest-HA1
+   Length
+         >= 3
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 20]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   Text
+         This attribute contains the hexadecimal representation of H(A1)
+         as described in [RFC2617], sections 3.1.3, 3.2.1, and 3.2.2.2.
+
+3.20.  SIP-AOR Attribute
+
+   Description
+         This attribute is used for the authorization of SIP messages.
+         The SIP-AOR attribute identifies the URI, the use of which must
+         be authenticated and authorized.  The RADIUS server uses this
+         attribute to authorize the processing of the SIP request.  The
+         SIP-AOR can be derived from, for example, the To header field
+         in a SIP REGISTER request (user under registration), or the
+         From header field in other SIP requests.  However, the exact
+         mapping of this attribute to SIP can change due to new
+         developments in the protocol.  This attribute MUST only be used
+         when the RADIUS client wants to authorize SIP users and MUST
+         only be used in Access-Request packets.
+   Type
+         122 for SIP-AOR
+   Length
+         >=3
+   Text
+         The syntax of this attribute corresponds either to a SIP URI
+         (with the format defined in [RFC3261] or a tel URI (with the
+         format defined in [RFC3966]).
+
+         The SIP-AOR attribute holds the complete URI, including
+         parameters and other parts.  It is up to the RADIUS server what
+         components of the URI are regarded in the authorization
+         decision.
+
+4.  Diameter Compatibility
+
+   This document defines support for Digest Authentication in RADIUS.  A
+   companion document "Diameter Session Initiation Protocol (SIP)
+   Application" [SIP-APP] defines support for Digest Authentication in
+   Diameter, and addresses compatibility issues between RADIUS and
+   Diameter.
+
+
+
+
+
+
+
+
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 21]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+5.  Table of Attributes
+
+   The following table provides a guide to which attributes may be found
+   in which kinds of packets, and in what quantity.
+
+   +-----+--------+--------+-----------+-----+-------------------------+
+   | Req | Accept | Reject | Challenge | #   | Attribute               |
+   +-----+--------+--------+-----------+-----+-------------------------+
+   | 1   | 0      | 0      | 0         | 1   | User-Name               |
+   | 1   | 1      | 1      | 1         | 80  | Message-Authenticator   |
+   | 0-1 | 0      | 0      | 0         | 103 | Digest-Response         |
+   | 0-1 | 0      | 0      | 1         | 104 | Digest-Realm            |
+   | 0-1 | 0      | 0      | 1         | 105 | Digest-Nonce            |
+   | 0   | 0-1    | 0      | 0         | 106 | Digest-Response-Auth    |
+   |     |        |        |           |     | (see Note 1, 2)         |
+   | 0   | 0-1    | 0      | 0         | 107 | Digest-Nextnonce        |
+   | 0-1 | 0      | 0      | 0         | 108 | Digest-Method           |
+   | 0-1 | 0      | 0      | 0         | 109 | Digest-URI              |
+   | 0-1 | 0      | 0      | 0+        | 110 | Digest-Qop              |
+   | 0-1 | 0      | 0      | 0-1       | 111 | Digest-Algorithm (see   |
+   |     |        |        |           |     | Note 3)                 |
+   | 0-1 | 0      | 0      | 0         | 112 | Digest-Entity-Body-Hash |
+   | 0-1 | 0      | 0      | 0         | 113 | Digest-CNonce           |
+   | 0-1 | 0      | 0      | 0         | 114 | Digest-Nonce-Count      |
+   | 0-1 | 0      | 0      | 0         | 115 | Digest-Username         |
+   | 0-1 | 0      | 0      | 0-1       | 116 | Digest-Opaque           |
+   | 0+  | 0+     | 0      | 0+        | 117 | Digest-Auth-Param       |
+   | 0-1 | 0      | 0      | 0         | 118 | Digest-AKA-Auts         |
+   | 0   | 0      | 0      | 0+        | 119 | Digest-Domain           |
+   | 0   | 0      | 0      | 0-1       | 120 | Digest-Stale            |
+   | 0   | 0-1    | 0      | 0         | 121 | Digest-HA1 (see Note 1, |
+   |     |        |        |           |     | 2)                      |
+   | 0-1 | 0      | 0      | 0         | 122 | SIP-AOR                 |
+   +-----+--------+--------+-----------+-----+-------------------------+
+
+                                  Table 1
+
+   [Note 1] Digest-HA1 MUST be used instead of Digest-Response-Auth if
+      Digest-Qop is 'auth-int'.
+
+   [Note 2] Digest-Response-Auth MUST be used instead of Digest-HA1 if
+      Digest-Qop is 'auth'.
+
+   [Note 3] If Digest-Algorithm is missing, 'MD5' is assumed.
+
+
+
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 22]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+6.  Examples
+
+   This is an example selected from the traffic between a softphone (A),
+   a Proxy Server (B), and an example.com RADIUS server (C).  The
+   communication between the Proxy Server and a SIP Public Switched
+   Telephone Network (PSTN) gateway is omitted for brevity.  The SIP
+   messages are not shown completely.
+
+   A->B
+
+      INVITE sip:97226491335@example.com SIP/2.0
+      From: <sip:12345678@example.com>
+      To: <sip:97226491335@example.com>
+
+   B->A
+
+      SIP/2.0 100 Trying
+
+   B->C
+
+      Code = 1 (Access-Request)
+      Attributes:
+      NAS-IP-Address = c0 0 2 26 (192.0.2.38)
+      NAS-Port-Type = 5 (Virtual)
+      User-Name = 12345678
+      Digest-Method = INVITE
+      Digest-URI = sip:97226491335@example.com
+      Message-Authenticator =
+       08 af 7e 01 b6 8d 74 c3 a4 3c 33 e1 56 2a 80 43
+
+   C->B
+
+      Code = 11 (Access-Challenge)
+      Attributes:
+      Digest-Nonce = 3bada1a0
+      Digest-Realm = example.com
+      Digest-Qop = auth
+      Digest-Algorithm = MD5
+      Message-Authenticator =
+       f8 01 26 9f 70 5e ef 5d 24 ac f5 ca fb 27 da 40
+
+   B->A
+
+      SIP/2.0 407 Proxy Authentication Required
+      Proxy-Authenticate: Digest realm="example.com"
+           ,nonce="3bada1a0",qop=auth,algorithm=MD5
+      Content-Length: 0
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 23]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   A->B
+
+      ACK sip:97226491335@example.com SIP/2.0
+
+   A->B
+
+      INVITE sip:97226491335@example.com SIP/2.0
+      Proxy-Authorization: Digest algorithm="md5",nonce="3bada1a0"
+           ,realm="example.com"
+           ,response="f3ce87e6984557cd0fecc26f3c5e97a4"
+           ,uri="sip:97226491335@example.com",username="12345678"
+           ,qop=auth,algorithm=MD5
+      From: <sip:12345678@example.com>
+      To: <sip:97226491335@example.com>
+
+   B->C
+
+      Code = 1 (Access-Request)
+      Attributes:
+      NAS-IP-Address = c0 0 2 26 (192.0.2.38)
+      NAS-Port-Type = 5 (Virtual)
+      User-Name = 12345678
+      Digest-Response = f3ce87e6984557cd0fecc26f3c5e97a4
+      Digest-Realm = example.com
+      Digest-Nonce = 3bada1a0
+      Digest-Method = INVITE
+      Digest-URI = sip:97226491335@example.com
+      Digest-Qop = auth
+      Digest-Algorithm = md5
+      Digest-Username =  12345678
+      SIP-AOR =  sip:12345678@example.com
+      Message-Authenticator =
+          ff 67 f4 13 8e b8 59 32 22 f9 37 0f 32 f8 e0 ff
+
+   C->B
+
+      Code = 2 (Access-Accept)
+      Attributes:
+      Digest-Response-Auth =
+                      6303c41b0e2c3e524e413cafe8cce954
+      Message-Authenticator =
+          75 8d 44 49 66 1f 7b 47 9d 10 d0 2d 4a 2e aa f1
+
+   B->A
+
+      SIP/2.0 180 Ringing
+
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 24]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   B->A
+
+      SIP/2.0 200 OK
+
+   A->B
+
+      ACK sip:97226491335@example.com SIP/2.0
+
+   A second example shows the traffic between a web browser (A), web
+   server (B), and a RADIUS server (C).
+
+   A->B
+
+      GET /index.html HTTP/1.1
+
+   B->C
+
+      Code = 1 (Access-Request)
+      Attributes:
+      NAS-IP-Address = c0 0 2 26 (192.0.2.38)
+      NAS-Port-Type = 5 (Virtual)
+      Digest-Method = GET
+      Digest-URI = /index.html
+      Message-Authenticator =
+       34 a6 26 46 f3 81 f9 b4 97 c0 dd 9d 11 8f ca c7
+
+   C->B
+
+      Code = 11 (Access-Challenge)
+      Attributes:
+      Digest-Nonce = a3086ac8
+      Digest-Realm = example.com
+      Digest-Qop = auth
+      Digest-Algorithm = MD5
+      Message-Authenticator =
+       f8 01 26 9f 70 5e ef 5d 24 ac f5 ca fb 27 da 40
+
+   B->A
+
+      HTTP/1.1 401 Authentication Required
+      WWW-Authenticate: Digest realm="example.com",
+          nonce="a3086ac8",qop=auth,algorithm=MD5
+      Content-Length: 0
+
+
+
+
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 25]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   A->B
+
+      GET /index.html HTTP/1.1
+      Authorization: Digest algorithm=MD5,nonce="a3086ac8"
+           ,realm="example.com"
+           ,response="f052b68058b2987aba493857ae1ab002"
+           ,uri="/index.html",username="12345678"
+           ,qop=auth,algorithm=MD5
+
+   B->C
+
+      Code = 1 (Access-Request)
+      Attributes:
+      NAS-IP-Address = c0 0 2 26 (192.0.2.38)
+      NAS-Port-Type = 5 (Virtual)
+      User-Name = 12345678
+      Digest-Response = f052b68058b2987aba493857ae1ab002
+      Digest-Realm = example.com
+      Digest-Nonce = a3086ac8
+      Digest-Method = GET
+      Digest-URI = /index.html
+      Digest-Username =  12345678
+      Digest-Qop = auth
+      Digest-Algorithm = MD5
+      Message-Authenticator =
+          06 e1 65 23 57 94 e6 de 87 5a e8 ce a2 7d 43 6b
+
+   C->B
+
+      Code = 2 (Access-Accept)
+      Attributes:
+      Digest-Response-Auth =
+          e644aa513effbfe1caff67103ff6433c
+      Message-Authenticator =
+          7a 66 73 a3 52 44 dd ca 90 e2 f6 10 61 2d 81 d7
+
+   B->A
+
+      HTTP/1.1 200 OK
+      ...
+
+      <html>
+      ...
+
+
+
+
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 26]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+7.  IANA Considerations
+
+   This document serves as an IANA registration request for a number of
+   values from the RADIUS attribute type number space.  The IANA has
+   assigned the following:
+
+           +-------------------------+------------------------+
+           | placeholder             | value assigned by IANA |
+           +-------------------------+------------------------+
+           | Digest-Response         | 103                    |
+           | Digest-Realm            | 104                    |
+           | Digest-Nonce            | 105                    |
+           | Digest-Nextnonce        | 106                    |
+           | Digest-Response-Auth    | 107                    |
+           | Digest-Method           | 108                    |
+           | Digest-URI              | 109                    |
+           | Digest-Qop              | 110                    |
+           | Digest-Algorithm        | 111                    |
+           | Digest-Entity-Body-Hash | 112                    |
+           | Digest-CNonce           | 113                    |
+           | Digest-Nonce-Count      | 114                    |
+           | Digest-Username         | 115                    |
+           | Digest-Opaque           | 116                    |
+           | Digest-Auth-Param       | 117                    |
+           | Digest-AKA-Auts         | 118                    |
+           | Digest-Domain           | 119                    |
+           | Digest-Stale            | 120                    |
+           | Digest-HA1              | 121                    |
+           | SIP-AOR                 | 122                    |
+           +-------------------------+------------------------+
+
+                                  Table 2
+
+8.  Security Considerations
+
+   The RADIUS extensions described in this document enable RADIUS to
+   transport the data that is required to perform a digest calculation.
+   As a result, RADIUS inherits the vulnerabilities of HTTP Digest (see
+   [RFC2617], section 4) in addition to RADIUS security vulnerabilities
+   described in [RFC2865], section 8, and [RFC3579], section 4.
+
+   An attacker compromising a RADIUS client or proxy can carry out
+   man-in-the-middle attacks even if the paths between A, B and B, C
+   (Figure 2) have been secured with TLS or IPsec.
+
+   The RADIUS server MUST check the Digest-Realm attribute it has
+   received from a client.  If the RADIUS client is not authorized to
+   serve HTTP-style clients of that realm, it might be compromised.
+
+
+
+Sterman, et al.             Standards Track                    [Page 27]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+8.1.  Denial of Service
+
+   RADIUS clients implementing the extension described in this document
+   may authenticate HTTP-style requests received over the Internet.  As
+   compared with the use of RADIUS to authenticate link-layer network
+   access, attackers may find it easier to cover their tracks in such a
+   scenario.
+
+   An attacker can attempt a denial-of-service attack on one or more
+   RADIUS servers by sending a large number of HTTP-style requests.  To
+   make simple denial-of-service attacks more difficult, the RADIUS
+   server MUST check whether it has generated the nonce received from an
+   HTTP-style client.  This SHOULD be done statelessly.  For example, a
+   nonce could consist of a cryptographically random part and some kind
+   of signature provided by the RADIUS client, as described in
+   [RFC2617], section 3.2.1.
+
+8.2.  Confidentiality and Data Integrity
+
+   The attributes described in this document are sent in cleartext.
+   RADIUS servers SHOULD include Digest-Qop and Digest-Algorithm
+   attributes in Access-Challenge messages.  A man in the middle can
+   modify or remove those attributes in a bidding down attack, causing
+   the RADIUS client to use a weaker authentication scheme than
+   intended.
+
+   The Message-Authenticator attribute, described in [RFC3579], section
+   3.2 MUST be included in Access-Request, Access-Challenge,
+   Access-Reject, and Access-Accept messages that contain attributes
+   described in this specification.
+
+   The Digest-HA1 attribute contains no random components if the
+   algorithm is 'MD5' or 'AKAv1-MD5'.  This makes offline dictionary
+   attacks easier and enables replay attacks.
+
+   Some parameter combinations require the protection of RADIUS packets
+   against eavesdropping and tampering.  Implementations SHOULD try to
+   determine automatically whether IPsec is configured to protect
+   traffic between the RADIUS client and the RADIUS server.  If this is
+   not possible, the implementation checks a configuration parameter
+   telling it whether IPsec will protect RADIUS traffic.  The default
+   value of this configuration parameter tells the implementation that
+   RADIUS packets will not be protected.
+
+   HTTP-style clients can use TLS with server side certificates together
+   with HTTP-Digest Authentication.  Instead of TLS, IPsec can be used,
+   too.  TLS or IPsec secure the connection while Digest Authentication
+   authenticates the user.  The RADIUS transaction can be regarded as
+
+
+
+Sterman, et al.             Standards Track                    [Page 28]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   one leg on the path between the HTTP-style client and the HTTP-style
+   server.  To prevent RADIUS from representing the weak link, a RADIUS
+   client receiving an HTTP-style request via TLS or IPsec could use an
+   equally secure connection to the RADIUS server.  There are several
+   ways to achieve this, for example:
+
+   o  The RADIUS client may reject HTTP-style requests received over TLS
+      or IPsec.
+
+   o  The RADIUS client may require that traffic be sent and received
+      over IPsec.
+
+   RADIUS over IPsec, if used, MUST conform to the requirements
+   described in [RFC3579], section 4.2.
+
+9.  Acknowledgements
+
+   We would like to acknowledge Kevin McDermott (Cisco Systems) for
+   providing comments and experimental implementation.
+
+   Many thanks to all reviewers, especially to Miguel Garcia, Jari
+   Arkko, Avi Lior, and Jun Wang.
+
+10.  References
+
+10.1.  Normative References
+
+   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
+              Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+   [RFC2617]  Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S.,
+              Leach, P., Luotonen, A., and L. Stewart, "HTTP
+              Authentication: Basic and Digest Access Authentication",
+              RFC 2617, June 1999.
+
+   [RFC2865]  Rigney, C., Willens, S., Rubens, A., and W. Simpson,
+              "Remote Authentication Dial In User Service (RADIUS)", RFC
+              2865, June 2000.
+
+   [RFC3261]  Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston,
+              A., Peterson, J., Sparks, R., Handley, M., and E.
+              Schooler, "SIP: Session Initiation Protocol", RFC 3261,
+              June 2002.
+
+   [RFC3579]  Aboba, B. and P. Calhoun, "RADIUS (Remote Authentication
+              Dial In User Service) Support For Extensible
+              Authentication Protocol (EAP)", RFC 3579, September 2003.
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 29]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+   [RFC3966]  Schulzrinne, H., "The tel URI for Telephone Numbers", RFC
+              3966, December 2004.
+
+10.2.  Informative References
+
+   [SIP-APP]  Garcia-Martin, M., "Diameter Session Initiation Protocol
+              (SIP) Application", Work in Progress), April 2006.
+
+   [RFC1994]  Simpson, W., "PPP Challenge Handshake Authentication
+              Protocol (CHAP)", RFC 1994, August 1996.
+
+   [RFC2069]  Franks, J., Hallam-Baker, P., Hostetler, J., Leach, P.,
+              Luotonen, A., Sink, E., and L. Stewart, "An Extension to
+              HTTP : Digest Access Authentication", RFC 2069, January
+              1997.
+
+   [RFC4346]  Dierks, T. and E. Rescorla, "The Transport Layer Security
+              (TLS) Protocol Version 1.1", RFC 4346, April 2006.
+
+   [RFC3851]  Ramsdell, B., "Secure/Multipurpose Internet Mail
+              Extensions (S/MIME) Version 3.1 Message Specification",
+              RFC 3851, July 2004.
+
+   [RFC3310]  Niemi, A., Arkko, J., and V. Torvinen, "Hypertext Transfer
+              Protocol (HTTP) Digest Authentication Using Authentication
+              and Key Agreement (AKA)", RFC 3310, September 2002.
+
+   [RFC3588]  Calhoun, P., Loughney, J., Guttman, E., Zorn, G., and J.
+              Arkko, "Diameter Base Protocol", RFC 3588, September 2003.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 30]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+Authors' Addresses
+
+   Baruch Sterman
+   Kayote Networks
+   P.O. Box 1373
+   Efrat  90435
+   Israel
+
+   EMail: baruch@kayote.com
+
+
+   Daniel Sadolevsky
+   SecureOL, Inc.
+   Jerusalem Technology Park
+   P.O. Box 16120
+   Jerusalem  91160
+   Israel
+
+   EMail: dscreat@dscreat.com
+
+
+   David Schwartz
+   Kayote Networks
+   P.O. Box 1373
+   Efrat  90435
+   Israel
+
+   EMail: david@kayote.com
+
+
+   David Williams
+   Cisco Systems
+   7025 Kit Creek Road
+   P.O. Box 14987
+   Research Triangle Park  NC 27709
+   USA
+
+   EMail: dwilli@cisco.com
+
+
+   Wolfgang Beck
+   Deutsche Telekom AG
+   Deutsche Telekom Allee 7
+   Darmstadt  64295
+   Germany
+
+   EMail: beckw@t-systems.com
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 31]
+\f
+RFC 4590              RADIUS Digest Authentication             July 2006
+
+
+Full Copyright Statement
+
+   Copyright (C) The Internet Society (2006).
+
+   This document is subject to the rights, licenses and restrictions
+   contained in BCP 78, and except as set forth therein, the authors
+   retain all their rights.
+
+   This document and the information contained herein are provided on an
+   "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+   OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+   ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+   INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+   INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+   The IETF takes no position regarding the validity or scope of any
+   Intellectual Property Rights or other rights that might be claimed to
+   pertain to the implementation or use of the technology described in
+   this document or the extent to which any license under such rights
+   might or might not be available; nor does it represent that it has
+   made any independent effort to identify any such rights.  Information
+   on the procedures with respect to rights in RFC documents can be
+   found in BCP 78 and BCP 79.
+
+   Copies of IPR disclosures made to the IETF Secretariat and any
+   assurances of licenses to be made available, or the result of an
+   attempt made to obtain a general license or permission for the use of
+   such proprietary rights by implementers or users of this
+   specification can be obtained from the IETF on-line IPR repository at
+   http://www.ietf.org/ipr.
+
+   The IETF invites any interested party to bring to its attention any
+   copyrights, patents or patent applications, or other proprietary
+   rights that may cover technology that may be required to implement
+   this standard.  Please address the information to the IETF at
+   ietf-ipr@ietf.org.
+
+Acknowledgement
+
+   Funding for the RFC Editor function is provided by the IETF
+   Administrative Support Activity (IASA).
+
+
+
+
+
+
+
+Sterman, et al.             Standards Track                    [Page 32]
+\f
diff --git a/doc/rfc/update.sh b/doc/rfc/update.sh
new file mode 100755 (executable)
index 0000000..e61909f
--- /dev/null
@@ -0,0 +1,64 @@
+#!/bin/sh
+#
+#  This script makes an HTML page from a simple directory listing
+#
+#
+cat >index.html <<EOF
+<HTML>
+<TITLE>Index of FreeRADIUS.org's RFC site</TITLE>
+<BODY>
+
+<H1>Index of FreeRADIUS.org's RFC site</H1>
+
+List of <A HREF="attributes.html">RADIUS attributes</A>
+<P>
+
+EOF
+
+#
+#  include the message, if any exists
+#
+if [ -e message ]; then
+  echo "<PRE>" >> index.html
+  cat .message >> index.html
+  echo "</PRE>" >> index.html
+fi
+
+#
+#  for all of the text files, do this
+#
+cat >>index.html <<EOF
+<h2>RFC's</h2>
+EOF
+
+for x in rfc*.html;do
+  y=`echo $x | sed 's/rfc//;s/\.html//'`
+  echo "<A HREF=\"$x\">RFC $y</A>" >> index.html
+  if [ -e $x.gz ]; then
+    echo "<A HREF=\"$x.gz\">(gzipped)</A>" >> index.html
+  fi
+  y="attributes-rfc$y.html";
+  if [ -f $y ];then
+    echo "<A HREF=\"$y\">(attributes)</A>" >> index.html
+  fi
+  echo "<BR />" >> index.html
+done
+
+cat >>index.html <<EOF
+<h2>Other files</h2>
+EOF
+
+#
+#  for all of the text files, do this
+#
+for x in *.txt;do
+  y=`echo $x | sed ';s/\.txt/.html/'`
+  if [ ! -f $y ];then
+    echo "<A HREF=\"$x\">$x</A>" >> index.html
+    if [ -e $x.gz ]; then
+      echo "<A HREF=\"$x.gz\">(gzipped)</A>" >> index.html
+    fi
+    echo "<BR />" >> index.html
+  fi
+done
+echo "</BODY></HTML>" >> index.html
diff --git a/doc/rlm_attr_filter b/doc/rlm_attr_filter
deleted file mode 100644 (file)
index b460ca1..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-       Attribute Filtering Module
-
-
--1. CAVEAT
-
-
-RLM_ATTR_FILTER
-
-0.  INTRODUCTION
-
-  This module exists for filtering certain attributes and values in received
-  radius packets from remote proxy servers.  It gives the proxier (us) a very
-  flexible framework to filter the attributes that proxy servers send us in
-  their replies.  This makes sense in an out-sourced dialup situation for
-  example, where the client proxy is permitted only certain values for setting
-  the Idle-Timeout.
-
-  Filter rules are defined and applied on a per-realm basis, where the realm
-  can be anything you have defined via the rlm_realm module.
-
-1.  MODULE CONFIGURATION
-
-  The module configuration section is very simple.  There is only one attribute
-  that needs to be set, the file to read the filter rules from.
-
-  As an example, here is the default configuration from radiusd.conf:
-
-       modules {
-           ...
-           attr_filter {
-               attrsfile = ${confdir}/attrs
-          }
-           ...
-       }
-
-  If attrsfile is not specified, it defaults to the above configuration.
-
-  This module supports multiple named instances per the normal method.
-
-  Once defined in the modules section of the config file, you must add the
-  module instance name ( the name of the module itself by default ) into the  
-  'authorize{}' section.  It should be placed *before* the realm modules.
-
-  As an example:
-  
-       authorize {
-           preprocess
-           attr_filter
-           realm
-          files
-       }
-
-  If the incoming packet is not a proxy reply, the module returns a NOOP,
-  so that the rest of the 'authorize{}' is called normally.
-
-3.  MODULE OPTIONS
-
-  The file that defines the attribute filter rules is layed out and parsed
-  very similar to the users file.  There are a couple main differences:
-
-     o  There are no "check items" on the first line of the profile other
-        than the "realm".
-
-     o  There is only one DEFAULT entry.  This is due to the fact that there
-        are no "check items" beyond the realm name.  Fall-Through does work
-        though, allowing you to put the commonly allowed attribute rules into
-        the DEFAULT entry and only put realm specific rules in the specific
-        realm entry.
-
-     o  The operators used for specifying the attributes are as follows:
-
-           =    -  NOT ALLOWED.  If used, it becomes "=="
-
-           :=   -  Set ( used to ensure a specific a/v is present )
-           ==   -  Equal  ( exact )
-          =*   -  Always Equal ( will allow all values for attribute )
-           !*   -  Always Not Equal ( will block all values for attribute )
-           !=   -  Not equal
-           >=   -  Greater than or equal to
-           <=   -  Less than or equal to
-           >    -  Greater than
-           <    -  Less than
-
-           If you have regular expressions enabled you also have:
-
-           =~   -  Regular expression equal
-           !~   -  Regular expression not equal
-
-
-  See the comments in the default 'attrs' file for examples and additional
-  explanation.
-
-4.  MODULE FUNCTION
-
-  The way the module works is as follows:
-
-     o  Build a list of a/v pair rules from the 'attrs' file at module
-        instantiation.
-
-     o  When a proxy reply packet is received and passed to the module, it
-        checks for a Realm attribute in the original request a/v pairs.
-        ( The Realm attribute is added there by the proxy code ).
-
-     o  The module walks the list of a/v pair rules until it finds a
-        match for the Realm value or it reaches the DEFAULT entry.
-
-     o  If there are any rules with SET operators, those attributes are 
-       added to the top of a temporary reply list.
-     o  Each a/v pair in the proxy reply is compared to the list of 
-       rules.
-   
-     o  If an a/v pair in the proxy reply passes *ALL* of the rules that
-       relate to the attribute, the a/v is added to a temporary list.  
-        ( Note, if it fails 1 or more rules, or is not matched, then the
-          a/v pair will *NOT* be transferred to the temporary list. )
-
-     o  When all the reply vps have been checked, the original proxy reply
-        vps are freed and the temporary list ( containing only those a/v
-        that passed the rules ) becomes the new proxy reply vps.
-
-     o  The module then returns UPDATED and the rest of the authorize block
-        is called as usual.
-
----
-Please send corrections/input/comments/flames to <cparker@starnetusa.net>
-
diff --git a/doc/rlm_digest b/doc/rlm_digest
deleted file mode 100644 (file)
index 56c51d6..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-       Digest module configuration
-
-0. INTRODUCTION
-
-  The digest module performs HTTP digest authentication, as per
-  the IETF draft rfc/draft-sterman-aaa-sip-00.txt.  It has been
-  successfully tested against a Cisco SIP server.
-
-  However, the draft has been expired by the IETF, so it's unlikely to
-  become an "official" standard.
-
-1. USAGE
-
-  To use this module, uncomment the lines relating to 'digest' from
-raddb/radiusd.conf.  Once that is done, any RADIUS request containing
-the digest attributes will automatically be authenticated using the
-'digest' module.
-
-  Note tha the 'digest' module REQUIRES access to the clear-text
-password for the user, in order to perform digest authentication.
-
-2. TESTING
-
-  Add the following lines to the top of your 'raddb/users' file:
-
-#---
-test   Auth-Type := Digest, User-Password = "test"
-       Reply-Message = "Hello, test with digest"
-#---
-
-
-  Once the server has been re-started (debugging mode is recommended),
-  use 'radclient' to send the following packet to the server:
-
-  $  radclient -f digest localhost auth testing123
-
-  Where 'digest' is a file containing:
-
-User-Name = "test", Digest-Response = "631d6d73147add2f9e437f59bbc3aeb7", Digest-Realm = "testrealm", Digest-Nonce = "1234abcd", Digest-Method = "INVITE", Digest-URI = "sip:5555551212@example.com", Digest-Algorithm = "MD5", Digest-User-Name = "test"
-
-  You should see the authentication succeed.
-
-$Id$
diff --git a/doc/rlm_expiration b/doc/rlm_expiration
new file mode 100644 (file)
index 0000000..f9279de
--- /dev/null
@@ -0,0 +1,23 @@
+Module to expire user accounts.
+
+This module can be used to expire user accounts. Expired users receive
+an Access-Reject on every authentication attempt. Expiration is based
+on the Expiration attribute which should be present in the check item
+list for the user we wish to perform expiration checks.
+
+
+
+Expiration attribute format:
+
+You can use Expiration := "23 Sep 2004" and the user will 
+no longer be able to connect at 00:00 (midnight) on September 23rd, 
+2004.  If you want a certain time (other than midnight) you can do 
+use  Expiration := "23 Sep 2004 12:00".
+The nas will receive a Session-Timeout attribute calculated to kick
+the user off when the Expiration time occurs.
+
+
+
+Example entry (users files):
+
+user1  Expiration := "23 Sep 2004"
index 00331f2..59d3c1f 100644 (file)
@@ -192,6 +192,14 @@ the rlm_ldap module:
 #
 #      password_attribute = "userPassword"
 
+#      password_radius_attribute: Defined the RADIUS attribute where the extracted
+#      user password will be stored to. Can be used to set it to NT-Password or any
+#      other similar attribute instead of the default
+#
+#      default: User-Password
+#
+#      password_radius_attribute = "NT-Password"
+
 #      edir_account_policy_check: Specifies if the module has to enforce
 #      Novell eDirectory account policy check and intruder detection for
 #      RADIUS users.  This will work only if FreeRADIUS is configured to build
@@ -342,7 +350,7 @@ The "users" file won't work, because it can't add items to the request.
 
 
 DIRECTORY COMPATIBILITY NOTE: If you use LDAP only for authorization and
-authentication (e.g. you can not afford schema extention), I propose to set
+authentication (e.g. you can not afford schema extension), we suggest you set
 all necessary attributes in raddb/users file with following authorize section
 of radiusd.conf :
 
index c3e39db..ee32edb 100644 (file)
@@ -39,6 +39,8 @@
      a. The user IS NOT found in radcheck
      b. The user IS found in radcheck, but the check items don't match
      c. The user IS found in radcheck, the check items DO match AND
+        Fall-Through is set in the radreply table
+     d. The user IS found in radcheck, the check items DO match AND
        the read_groups directive is set to 'yes'
   4. If groups are to be processed for this user, the first thing that is
      done is the list of groups this user is a member of is pulled from the
      there is a match, the reply items for this group are pulled from the
      radgroupreply table and applied.
   6. Processing continues to the next group IF:
-     a. There was not a match for the last group's check items
+     a. There was not a match for the last group's check items OR
+     b. Fall-Through was set in the last group's reply items
      (The above is exactly the same as in the users file)
   7. Finally, if the user has a User-Profile attribute set or the Default
      Profile option is set in the sql.conf, then steps 4-6 are repeated for
      the groups that the profile is a member of.
 
+  For any fairly complex setup, it is likely that most of the actual
+  processing will be done in the groups.  In these cases, the user entry in
+  radcheck will be of limited use except for things like setting the user's
+  password.  So, one might have the following setup:
+
+  radcheck table:
+  joeuser        User-Password      ==       somepassword
+
+  radreply table:
+  joeuser        Fall-Through       =        Yes
+
+  radgroupcheck table:
+  Check items for various connection scenarios
+
+  radgroupreply table:
+  reply items for the groups
+
+  usergroup table:
+  joeuser      WLANgroup    1(this is the priority)
+  joeuser      PPPgroup     2
+
   A web page with some helpful documentation is:
 
        http://www.frontios.com/freeradius.html
index fd8b74f..b170e89 100644 (file)
@@ -2,17 +2,26 @@ rlm_sqlcounter installation and running guide
 by Ram Narula ram@princess1.net
 Internet for Education (Thailand)
 
+*) Pre-requisites:
+Make sure to have configured radiusd with rlm_sqlcounter
+installed
+
+> make clean
+> ./configure --with-experimental-modules
+> make
+> make install
+
 Make sure to have radiusd running properly under sql
 and there must be a "sql" entry under accounting{ } section
 of radiusd.conf
 
 *) Configuration:
 
-The server has an example "dailycounter" in radiusd.conf.  It can be
-used for initial testing.  Other examples are given below.
+[1] Create a text file called sqlcounter.conf in the same
+directory where radiusd.conf resides (usually /usr/local/etc/raddb)
+with the following content (for mysql):
 
----------------------------------------------------------------------
-# Never reset
+#-----#
 sqlcounter noresetcounter {
                 counter-name = Max-All-Session-Time
                 check-name = Max-All-Session
@@ -25,13 +34,13 @@ sqlcounter noresetcounter {
 
         }
 
-# Reset daily
-# This is used to limit users per day, e.g. 3 hours/day
+
 sqlcounter dailycounter {
+                driver = "rlm_sqlcounter"
                 counter-name = Daily-Session-Time
                 check-name = Max-Daily-Session
-               reply-name = Session-Timeout
-                sqlmod-inst = sql
+                reply-name = Session-Timeout
+                sqlmod-inst = sqlcca3
                 key = User-Name
                 reset = daily
 
@@ -39,22 +48,21 @@ sqlcounter dailycounter {
 
         }
 
-# Reset monthly
-# This is used to limit users per month, e.g. 10 hours/month
 sqlcounter monthlycounter {
                 counter-name = Monthly-Session-Time
                 check-name = Max-Monthly-Session
-               reply-name = Session-Timeout
-                sqlmod-inst = sql
+                reply-name = Session-Timeout
+                sqlmod-inst = sqlcca3
                 key = User-Name
                 reset = monthly
 
                 query = "SELECT SUM(AcctSessionTime - GREATEST((%b - UNIX_TIMESTAMP(AcctStartTime)), 0)) FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) + AcctSessionTime > '%b'"
 
        }
-----------------------------------------------------------------------
 
-The respective queries for postgresql are:
+#-----#
+
+The respective lines for postgresql are:
 
 query = "SELECT SUM(AcctSessionTime) FROM radacct WHERE UserName='%{%k}'"
 query = "SELECT SUM(AcctSessionTime - GREATER((%b - AcctStartTime::ABSTIME::INT4), 0)) FROM radacct WHERE UserName='%{%k}' AND AcctStartTime::ABSTIME::INT4 + AcctSessionTime > '%b'"
@@ -87,8 +95,14 @@ BEGIN
 END;
 ' LANGUAGE 'plpgsql';
 
-[2] Add the appropriate module configuration (as above) to radiusd.conf,
-in the "modules" section.
+[2] Include the above file to radiusd.conf by adding a line in
+modules{ } section
+
+modules {
+
+$INCLUDE  ${confdir}/sqlcounter.conf
+
+...some other entries here...
 
 [3] Make sure to have the sqlcounter names under authorize section
 like the followings:
@@ -99,16 +113,24 @@ authorize {
 ...some entries here...
 ...some entries here...
 
-# You probably only want only one of these
-       noresetcounter
-       dailycounter
-       monthlycounter
-... other entries here ...
+noresetcounter
+dailycounter
+monthlycounter
 }
 
+noresetcounter: the counter that never resets, can be used
+for real session-time cumulation 
+
+dailycounter: the counter that resets everyday, can be used
+for limiting daily access time (eg. 3 hours a day)
+
+monthlycounter: the counter that resets monthly, can be used for
+limiting monthly access time (eg. 50 hours per month)
+
 You can make your own names and directives for resetting the counter
 by reading the sample sqlcounter configuration in
-raddb/radiusd.conf
+raddb/experimental.conf
+
 
 
 *) Implementation:
@@ -154,7 +176,7 @@ in sql:
 
 
 Note that Max-All-Session, Max-Daily-Session and Max-Monthly-Session are
-defined in sqlcounter.conf
+definied in sqlcounter.conf
 
 VERY IMPORTANT:
 Accounting must be done via sql or this will not work. 
index 4a88861..166fcea 100644 (file)
@@ -1,8 +1,19 @@
-Welcome to the new SQL Based IP Pool module.
+Welcome to the SQL Based IP Pool module.
+
+**********************************************************************
+As of September 2006 this module is still under some development and
+currently is only tested by the developers on PostgreSQL (Version 8.1)
+                         Use it at your own risk!
+If plan to attempt to use a DB other than PostgreSQL please expect to
+have to do extra work which is not for SQL newbies. 
+Having said that it works great for us in production and should (with
+some work) function correctly with other SQL server types.
+**********************************************************************
+
 
 To use the sqlipool module you simply need to have an IP-Pool Attribute
 (Keep in mind that its a **CHECK** item, not reply) in the required
-configuration file, which is either in files(users),sql or any other
+configuration file, which is either in files(users), sql or any other
 type of configuration schema.
 
 The initialization of the radippool table is left to the user instead of
@@ -12,17 +23,18 @@ resized, deleted at run time without radiusd needing to be restarted.
 
 The only required fields are, pool_name and ip_address. A pool consists
 of one or more rows in the table with the same pool_name and a different
-ip_address. The is no restriction on which ip addresses/ranges may be in
+ip_address. There is no restriction on which ip addresses/ranges may be in
 the same pool, and addresses do not need to be concurrent.
 
 We are currently using the variable definitions of the xlat module, so
 before editing the sqlippool.conf file, please go and read the
 variables.txt in the freeradius/doc directory. It will help you alot!..
 
-On the other hand, there is a "key", which is really the key for the
-pool modules in freeradius. As you may noticed, there is a pool-key
-variable on the config file to have a unique connection identifier for
-the requests.So, it should be set to the unique attribute of the
-packages that we are receiving. Also this unique identifier must be
-received in accounting-stop packages so that we release the used ip,
-from the pool and put it to the free-ips list.
+As you may noticed, there is a pool-key variable in the config file which
+allows you to select which attribute is unique according to your NAS setup.
+On a standard dialup NAS this is going to be "NAS-Port" but on an ethernet
+or wireless network it will probably be "Calling-Station-Id". Other more
+exotic options like "3GPP-IMSI" may also exist depending on your NAS.
+The only requirement is that the pool-key must be unique and must be
+received in both Access-Request and Accounting packages so that we know to
+clear the lease on the ip when the session disconnects.
index 5bb2f12..3cdf8c7 100644 (file)
      %{proxy-reply:Attribute-Name}   The value of the given Attribute-Name
                                      in the proxy reply packet (if it exists)
 
-  The above variable expansions also support the meta-attribute
-Packet-Type as well. See the RADIUS dictionary for details on its
-values.
+  The above variable expansions also support the following
+meta-attributes.  These are not normal RADIUS attributes, but are
+created by the server to be used like them, for ease of use.  They can
+only be queried, and cannot be assigned.
+
+       Packet-Type             RADIUS packet type (Access-Request, etc.)
+
+       Packet-Src-IP-Address   IP address from which the packet was sent
+
+       Packet-Dst-IP-Address   IP address to which the packet was sent
+                               This may be "0.0.0.0", if the server
+                               was configured with "bind_address = *".
+
+       Packet-Src-Port         UDP port from which the packet was sent
+
+       Packet-Dst-Port         UDP port to which the packet was sent.
+
+        
      %{check:Attribute-Name}         Corresponding value for Attribute-Name
                                      in check items for request
        
@@ -92,8 +106,18 @@ defined in 'sh'.  For example:
     When attribute Bar is unset:  returns literal string 'baz'
 
 
-  Multiple-valued attributes
-  --------------------------
+  String Lengths
+  --------------
+
+  The dynamic translations support a few additional operatons, too.
+
+     %{#string}
+       The number of characters in %{string}.  If %{string} is not
+       set, then the length is not set.  This will NOT work for the
+       one-character variables defined below.
+
+       e.g. %{#Junk-junk:-foo} will yeild the string "foo".
+
 
      %{Attribute-Name[index]}
        Reference the N'th occurance of the given attribute.  The
@@ -105,6 +129,20 @@ defined in 'sh'.  For example:
             Cisco-AVPair attribute (if it exists) in the request
             packet,
 
+     %{Attribute-Name[#]}
+       Returns the total number of attributes of that name in
+       the relevant attribute list.  The number will usually
+       be between 0 and 200.
+
+       e.g. For most requests, %{request:User-Name[#]} == 1
+
+     %{Attribute-Name[*]}
+       Expands to a single string, with the value of each array
+       member separated by a newline.
+
+     %{#Attribute-Name[index]}
+       Expands to the length of the string %{Attribute-Name[index]}.
+
 
   Attributes as environment variables in executed programs
   --------------------------------------------------------
index 889f05d..b6a33c7 100644 (file)
@@ -3502,6 +3502,10 @@ lt_dlopenext (filename)
     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FR_DEPLIB));
     return 0;  /* leaks tmp and handle */
   }
+  if (handle && errors) {
+    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FR_DEPLIB));
+    return 0;  /* leaks tmp and handle */
+  }
 
   /* If we found FILENAME, stop searching -- whether we were able to
      load the file as a module or not.  If the file exists but loading
@@ -3528,6 +3532,10 @@ lt_dlopenext (filename)
   else
     {
       tmp[len] = LT_EOS_CHAR;
+  if (handle && errors) {
+    LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FR_DEPLIB));
+    return 0;  /* leaks tmp and handle */
+  }
     }
 
   strcat(tmp, shlib_ext);
diff --git a/ltconfig b/ltconfig
deleted file mode 100755 (executable)
index cb0f4de..0000000
--- a/ltconfig
+++ /dev/null
@@ -1,3074 +0,0 @@
-#! /bin/sh
-
-# ltconfig - Create a system-specific libtool.
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# This file 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# A lot of this script is taken from autoconf-2.10.
-
-# Check that we are running under the correct shell.
-SHELL=${CONFIG_SHELL-/bin/sh}
-echo=echo
-if test "X$1" = X--no-reexec; then
-  # Discard the --no-reexec flag, and continue.
-  shift
-elif test "X$1" = X--fallback-echo; then
-  # Avoid inline document here, it may be left over
-  :
-elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then
-  # Yippee, $echo works!
-  :
-else
-  # Restart under the correct shell.
-  exec "$SHELL" "$0" --no-reexec ${1+"$@"}
-fi
-
-if test "X$1" = X--fallback-echo; then
-  # used as fallback echo
-  shift
-  cat <<EOF
-$*
-EOF
-  exit 0
-fi
-
-# Find the correct PATH separator.  Usually this is `:', but
-# DJGPP uses `;' like DOS.
-if test "X${PATH_SEPARATOR+set}" != Xset; then
-  UNAME=${UNAME-`uname 2>/dev/null`}
-  case X$UNAME in
-    *-DOS) PATH_SEPARATOR=';' ;;
-    *)     PATH_SEPARATOR=':' ;;
-  esac
-fi
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
-
-if test "X${echo_test_string+set}" != Xset; then
-  # find a string as large as possible, as long as the shell can cope with it
-  for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do
-    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
-    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
-       echo_test_string="`eval $cmd`" &&
-       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then
-      break
-    fi
-  done
-fi
-
-if test "X`($echo '\t') 2>/dev/null`" != 'X\t' ||
-   test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then
-  # The Solaris, AIX, and Digital Unix default echo programs unquote
-  # backslashes.  This makes it impossible to quote backslashes using
-  #   echo "$something" | sed 's/\\/\\\\/g'
-  #
-  # So, first we look for a working echo in the user's PATH.
-
-  IFS="${IFS=  }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-  for dir in $PATH /usr/ucb; do
-    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
-       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
-       test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-      echo="$dir/echo"
-      break
-    fi
-  done
-  IFS="$save_ifs"
-
-  if test "X$echo" = Xecho; then
-    # We didn't find a better echo, so look for alternatives.
-    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
-       test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-      # This shell has a builtin print -r that does the trick.
-      echo='print -r'
-    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
-        test "X$CONFIG_SHELL" != X/bin/ksh; then
-      # If we have ksh, try running ltconfig again with it.
-      ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}"
-      export ORIGINAL_CONFIG_SHELL
-      CONFIG_SHELL=/bin/ksh
-      export CONFIG_SHELL
-      exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"}
-    else
-      # Try using printf.
-      echo='printf "%s\n"'
-      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
-        test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-       # Cool, printf works
-       :
-      elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
-          test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-       CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL"
-       export CONFIG_SHELL
-       SHELL="$CONFIG_SHELL"
-       export SHELL
-       echo="$CONFIG_SHELL $0 --fallback-echo"
-      elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' &&
-          test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then
-       echo="$CONFIG_SHELL $0 --fallback-echo"
-      else
-       # maybe with a smaller string...
-       prev=:
-
-       for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do
-         if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then
-           break
-         fi
-         prev="$cmd"
-       done
-
-       if test "$prev" != 'sed 50q "$0"'; then
-         echo_test_string=`eval $prev`
-         export echo_test_string
-         exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"}
-       else
-         # Oops.  We lost completely, so just stick with echo.
-         echo=echo
-       fi
-      fi
-    fi
-  fi
-fi
-
-# Sed substitution that helps us do robust quoting.  It backslashifies
-# metacharacters that are still active within double-quoted strings.
-Xsed='sed -e s/^X//'
-sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'
-
-# Same as above, but do not quote variable references.
-double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'
-
-# Sed substitution to delay expansion of an escaped shell variable in a
-# double_quote_subst'ed string.
-delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
-
-# The name of this program.
-progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'`
-
-# Constants:
-PROGRAM=ltconfig
-PACKAGE=libtool
-VERSION=1.3.4
-TIMESTAMP=" (1.385.2.196 1999/12/07 21:47:57)"
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-rm="rm -f"
-
-help="Try \`$progname --help' for more information."
-
-# Global variables:
-default_ofile=libtool
-can_build_shared=yes
-enable_shared=yes
-# All known linkers require a `.a' archive for static linking (except M$VC,
-# which needs '.lib').
-enable_static=yes
-enable_fast_install=yes
-enable_dlopen=unknown
-enable_win32_dll=no
-ltmain=
-silent=
-srcdir=
-ac_config_guess=
-ac_config_sub=
-host=
-nonopt=
-ofile="$default_ofile"
-verify_host=yes
-with_gcc=no
-with_gnu_ld=no
-need_locks=yes
-ac_ext=c
-objext=o
-libext=a
-exeext=
-cache_file=
-
-old_AR="$AR"
-old_CC="$CC"
-old_CFLAGS="$CFLAGS"
-old_CPPFLAGS="$CPPFLAGS"
-old_LDFLAGS="$LDFLAGS"
-old_LD="$LD"
-old_LN_S="$LN_S"
-old_LIBS="$LIBS"
-old_NM="$NM"
-old_RANLIB="$RANLIB"
-old_DLLTOOL="$DLLTOOL"
-old_OBJDUMP="$OBJDUMP"
-old_AS="$AS"
-
-# Parse the command line options.
-args=
-prev=
-for option
-do
-  case "$option" in
-  -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
-  *) optarg= ;;
-  esac
-
-  # If the previous option needs an argument, assign it.
-  if test -n "$prev"; then
-    eval "$prev=\$option"
-    prev=
-    continue
-  fi
-
-  case "$option" in
-  --help) cat <<EOM
-Usage: $progname [OPTION]... [HOST [LTMAIN]]
-
-Generate a system-specific libtool script.
-
-    --debug                enable verbose shell tracing
-    --disable-shared       do not build shared libraries
-    --disable-static       do not build static libraries
-    --disable-fast-install do not optimize for fast installation
-    --enable-dlopen        enable dlopen support
-    --enable-win32-dll     enable building dlls on win32 hosts
-    --help                 display this help and exit
-    --no-verify            do not verify that HOST is a valid host type
--o, --output=FILE          specify the output file [default=$default_ofile]
-    --quiet                same as \`--silent'
-    --silent               do not print informational messages
-    --srcdir=DIR           find \`config.guess' in DIR
-    --version              output version information and exit
-    --with-gcc             assume that the GNU C compiler will be used
-    --with-gnu-ld          assume that the C compiler uses the GNU linker
-    --disable-lock         disable file locking
-    --cache-file=FILE      configure cache file
-
-LTMAIN is the \`ltmain.sh' shell script fragment or \`ltmain.c' program
-that provides basic libtool functionality.
-
-HOST is the canonical host system name [default=guessed].
-EOM
-  exit 0
-  ;;
-
-  --debug)
-    echo "$progname: enabling shell trace mode"
-    set -x
-    ;;
-
-  --disable-shared) enable_shared=no ;;
-
-  --disable-static) enable_static=no ;;
-
-  --disable-fast-install) enable_fast_install=no ;;
-
-  --enable-dlopen) enable_dlopen=yes ;;
-
-  --enable-win32-dll) enable_win32_dll=yes ;;
-
-  --quiet | --silent) silent=yes ;;
-
-  --srcdir) prev=srcdir ;;
-  --srcdir=*) srcdir="$optarg" ;;
-
-  --no-verify) verify_host=no ;;
-
-  --output | -o) prev=ofile ;;
-  --output=*) ofile="$optarg" ;;
-
-  --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"; exit 0 ;;
-
-  --with-gcc) with_gcc=yes ;;
-  --with-gnu-ld) with_gnu_ld=yes ;;
-
-  --disable-lock) need_locks=no ;;
-
-  --cache-file=*) cache_file="$optarg" ;;
-
-  -*)
-    echo "$progname: unrecognized option \`$option'" 1>&2
-    echo "$help" 1>&2
-    exit 1
-    ;;
-
-  *)
-    if test -z "$ltmain"; then
-      ltmain="$option"
-    elif test -z "$host"; then
-# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1
-#      if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then
-#        echo "$progname: warning \`$option' is not a valid host type" 1>&2
-#      fi
-      host="$option"
-    else
-      echo "$progname: too many arguments" 1>&2
-      echo "$help" 1>&2
-      exit 1
-    fi ;;
-  esac
-done
-
-if test -z "$ltmain"; then
-  echo "$progname: you must specify a LTMAIN file" 1>&2
-  echo "$help" 1>&2
-  exit 1
-fi
-
-if test ! -f "$ltmain"; then
-  echo "$progname: \`$ltmain' does not exist" 1>&2
-  echo "$help" 1>&2
-  exit 1
-fi
-
-# Quote any args containing shell metacharacters.
-ltconfig_args=
-for arg
-do
-  case "$arg" in
-  *" "*|*"     "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
-  ltconfig_args="$ltconfig_args '$arg'" ;;
-  *) ltconfig_args="$ltconfig_args $arg" ;;
-  esac
-done
-
-# A relevant subset of AC_INIT.
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 5 compiler messages saved in config.log
-# 6 checking for... messages and results
-if test "$silent" = yes; then
-  exec 6>/dev/null
-else
-  exec 6>&1
-fi
-exec 5>>./config.log
-
-# NLS nuisances.
-# Only set LANG and LC_ALL to C if already set.
-# These must not be set unconditionally because not all systems understand
-# e.g. LANG=C (notably SCO).
-if test "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi
-if test "X${LANG+set}"   = Xset; then LANG=C;   export LANG;   fi
-
-if test -n "$cache_file" && test -r "$cache_file"; then
-  echo "loading cache $cache_file within ltconfig"
-  . $cache_file
-fi
-
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
-  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
-  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
-    ac_n= ac_c='
-' ac_t='       '
-  else
-    ac_n=-n ac_c= ac_t=
-  fi
-else
-  ac_n= ac_c='\c' ac_t=
-fi
-
-if test -z "$srcdir"; then
-  # Assume the source directory is the same one as the path to LTMAIN.
-  srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'`
-  test "$srcdir" = "$ltmain" && srcdir=.
-fi
-
-trap "$rm conftest*; exit 1" 1 2 15
-if test "$verify_host" = yes; then
-  # Check for config.guess and config.sub.
-  ac_aux_dir=
-  for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
-    if test -f $ac_dir/config.guess; then
-      ac_aux_dir=$ac_dir
-      break
-    fi
-  done
-  if test -z "$ac_aux_dir"; then
-    echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2
-    echo "$help" 1>&2
-    exit 1
-  fi
-  ac_config_guess=$ac_aux_dir/config.guess
-  ac_config_sub=$ac_aux_dir/config.sub
-
-  # Make sure we can run config.sub.
-  if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then :
-  else
-    echo "$progname: cannot run $ac_config_sub" 1>&2
-    echo "$help" 1>&2
-    exit 1
-  fi
-
-  echo $ac_n "checking host system type""... $ac_c" 1>&6
-
-  host_alias=$host
-  case "$host_alias" in
-  "")
-    if host_alias=`$SHELL $ac_config_guess`; then :
-    else
-      echo "$progname: cannot guess host type; you must specify one" 1>&2
-      echo "$help" 1>&2
-      exit 1
-    fi ;;
-  esac
-  host=`$SHELL $ac_config_sub $host_alias`
-  echo "$ac_t$host" 1>&6
-
-  # Make sure the host verified.
-  test -z "$host" && exit 1
-
-elif test -z "$host"; then
-  echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2
-  echo "$help" 1>&2
-  exit 1
-else
-  host_alias=$host
-fi
-
-# Transform linux* to *-*-linux-gnu*, to support old configure scripts.
-case "$host_os" in
-linux-gnu*) ;;
-linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'`
-esac
-
-host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-
-case "$host_os" in
-aix3*)
-  # AIX sometimes has problems with the GCC collect2 program.  For some
-  # reason, if we set the COLLECT_NAMES environment variable, the problems
-  # vanish in a puff of smoke.
-  if test "X${COLLECT_NAMES+set}" != Xset; then
-    COLLECT_NAMES=
-    export COLLECT_NAMES
-  fi
-  ;;
-esac
-
-# Determine commands to create old-style static archives.
-old_archive_cmds='$AR cru $oldlib$oldobjs'
-old_postinstall_cmds='chmod 644 $oldlib'
-old_postuninstall_cmds=
-
-# Set a sane default for `AR'.
-test -z "$AR" && AR=ar
-
-# Set a sane default for `OBJDUMP'.
-test -z "$OBJDUMP" && OBJDUMP=objdump
-
-# If RANLIB is not set, then run the test.
-if test "${RANLIB+set}" != "set"; then
-  result=no
-
-  echo $ac_n "checking for ranlib... $ac_c" 1>&6
-  IFS="${IFS=  }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-  for dir in $PATH; do
-    test -z "$dir" && dir=.
-    if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then
-      RANLIB="ranlib"
-      result="ranlib"
-      break
-    fi
-  done
-  IFS="$save_ifs"
-
-  echo "$ac_t$result" 1>&6
-fi
-
-if test -n "$RANLIB"; then
-  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
-  old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
-fi
-
-# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin.
-test -z "$DLLTOOL" && DLLTOOL=dlltool
-test -z "$OBJDUMP" && OBJDUMP=objdump
-test -z "$AS" && AS=as
-
-# Check to see if we are using GCC.
-if test "$with_gcc" != yes || test -z "$CC"; then
-  # If CC is not set, then try to find GCC or a usable CC.
-  if test -z "$CC"; then
-    echo $ac_n "checking for gcc... $ac_c" 1>&6
-    IFS="${IFS=        }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-    for dir in $PATH; do
-      test -z "$dir" && dir=.
-      if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then
-       CC="gcc"
-       break
-      fi
-    done
-    IFS="$save_ifs"
-
-    if test -n "$CC"; then
-      echo "$ac_t$CC" 1>&6
-    else
-      echo "$ac_t"no 1>&6
-    fi
-  fi
-
-  # Not "gcc", so try "cc", rejecting "/usr/ucb/cc".
-  if test -z "$CC"; then
-    echo $ac_n "checking for cc... $ac_c" 1>&6
-    IFS="${IFS=        }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-    cc_rejected=no
-    for dir in $PATH; do
-      test -z "$dir" && dir=.
-      if test -f $dir/cc || test -f $dir/cc$ac_exeext; then
-       if test "$dir/cc" = "/usr/ucb/cc"; then
-         cc_rejected=yes
-         continue
-       fi
-       CC="cc"
-       break
-      fi
-    done
-    IFS="$save_ifs"
-    if test $cc_rejected = yes; then
-      # We found a bogon in the path, so make sure we never use it.
-      set dummy $CC
-      shift
-      if test $# -gt 0; then
-       # We chose a different compiler from the bogus one.
-       # However, it has the same name, so the bogon will be chosen
-       # first if we set CC to just the name; use the full file name.
-       shift
-       set dummy "$dir/cc" "$@"
-       shift
-       CC="$@"
-      fi
-    fi
-
-    if test -n "$CC"; then
-      echo "$ac_t$CC" 1>&6
-    else
-      echo "$ac_t"no 1>&6
-    fi
-
-    if test -z "$CC"; then
-      echo "$progname: error: no acceptable cc found in \$PATH" 1>&2
-      exit 1
-    fi
-  fi
-
-  # Now see if the compiler is really GCC.
-  with_gcc=no
-  echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6
-  echo "$progname:581: checking whether we are using GNU C" >&5
-
-  $rm conftest.c
-  cat > conftest.c <<EOF
-#ifdef __GNUC__
-  yes;
-#endif
-EOF
-  if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:589: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
-    with_gcc=yes
-  fi
-  $rm conftest.c
-  echo "$ac_t$with_gcc" 1>&6
-fi
-
-# Allow CC to be a program name with arguments.
-set dummy $CC
-compiler="$2"
-
-echo $ac_n "checking for object suffix... $ac_c" 1>&6
-$rm conftest*
-echo 'int i = 1;' > conftest.c
-echo "$progname:603: checking for object suffix" >& 5
-if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then
-  # Append any warnings to the config.log.
-  cat conftest.err 1>&5
-
-  for ac_file in conftest.*; do
-    case $ac_file in
-    *.c) ;;
-    *) objext=`echo $ac_file | sed -e s/conftest.//` ;;
-    esac
-  done
-else
-  cat conftest.err 1>&5
-  echo "$progname: failed program was:" >&5
-  cat conftest.c >&5
-fi
-$rm conftest*
-echo "$ac_t$objext" 1>&6
-
-echo $ac_n "checking for executable suffix... $ac_c" 1>&6
-if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  ac_cv_exeext="no"
-  $rm conftest*
-  echo 'main () { return 0; }' > conftest.c
-  echo "$progname:629: checking for executable suffix" >& 5
-  if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then
-    # Append any warnings to the config.log.
-    cat conftest.err 1>&5
-
-    for ac_file in conftest.*; do
-      case $ac_file in
-      *.c | *.err | *.$objext ) ;;
-      *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;;
-      esac
-    done
-  else
-    cat conftest.err 1>&5
-    echo "$progname: failed program was:" >&5
-    cat conftest.c >&5
-  fi
-  $rm conftest*
-fi
-if test "X$ac_cv_exeext" = Xno; then
-  exeext=""
-else
-  exeext="$ac_cv_exeext"
-fi
-echo "$ac_t$ac_cv_exeext" 1>&6
-
-echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6
-pic_flag=
-special_shlib_compile_flags=
-wl=
-link_static_flag=
-no_builtin_flag=
-
-if test "$with_gcc" = yes; then
-  wl='-Wl,'
-  link_static_flag='-static'
-
-  case "$host_os" in
-  beos* | irix5* | irix6* | osf3* | osf4* | osf5*)
-    # PIC is the default for these OSes.
-    ;;
-  aix*)
-    # Below there is a dirty hack to force normal static linking with -ldl
-    # The problem is because libdl dynamically linked with both libc and
-    # libC (AIX C++ library), which obviously doesn't included in libraries
-    # list by gcc. This cause undefined symbols with -static flags.
-    # This hack allows C programs to be linked with "-static -ldl", but
-    # we not sure about C++ programs.
-    link_static_flag="$link_static_flag ${wl}-lC"
-    ;;
-  cygwin* | mingw* | os2*)
-    # We can build DLLs from non-PIC.
-    ;;
-  amigaos*)
-    # FIXME: we need at least 68020 code to build shared libraries, but
-    # adding the `-m68020' flag to GCC prevents building anything better,
-    # like `-m68040'.
-    pic_flag='-m68020 -resident32 -malways-restore-a4'
-    ;;
-  sysv4*MP*)
-    if test -d /usr/nec; then
-       pic_flag=-Kconform_pic
-    fi
-    ;;
-  *)
-    pic_flag='-fPIC'
-    ;;
-  esac
-else
-  # PORTME Check for PIC flags for the system compiler.
-  case "$host_os" in
-  aix3* | aix4*)
-    # All AIX code is PIC.
-    link_static_flag='-bnso -bI:/lib/syscalls.exp'
-    ;;
-
-  hpux9* | hpux10* | hpux11*)
-    # Is there a better link_static_flag that works with the bundled CC?
-    wl='-Wl,'
-    link_static_flag="${wl}-a ${wl}archive"
-    pic_flag='+Z'
-    ;;
-
-  irix5* | irix6*)
-    wl='-Wl,'
-    link_static_flag='-non_shared'
-    # PIC (with -KPIC) is the default.
-    ;;
-
-  cygwin* | mingw* | os2*)
-    # We can build DLLs from non-PIC.
-    ;;
-
-  osf3* | osf4* | osf5*)
-    # All OSF/1 code is PIC.
-    wl='-Wl,'
-    link_static_flag='-non_shared'
-    ;;
-
-  sco3.2v5*)
-    pic_flag='-Kpic'
-    link_static_flag='-dn'
-    special_shlib_compile_flags='-belf'
-    ;;
-
-  solaris*)
-    pic_flag='-KPIC'
-    link_static_flag='-Bstatic'
-    wl='-Wl,'
-    ;;
-
-  sunos4*)
-    pic_flag='-PIC'
-    link_static_flag='-Bstatic'
-    wl='-Qoption ld '
-    ;;
-
-  sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
-    pic_flag='-KPIC'
-    link_static_flag='-Bstatic'
-    wl='-Wl,'
-    ;;
-
-  uts4*)
-    pic_flag='-pic'
-    link_static_flag='-Bstatic'
-    ;;
-  sysv4*MP*)
-    if test -d /usr/nec ;then
-      pic_flag='-Kconform_pic'
-      link_static_flag='-Bstatic'
-    fi
-    ;;
-  *)
-    can_build_shared=no
-    ;;
-  esac
-fi
-
-if test -n "$pic_flag"; then
-  echo "$ac_t$pic_flag" 1>&6
-
-  # Check to make sure the pic_flag actually works.
-  echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6
-  $rm conftest*
-  echo "int some_variable = 0;" > conftest.c
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS $pic_flag -DPIC"
-  echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5
-  if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then
-    # Append any warnings to the config.log.
-    cat conftest.err 1>&5
-    
-    case "$host_os" in
-    hpux9* | hpux10* | hpux11*)
-      # On HP-UX, both CC and GCC only warn that PIC is supported... then they
-      # create non-PIC objects.  So, if there were any warnings, we assume that
-      # PIC is not supported.
-      if test -s conftest.err; then
-       echo "$ac_t"no 1>&6
-       can_build_shared=no
-       pic_flag=
-      else
-       echo "$ac_t"yes 1>&6
-       pic_flag=" $pic_flag"
-      fi
-      ;;
-    *)
-      echo "$ac_t"yes 1>&6
-      pic_flag=" $pic_flag"
-      ;;
-    esac
-  else
-    # Append any errors to the config.log.
-    cat conftest.err 1>&5
-    can_build_shared=no
-    pic_flag=
-    echo "$ac_t"no 1>&6
-  fi
-  CFLAGS="$save_CFLAGS"
-  $rm conftest*
-else
-  echo "$ac_t"none 1>&6
-fi
-
-# Check to see if options -o and -c are simultaneously supported by compiler
-echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6
-$rm -r conftest 2>/dev/null
-mkdir conftest
-cd conftest
-$rm conftest*
-echo "int some_variable = 0;" > conftest.c
-mkdir out
-# According to Tom Tromey, Ian Lance Taylor reported there are C compilers
-# that will create temporary files in the current directory regardless of
-# the output directory.  Thus, making CWD read-only will cause this test
-# to fail, enabling locking or at least warning the user not to do parallel
-# builds.
-chmod -w .
-save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS -o out/conftest2.o"
-echo "$progname:829: checking if $compiler supports -c -o file.o" >&5
-if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then
-
-  # The compiler can only warn and ignore the option if not recognized
-  # So say no if there are warnings
-    if test -s out/conftest.err; then
-      echo "$ac_t"no 1>&6
-      compiler_c_o=no
-    else
-      echo "$ac_t"yes 1>&6
-      compiler_c_o=yes
-    fi
-else
-  # Append any errors to the config.log.
-  cat out/conftest.err 1>&5
-  compiler_c_o=no
-  echo "$ac_t"no 1>&6
-fi
-CFLAGS="$save_CFLAGS"
-chmod u+w .
-$rm conftest* out/*
-rmdir out
-cd ..
-rmdir conftest
-$rm -r conftest 2>/dev/null
-
-if test x"$compiler_c_o" = x"yes"; then
-  # Check to see if we can write to a .lo
-  echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6
-  $rm conftest*
-  echo "int some_variable = 0;" > conftest.c
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -c -o conftest.lo"
-  echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5
-if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then
-
-    # The compiler can only warn and ignore the option if not recognized
-    # So say no if there are warnings
-      if test -s conftest.err; then
-       echo "$ac_t"no 1>&6
-       compiler_o_lo=no
-      else
-       echo "$ac_t"yes 1>&6
-       compiler_o_lo=yes
-      fi
-  else
-    # Append any errors to the config.log.
-    cat conftest.err 1>&5
-    compiler_o_lo=no
-    echo "$ac_t"no 1>&6
-  fi
-  CFLAGS="$save_CFLAGS"
-  $rm conftest*
-else
-  compiler_o_lo=no
-fi
-
-# Check to see if we can do hard links to lock some files if needed
-hard_links="nottested"
-if test "$compiler_c_o" = no && test "$need_locks" != no; then
-  # do not overwrite the value of need_locks provided by the user
-  echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6
-  hard_links=yes
-  $rm conftest*
-  ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  touch conftest.a
-  ln conftest.a conftest.b 2>&5 || hard_links=no
-  ln conftest.a conftest.b 2>/dev/null && hard_links=no
-  echo "$ac_t$hard_links" 1>&6
-  $rm conftest*
-  if test "$hard_links" = no; then
-    echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2
-    need_locks=warn
-  fi
-else
-  need_locks=no
-fi
-
-if test "$with_gcc" = yes; then
-  # Check to see if options -fno-rtti -fno-exceptions are supported by compiler
-  echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6
-  $rm conftest*
-  echo "int some_variable = 0;" > conftest.c
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c"
-  echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
-  if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then
-
-    # The compiler can only warn and ignore the option if not recognized
-    # So say no if there are warnings
-      if test -s conftest.err; then
-       echo "$ac_t"no 1>&6
-       compiler_rtti_exceptions=no
-      else
-       echo "$ac_t"yes 1>&6
-       compiler_rtti_exceptions=yes
-      fi
-  else
-    # Append any errors to the config.log.
-    cat conftest.err 1>&5
-    compiler_rtti_exceptions=no
-    echo "$ac_t"no 1>&6
-  fi
-  CFLAGS="$save_CFLAGS"
-  $rm conftest*
-
-  if test "$compiler_rtti_exceptions" = "yes"; then
-    no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions'
-  else
-    no_builtin_flag=' -fno-builtin'
-  fi
-  
-fi
-
-# Check for any special shared library compilation flags.
-if test -n "$special_shlib_compile_flags"; then
-  echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2
-  if echo "$old_CC $old_CFLAGS " | egrep -e "[         ]$special_shlib_compile_flags[  ]" >/dev/null; then :
-  else
-    echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2
-    can_build_shared=no
-  fi
-fi
-
-echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6
-$rm conftest*
-echo 'main(){return(0);}' > conftest.c
-save_LDFLAGS="$LDFLAGS"
-LDFLAGS="$LDFLAGS $link_static_flag"
-echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5
-if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
-  echo "$ac_t$link_static_flag" 1>&6
-else
-  echo "$ac_t"none 1>&6
-  link_static_flag=
-fi
-LDFLAGS="$save_LDFLAGS"
-$rm conftest*
-
-if test -z "$LN_S"; then
-  # Check to see if we can use ln -s, or we need hard links.
-  echo $ac_n "checking whether ln -s works... $ac_c" 1>&6
-  $rm conftest.dat
-  if ln -s X conftest.dat 2>/dev/null; then
-    $rm conftest.dat
-    LN_S="ln -s"
-  else
-    LN_S=ln
-  fi
-  if test "$LN_S" = "ln -s"; then
-    echo "$ac_t"yes 1>&6
-  else
-    echo "$ac_t"no 1>&6
-  fi
-fi
-
-# Make sure LD is an absolute path.
-if test -z "$LD"; then
-  ac_prog=ld
-  if test "$with_gcc" = yes; then
-    # Check if gcc -print-prog-name=ld gives a path.
-    echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6
-    echo "$progname:991: checking for ld used by GCC" >&5
-    ac_prog=`($CC -print-prog-name=ld) 2>&5`
-    case "$ac_prog" in
-    # Accept absolute paths.
-    [\\/]* | [A-Za-z]:[\\/]*)
-      re_direlt='/[^/][^/]*/\.\./'
-      # Canonicalize the path of ld
-      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
-      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
-       ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
-      done
-      test -z "$LD" && LD="$ac_prog"
-      ;;
-    "")
-      # If it fails, then pretend we are not using GCC.
-      ac_prog=ld
-      ;;
-    *)
-      # If it is relative, then search for the first ld in PATH.
-      with_gnu_ld=unknown
-      ;;
-    esac
-  elif test "$with_gnu_ld" = yes; then
-    echo $ac_n "checking for GNU ld... $ac_c" 1>&6
-    echo "$progname:1015: checking for GNU ld" >&5
-  else
-    echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6
-    echo "$progname:1018: checking for non-GNU ld" >&5
-  fi
-
-  if test -z "$LD"; then
-    IFS="${IFS=        }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-    for ac_dir in $PATH; do
-      test -z "$ac_dir" && ac_dir=.
-      if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
-       LD="$ac_dir/$ac_prog"
-       # Check to see if the program is GNU ld.  I'd rather use --version,
-       # but apparently some GNU ld's only accept -v.
-       # Break only if it was the GNU/non-GNU ld that we prefer.
-       if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
-         test "$with_gnu_ld" != no && break
-       else
-         test "$with_gnu_ld" != yes && break
-       fi
-      fi
-    done
-    IFS="$ac_save_ifs"
-  fi
-
-  if test -n "$LD"; then
-    echo "$ac_t$LD" 1>&6
-  else
-    echo "$ac_t"no 1>&6
-  fi
-
-  if test -z "$LD"; then
-    echo "$progname: error: no acceptable ld found in \$PATH" 1>&2
-    exit 1
-  fi
-fi
-
-# Check to see if it really is or is not GNU ld.
-echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6
-# I'd rather use --version here, but apparently some GNU ld's only accept -v.
-if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
-  with_gnu_ld=yes
-else
-  with_gnu_ld=no
-fi
-echo "$ac_t$with_gnu_ld" 1>&6
-
-# See if the linker supports building shared libraries.
-echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6
-
-allow_undefined_flag=
-no_undefined_flag=
-need_lib_prefix=unknown
-need_version=unknown
-# when you set need_version to no, make sure it does not cause -set_version
-# flags to be left without arguments
-archive_cmds=
-archive_expsym_cmds=
-old_archive_from_new_cmds=
-export_dynamic_flag_spec=
-whole_archive_flag_spec=
-thread_safe_flag_spec=
-hardcode_libdir_flag_spec=
-hardcode_libdir_separator=
-hardcode_direct=no
-hardcode_minus_L=no
-hardcode_shlibpath_var=unsupported
-runpath_var=
-always_export_symbols=no
-export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols'
-# include_expsyms should be a list of space-separated symbols to be *always*
-# included in the symbol list
-include_expsyms=
-# exclude_expsyms can be an egrep regular expression of symbols to exclude
-# it will be wrapped by ` (' and `)$', so one must not match beginning or
-# end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
-# as well as any symbol that contains `d'.
-exclude_expsyms="_GLOBAL_OFFSET_TABLE_"
-# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
-# platforms (ab)use it in PIC code, but their linkers get confused if
-# the symbol is explicitly referenced.  Since portable code cannot
-# rely on this symbol name, it's probably fine to never include it in
-# preloaded symbol tables.
-
-case "$host_os" in
-cygwin* | mingw*)
-  # FIXME: the MSVC++ port hasn't been tested in a loooong time
-  # When not using gcc, we currently assume that we are using
-  # Microsoft Visual C++.
-  if test "$with_gcc" != yes; then
-    with_gnu_ld=no
-  fi
-  ;;
-
-esac
-
-ld_shlibs=yes
-if test "$with_gnu_ld" = yes; then
-  # If archive_cmds runs LD, not CC, wlarc should be empty
-  wlarc='${wl}'
-
-  # See if GNU ld supports shared libraries.
-  case "$host_os" in
-  aix3* | aix4*)
-    # On AIX, the GNU linker is very broken
-    ld_shlibs=no
-    cat <<EOF 1>&2
-
-*** Warning: the GNU linker, at least up to release 2.9.1, is reported
-*** to be unable to reliably create shared libraries on AIX.
-*** Therefore, libtool is disabling shared libraries support.  If you
-*** really care for shared libraries, you may want to modify your PATH
-*** so that a non-GNU linker is found, and then restart.
-
-EOF
-    ;;
-
-  amigaos*)
-    archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-
-    # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
-    # that the semantics of dynamic libraries on AmigaOS, at least up
-    # to version 4, is to share data among multiple programs linked
-    # with the same dynamic library.  Since this doesn't match the
-    # behavior of shared libraries on other platforms, we can use
-    # them.
-    ld_shlibs=no
-    ;;
-
-  beos*)
-    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      allow_undefined_flag=unsupported
-      # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
-      # support --undefined.  This deserves some investigation.  FIXME
-      archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
-    else
-      ld_shlibs=no
-    fi
-    ;;
-
-  cygwin* | mingw*)
-    # hardcode_libdir_flag_spec is actually meaningless, as there is
-    # no search path for DLLs.
-    hardcode_libdir_flag_spec='-L$libdir'
-    allow_undefined_flag=unsupported
-    always_export_symbols=yes
-
-    # Extract the symbol export list from an `--export-all' def file,
-    # then regenerate the def file from the symbol export list, so that
-    # the compiled dll only exports the symbol export list.
-    export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
-      test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
-      $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def  $objdir/$soname-ltdll.$objext $libobjs $convenience~
-      sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]* ; *//" < $objdir/$soname-def > $export_symbols'
-
-    archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~
-      _lt_hint=1;
-      for symbol in `cat $export_symbols`; do
-       echo "  \$symbol @ \$_lt_hint ; " >> $objdir/$soname-def;
-       _lt_hint=`expr 1 + \$_lt_hint`;
-      done~
-      test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~
-      test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~
-      $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
-      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
-      $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~
-      $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~
-      $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts'
-
-      old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a' 
-    ;;
-
-  netbsd*)
-    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
-      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
-      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-    else
-      archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib'
-      # can we support soname and/or expsyms with a.out? -oliva
-    fi
-    ;;
-
-  solaris* | sysv5*)
-    if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then
-      ld_shlibs=no
-      cat <<EOF 1>&2
-
-*** Warning: The releases 2.8.* of the GNU linker cannot reliably
-*** create shared libraries on Solaris systems.  Therefore, libtool
-*** is disabling shared libraries support.  We urge you to upgrade GNU
-*** binutils to release 2.9.1 or newer.  Another option is to modify
-*** your PATH or compiler configuration so that the native linker is
-*** used, and then restart.
-
-EOF
-    elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
-      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-    else
-      ld_shlibs=no
-    fi
-    ;;      
-
-  sunos4*)
-    archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts'
-    wlarc=
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  *)
-    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
-      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib'
-      archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
-    else
-      ld_shlibs=no
-    fi
-    ;;
-  esac
-
-  if test "$ld_shlibs" = yes; then
-    runpath_var=LD_RUN_PATH
-    hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir'
-    export_dynamic_flag_spec='${wl}--export-dynamic'
-    case $host_os in
-    cygwin* | mingw*)
-      # dlltool doesn't understand --whole-archive et. al.
-      whole_archive_flag_spec=
-      ;;
-    *)
-      # ancient GNU ld didn't support --whole-archive et. al.
-      if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then
-        whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
-      else
-        whole_archive_flag_spec=
-      fi
-      ;;
-    esac
-  fi
-else
-  # PORTME fill in a description of your system's linker (not GNU ld)
-  case "$host_os" in
-  aix3*)
-    allow_undefined_flag=unsupported
-    always_export_symbols=yes
-    archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname'
-    # Note: this linker hardcodes the directories in LIBPATH if there
-    # are no directories specified by -L.
-    hardcode_minus_L=yes
-    if test "$with_gcc" = yes && test -z "$link_static_flag"; then
-      # Neither direct hardcoding nor static linking is supported with a
-      # broken collect2.
-      hardcode_direct=unsupported
-    fi
-    ;;
-
-  aix4*)
-    hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib'
-    hardcode_libdir_separator=':'
-    if test "$with_gcc" = yes; then
-      collect2name=`${CC} -print-prog-name=collect2`
-      if test -f "$collect2name" && \
-        strings "$collect2name" | grep resolve_lib_name >/dev/null
-      then
-       # We have reworked collect2
-       hardcode_direct=yes
-      else
-       # We have old collect2
-       hardcode_direct=unsupported
-       # It fails to find uninstalled libraries when the uninstalled
-       # path is not listed in the libpath.  Setting hardcode_minus_L
-       # to unsupported forces relinking
-       hardcode_minus_L=yes
-       hardcode_libdir_flag_spec='-L$libdir'
-       hardcode_libdir_separator=
-      fi
-      shared_flag='-shared'
-    else
-      shared_flag='${wl}-bM:SRE'
-      hardcode_direct=yes
-    fi
-    allow_undefined_flag=' ${wl}-berok'
-    archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}'
-    archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}'
-    case "$host_os" in aix4.[01]|aix4.[01].*)
-      # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on
-      always_export_symbols=yes ;;
-    esac
-   ;;
-
-  amigaos*)
-    archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-    # see comment about different semantics on the GNU ld section
-    ld_shlibs=no
-    ;;
-
-  cygwin* | mingw*)
-    # When not using gcc, we currently assume that we are using
-    # Microsoft Visual C++.
-    # hardcode_libdir_flag_spec is actually meaningless, as there is
-    # no search path for DLLs.
-    hardcode_libdir_flag_spec=' '
-    allow_undefined_flag=unsupported
-    # Tell ltmain to make .lib files, not .a files.
-    libext=lib
-    # FIXME: Setting linknames here is a bad hack.
-    archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames='
-    # The linker will automatically build a .lib file if we build a DLL.
-    old_archive_from_new_cmds='true'
-    # FIXME: Should let the user specify the lib program.
-    old_archive_cmds='lib /OUT:$oldlib$oldobjs'
-    fix_srcfile_path='`cygpath -w $srcfile`'
-    ;;
-
-  freebsd1*)
-    ld_shlibs=no
-    ;;
-
-  # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
-  # support.  Future versions do this automatically, but an explicit c++rt0.o
-  # does not break anything, and helps significantly (at the cost of a little
-  # extra space).
-  freebsd2.2*)
-    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  # Unfortunately, older versions of FreeBSD 2 do not have this feature.
-  freebsd2*)
-    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
-    hardcode_direct=yes
-    hardcode_minus_L=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
-  freebsd*)
-    archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  hpux9* | hpux10* | hpux11*)
-    case "$host_os" in
-    hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;;
-    *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;;
-    esac
-    hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
-    hardcode_libdir_separator=:
-    hardcode_direct=yes
-    hardcode_minus_L=yes # Not in the search PATH, but as the default
-                        # location of the library.
-    export_dynamic_flag_spec='${wl}-E'
-    ;;
-
-  irix5* | irix6*)
-    if test "$with_gcc" = yes; then
-      archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
-    else
-      archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
-    fi
-    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-    hardcode_libdir_separator=:
-    ;;
-
-  netbsd*)
-    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
-      archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'  # a.out
-    else
-      archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts'      # ELF
-    fi
-    hardcode_libdir_flag_spec='${wl}-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  openbsd*)
-    archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_direct=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  os2*)
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_minus_L=yes
-    allow_undefined_flag=unsupported
-    archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def'
-    old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def'
-    ;;
-
-  osf3*)
-    if test "$with_gcc" = yes; then
-      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
-      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
-    else
-      allow_undefined_flag=' -expect_unresolved \*'
-      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
-    fi
-    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-    hardcode_libdir_separator=:
-    ;;
-
-  osf4* | osf5*)  # As osf3* with the addition of the -msym flag
-    if test "$with_gcc" = yes; then
-      allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*'
-      archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
-    else
-      allow_undefined_flag=' -expect_unresolved \*'
-      archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
-    fi
-    hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
-    hardcode_libdir_separator=:
-    ;;
-
-  sco3.2v5*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    hardcode_shlibpath_var=no
-    runpath_var=LD_RUN_PATH
-    hardcode_runpath_var=yes
-    ;;
-
-  solaris*)
-    no_undefined_flag=' -z text'
-    # $CC -shared without GNU ld will not create a library from C++
-    # object files and a static libstdc++, better avoid it by now
-    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
-    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
-               $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
-    hardcode_libdir_flag_spec='-R$libdir'
-    hardcode_shlibpath_var=no
-    case "$host_os" in
-    solaris2.[0-5] | solaris2.[0-5].*) ;;
-    *) # Supported since Solaris 2.6 (maybe 2.5.1?)
-      whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;;
-    esac
-    ;;
-
-  sunos4*)
-    archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_direct=yes
-    hardcode_minus_L=yes
-    hardcode_shlibpath_var=no
-    ;;
-
-  sysv4)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    runpath_var='LD_RUN_PATH'
-    hardcode_shlibpath_var=no
-    hardcode_direct=no #Motorola manual says yes, but my tests say they lie 
-    ;;  
-
-  sysv4.3*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    hardcode_shlibpath_var=no
-    export_dynamic_flag_spec='-Bexport'
-    ;;
-
-  sysv5*)
-    no_undefined_flag=' -z text'
-    # $CC -shared without GNU ld will not create a library from C++
-    # object files and a static libstdc++, better avoid it by now
-    archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts'
-    archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
-               $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp'
-    hardcode_libdir_flag_spec=
-    hardcode_shlibpath_var=no
-    runpath_var='LD_RUN_PATH'
-    ;;
-
-  uts4*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_shlibpath_var=no
-    ;;
-
-  dgux*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    hardcode_libdir_flag_spec='-L$libdir'
-    hardcode_shlibpath_var=no
-    ;;
-
-  sysv4*MP*)
-    if test -d /usr/nec; then
-      archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-      hardcode_shlibpath_var=no
-      runpath_var=LD_RUN_PATH
-      hardcode_runpath_var=yes
-      ld_shlibs=yes
-    fi
-    ;;
-
-  sysv4.2uw2*)
-    archive_cmds='$LD -G -o $lib $libobjs $deplibs $linkopts'
-    hardcode_direct=yes
-    hardcode_minus_L=no
-    hardcode_shlibpath_var=no
-    hardcode_runpath_var=yes
-    runpath_var=LD_RUN_PATH
-    ;;
-
-  unixware7*)
-    archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts'
-    runpath_var='LD_RUN_PATH'
-    hardcode_shlibpath_var=no
-    ;;
-
-  *)
-    ld_shlibs=no
-    ;;
-  esac
-fi
-echo "$ac_t$ld_shlibs" 1>&6
-test "$ld_shlibs" = no && can_build_shared=no
-
-if test -z "$NM"; then
-  echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6
-  case "$NM" in
-  [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path.
-  *)
-    IFS="${IFS=        }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}"
-    for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do
-      test -z "$ac_dir" && ac_dir=.
-      if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then
-       # Check to see if the nm accepts a BSD-compat flag.
-       # Adding the `sed 1q' prevents false positives on HP-UX, which says:
-       #   nm: unknown option "B" ignored
-       if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
-         NM="$ac_dir/nm -B"
-         break
-       elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
-         NM="$ac_dir/nm -p"
-         break
-       else
-         NM=${NM="$ac_dir/nm"} # keep the first match, but
-         continue # so that we can try to find one that supports BSD flags
-       fi
-      fi
-    done
-    IFS="$ac_save_ifs"
-    test -z "$NM" && NM=nm
-    ;;
-  esac
-  echo "$ac_t$NM" 1>&6
-fi
-
-# Check for command to grab the raw symbol name followed by C symbol from nm.
-echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6
-
-# These are sane defaults that work on at least a few old systems.
-# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
-
-# Character class describing NM global symbol codes.
-symcode='[BCDEGRST]'
-
-# Regexp to match symbols that can be accessed directly from C.
-sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
-
-# Transform the above into a raw symbol and a C symbol.
-symxfrm='\1 \2\3 \3'
-
-# Transform an extracted symbol line into a proper C declaration
-global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'"
-
-# Define system-specific variables.
-case "$host_os" in
-aix*)
-  symcode='[BCDT]'
-  ;;
-cygwin* | mingw*)
-  symcode='[ABCDGISTW]'
-  ;;
-hpux*) # Its linker distinguishes data from code symbols
-  global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'"
-  ;;
-irix*)
-  symcode='[BCDEGRST]'
-  ;;
-solaris*)
-  symcode='[BDT]'
-  ;;
-sysv4)
-  symcode='[DFNSTU]'
-  ;;
-esac
-
-# If we're using GNU nm, then use its standard symbol codes.
-if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then
-  symcode='[ABCDGISTW]'
-fi
-
-# Try without a prefix undercore, then with it.
-for ac_symprfx in "" "_"; do
-
-  # Write the raw and C identifiers.
-  global_symbol_pipe="sed -n -e 's/^.*[        ]\($symcode\)[  ][      ]*\($ac_symprfx\)$sympat$/$symxfrm/p'"
-
-  # Check to see that the pipe works correctly.
-  pipe_works=no
-  $rm conftest*
-  cat > conftest.c <<EOF
-#ifdef __cplusplus
-extern "C" {
-#endif
-char nm_test_var;
-void nm_test_func(){}
-#ifdef __cplusplus
-}
-#endif
-main(){nm_test_var='a';nm_test_func();return(0);}
-EOF
-
-  echo "$progname:1635: checking if global_symbol_pipe works" >&5
-  if { (eval echo $progname:1636: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then
-    # Now try to grab the symbols.
-    nlist=conftest.nm
-    if { echo "$progname:1639: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then
-
-      # Try sorting and uniquifying the output.
-      if sort "$nlist" | uniq > "$nlist"T; then
-       mv -f "$nlist"T "$nlist"
-      else
-       rm -f "$nlist"T
-      fi
-
-      # Make sure that we snagged all the symbols we need.
-      if egrep ' nm_test_var$' "$nlist" >/dev/null; then
-       if egrep ' nm_test_func$' "$nlist" >/dev/null; then
-         cat <<EOF > conftest.c
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-EOF
-         # Now generate the symbol file.
-         eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c'
-
-         cat <<EOF >> conftest.c
-#if defined (__STDC__) && __STDC__
-# define lt_ptr_t void *
-#else
-# define lt_ptr_t char *
-# define const
-#endif
-
-/* The mapping between symbol names and symbols. */
-const struct {
-  const char *name;
-  lt_ptr_t address;
-}
-lt_preloaded_symbols[] =
-{
-EOF
-         sed 's/^. \(.*\) \(.*\)$/  {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c
-         cat <<\EOF >> conftest.c
-  {0, (lt_ptr_t) 0}
-};
-
-#ifdef __cplusplus
-}
-#endif
-EOF
-         # Now try linking the two files.
-         mv conftest.$objext conftstm.$objext
-         save_LIBS="$LIBS"
-         save_CFLAGS="$CFLAGS"
-         LIBS="conftstm.$objext"
-         CFLAGS="$CFLAGS$no_builtin_flag"
-         if { (eval echo $progname:1691: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
-           pipe_works=yes
-         else
-           echo "$progname: failed program was:" >&5
-           cat conftest.c >&5
-         fi
-         LIBS="$save_LIBS"
-       else
-         echo "cannot find nm_test_func in $nlist" >&5
-       fi
-      else
-       echo "cannot find nm_test_var in $nlist" >&5
-      fi
-    else
-      echo "cannot run $global_symbol_pipe" >&5
-    fi
-  else
-    echo "$progname: failed program was:" >&5
-    cat conftest.c >&5
-  fi
-  $rm conftest* conftst*
-
-  # Do not use the global_symbol_pipe unless it works.
-  if test "$pipe_works" = yes; then
-    break
-  else
-    global_symbol_pipe=
-  fi
-done
-if test "$pipe_works" = yes; then
-  echo "${ac_t}ok" 1>&6
-else
-  echo "${ac_t}failed" 1>&6
-fi
-
-if test -z "$global_symbol_pipe"; then
-  global_symbol_to_cdecl=
-fi
-
-# Check hardcoding attributes.
-echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6
-hardcode_action=
-if test -n "$hardcode_libdir_flag_spec" || \
-   test -n "$runpath_var"; then
-
-  # We can hardcode non-existant directories.
-  if test "$hardcode_direct" != no &&
-     # If the only mechanism to avoid hardcoding is shlibpath_var, we
-     # have to relink, otherwise we might link with an installed library
-     # when we should be linking with a yet-to-be-installed one
-     ## test "$hardcode_shlibpath_var" != no &&
-     test "$hardcode_minus_L" != no; then
-    # Linking always hardcodes the temporary library directory.
-    hardcode_action=relink
-  else
-    # We can link without hardcoding, and we can hardcode nonexisting dirs.
-    hardcode_action=immediate
-  fi
-else
-  # We cannot hardcode anything, or else we can only hardcode existing
-  # directories.
-  hardcode_action=unsupported
-fi
-echo "$ac_t$hardcode_action" 1>&6
-
-
-reload_flag=
-reload_cmds='$LD$reload_flag -o $output$reload_objs'
-echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6
-# PORTME Some linkers may need a different reload flag.
-reload_flag='-r'
-echo "$ac_t$reload_flag" 1>&6
-test -n "$reload_flag" && reload_flag=" $reload_flag"
-
-# PORTME Fill in your ld.so characteristics
-library_names_spec=
-libname_spec='lib$name'
-soname_spec=
-postinstall_cmds=
-postuninstall_cmds=
-finish_cmds=
-finish_eval=
-shlibpath_var=
-shlibpath_overrides_runpath=unknown
-version_type=none
-dynamic_linker="$host_os ld.so"
-sys_lib_dlsearch_path_spec="/lib /usr/lib"
-sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
-file_magic_cmd=
-file_magic_test_file=
-deplibs_check_method='unknown'
-# Need to set the preceding variable on all platforms that support
-# interlibrary dependencies.
-# 'none' -- dependencies not supported.
-# `unknown' -- same as none, but documents that we really don't know.
-# 'pass_all' -- all dependencies passed with no checks.
-# 'test_compile' -- check by making test program.
-# 'file_magic [regex]' -- check by looking for files in library path
-# which responds to the $file_magic_cmd with a given egrep regex.
-# If you have `file' or equivalent on your system and you're not sure
-# whether `pass_all' will *always* work, you probably want this one.
-echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6
-case "$host_os" in
-aix3*)
-  version_type=linux
-  library_names_spec='${libname}${release}.so$versuffix $libname.a'
-  shlibpath_var=LIBPATH
-
-  # AIX has no versioning support, so we append a major version to the name.
-  soname_spec='${libname}${release}.so$major'
-  ;;
-
-aix4*)
-  version_type=linux
-  # AIX has no versioning support, so currently we can not hardcode correct
-  # soname into executable. Probably we can add versioning support to
-  # collect2, so additional links can be useful in future.
-  # We preserve .a as extension for shared libraries though AIX4.2
-  # and later linker supports .so
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a'
-  shlibpath_var=LIBPATH
-  deplibs_check_method=pass_all
-  ;;
-
-amigaos*)
-  library_names_spec='$libname.ixlibrary $libname.a'
-  # Create ${libname}_ixlibrary.a entries in /sys/libs.
-  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done'
-  ;;
-
-beos*)
-  library_names_spec='${libname}.so'
-  dynamic_linker="$host_os ld.so"
-  shlibpath_var=LIBRARY_PATH
-  deplibs_check_method=pass_all
-  lt_cv_dlopen="load_add_on"
-  lt_cv_dlopen_libs=
-  lt_cv_dlopen_self=yes
-  ;;
-
-bsdi4*)
-  version_type=linux
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=/shlib/libc.so
-  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
-  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
-  export_dynamic_flag_spec=-rdynamic
-  # the default ld.so.conf also contains /usr/contrib/lib and
-  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
-  # libtool to hard-code these into programs
-  ;;
-
-cygwin* | mingw*)
-  version_type=windows
-  need_version=no
-  need_lib_prefix=no
-  if test "$with_gcc" = yes; then
-    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a'
-  else
-    library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib'
-  fi
-  dynamic_linker='Win32 ld.exe'
-  deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
-  file_magic_cmd='${OBJDUMP} -f'
-  # FIXME: first we should search . and the directory the executable is in
-  shlibpath_var=PATH
-  lt_cv_dlopen="LoadLibrary"
-  lt_cv_dlopen_libs=
-  ;;
-
-freebsd1*)
-  dynamic_linker=no
-  ;;
-  
-freebsd*)
-  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
-  version_type=freebsd-$objformat
-  case "$version_type" in
-    freebsd-elf*)
-      deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object'
-      file_magic_cmd=/usr/bin/file
-      file_magic_test_file=`echo /usr/lib/libc.so*`
-      library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
-      need_version=no
-      need_lib_prefix=no
-      ;;
-    freebsd-*)
-      deplibs_check_method=unknown
-      library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix'
-      need_version=yes
-      ;;
-  esac
-  shlibpath_var=LD_LIBRARY_PATH
-  case "$host_os" in
-  freebsd2* | freebsd3.[01]* | freebsdelf3.[01]*)
-    shlibpath_overrides_runpath=yes
-    ;;
-  *) # from 3.2 on
-    shlibpath_overrides_runpath=no
-    ;;
-  esac
-  ;;
-
-gnu*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-hpux9* | hpux10* | hpux11*)
-  # Give a soname corresponding to the major version so that dld.sl refuses to
-  # link against other versions.
-  dynamic_linker="$host_os dld.sl"
-  version_type=sunos
-  need_lib_prefix=no
-  need_version=no
-  shlibpath_var=SHLIB_PATH
-  shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
-  library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl'
-  soname_spec='${libname}${release}.sl$major'
-  # HP-UX runs *really* slowly unless shared libraries are mode 555.
-  postinstall_cmds='chmod 555 $lib'
-  ;;
-
-irix5* | irix6*)
-  version_type=irix
-  need_lib_prefix=no
-  need_version=no
-  soname_spec='${libname}${release}.so.$major'
-  library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so'
-  case "$host_os" in
-  irix5*)
-    libsuff= shlibsuff=
-    # this will be overridden with pass_all, but let us keep it just in case
-    deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1"
-    ;;
-  *)
-    case "$LD" in # libtool.m4 will add one of these switches to LD
-    *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;;
-    *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;;
-    *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;;
-    *) libsuff= shlibsuff= libmagic=never-match;;
-    esac
-    ;;
-  esac
-  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
-  shlibpath_overrides_runpath=no
-  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
-  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=`echo /lib${libsuff}/libc.so*`
-  deplibs_check_method='pass_all'
-  ;;
-
-# No shared lib support for Linux oldld, aout, or coff.
-linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*)
-  dynamic_linker=no
-  ;;
-
-# This must be Linux ELF.
-linux-gnu*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
-
-  if test -f /lib/ld.so.1; then
-    dynamic_linker='GNU ld.so'
-  else
-    dynamic_linker='Linux ld.so'
-  fi
-  ;;
-
-netbsd*)
-  version_type=sunos
-  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
-    library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
-    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
-    dynamic_linker='NetBSD (a.out) ld.so'
-  else
-    library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so'
-    soname_spec='${libname}${release}.so$major'
-    dynamic_linker='NetBSD ld.elf_so'
-  fi
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-openbsd*)
-  version_type=sunos
-  if test "$with_gnu_ld" = yes; then
-    need_lib_prefix=no
-    need_version=no
-  fi
-  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
-  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-os2*)
-  libname_spec='$name'
-  need_lib_prefix=no
-  library_names_spec='$libname.dll $libname.a'
-  dynamic_linker='OS/2 ld.exe'
-  shlibpath_var=LIBPATH
-  ;;
-
-osf3* | osf4* | osf5*)
-  version_type=osf
-  need_version=no
-  soname_spec='${libname}${release}.so'
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so'
-  shlibpath_var=LD_LIBRARY_PATH
-  # this will be overridden with pass_all, but let us keep it just in case
-  deplibs_check_method='file_magic COFF format alpha shared library'
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=/shlib/libc.so
-  deplibs_check_method='pass_all'
-  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
-  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
-  ;;
-
-sco3.2v5*)
-  version_type=osf
-  soname_spec='${libname}${release}.so$major'
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-solaris*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  # ldd complains unless libraries are executable
-  postinstall_cmds='chmod +x $lib'
-  deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib"
-  file_magic_cmd=/usr/bin/file
-  file_magic_test_file=/lib/libc.so
-  ;;
-
-sunos4*)
-  version_type=sunos
-  library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix'
-  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=yes
-  if test "$with_gnu_ld" = yes; then
-    need_lib_prefix=no
-  fi
-  need_version=yes
-  ;;
-
-sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
-  version_type=linux
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  case "$host_vendor" in
-    ncr)
-      deplibs_check_method='pass_all'
-      ;;
-    motorola)
-      need_lib_prefix=no
-      need_version=no
-      shlibpath_overrides_runpath=no
-      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
-      deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
-      file_magic_cmd=/usr/bin/file
-      file_magic_test_file=`echo /usr/lib/libc.so*`
-      ;;
-  esac
-  ;;
-
-uts4*)
-  version_type=linux
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-dgux*)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so'
-  soname_spec='${libname}${release}.so$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  ;;
-
-sysv4*MP*)
-  if test -d /usr/nec ;then
-    version_type=linux
-    library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so'
-    soname_spec='$libname.so.$major'
-    shlibpath_var=LD_LIBRARY_PATH
-  fi
-  ;;
-
-*)
-  dynamic_linker=no
-  ;;
-esac
-echo "$ac_t$dynamic_linker" 1>&6
-test "$dynamic_linker" = no && can_build_shared=no
-
-# Report the final consequences.
-echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6
-
-# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in
-# configure.in, otherwise build static only libraries.
-case "$host_os" in
-cygwin* | mingw* | os2*)
-  if test x$can_build_shared = xyes; then
-    test x$enable_win32_dll = xno && can_build_shared=no
-    echo "checking if package supports dlls... $can_build_shared" 1>&6
-  fi
-;;
-esac
-
-if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then
-  case "$deplibs_check_method" in
-  "file_magic "*)
-    file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
-    if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
-       egrep "$file_magic_regex" > /dev/null; then
-      :
-    else
-      cat <<EOF 1>&2
-
-*** Warning: the command libtool uses to detect shared libraries,
-*** $file_magic_cmd, produces output that libtool cannot recognize.
-*** The result is that libtool may fail to recognize shared libraries
-*** as such.  This will affect the creation of libtool libraries that
-*** depend on shared libraries, but programs linked with such libtool
-*** libraries will work regardless of this problem.  Nevertheless, you
-*** may want to report the problem to your system manager and/or to
-*** bug-libtool@gnu.org
-
-EOF
-    fi ;;
-  esac
-fi
-
-echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6
-test "$can_build_shared" = "no" && enable_shared=no
-
-# On AIX, shared libraries and static libraries use the same namespace, and
-# are all built from PIC.
-case "$host_os" in
-aix3*)
-  test "$enable_shared" = yes && enable_static=no
-  if test -n "$RANLIB"; then
-    archive_cmds="$archive_cmds~\$RANLIB \$lib"
-    postinstall_cmds='$RANLIB $lib'
-  fi
-  ;;
-
-aix4*)
-  test "$enable_shared" = yes && enable_static=no
-  ;;
-esac
-
-echo "$ac_t$enable_shared" 1>&6
-
-# Make sure either enable_shared or enable_static is yes.
-test "$enable_shared" = yes || enable_static=yes
-
-echo "checking whether to build static libraries... $enable_static" 1>&6
-
-if test "$hardcode_action" = relink; then
-  # Fast installation is not supported
-  enable_fast_install=no
-elif test "$shlibpath_overrides_runpath" = yes ||
-     test "$enable_shared" = no; then
-  # Fast installation is not necessary
-  enable_fast_install=needless
-fi
-
-echo $ac_n "checking for objdir... $ac_c" 1>&6
-rm -f .libs 2>/dev/null
-mkdir .libs 2>/dev/null
-if test -d .libs; then
-  objdir=.libs
-else
-  # MS-DOS does not allow filenames that begin with a dot.
-  objdir=_libs
-fi
-rmdir .libs 2>/dev/null
-echo "$ac_t$objdir" 1>&6
-
-if test "x$enable_dlopen" != xyes; then
-  enable_dlopen=unknown
-  enable_dlopen_self=unknown
-  enable_dlopen_self_static=unknown
-else
-if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then
-  lt_cv_dlopen=no lt_cv_dlopen_libs=
-echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
-echo "$progname:2212: checking for dlopen in -ldl" >&5
-ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  ac_save_LIBS="$LIBS"
-LIBS="-ldl  $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2220 "ltconfig"
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen();
-
-int main() {
-dlopen()
-; return 0; }
-EOF
-if { (eval echo $progname:2233: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"
-else
-  echo "$ac_t""no" 1>&6
-echo $ac_n "checking for dlopen""... $ac_c" 1>&6
-echo "$progname:2252: checking for dlopen" >&5
-if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  cat > conftest.$ac_ext <<EOF
-#line 2257 "ltconfig"
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char dlopen(); below.  */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dlopen();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined (__stub_dlopen) || defined (__stub___dlopen)
-choke me
-#else
-dlopen();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo $progname:2282: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_func_dlopen=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_func_dlopen=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="dlopen"
-else
-  echo "$ac_t""no" 1>&6
-echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6
-echo "$progname:2299: checking for dld_link in -ldld" >&5
-ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  ac_save_LIBS="$LIBS"
-LIBS="-ldld  $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2307 "ltconfig"
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char dld_link();
-
-int main() {
-dld_link()
-; return 0; }
-EOF
-if { (eval echo $progname:2320: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"
-else
-  echo "$ac_t""no" 1>&6
-echo $ac_n "checking for shl_load""... $ac_c" 1>&6
-echo "$progname:2339: checking for shl_load" >&5
-if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  cat > conftest.$ac_ext <<EOF
-#line 2344 "ltconfig"
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char shl_load(); below.  */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char shl_load();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined (__stub_shl_load) || defined (__stub___shl_load)
-choke me
-#else
-shl_load();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo $progname:2369: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_func_shl_load=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_func_shl_load=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="shl_load"
-else
-  echo "$ac_t""no" 1>&6
-echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
-echo "$progname:2387: checking for shl_load in -ldld" >&5
-ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  ac_save_LIBS="$LIBS"
-LIBS="-ldld  $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 2395 "ltconfig"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error.  */
-/* We use char because int might match the return type of a gcc2
-    builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char shl_load();
-
-int main() {
-shl_load()
-; return 0; }
-EOF
-if { (eval echo $progname:2409: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=yes"
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"
-else
-  echo "$ac_t""no" 1>&6
-fi
-
-
-fi
-
-    
-fi
-
-  
-fi
-
-
-fi
-
-fi
-
-  if test "x$lt_cv_dlopen" != xno; then
-    enable_dlopen=yes
-  fi
-
-  case "$lt_cv_dlopen" in
-  dlopen)
-for ac_hdr in dlfcn.h; do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "$progname:2452: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  cat > conftest.$ac_ext <<EOF
-#line 2457 "ltconfig"
-#include <$ac_hdr>
-int fnord = 0;
-EOF
-ac_try="$ac_compile >/dev/null 2>conftest.out"
-{ (eval echo $progname:2462: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
-  rm -rf conftest*
-  eval "ac_cv_header_$ac_safe=yes"
-else
-  echo "$ac_err" >&5
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -rf conftest*
-  eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-else
-  echo "$ac_t""no" 1>&6
-fi
-done
-
-    if test "x$ac_cv_header_dlfcn_h" = xyes; then
-      CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
-    fi
-    eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
-    LIBS="$lt_cv_dlopen_libs $LIBS"
-
-  echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6
-echo "$progname:2490: checking whether a program can dlopen itself" >&5
-if test "${lt_cv_dlopen_self+set}" = set; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  if test "$cross_compiling" = yes; then
-    lt_cv_dlopen_self=cross
-  else
-    cat > conftest.c <<EOF
-#line 2498 "ltconfig"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LTDL_GLOBAL   RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-#  define LTDL_GLOBAL  DL_GLOBAL
-# else
-#  define LTDL_GLOBAL  0
-# endif
-#endif
-
-/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
-   find out it does not work in some platform. */
-#ifndef LTDL_LAZY_OR_NOW
-# ifdef RTLD_LAZY
-#  define LTDL_LAZY_OR_NOW     RTLD_LAZY
-# else
-#  ifdef DL_LAZY
-#   define LTDL_LAZY_OR_NOW    DL_LAZY
-#  else
-#   ifdef RTLD_NOW
-#    define LTDL_LAZY_OR_NOW   RTLD_NOW
-#   else
-#    ifdef DL_NOW
-#     define LTDL_LAZY_OR_NOW  DL_NOW
-#    else
-#     define LTDL_LAZY_OR_NOW  0
-#    endif
-#   endif
-#  endif
-# endif
-#endif
-
-fnord() { int i=42;}
-main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
-    if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
-              if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } 
-
-EOF
-if { (eval echo $progname:2544: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
-  lt_cv_dlopen_self=yes
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -fr conftest*
-  lt_cv_dlopen_self=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$lt_cv_dlopen_self" 1>&6
-
-  if test "$lt_cv_dlopen_self" = yes; then
-    LDFLAGS="$LDFLAGS $link_static_flag"
-  echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6
-echo "$progname:2563: checking whether a statically linked program can dlopen itself" >&5
-if test "${lt_cv_dlopen_self_static+set}" = set; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  if test "$cross_compiling" = yes; then
-    lt_cv_dlopen_self_static=cross
-  else
-    cat > conftest.c <<EOF
-#line 2571 "ltconfig"
-
-#if HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-#include <stdio.h>
-
-#ifdef RTLD_GLOBAL
-# define LTDL_GLOBAL   RTLD_GLOBAL
-#else
-# ifdef DL_GLOBAL
-#  define LTDL_GLOBAL  DL_GLOBAL
-# else
-#  define LTDL_GLOBAL  0
-# endif
-#endif
-
-/* We may have to define LTDL_LAZY_OR_NOW in the command line if we
-   find out it does not work in some platform. */
-#ifndef LTDL_LAZY_OR_NOW
-# ifdef RTLD_LAZY
-#  define LTDL_LAZY_OR_NOW     RTLD_LAZY
-# else
-#  ifdef DL_LAZY
-#   define LTDL_LAZY_OR_NOW    DL_LAZY
-#  else
-#   ifdef RTLD_NOW
-#    define LTDL_LAZY_OR_NOW   RTLD_NOW
-#   else
-#    ifdef DL_NOW
-#     define LTDL_LAZY_OR_NOW  DL_NOW
-#    else
-#     define LTDL_LAZY_OR_NOW  0
-#    endif
-#   endif
-#  endif
-# endif
-#endif
-
-fnord() { int i=42;}
-main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW);
-    if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord");
-    if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } 
-
-EOF
-if { (eval echo $progname:2617: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
-  lt_cv_dlopen_self_static=yes
-else
-  echo "$progname: failed program was:" >&5
-  cat conftest.$ac_ext >&5
-  rm -fr conftest*
-  lt_cv_dlopen_self_static=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6
-fi
-    ;;
-  esac
-
-  case "$lt_cv_dlopen_self" in
-  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
-  *) enable_dlopen_self=unknown ;;
-  esac
-
-  case "$lt_cv_dlopen_self_static" in
-  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
-  *) enable_dlopen_self_static=unknown ;;
-  esac
-fi
-
-# Copy echo and quote the copy, instead of the original, because it is
-# used later.
-ltecho="$echo"
-if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then
-   ltecho="$CONFIG_SHELL \$0 --fallback-echo"
-fi
-LTSHELL="$SHELL"
-
-LTCONFIG_VERSION="$VERSION"
-
-# Only quote variables if we're using ltmain.sh.
-case "$ltmain" in
-*.sh)
-  # Now quote all the things that may contain metacharacters.
-  for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \
-    old_LD old_LDFLAGS old_LIBS \
-    old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \
-    AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \
-    reload_flag reload_cmds wl \
-    pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \
-    thread_safe_flag_spec whole_archive_flag_spec libname_spec \
-    library_names_spec soname_spec \
-    RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \
-    old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \
-    file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \
-    finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \
-    hardcode_libdir_flag_spec hardcode_libdir_separator  \
-    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
-    compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do
-
-    case "$var" in
-    reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \
-    old_postinstall_cmds | old_postuninstall_cmds | \
-    export_symbols_cmds | archive_cmds | archive_expsym_cmds | \
-    postinstall_cmds | postuninstall_cmds | \
-    finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
-      # Double-quote double-evaled strings.
-      eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
-      ;;
-    *)
-      eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
-      ;;
-    esac
-  done
-
-  case "$ltecho" in
-  *'\$0 --fallback-echo"')
-    ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'`
-    ;;
-  esac
-
-  trap "$rm \"$ofile\"; exit 1" 1 2 15
-  echo "creating $ofile"
-  $rm "$ofile"
-  cat <<EOF > "$ofile"
-#! $SHELL
-
-# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
-# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
-# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh.
-#
-# Copyright (C) 1996-1999 Free Software Foundation, Inc.
-# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
-#
-# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# Sed that helps us avoid accidentally triggering echo(1) options like -n.
-Xsed="sed -e s/^X//"
-
-# The HP-UX ksh and POSIX shell print the target directory to stdout
-# if CDPATH is set.
-if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
-
-### BEGIN LIBTOOL CONFIG
-EOF
-  cfgfile="$ofile"
-  ;;
-
-*)
-  # Double-quote the variables that need it (for aesthetics).
-  for var in old_CC old_CFLAGS old_CPPFLAGS \
-    old_LD old_LDFLAGS old_LIBS \
-    old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do
-    eval "$var=\\\"\$var\\\""
-  done
-
-  # Just create a config file.
-  cfgfile="$ofile.cfg"
-  trap "$rm \"$cfgfile\"; exit 1" 1 2 15
-  echo "creating $cfgfile"
-  $rm "$cfgfile"
-  cat <<EOF > "$cfgfile"
-# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file.
-# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
-EOF
-  ;;
-esac
-
-cat <<EOF >> "$cfgfile"
-# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-#
-# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\
-# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\
-# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\
-# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\
-#   $0$ltconfig_args
-#
-# Compiler and other test output produced by $progname, useful for
-# debugging $progname, is in ./config.log if it exists.
-
-# The version of $progname that generated this script.
-LTCONFIG_VERSION=$LTCONFIG_VERSION
-
-# Shell to use when invoking shell scripts.
-SHELL=$LTSHELL
-
-# Whether or not to build shared libraries.
-build_libtool_libs=$enable_shared
-
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
-# Whether or not to optimize for fast installation.
-fast_install=$enable_fast_install
-
-# The host system.
-host_alias=$host_alias
-host=$host
-
-# An echo program that does not interpret backslashes.
-echo=$ltecho
-
-# The archiver.
-AR=$AR
-
-# The default C compiler.
-CC=$CC
-
-# The linker used to build libraries.
-LD=$LD
-
-# Whether we need hard or soft links.
-LN_S=$LN_S
-
-# A BSD-compatible nm program.
-NM=$NM
-
-# Used on cygwin: DLL creation program.
-DLLTOOL="$DLLTOOL"
-
-# Used on cygwin: object dumper.
-OBJDUMP="$OBJDUMP"
-
-# Used on cygwin: assembler.
-AS="$AS"
-
-# The name of the directory that contains temporary libtool files.
-objdir=$objdir
-
-# How to create reloadable object files.
-reload_flag=$reload_flag
-reload_cmds=$reload_cmds
-
-# How to pass a linker flag through the compiler.
-wl=$wl
-
-# Object file suffix (normally "o").
-objext="$objext"
-
-# Old archive suffix (normally "a").
-libext="$libext"
-
-# Executable file suffix (normally "").
-exeext="$exeext"
-
-# Additional compiler flags for building library objects.
-pic_flag=$pic_flag
-
-# Does compiler simultaneously support -c and -o options?
-compiler_c_o=$compiler_c_o
-
-# Can we write directly to a .lo ?
-compiler_o_lo=$compiler_o_lo
-
-# Must we lock files when doing compilation ?
-need_locks=$need_locks
-
-# Do we need the lib prefix for modules?
-need_lib_prefix=$need_lib_prefix
-
-# Do we need a version for libraries?
-need_version=$need_version
-
-# Whether dlopen is supported.
-dlopen=$enable_dlopen
-
-# Whether dlopen of programs is supported.
-dlopen_self=$enable_dlopen_self
-
-# Whether dlopen of statically linked programs is supported.
-dlopen_self_static=$enable_dlopen_self_static
-
-# Compiler flag to prevent dynamic linking.
-link_static_flag=$link_static_flag
-
-# Compiler flag to turn off builtin functions.
-no_builtin_flag=$no_builtin_flag
-
-# Compiler flag to allow reflexive dlopens.
-export_dynamic_flag_spec=$export_dynamic_flag_spec
-
-# Compiler flag to generate shared objects directly from archives.
-whole_archive_flag_spec=$whole_archive_flag_spec
-
-# Compiler flag to generate thread-safe objects.
-thread_safe_flag_spec=$thread_safe_flag_spec
-
-# Library versioning type.
-version_type=$version_type
-
-# Format of library name prefix.
-libname_spec=$libname_spec
-
-# List of archive names.  First name is the real one, the rest are links.
-# The last name is the one that the linker finds with -lNAME.
-library_names_spec=$library_names_spec
-
-# The coded name of the library, if different from the real name.
-soname_spec=$soname_spec
-
-# Commands used to build and install an old-style archive.
-RANLIB=$RANLIB
-old_archive_cmds=$old_archive_cmds
-old_postinstall_cmds=$old_postinstall_cmds
-old_postuninstall_cmds=$old_postuninstall_cmds
-
-# Create an old-style archive from a shared archive.
-old_archive_from_new_cmds=$old_archive_from_new_cmds
-
-# Commands used to build and install a shared archive.
-archive_cmds=$archive_cmds
-archive_expsym_cmds=$archive_expsym_cmds
-postinstall_cmds=$postinstall_cmds
-postuninstall_cmds=$postuninstall_cmds
-
-# Method to check whether dependent libraries are shared objects.
-deplibs_check_method=$deplibs_check_method
-
-# Command to use when deplibs_check_method == file_magic.
-file_magic_cmd=$file_magic_cmd
-
-# Flag that allows shared libraries with undefined symbols to be built.
-allow_undefined_flag=$allow_undefined_flag
-
-# Flag that forces no undefined symbols.
-no_undefined_flag=$no_undefined_flag
-
-# Commands used to finish a libtool library installation in a directory.
-finish_cmds=$finish_cmds
-
-# Same as above, but a single script fragment to be evaled but not shown.
-finish_eval=$finish_eval
-
-# Take the output of nm and produce a listing of raw symbols and C names.
-global_symbol_pipe=$global_symbol_pipe
-
-# Transform the output of nm in a proper C declaration
-global_symbol_to_cdecl=$global_symbol_to_cdecl
-
-# This is the shared library runtime path variable.
-runpath_var=$runpath_var
-
-# This is the shared library path variable.
-shlibpath_var=$shlibpath_var
-
-# Is shlibpath searched before the hard-coded library search path?
-shlibpath_overrides_runpath=$shlibpath_overrides_runpath
-
-# How to hardcode a shared library path into an executable.
-hardcode_action=$hardcode_action
-
-# Flag to hardcode \$libdir into a binary during linking.
-# This must work even if \$libdir does not exist.
-hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec
-
-# Whether we need a single -rpath flag with a separated argument.
-hardcode_libdir_separator=$hardcode_libdir_separator
-
-# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
-# resulting binary.
-hardcode_direct=$hardcode_direct
-
-# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
-# resulting binary.
-hardcode_minus_L=$hardcode_minus_L
-
-# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
-# the resulting binary.
-hardcode_shlibpath_var=$hardcode_shlibpath_var
-
-# Compile-time system search path for libraries
-sys_lib_search_path_spec=$sys_lib_search_path_spec
-
-# Run-time system search path for libraries
-sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec
-
-# Fix the shell variable \$srcfile for the compiler.
-fix_srcfile_path="$fix_srcfile_path"
-
-# Set to yes if exported symbols are required.
-always_export_symbols=$always_export_symbols
-
-# The commands to list exported symbols.
-export_symbols_cmds=$export_symbols_cmds
-
-# Symbols that should not be listed in the preloaded symbols.
-exclude_expsyms=$exclude_expsyms
-
-# Symbols that must always be exported.
-include_expsyms=$include_expsyms
-
-EOF
-
-case "$ltmain" in
-*.sh)
-  echo '### END LIBTOOL CONFIG' >> "$ofile"
-  echo >> "$ofile"
-  case "$host_os" in
-  aix3*)
-    cat <<\EOF >> "$ofile"
-
-# AIX sometimes has problems with the GCC collect2 program.  For some
-# reason, if we set the COLLECT_NAMES environment variable, the problems
-# vanish in a puff of smoke.
-if test "X${COLLECT_NAMES+set}" != Xset; then
-  COLLECT_NAMES=
-  export COLLECT_NAMES
-fi
-EOF
-    ;;
-  esac
-
-  # Append the ltmain.sh script.
-  sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1)
-  # We use sed instead of cat because bash on DJGPP gets confused if
-  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
-  # text mode, it properly converts lines to CR/LF.  This bash problem
-  # is reportedly fixed, but why not run on old versions too?
-
-  chmod +x "$ofile"
-  ;;
-
-*)
-  # Compile the libtool program.
-  echo "FIXME: would compile $ltmain"
-  ;;
-esac
-
-test -n "$cache_file" || exit 0
-
-# AC_CACHE_SAVE
-trap '' 1 2 15
-cat > confcache <<\EOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs.  It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
-#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already.  You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
-#
-EOF
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
-  case `(ac_space=' '; set | grep ac_space) 2>&1` in
-  *ac_space=\ *)
-    # `set' does not quote correctly, so add quotes (double-quote substitution
-    # turns \\\\ into \\, and sed turns \\ into \).
-    sed -n \
-      -e "s/'/'\\\\''/g" \
-      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
-    ;;
-  *)
-    # `set' quotes correctly as required by POSIX, so do not add quotes.
-    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
-    ;;
-  esac >> confcache
-if cmp -s $cache_file confcache; then
-  :
-else
-  if test -w $cache_file; then
-    echo "updating cache $cache_file"
-    cat confcache > $cache_file
-  else
-    echo "not updating unwritable cache $cache_file"
-  fi
-fi
-rm -f confcache
-
-exit 0
-
-# Local Variables:
-# mode:shell-script
-# sh-indentation:2
-# End:
index bd77498..258acc1 100644 (file)
@@ -23,7 +23,7 @@ radclient - send packets to a RADIUS server, show reply
 .RB [ \-t
 .IR timeout ]
 .RB [ \-qvx ]
-\fIserver {acct|auth|status|disconnect} secret\fP
+\fIserver {acct|auth|status|disconnect|auto} secret\fP
 .SH DESCRIPTION
 \fBradclient\fP is a radius client program. It can send arbitrary radius
 packets to a radius server, then shows the reply. It can be used to
@@ -92,7 +92,21 @@ accounting packets, and \fBradius\fP for all other requests. If a
 service is not found in \fI/etc/services\fP, 1813 and 1812 are used
 respectively.
 
-.IP acct\ |\ auth\ |\ status\ |\ disconnect
+The RADIUS attributes read by \fIradclient\fP can contain the special
+attribute \fBPacket-Dst-IP-Address\fP.  If this attribute exists, then
+that IP address is where the packet is sent, and the \fBserver\fP
+specified on the command-line is ignored.
+
+If the RADIUS attribute list always contains the
+\fBPacket-Dst-IP-Address\fP attribute, then the \fBserver\fP parameter
+can be given as \fB-\fP.
+
+The RADIUS attributes read by \fIradclient\fP can contain the special
+attribute \fBPacket-Dst-Port\fP.  If this attribute exists, then that
+UDP port is where the packet is sent, and the \fB:port\fP specified
+on the command-line is ignored.
+
+.IP acct\ |\ auth\ |\ status\ |\ disconnect\ |\ auto
 Use \fBauth\fP to send an authentication packet (Access-Request),
 \fBacct\fP to send an accounting packet (Accounting-Request),
 \fBstatus\fP to send an status packet (Status-Server), or
@@ -100,6 +114,15 @@ Use \fBauth\fP to send an authentication packet (Access-Request),
 values, you can also use a decimal code here. For example, code 12 is
 also \fBStatus-Server\fP.
 
+The RADIUS attributes read by \fIradclient\fP can contain the special
+attribute \fBPacket-Type\fP.  If this attribute exists, then that type
+of packet is sent, and the \fItype\fP specified on the command-line
+is ignored.
+
+If the RADIUS attribute list always contains the
+\fBPacket-Type\fP attribute, then the \fBtype\fP parameter can be
+given as \fBauto\fP.
+
 .IP secret
 The shared secret for this client.  It needs to be defined on the
 radius server side too, for the IP address you are sending the radius
index bbb7db5..ed75468 100644 (file)
@@ -1,63 +1,98 @@
-.TH RADWHO 1 "23 February 2001" "" "FreeRADIUS Daemon"
+.TH RADWHO 1 "7 April 2005" "" "FreeRADIUS Daemon"
 .SH NAME
 radwho - show online users
 .SH SYNOPSIS
 .B radwho
+.RB [ \-c ]
 .RB [ \-d
 .IR raddb_directory ]
-.RB [ \-l ]
-.RB [ \-h ]
 .RB [ \-f ]
-.RB [ \-n ]
-.RB [ \-s ]
 .RB [ \-i ]
+.RB [ \-n ]
+.RB [ \-N
+.IR nas_ip_address ]
 .RB [ \-p ]
-.RB [ \-c ]
+.RB [ \-P
+.IR nas_port ]
 .RB [ \-r ]
+.RB [ \-R ]
+.RB [ \-s ]
+.RB [ \-S ]
+.RB [ \-u
+.IR user ]
+.RB [ \-U
+.IR user ]
+.RB [ \-Z ]
 .SH DESCRIPTION
 The FreeRADIUS server can be configured to maintain an active session
 database in a file called \fIradutmp\fP. This utility shows the
 content of that session database.
 .SH OPTIONS
+.IP \-c
+Shows caller ID (if available) instead of the full name.
 .IP \-d\ \fIraddb_directory\fP
 The directory that contains the RADIUS configuration files. Defaults to
 \fI/etc/raddb\fP.
-.IP \-l
-Show local shell users too. In this case, \fBradwho\fP reads the
-local "session database" aka the systems \fIutmp\fP file as well
-and shows the contents of that file before the contents of the
-radius "session database" aka the \fIradutmp\fP file, in the
-same format.
-.IP \-h
-Hide shell users. Doesn't show the entries for users that do not
-have a SLIP or PPP session.
 .IP \-f
 Behave as the 'fingerd' daemon - waits for one line of input, then
 prints the output with lines \\r\\n terminated.
+.IP \-i
+Shows the session ID instead of the full name.
 .IP \-n
 Normally radwho looks up the username in the systems password file,
 and shows the full username as well. The \fB-n\fP flags prevents this.
-.IP \-s
-Show full name.
-.IP \-i
-Shows the session ID instead of the full name.
+.IP \-N\ \fInas_ip_address\fP
+Show only those entries which match the given NAS IP address.
 .IP \-p
 Adds an extra column for the port type - I for ISDN, A for Analog.
-.IP \-c
-Shows caller ID (if available) instead of the full name.
+.IP \-P\ \fInas_port\fP
+Show only those entries which match the given NAS port.
 .IP \-r
 Outputs all data in \fIraw\fP format - no headers, no formatting,
-fields are comma-seperated.
+fields are comma-separated.
+.IP \-R
+Output all data in RADIUS attribute format.  All fields are printed.
+.IP \-s
+Show full name.
+.IP \-S
+Hide shell users. Doesn't show the entries for users that do not
+have a SLIP or PPP session.
+.IP \-u\ \fIuser\fP
+Show only those entries which match the given username (case insensitive).
+.IP \-U\ \fIuser\fP
+Show only those entries which match the given username (case sensitive).
+.IP \-Z
+When combined with \fI-R\fP, prints out the contents of an
+Accounting-Request packet which can be passed to \fIradclient\fP, in
+order to "zap" that users session from \fIradutmp\fP.
+.PP
+For example,
+.RS
+.sp
+.nf
+.ne 3
+$ radwho -ZRN 10.0.0.1 | radclient -f - radius.example.net acct testing123
+.fi
+.sp
+.RE
+will result in all an Accounting-Request packet being sent to the
+RADIUS server, which tells the server that the NAS rebooted.  i.e. It
+"zaps" all of the users on that NAS.
 
-.SH SEE ALSO
-radiusd(8).
-.SH AUTHOR
-Miquel van Smoorenburg, miquels@cistron.nl.
+To "zap" one user, specifiy NAS, username, and NAS port:
+.RS
+.sp
+.nf
+.ne 3
+$ radwho -ZRN 10.0.0.1 -u user -P 10 | radclient -f - radius.example.net acct testing123
+.fi
+.sp
+.RE
+Other combinations are also possible.
 
 .SH SEE ALSO
 radiusd(8),
-radiusd.conf(5),
-wtmp(5),
-last(1).
+radclient(1),
+radiusd.conf(5).
 .SH AUTHOR
 Miquel van Smoorenburg, miquels@cistron.nl.
index 3403cb0..a87bf60 100644 (file)
@@ -1,47 +1,62 @@
-.TH RADZAP 1 "16 May 2002" "" "FreeRadius Daemon"
+.TH RADZAP 1 "8 April 2005" "" "FreeRadius Daemon"
 .SH NAME
 radzap - remove rogue entries from the active sessions database
 .SH SYNOPSIS
 .B radzap
 .RB [ \-d
 .IR raddb_directory ]
-.RB [ \-r
-.IR radius_server ]
-.RB [ \-p
-.IR accounting_port ]
-.RB [ \-v ]
-.I nas
-.RB [ port ]
-.RB [ username ]
+.RB [ \-N
+.IR nas_ip_address ]
+.RB [ \-P
+.IR nas_port ]
+.RB [ \-u
+.IR user ]
+.RB [ \-U
+.IR user ]
+\fIserver[:port] secret\fP
 .SH DESCRIPTION
 The FreeRadius server can be configured to maintain an active session
 database in a file called \fIradutmp\fP. Commands like \fBradwho\fP(1)
 use this database. Sometimes that database can get out of sync, and
 then it might contain rogue entries. \fBradzap\fP can clean up this
 database.
+
+As of FreeRADIUS 1.1.0, \fBradzap\fP is a simple shell-script wrapper
+around \fBradwho\fP(1) and \fBradclient\fP(1).
+
+The sessions are "zapped" by sending an Accounting-Request packet
+which contains the information necessary for the server to delete the
+session record.  \fBradzap\fP sends a packet to the server, rather
+than writing to \fIradutmp\fP directly, because session records may
+also be maintained in SQL.
 .SH OPTIONS
 .IP \-d\ \fIraddb_directory\fP
 The directory that contains the RADIUS configuration files.
-.IP \-r\ \fIradius_server\fP
-Host name or IP address of the RADIUS server.
-.IP \-p\ \fIaccounting_port\fP
-The port to which accounting packets are sent.  See "/etc/services",
-port "radacct" for the default on your system (usually 1646 or 1813).
-.IP \-v
-Verbose. Shows you what it is doing.
-.IP nas
-Hostname or IP address of the NAS (Network Access Server, sometimes
-called "terminal server") of the session you want to remove.
-.IP port
-Port of the session you want to remove. This is the NAS-Port
-radius attribute, it doesn't have anything to do with UDP port
-numbers. Must be an integer. \fB-1\fP means "any", and is the
-default if this option is not specified.
-.IP username
-Optional: the username of the session you want to remove.
+\fBradzap\fP reads \fIradiusd.conf\fP to determine the location of the
+\fIradutmp\fP file.
+.IP \-N\ \fInas_ip_address\fP
+Zap the entries which match the given NAS IP address.
+.IP \-P\ \fInas_port\fP
+Zap the entries which match the given NAS port.
+.IP \-u\ \fIuser\fP
+Zap the entries which match the given username (case insensitive).
+.IP \-U\ \fIuser\fP
+Zap the entries which match the given username (case sensitive).
+.IP server[:port]
+The hostname or IP address of the remote server. Optionally a UDP port
+can be specified. If no UDP port is specified, it is looked up in
+\fI/etc/services\fP. The service name looked for is \fBradacct\fP for
+accounting packets, and \fBradius\fP for all other requests. If a
+service is not found in \fI/etc/services\fP, 1813 and 1812 are used
+respectively.
+.IP secret
+The shared secret for this client.  It needs to be defined on the
+radius server side too, for the IP address you are sending the radius
+packets from.
 .SH SEE ALSO
 radwho(1),
+radclient(1),
 radiusd(8),
 radiusd.conf(5).
 .SH AUTHOR
-Miquel van Smoorenburg, miquels@cistron.nl., and others.
+Alan DeKok <aland@ox.org>
index c186e6e..fdaf1df 100644 (file)
@@ -1,31 +1,9 @@
-.TH CLIENTS 5 "16 March 2001"
+.TH CLIENTS 5 "22 August 2002"
 .SH NAME
-clients \- RADIUS clients file
+clients \- FreeRADIUS configuration file.
 .SH DESCRIPTION
-The \fIclients\fP file resides in the radius database directory,
-by default \fI/etc/raddb\fP. Its use is depreciated in favour of 
-\fIclients.conf\fP.
-
-Every line starting with a hash sign
-.RB (' # ')
-is treated as comment and ignored.
-.PP
-Each line of the file contains two white-space delimited fields.
-.IP client\ hostname
-The RADIUS clients hostname.  This may be a plain hostname, or a
-dotted-quad IP address.
-.IP secret
-This is the so-called "shared secret" that is held between a RADIUS
-server and client. It is used to encrypt passwords in RADIUS packets,
-and also for authentication. You need to configure the same secret
-on the client (terminal server) as in this file.
-.PP
-The
-.I clients
-file is read by \fBradiusd\fP on startup only.
-.SH FILES
-.I /etc/raddb/clients
+This configuration file is no longer used by the server, and will not
+be read by the server. See the "scripts/clients.pl" program for a way
+to migrate this file to the new format.
 .SH "SEE ALSO"
-.BR radiusd (8),
 .BR clients.conf (5)
-.BR naslist (5)
diff --git a/man/man5/clients.conf.5 b/man/man5/clients.conf.5
new file mode 100644 (file)
index 0000000..428646b
--- /dev/null
@@ -0,0 +1,113 @@
+.TH clients.conf 5 "13 June 2005" "" "FreeRADIUS client configuration"
+.SH NAME
+clients.conf \- FreeRADIUS client configuration
+.SH DESCRIPTION
+The 
+.I clients.conf
+file contains definitions of RADIUS clients.
+.PP
+The information in this file overrides any information provided in
+the deprecated 
+.BR clients (5)
+and 
+.BR naslist (5)
+files.
+.PP
+The file format is the same as that used for
+.I radiusd.conf.
+See 
+.BR radiusd.conf (5)
+for more details.
+.PP
+Each RADIUS client entry has the following basic form:
+.IP
+.nf
+client <hostname|ip-address|ip-network> {
+       <attribute> = <value>
+ }
+.fi
+.LP
+ip-network is used to specify a network of clients. Networks are
+specified in CIDR notation. If multiple overlapping networks are
+defined, the best match (smallest possible network) will be chosen for
+a packet.
+.SH ATTRIBUTES
+The attributes that can appear in a 
+.B client
+section are listed below. Required attributes are labelled as
+such. All other attributes are optional.
+.PP
+.TP 0.5i
+.B secret [Required]
+The RADIUS shared secret used for communication between the client/NAS
+and the RADIUS server.
+.TP 0.5i
+.B shortname [Required]
+A short alias that can be used in place of the IP address or fully
+qualified hostname provided in the first line of the section.
+.TP 0.5i
+.B nastype
+The nastype attribute is used to tell the 
+.BR checkrad.pl
+script which NAS-specific method it should use when checking
+simultaneous use.
+
+The following values are currently recognized:
+.nf
+cisco
+computone
+livingston
+max40xx
+multitech
+netserver
+pathras
+patton
+portslave
+tc
+usrhiper
+other
+.fi
+.TP 0.5i
+.B login
+Reserved for future use.
+.TP 0.5i
+.B password
+Reserved for future use.
+.SH EXAMPLES
+.IP
+.nf
+client 127.0.0.1 {
+        secret          = testing123
+        shortname       = localhost
+        nastype         = other     
+}
+.fi
+.LP
+This adds a client for the loopback address. This is useful in testing
+the 
+server locally, for example with 
+.BR radclient (1).
+.IP
+.nf
+client 192.168.0.0/24 {
+       secret          = testing123-1
+       shortname       = private-network-1
+}
+.fi
+.LP
+This entry represents any client from the 192.168.0.0/24 network. 
+.SH FILES
+.I /etc/raddb/clients.conf
+
+.I /etc/raddb/radiusd.conf
+.SH "SEE ALSO"
+.BR radiusd (8),
+.BR radiusd.conf (5),
+.BR clients (5),
+.BR naslist (5)
+
+.SH AUTHOR
+This manual page was authored by Shawn K. O'Shea <shawn@eth0.net>.
+
+FreeRADIUS is authored by the FreeRADIUS team. 
+http://freeradius.org/
index a88e633..893d199 100644 (file)
@@ -1,30 +1,11 @@
-.TH NASLIST 5 "15 September 1997"
+.TH NASLIST 5 "12 August 2005"
 .SH NAME
 naslist \- RADIUS naslist file
 .SH DESCRIPTION
-The \fInaslist\fP file resides in the radius database directory,
-by default \fI/etc/raddb\fP. It contains a list of RADIUS network access
-servers (NASes).
-Every line starting with a hash sign
-.RB (' # ')
-is treated as comment and ignored.
-.PP
-Each line of the file contains three white-space delimited fields.
-.IP client\ hostname
-The NAS hostname. This may be a plain hostname, or a
-dotted-quad IP address.
-.IP shortname
-This field is optional, and declares a short alias for the NAS.
-.IP NAStype
-Type of NAS (terminalserver). This can be \fIlivingston\fP, \fIcisco\fP,
-\fIportslave\fP or \fIother\fP. This is passed to the external \fBchecklogin\fP
-program when it is called to detect double logins.
-.PP
-The
-.I naslist
-file is read by \fBradiusd\fP on startup only.
-.SH FILES
-.I /etc/raddb/naslist
+naslist \- FreeRADIUS configuration file.
+.SH DESCRIPTION
+This configuration file is no longer used by the server, and will not
+be read by the server. See the "scripts/clients.pl" program for a way
+to migrate this file to the new format.
 .SH "SEE ALSO"
-.BR radiusd (8),
-.BR clients (5)
+.BR clients.conf (5)
diff --git a/man/man5/radrelay.conf.5 b/man/man5/radrelay.conf.5
new file mode 100644 (file)
index 0000000..9dc12bd
--- /dev/null
@@ -0,0 +1,134 @@
+.TH radrelay.conf 5 "27 May 2005" "" "FreeRADIUS configuration file"
+.SH NAME
+radrelay.conf \- configuration file for the FreeRADIUS server "radrelay" personality
+.SH DESCRIPTION
+The \fBradrelay.conf\fP file resides in the radius database directory,
+by default \fB/etc/raddb\fP.  It defines the global configuration for
+the FreeRADIUS server, when the server is operating as "radrelay".
+.SH "FILE FORMAT"
+For a detailed description of the file format, see "man radiusd.conf".
+The configuration entries are much the same for radrelay.conf, with a
+few differences as noted here.
+.SH "REPLICATION FOR BACKUPS"
+Many sites run multiple radius servers; at least one primary and one
+backup server. When the primary goes down, most NASes detect that and
+switch to the backup server.
+
+That will cause your accounting packets to go the the backup server -
+and some NASes don't even switch back to the primary server when it
+comes back up.
+
+The result is that accounting records are missed, and/or the
+administrator must jump through hoops in order to combine the
+different detail files from multiple servers. It also means that the
+session database ("radutmp", used for radwho and simultaneous use
+detection) gets out of sync.
+
+radrelay solves this issue by "relaying" packets from one server to
+another, so they both have the same set of accounting data.
+.SH "BUFFERING FOR HIGH-LOAD SERVERS"
+If the RADIUS server suddenly receives a many accounting packets,
+there may be insufficient CPU power to process them all in a timely
+manner.  This problem is especially noticable when the accounting
+packets are going to a back-end database.
+
+Similarly, you may have one database that tracks "live" sessions, and
+another that tracks historical accounting data.  In that case,
+accessing the first database is fast, as it is small.  Accessing the
+second database many be slower, as it may contain multiple gigabytes
+of data.  In addition, writing to the first database in a timely
+manner is important, while data may be written to the second database
+with a few minutes delay, without any harm being done.
+.SH "RELAYING OF ACCOUNTING PACKETS"
+The \fBradrelay.conf\fP file controls the "radrelay" personality of
+the server, which can perform both of the functions above at the same
+time.
+.SH USAGE
+First, you should configure the main radius server to log to an extra,
+single detail file.  This may be done by adding an extra instance of
+the detail module to \fBradiusd.conf\fP:
+
+For example:
+
+.DS
+       detail radrelay-detail {
+.br
+               detailfile = ${radacctdir}/radrelay/detail
+.br
+               detailperm = 0600
+.br
+               dirperm = 0755
+.br
+               locking = yes
+.br
+       }
+.br
+       ...
+.br
+       accounting {
+.br
+               ...
+.br
+               radrelay-detail
+.br
+               ...
+.br
+       }
+.br
+.DE
+This configuration will cause accounting packets to be logged to the
+\fI${radacctdir}/radrelay/detail\fP file.  This file should not be
+rotated by standard log rotation scripts, as the \fBradrelay\fP
+program will read and rotate it.
+.SH RADRELAY.CONF EXAMPLE
+See the \fBradrelay.conf\fP file for detailed instructions on
+configuration entries, what they mean, and how to use them.
+
+To have the "radrelay" portion of the server read the above detail
+file, configure \fBradrelay.conf\fP with the following section:
+
+.DS
+.br
+       listen {
+.br
+               type = detail
+.br
+               detail = ${radacctdir}/radrelay/detail
+.br
+               max_outstanding = 100
+.br
+               identity = radrelay
+.br
+       }
+.br
+.DE
+
+The server will read the accounting packets from the detail file, and
+process them just as if it had received them from the NAS.  Therefore,
+you should configure the "accounting" section of \fBradrelay.conf\fP
+to write the accounting records to an "sql" module, or to proxy them
+to another RADIUS server.
+
+Then, start the server via the following command:
+
+$ radiusd -n radrelay
+
+The server should start up, read the detail file, and process
+accounting packets from it.
+.SH NOTES
+The \fBradiusd.conf\fP file is not read at all when the server is
+running as radrelay.  Please edit \fBradrelay.conf\fP.
+.SH CREDITS
+The original "radrelay" program was written by Miquel van Smoorenburg
+for the Cistron radius project, and ported to FreeRADIUS by Simon
+Ekstrand.  The "radsqlrelay" was written by Kostas Kalavras.  It was
+never released as part of an offical FreeRADIUS release, but served as
+a basis for the design of this implementation.
+.PP
+.SH FILES
+/etc/raddb/radrelay.conf
+.SH "SEE ALSO"
+.BR radiusd (8),
+.BR radiusd.conf (5)
+.SH AUTHOR
+Alan DeKok <aland@ox.org>
index 0db2cc2..6f79c07 100644 (file)
@@ -3,23 +3,24 @@
 rlm_attr_filter \- FreeRADIUS Module
 .SH DESCRIPTION
 The \fIrlm_attr_filter\fP module exists for filtering certain
-attributes and values in received ( or transmitted ) radius packets
-from ( or to ) remote proxy servers.  It gives the proxier ( us ) a
-flexible framework to filter the attributes we send to or receive
-from these remote proxies.  This makes sense, for example, in an
-out-sourced dialup situation to various policy decisions, such as
-restricting a client to certain ranges of Idle-Timeout or
-Session-Timeout.
+attributes and values in received ( or transmitted ) radius packets.
+It gives the server a flexible framework to filter the attributes we
+send to or receive from home servers or NASes.  This makes sense, for
+example, in an out-sourced dialup situation to various policy
+decisions, such as restricting a client to certain ranges of
+Idle-Timeout or Session-Timeout.
 .PP
-Filter rules are defined and applied on a per-realm basis, where the
-realm is anything that is defined and matched based on the
-configuration of the \fIrlm_realm\fP module.
+Filter rules are normally defined and applied on a per-realm basis,
+where the realm is anything that is defined and matched based on the
+configuration of the \fIrlm_realm\fP module.  Filter rules can
+optionally be applied using another attribute, by editing the
+\fIkey\fP configuration for this module.
 .PP
 The file that defines the attribute filtering rules follows a similar
 syntax to the \fIusers\fP file.  There are a few differences however:
 .PP
 .DS
-    There are no check-items allowed other than the realm.
+    There are no check-items allowed other than the name of the key.
 .PP
     There can only be a single DEFAULT entry.
 .PP
@@ -58,7 +59,7 @@ Greater Than or Equal
 Less Than or Equal
 .TP
 .B    >   
-Greather Than
+Greater Than
 .TP
 .B    <   
 Less Than
@@ -79,15 +80,22 @@ See the default \fI/etc/raddb/attrs\fP for working examples of
 sample rule ordering and how to use the different operators.
 .DE
 .PP
-The main configuration item is:
+The configuration items are:
 .IP attrsfile
 This specifies the location of the file used to load the filter rules.
+This file is used to filter the accounting response, packet before it
+is proxied, proxy response from the home server, or our response to
+the NAS.
+.IP key
+Usually %{Realm} (the default).  Can also be %{User-Name}, or other
+attribute that exists in the request.  Note that the module always
+keys off of attributes in the request, and NOT in any other packet.
 .PP
 .SH SECTIONS
-.BR authorization,
 .BR accounting,
-.BR preproxy,
-.BR postproxy
+.BR pre-proxy,
+.BR post-proxy,
+.BR post-auth
 .PP
 .SH FILES
 .I /etc/raddb/radiusd.conf
index f6274f8..2936b05 100644 (file)
@@ -44,6 +44,10 @@ syntax in the Users file to set a cap of 3600 seconds ( 8 hours ):
 DEFAULT Max-Daily-Session := 3600
 .DE
 .PP
+.IP reply-name
+This is the name of the attribute which will contain the remaining value for
+the counter in the reply packet when the user is successfully authorized. The
+default attribute name is "Session-Timeout".
 .IP allowed-servicetype
 This can be used to only apply the limitations to specific service types of
 sessions.  For example, setting this to Framed-User will only apply the counter
diff --git a/man/man5/rlm_digest.5 b/man/man5/rlm_digest.5
new file mode 100644 (file)
index 0000000..af97ee8
--- /dev/null
@@ -0,0 +1,67 @@
+.TH rlm_digest 5 "31 March 2005" "" "FreeRADIUS Module"
+.SH NAME
+rlm_digest \- FreeRADIUS Module
+.SH DESCRIPTION
+The \fIrlm_digest\fP module authenticates RADIUS Access-Request
+packets that contain Cisco SIP digest authentication attributes.  The
+module should be listed in the \fIauthorize\fP and \fIauthenticate\fP
+sections of \fIradiusd.conf\fP.
+.SH CONFIGURATION
+The digest module requires no additional configuration items.  When it
+is being used to authenticate requests, however, it does require
+access to the clear-text password for the user.  Hashed passwords are
+not acceptable, and will not work.
+.SH EXAMPLES
+Add the following lines to the top of your 'raddb/users' file:
+.PP
+.DS
+#---
+.br
+test   Auth-Type := Digest, User-Password = "test"
+.br
+       Reply-Message = "Hello, test with digest"
+.br
+#---
+.DE
+
+Once the server has been started (debugging mode is recommended),
+use '\fIradclient\fP to send the following packet to the server:
+.PP
+.DS
+$  radclient -f digest localhost auth testing123
+.DE
+
+Where 'digest' is a file containing:
+.PP
+.DS
+  User-Name = "test",
+.br
+  Digest-Response = "631d6d73147add2f9e437f59bbc3aeb7",
+.br
+  Digest-Realm = "testrealm",
+.br
+  Digest-Nonce = "1234abcd",
+.br
+  Digest-Method = "INVITE",
+.br
+  Digest-URI = "sip:5555551212@example.com",
+.br
+  Digest-Algorithm = "MD5",
+.br
+  Digest-User-Name = "test",
+.br
+  Message-Authenticator = ""
+.DE
+
+You should see the authentication succeed.
+
+.SH SECTIONS
+.BR authorize,
+.BR authenticate
+.PP
+.SH FILES
+.I /etc/raddb/radiusd.conf,
+.I draft-sterman-aaa-sip-00.txt
+.PP
+.SH AUTHOR
+Alan DeKok <aland@ox.org>
index 70d5cb5..65ea8e1 100644 (file)
@@ -21,6 +21,24 @@ pre_proxy stage of this module.
 This option allows FreeRADIUS to parse an old style Cistron syntax.
 The default is 'no'.  If you need to parse an old style Cistron
 file, set this option to 'cistron'.
+.IP key
+This option lets you set the attribute to use as a key to find
+entries.  The default is "%{Stripped-User-Name:-%{User-Name}}".  Note
+that the key MUST supply real data.  Dynamic attributes like "Group"
+will not work, because the "Group" attribute can only be used as a
+comparison, to see if a user is in a Unix group.  It will not return
+the name of the Unix group that a user is in.
+.PP
+If you want to use groups as a key, see the \fIrlm_passed\fP, which
+will create a real attribute that contains the group name.
+.PP
+This configuration entry enables you to have configurations that
+perform per-group checks, and return per-group attributes, where the
+group membership is dynamically defined by a previous module.  It also
+lets you do things like key off of attributes in the reply, and
+express policies like like "when I send replies containing attribute
+FOO with value BAR, do more checks, and maybe send additional
+attributes".
 .SH CONFIGURATION
 .PP
 .DS
@@ -37,6 +55,8 @@ modules {
 .br
     compat = no
 .br
+    key = %{Stripped-User-Name:-%{User-Name}}
+.br
   }
 .br
   ... stuff here ...
index 9e8572b..2aedda1 100644 (file)
@@ -1,29 +1,32 @@
-.TH rlm_mschap 5 "19 May 2006" "" "FreeRADIUS Module"
+.TH rlm_mschap 5 "13 March 2004" "" "FreeRADIUS Module"
 .SH NAME
 rlm_mschap \- FreeRADIUS Module
 .SH DESCRIPTION
 The \fIrlm_mschap\fP module provides MS-CHAP and MS-CHAPv2
 authentication support. 
 .PP
-This module validates a user with MS-CHAP or MS-CHAPv2 authentication.
-It should be listed in both the \fIauthorize\fP and \fIauthenticate\fP
-sections.  In \fIauthorize\fP, it will look for MS-CHAP
-Challenge/Response attributes in the Acess-Request, and configure
-itself to be the module called for the \fIauthenticate\fP section.
+This module validates a user with MS-CHAP or MS-CHAPv2 
+authentication.
+If called in Authorize, it will look for MS-CHAP Challenge/Response
+attributes in the Acess-Request and adds an Auth-Type
+attribute set to MS-CHAP in the Config-Items list unless 
+Auth-Type has already set.
 .PP
 The module can authenticate the MS-CHAP session via plain-text
 passwords (User-Password attribute), or NT passwords (NT-Password
-attribute).  The module can perform authentication against an NT
-domain by using the \fIntlm_auth\fP program.
-.SH SMB Integration
+attribute).  The module cannot perform authentication against an NT
+domain.
+.PP
 The module also enforces the SMB-Account-Ctrl attribute.  See the
 Samba documentation for the meaning of SMB account control.  The
-module does not read Samba password files.  Instead, the
-\fIrlm_passwd\fP module should be used to read a Samba password file,
-and to supply an NT-Password attribute which this module can use.  See
-the \fIetc_smbpasswd\fP module in \fIradiusd.conf\fP for more details.
-.SH MODULE CONFIGURATION
+module does not read Samba password files.  Instead, the fIrlm_passwd\fP
+module can be used to read a Samba password file, and supply an
+NT-Password attribute which this module can use.
+.PP
 The main configuration items to be aware of are:
+.IP authtype
+This is the string used to set the authtype.  Normally it should be
+left to the default value of MS-CHAP.
 .IP use_mppe
 Unless this is set to 'no', FreeRADIUS will add MS-CHAP-MPPE-Keys for
 MS-CHAPv1 and MS-MPPE-Recv-Key/MS-MPPE-Send-Key for MS-CHAPv2.  The
@@ -40,20 +43,45 @@ The default is 'no'.
 Windows clients send User-Name in the form of "DOMAIN\\User", but send the
 challenge/response based only on the User portion.  Setting this value
 to yes, enables a work-around for this error.  The default is 'no'.
-.IP ntlm_auth
-Use the \fIntlm_auth\fP program for authentication against Samba, or a
-Windows NT or Active Directory Domain Controller.  For machine
-authentication, the following configuration should be used:
-.DS
-ntlm_auth = "/path/to/ntlm_auth --username=%{mschap:User-Name:-None} --challenge=%{mschap:Challenge:-00} --nt-response=%{mschap:NT-Response:-00} --domain=%{mschap:NT-Domain:-YOUR_DEFAULT_DOMAIN}
-.DE
-If configured, \fIntlm_auth\fP will always be called, even if there is
-a clear-text or NT-Password available for the user.  You can force
-\fIntlm_auth\fP to not be used by setting
+.PP
+.SH CONFIGURATION
 .DS
-MS-CHAP-Use-NTLM-Auth := No
+modules {
+  ...
+.br
+  mschap {
+.br
+       authtype = MS-CHAP
+.br
+       use_mppe = yes  
+.br
+  }
+.br
+  ...
+.br
+}
+.br
+ ...
+.br
+authorize {
+  ...
+.br
+  mschap
+.br
+  ...
+.br
+}
+ ...
+.br
+authenticate {
+  ...
+.br
+  mschap
+.br
+  ...
+.br
+}
 .DE
-in the \fIusers\fP file, or in a database such as SQL.
 .PP
 .SH SECTIONS
 .BR authorization,
index b4dbfac..4223daa 100644 (file)
-.TH rlm_pap 5 "3 February 2004" "" "FreeRADIUS Module"
+.TH rlm_pap 5 "8 February 2005" "" "FreeRADIUS Module"
 .SH NAME
 rlm_pap \- FreeRADIUS Module
 .SH DESCRIPTION
-The \fIrlm_pap\fP module performs PAP authentication.
+The \fIrlm_pap\fP module authenticates RADIUS Access-Request packets
+that contain a User-Password attribute.  The module should also be
+listed last in the \fIauthorize\fP section, so that it can set the
+Auth-Type attribute as appropriate.
 .PP
-This module performs authentication when the Access-Request contains a
-User-Password attribute AND when a "known good" password has been
-configured for the user.  In addition, it takes care of decoding the
-"known good" password from hex or Base64 encoding to a form it can use
-for authentication.
+When a RADIUS packet contains a clear-text password in the form of a
+User-Password attribute, the \fIrlm_pap\fP module may be used for
+authentication.  The module requires a "known good" password, which it
+uses to validate the password given in the RADIUS packet.  That "known
+good" password must be supplied by another module
+(e.g. \fIrlm_files\fP, \fIrlm_ldap\fP, etc.), and is usually taken
+from a database.
+.SH CONFIGURATION
 .PP
-As a result, as of 1.1.4, the "encryption_scheme" configuration item
-SHOULD NOT BE USED, and the rlm_ldap configuration
-item "password_header" SHOULD NOT BE USED.  Those items will continue to work
-in 1.1.4, and existing systems will work un-changed after upgrading to
-1.1.4.  We recommend, though, that sites using multiple instances of
-rlm_pap see if they can replace those multiple instances with one instance,
-using the new "auto_header" configuration, and remove the "password_header"
-configuration from rlm_ldap.
-.PP
-The configuration item(s):
+The only relevant configuration item is:
 .IP auto_header
-Automatically discover password headers.  Permitted values are "yes"
-and "no".  For backwards compatibility, the default is "no".
-.IP
-The recommended value is "yes".
-.IP encryption_scheme
-No longer used, and therefore no longer documented.
+If set to "yes", the module will look inside of the User-Password
+attribute for the headers {crypt}, {clear}, etc., and will
+automatically create the appropriate attribute, with the correct
+value.
 .PP
-When "auto_header" is set to "yes", the module will look in the
-configuration list for the User-Password attribute or the new
-Password-With-Header attribute.  If found, it will then look at the
-string value of those attributes, for one of the following headers:
+This module understands many kinds of password hashing methods, as
+given by the following table.
 .PP
 .DS
-.br    
-       {clear}
 .br
-       {cleartext}
+Header       Attribute          Description
+.br
+------       ---------          -----------
+.br
+{clear}      User-Password      clear-text passwords
+.br
+{cleartext}  User-Password      clear-text passwords
 .br
-       {crypt}
+{crypt}      Crypt-Password     Unix-style "crypt"ed passwords
 .br
-       {md5}
+{md5}        MD5-Password       MD5 hashed passwords
 .br
-       {smd5}
+{smd5}       SMD5-Password      MD5 hashed passwords, with a salt
 .br
-       {sha1}
+{sha}        SHA-Password       SHA1 hashed passwords
 .br
-       {ssha1}
+{ssha}       SSHA-Password      SHA1 hashed passwords, with a salt
 .br
-       {nt}
+{nt}         NT-Password        Windows NT hashed passwords
 .br
-       {x-nthash}
+{x-nthash}   NT-Password        Windows NT hashed passwords
 .br
-       {ns-mta-md5}
+{lm}         LM-Password        Windows Lan Manager (LM) passwords.
 .DE
+
+The module tries to be flexible when handling the various password
+formats.  It will automatically handle Base-64 encoded data, hex
+strings, and binary data, and convert them to a format that the server
+can use.
 .PP
-The text following the header is taken as the "known good" password,
-either cleartext, crypted, hashed, or hashed with a salt.  If the text
-is hex or Base64 encoded, it will be decoded to obtain the correct
-form of the "known good" password.  The User-Password in the
-Access-Request will then be crypted, or hashed as appropriate, and
-compared to the "known good" password.  If they match, the user is
-authenticated, otherwise the module returns reject.
-.SH CAVEATS
-In order for the "auto_header = yes" functionality to work, the
-\fIpap\fP module MUST be listed LAST in the \fIauthorize\fP section of
-\fIradiusd.conf\fP.  This lets other modules such as LDAP blindly add
-a "known good" password to the configuration items, and the PAP module
-will just figure it out.  In most cases, multiple instances of the PAP
-module, along with complex logic to determine which one to call when,
-can be replaced with one instance of the module, with it listed last
-in the \fIauthorize\fP section.
-.PP
-Note that the \fIns_mta_md5\fP module is no longer necessary, and can
-be removed.
-.PP
-Also, setting "Auth-Type = Local" or "Auth-Type = Crypt-Local" is no
-longer necessary.  Any such settings SHOULD BE DELETED.  Simply list
-\fIpap\fP LAST in the \fIauthorize\fP section, and the module will
-take care of figuring out what to do.  (Have we emphasized that enough?)
-.PP
-Another reason to list the module last is that it will take care of
-normalizing any crypt'd or hashed password retrieved from a database.
-So it is now safe to have clear-text passwords as "{clear}...",
-because the PAP module will take care of removing the "{clear}" prefix
-from the password.  Any other modules that need access to the
-cleartext password will
-.PP
-The module uses a number of new attributes.
-.IP Password-With-Header
-This attribute should contain a "known good" password, with a header
-such as "{crypt}, or "{md5}", etc.  It should be used when the
-passwords retrieved from a DB may have different headers.  When
-\fIpap\fP is listed in the \fIauthorize\fP section, the module will
-examine this attribute, and use it to create one of the other
-attributes listed below.  That other attribute is then used for
-authentication.
-.IP
-If the passwords in a DB do not have a header, and are always in one
-particular form, then the attributes listed below can be used
-directly.  In that case, the PAP module will do hex or Base64 decoding
-of the attribute contents, if necessary.  So \fIpap\fP should still be
-listed in the \fIauthorize\fP section, because it will enable the
-maximum flexibility for the server, and minimize configuration for the
-administrator.
-.IP Cleartext-Password
-This attribute should contain the cleartext for a "known good"
-password.  Previously, the User-Password attribute was overloaded to
-contain this, both in the FAQ and in databases in many sites.  Any
-configuration that sets a cleartext form of the password using
-User-Password SHOULD UPDATE to using Cleartext-Password.  Doing so
-will simplify a number of debugging issues.
-.IP Crypt-Password
-This attribute has been around for a while, but is documented here for
-completeness.  It contains the crypt'd form of the password.
-.IP MD5-Password
-This attribute contains the MD5 hashed form of the password.
-.IP SMD5-Password
-This attribute contains the MD5 hashed form of the password, with a salt.
-.IP SHA1-Password
-This attribute contains the SHA1 hashed form of the password.
-.IP SSHA1-Password
-This attribute contains the SHA1 hashed form of the password, with a salt.
-.IP NT-Password
-This attribute has been around for a while, but is documented here for
-completeness.  It contains the NT hash form of the password, as used
-by Active Directory and Samba.
+For backwards compatibility, there are old configuration parameters
+which may be work, although we do not recommend using them.
 .SH SECTIONS
 .BR authorize
 .BR authenticate
@@ -139,3 +72,4 @@ by Active Directory and Samba.
 .BR radiusd.conf (5)
 .SH AUTHOR
 Alan DeKok <aland@freeradius.org>
+
index bdbd394..5f01538 100644 (file)
@@ -35,9 +35,6 @@ default) the module will warn about duplicated records.
 .IP ignorenislike
 If set to 'yes', then all records from the file beginning with the '+'
 sign will be ignored.  The default is 'no'.
-.IP authtype
-If an entry matches, the Auth-Type for the request will be set to the
-one specified here.
 .IP format
 The format of the fields in the file, given as an example line from
 the file, with the content of the fields as the RADIUS attributes
@@ -57,6 +54,11 @@ prefix the attribute name in the "format" string with the '~' character.
 .PP
 To add an attribute to the reply (to be sent back to the NAS) prefix
 the attribute name in the "format" string with the '=' character.
+.IP ignoreempty
+This configuration item defaults to "yes".  If there is no value for
+the attribute, then the attribute is not added.  By setting this value
+to "no", you can force the attribute to be added, even if there is no
+value.
 
 .SH EXAMPLES
 .DS
diff --git a/man/man5/rlm_policy.5 b/man/man5/rlm_policy.5
new file mode 100644 (file)
index 0000000..b664580
--- /dev/null
@@ -0,0 +1,204 @@
+.TH rlm_policy 5 "7 December 2004" "" "FreeRADIUS Module"
+.SH NAME
+rlm_policy \- FreeRADIUS Module
+.SH DESCRIPTION
+The \fBrlm_policy\fP module implements a simple "policy" language.
+.PP
+The policy language implemented by this module is simple, and specific
+to RADIUS.  It does not implement variables, arrays, loops, goto's, or
+any other feature of a real language.  If those features are needed
+for your system, we suggest using \fBrlm_perl\fP.
+.PP
+What the policy module implements is a simple way to look for
+attributes in the request packet (or other places), and to add
+attributes to the reply packet (or other places) based on those
+decisions.  Where the module shines is that it is significantly more
+flexible than the old-style \fBusers\fP file.
+.PP
+The module has one configuration item:
+.IP filename
+The file where the policy is stored.
+
+.SH POLICY LANGUAGE
+.SS Named policies
+The policy is composed of a series of named policies.  The following
+example defines a policy named "foo".
+.PP
+.DS
+       policy foo {
+.br
+               ...
+.br
+       }
+.DE
+.PP
+Policy names MAY NOT be the same as attributes in the dictionary.
+Defining a policy with the same name as a dictionary attribute will
+cause an error message to be printed, and the policy will not be
+loaded.
+.PP
+When the policy module is listed in a module section like "authorize",
+the module calls a policy named "authorize".  The "post-auth",
+etc. sections behave the same.  These names cannot be changed.
+.PP
+.DS
+       include "policy.txt"
+.DE
+.PP
+The filename must be in a double-quoted string, and is assumed to be
+relative to the location of the current file.  If the filename ends
+with a '/', then it is assumed to be a directory, and all files in
+that directory will be read.
+.PP
+.DS
+       include "dir/"
+.DE
+.PP
+All file in "dir/" will be read and included into the policy
+definition.  Any dot files (".", "..", etc.) will not be included,
+however.
+.PP
+.SS Including multiple files
+The main file referred to from the \fIradiusd.conf\fP may include one
+or more other files, as in the following example.
+.PP
+.SS Referencing a named policy
+The following example references a named policy
+.DS
+       foo()
+.DE
+While the brackets are required, no arguments may be passed.
+.PP
+.SS Conditions
+"if" statements are supported.
+.PP
+       if (expression) {
+.br
+               ...
+.br
+       }
+.DE
+.PP
+and "else"
+.PP
+       if (expression) {
+.br
+               ...
+.br
+       } else {
+.br
+               ...
+.br
+       }
+.DE
+.PP
+also, "else if"
+.PP
+       if (expression) {
+.br
+               ...
+.br
+       } else if (expression) {
+.br
+               ...
+.br
+       }
+.DE
+.PP
+.SS Expressions within "if" statements
+Always have to have brackets around them.  Sorry.
+.PP
+The following kinds of expressions may be used, with their meanings.
+.IP (attribute-reference)
+TRUE if the referenced attribute exists, FALSE otherwise.  See below
+for details on attribute references.
+.IP (!(expression))
+FALSE if the expression returned TRUE, and TRUE if the nested expression
+returned FALSE.
+.IP "(attribute-reference == value)"
+Compares the attribute to the value.  The operators here can be "==",
+"!=", "=~", "!~", "<", "<=", ">", and ">=".
+.IP "(string1 == string2)"
+A special case of the above.  The "string1" is dynamically expanded at
+run time, while "string2" is not.  The operators here can be "==",
+"!=", "=~",and "!~".  Of these, the most useful is "=~', which lets
+you do things like ("%{ldap:query...}" =~ "foo=(.*) ").  The results
+of the regular expression match are put into %{1}, and can be used
+later.  See "doc/variables.txt" for more information.
+.IP "((expression1) || (expression2))"
+Short-circuit "or".  If expression1 is TRUE, expression2 is not
+evaluated.
+.IP "((expression1) && (expression2))"
+Short-circuit "and".  If expression1 is FALSE, expression2 is not
+evaluated.
+.IP Limitations.
+The && and || operators have equal precedence. You can't call a
+function as a expression.
+.PP
+.PP
+.SS Attribute references
+Attribute references are:
+.IP Attribute-Name
+Refers to an attribute of that name in the Access-Request or
+Accounting-Request packet.  May also refer to "server-side"
+attributes, which are not documented anywhere.
+.IP request:Attribute-Name
+An alternate way of referencing an attribute in the request packet.
+.PP
+.IP reply:Attribute-Name
+An attribute in the reply packet
+.PP
+.IP proxy-request:Attribute-Name
+An attribute in the Access-Request or Accounting-Request packet which
+will be proxied to the home server.
+.PP
+.IP proxy-reply:Attribute-Name
+An attribute in the Access-Accept or other packet which was received
+from a home server.
+.PP
+.IP control:Attribute-Name
+An attribute in the per-request configuration and control attributes.
+Also known as "check" attributes (doc/variables.txt).
+.PP
+.PP
+.SS Adding attributes to reply packet (or other location)
+       reply .= {
+.br
+               attribute-name = value
+.br
+               ...
+.br
+               attribute-name = value
+.br
+       }
+.DE
+.PP
+The first name can be "request", "reply", "control", "proxy-request",
+or "proxy-reply".
+.PP
+The operator can be
+.PP
+ .= - appends attributes to end of the list
+.PP
+ := - replaces existing list with the attributes in the list (bad idea)
+.PP
+ = - use operators from "attribute = value" to decide what to do. (see "users")
+.PP
+The block must contain only attributes and values.  Nothing else is permitted.
+
+.SH SECTIONS
+.BR authorize
+.BR post-auth
+.BR pre-proxy
+.BR post-proxy
+.PP
+.SH FILES
+.I /etc/raddb/radiusd.conf
+.PP
+.SH "SEE ALSO"
+.BR radiusd (8),
+.BR users (5),
+.BR radiusd.conf (5)
+.SH AUTHOR
+Alan DeKok <aland@ox.org>
+
index 243ceff..2c4e76e 100644 (file)
@@ -1,4 +1,4 @@
-.TH rlm_realm 5 "19 May 2006" "" "FreeRADIUS Module"
+.TH rlm_realm 5 "14 March 2004" "" "FreeRADIUS Module"
 .SH NAME
 rlm_realm \- FreeRADIUS Module
 .SH DESCRIPTION
@@ -32,12 +32,6 @@ configuration of the Realm as matched in the file, the username may
 be rewritten in a 'stripped' format, or with the Realm portion
 removed.  In either case, a Realm attribute is created and added to
 the packet on a match, which can be used by other modules.
-.PP
-In order to force proxying for a request, set the
-.DS
-Proxy-To-Realm := "realm-name"
-.DE
-in the \fIusers\fP file, or in a database such as SQL.
 .SH CONFIGURATION
 .PP
 .DS
index c38bc62..29cf77d 100644 (file)
@@ -13,7 +13,7 @@ of "radiusd.conf"), then this module allows you to log SQL queries to
 a file, and then process them at your leisure.
 .PP
 The benefit of this approach is that for a busy server, the overhead
-of performing SQL queries may be significant.  Also, if the SQL
+of performing SQL qeuries may be significant.  Also, if the SQL
 databases are large (as is typical for ones storing months of data),
 the INSERTs and UPDATEs may take a relatively long time.  Rather than
 slowing down the RADIUS server by having it interact with a database,
index efd6675..ff8ea55 100644 (file)
@@ -1,43 +1,27 @@
-.TH rlm_unix 5 "5 February 2004" "" "FreeRADIUS Module"
+.TH rlm_unix 5 "17 February 2005" "" "FreeRADIUS Module"
 .SH NAME
 rlm_unix \- FreeRADIUS Module
 .SH DESCRIPTION
-The \fIrlm_unix\fP module allows authentication against the system
-password, shadow, and group files.  It also provides FreeRADIUS an
-interface into a radwtmp file (used by "radlast") when added to the
-accounting section.
+The \fIrlm_unix\fP module reads crypt(3) passwords from the system
+password file, and allows the server to use them for authentication.
+The module also provides FreeRADIUS an interface into a radwtmp file
+(used by "radlast") when added to the accounting section.
 .PP
-The \fIrlm_unix\fP module provides the functionality for "Auth-Type =
-System", rather than "Auth-Type = Unix".  The "System" name is used
-for historical reasons.
+The \fIrlm_unix\fP module does provides the functionality for
+"Auth-Type = System".  The module should be listed in the
+"authenticate" section.  Please see the default \fIradiusd.conf\fP
+shipped with the server for an example of the correct usage of this
+module.
+.PP
+As of FreeRADIUS 1.1.0, the module no longer reads, or caches
+/etc/passwd, /etc/shadow, or /etc/group.  If you wish to cache those
+files, see \fIrlm_passwd\fP.  Most, if not all, configurations should
+not need those files to be cached.
 .PP
 The main configuration items to be aware of are:
-.IP cache
-This is a 'yes' or 'no' option.  If set to yes, FreeRADIUS will read
-the system files into memory, rather than perform a system call to
-lookup the information.  On *BSD systems, you should set this value to
-no.  On other systems, if you have a very large passwd and shadow
-files, you can try setting this to yes, which may increase the servers
-performance.  The default is no.
-.IP cache_reload
-This is the number of seconds to wait between refreshing the cached 
-files from the system.  It has no effect unless you enable caching.
-.IP passwd
-The path to the system passwd file.  Usually /etc/passwd.  If
-commented out, or not set, the server will retrieve the information
-via systemcalls.
-.IP shadow
-The path to the system shadow file.  Usually /etc/shadow.  This is not
-set by default.
-.IP group
-The path to the system group file.  Usually /etc/group.  This is not
-set by default.
 .IP radwtmp
 The path to the system wtmp file to be used for keeping the database
 of online users as read by the 'radlast' program.
-.IP usegroup
-This is a 'yes' or 'no' option.  If set to 'yes' this allows the Group
-attribute to be used as a check item.  Default is 'no'.
 .SH CONFIGURATION
 .PP
 .DS
@@ -46,18 +30,6 @@ modules {
 .br
   unix {
 .br
-    cache = no
-.br
-    cache_reload = 600
-.br
-    #passwd = /etc/passwd
-.br
-    #shadow = /etc/shadow
-.br
-    #group = /etc/group
-.br
-    usegroup = no
-.br
     radwtmp = ${logdir}/radwtmp
 .br
   }
@@ -77,6 +49,7 @@ modules {
 .SH "SEE ALSO"
 .BR radiusd (8),
 .BR radiusd.conf (5),
+.BR rlm_passwd (5),
 .BR radlast (1)
 .SH AUTHORS
 Chris Parker, cparker@segv.org
index 373b3ea..2bdde47 100644 (file)
@@ -27,12 +27,6 @@ radiusd - Authentication, Authorization and Accounting server
 .RB [ \-y ]
 .RB [ \-z ]
 .SH DESCRIPTION
-This is the FreeRADIUS implementation of the well known
-.B radius
-server program.  Even though this program is largely compatible with
-\fILivingston's\fP radius version 2.0, it is \fBnot\fP based on any
-part of that code.
-.PP
 FreeRADIUS is a high-performance and highly configurable RADIUS
 server.  As a result, it can be difficult to configure in systems with
 complex requirements.  Our suggestion is to proceed via the following
@@ -128,11 +122,11 @@ Defaults to \fI/etc/raddb\fP. \fBRadiusd\fP looks here for its configuration
 files such as the \fIdictionary\fP and the \fIusers\fP files.
 
 .IP "\-i \fIip-address\fP"
-Defines which IP addres to bind to for sending and receiving packets-
-useful for multi-homed hosts.
+Defines which IP address that the server uses for sending and
+receiving packets.
 
-This command line option is deprecated.  See the \fIbind_address\fP
-configuration item in the \fIradiusd.conf\fP file.
+If this command-line option is given, then the "bind_address" and all
+"listen{}" entries in \fIradiusd.conf\fP are ignored.
 
 .IP \-b
 If the \fBradius\fP server binary was compiled with \fIdbm\fP support,
@@ -160,12 +154,12 @@ Do not fork, stay running as a foreground process.
 
 .IP "\-p \fIport\fP"
 Normally radiusd listens on the ports specified in \fI/etc/services\fP
-(radius and radacct). With this option radiusd listens on the specified
-port for authentication requests and on the specified port +1 for
-accounting requests.
+(radius and radacct). When this option is given, radiusd listens on
+the specified port for authentication requests and on the specified
+port +1 for accounting requests.
 
-This command line option is deprecated.  See the \fIport\fP
-configuration item in the \fIradiusd.conf\fP file.
+If this command-line option is given, then the "port" directive in
+\fIradiusd.conf\fP is ignored.
 
 .IP \-s
 Run in "single server" mode.  The server normally runs with multiple
@@ -178,14 +172,13 @@ single server mode, the server will also not "daemonize"
 .IP \-v
 Print server version information and exit.
 
-.IP \-x
-Debug mode. In this mode the server will print details of every request
-on it's \fBstderr\fP output. Most useful in combination with \fB-s\fP.
-You can specify this option 2 times (-x -x or -xx) to get a bit more
-debugging output.
-
 .IP \-X
-Extended debug mode.  Equivalent to -sfxx, but simpler to explain.
+Debugging mode.  Equivalent to -sfxx.
+
+.IP \-x
+Finer-grained debug mode. In this mode the server will print details
+of every request on it's \fBstdout\fP output. You can specify this
+option multiple times (-x -x or -xx) to get more detailed output.
 
 .IP \-y
 Write details about every authentication request in the
index 51dcaed..1f423ec 100644 (file)
@@ -1,77 +1,16 @@
-.TH RADRELAY 1 "09 June 2002" "" "FreeRADIUS Daemon"
+.TH RADRELAY 8 "19 July 2005" "" "FreeRADIUS Daemon"
 .SH NAME
-radrelay -- replicate accounting data to another RADIUS server
-.SH SYNOPSIS
-.B radrelay
-.RB [ \-a
-.IR accounting_dir ]
-.RB [ \-d
-.IR radius_dir ]
-.RB [ \-f ]
-.RB [ \-i
-.IR source_ip ]
-.RB [ \-n
-.IR shortname ]
-.RB [ \-r
-.IR remote-server[:port] ]
-.RB [ \-s
-.IR secret ]
-.RB [ \-S
-.IR secret_file ]
-.RB [ \-x ]
-\fIdetailfile\fP
+radrelay -- Deprecated command.
 .SH DESCRIPTION
-\fBRadrelay\fP reads a file in the \fIdetail\fP file format,
-reconstructs radius packets from it and sends them to a remote
-radius server. When end-of-file is reached, the file is truncated.
-\fBRadrelay\fP then waits for additional data to be written to
-the file, and starts over again.
+The functions of \fIradrelay\fP have been added to \fIradiusd\fP.  One
+benefit is that one instance of \fIradiusd\fP can read multiple detail
+files, among others.
 .PP
-
-.SH OPTIONS
-
-.IP "\-a \fIaccounting_directory\fP"
-The base directory to use to read the detail file from.
-
-.IP "\-d \fIradius_directory\fP"
-The base radius (raddb) directory, where the config files live.
-
-.IP \-f
-Do \fInot\fP fork and run in the background as a daemon.
-
-.IP "\-i \fIsource_ip\fP"
-The source IP address to use for sending radius packets.
-
-.IP "\-n \fIshortname\fP"
-The radius configuration files (most probably clients.conf), will be
-searched for a client section with 'shortname' set to the used argument.
-Both the server secret and the remote-server address are obtained in
-this way. Do not use the -r, -s or -S parameters in combination with -n.
-
-.IP "\-r \fIremote-server\fP"
-The hostname or IP address of the remote server. Optionally a UDP port
-can be specified. If no UDP port is specified, it is looked up in
-\fI/etc/services\fP. The service name looked for is \fBradacct\fP for
-accounting packets. If a service is not found in \fI/etc/services\fP,
-1813 is used. The -r parameter can't be used in combination with -n.
-
-.IP "\-s \fIsecret\fP"
-Remote server secret.
-
-.IP "\-S \fIsecret_file\fP"
-Read remote server secret from file, the file should contain
-nothing other then the plain-text secret.
-
-.IP \-x
-Enable debug mode, -x will activate radrelay internal debugging, -xx will
-also activate librad debugging.
-
-.IP "detailfile"
-The detail file to use, this will be appended to the base accounting
-directory.
-
+The \fIrlm_sql_log\fP module does something similar, but for SQL
+queries.  See it's man page for details.
 .SH SEE ALSO
-radiusd(8),
-doc/radrelay.
+.BR radiusd(8),
+.BR radrelay.conf(5),
+.BR rlm_sql_log(5)
 .SH AUTHOR
-Miquel van Smoorenburg, miquels@cistron.nl.
+The FreeRADIUS Server Project
index e2cd82f..1ba3888 100644 (file)
@@ -7,7 +7,7 @@ radwatch - wrapper for radiusd
 .SH DESCRIPTION
 This is a wrapper for \fIradiusd\fP. It starts the radius server, then
 waits for it to terminate, which should never happen. If it does
-happen, \fBradwatch\fP sends mail to \fIroot\fP informing her of
+happen, \fBradwatch\fP sends a notification email to \fIroot\fP about
 the event, waits 10 seconds, then restarts the server.
 .PP
 This script \fBSHOULD NOT BE USED\fP!  It's only here for historical
index 686abe0..a4586ac 100644 (file)
@@ -1,13 +1,20 @@
+#
+# Makefile
+#
+# Version:      $Id$
+#
+
 include ../Make.inc
 
 #
 #  The list of files to install.
 #
-FILES  = acct_users attrs clients clients.conf dictionary eap.conf \
-         experimental.conf hints huntgroups ldap.attrmap \
-         mssql.conf naslist naspasswd oraclesql.conf postgresql.conf \
-         preproxy_users proxy.conf radiusd.conf realms snmp.conf \
-         sql.conf sqlippool.conf users otp.conf otppasswd.sample
+FILES = acct_users attrs attrs.access_reject attrs.accounting_response \
+       attrs.pre-proxy clients.conf dictionary \
+       eap.conf experimental.conf hints huntgroups ldap.attrmap        \
+       mssql.conf naspasswd oraclesql.conf otp.conf postgresql.conf    \
+       preproxy_users proxy.conf radiusd.conf radrelay.conf            \
+       realms snmp.conf sql.conf sqlippool.conf users
 
 all:
 
@@ -34,7 +41,7 @@ install:
                echo "** WARNING ** WARNING ** WARNING ** WARNING ** WARNING ** WARNING ** WARNING **";\
                echo "** WARNING ** WARNING ** WARNING ** WARNING ** WARNING ** WARNING ** WARNING **";\
        fi
-       chmod 640 $(R)$(raddbdir)/naspasswd $(R)$(raddbdir)/clients $(R)$(raddbdir)/clients.conf
+       chmod 640 $(R)$(raddbdir)/naspasswd $(R)$(raddbdir)/clients.conf
        if [ ! -d $(R)$(raddbdir)/certs ]; then \
                mkdir $(R)$(raddbdir)/certs; \
                mkdir $(R)$(raddbdir)/certs/demoCA; \
@@ -42,5 +49,9 @@ install:
                cp certs/* $(R)$(raddbdir)/certs 2>/dev/null || true; \
        fi
 
-clean:
+       if [ ! -d $(R)$(raddbdir)/sql ]; then \
+               mkdir $(R)$(raddbdir)/sql; \
+               cp sql/* $(R)$(raddbdir)/sql 2>/dev/null || true; \
+       fi
 
+clean:
index 8e15d01..fafac84 100644 (file)
@@ -4,13 +4,20 @@
 #      This is like the 'users' file, but it is processed only for
 #      accounting packets.
 #
-#DEFAULT Acct-Status-Type == Start
-#      Exec-Program = "/path/to/exec/acct/start"
+
+#  Select between different accounting methods based for example on the
+#  Realm, the Huntgroup-Name or any combinaison of the attribute/value
+#  pairs contained in an accounting packet.
 #
-#DEFAULT Acct-Status-Type == Stop
-#      Exec-Program = "/path/to/exec/acct/stop"
+#DEFAULT Realm == "foo.net", Acct-Type := sql_log.foo
 #
-#  For information on how the attributes from the request are passed
-#  to the program, see 'doc/variables.txt'
+#DEFAULT Huntgroup-Name == "wifi", Acct-Type := sql_log.wifi
 #
+#DEFAULT Client-IP-Address == 10.0.0.1, Acct-Type := sql_log.other
 #
+#DEFAULT Acct-Status-Type == Start, Acct-Type := sql_log.start
+
+#  Replace the User-Name with the Stripped-User-Name, if it exists.
+#
+#DEFAULT
+#      User-Name := "%{Stripped-User-Name:-%{User-Name}}"
index 59b5a63..5737b7f 100644 (file)
@@ -117,6 +117,9 @@ DEFAULT
        Reply-Message =* ANY,
        Proxy-State =* ANY,
        EAP-Message =* ANY,
+       MS-MPPE-Recv-Key =* ANY,
+       MS-MPPE-Send-Key =* ANY,
+       MS-CHAP-MPPE-Keys =* ANY,
        State =* ANY,
        Session-Timeout <= 28800,
        Idle-Timeout <= 600,
diff --git a/raddb/attrs.access_reject b/raddb/attrs.access_reject
new file mode 100644 (file)
index 0000000..8ecfe2d
--- /dev/null
@@ -0,0 +1,16 @@
+#
+#      Configuration file for the rlm_attr_filter module.
+#      Please see rlm_attr_filter(5) manpage for more information.
+#
+#      $Id$
+#
+#      This configuration file is used to remove almost all of the attributes
+#      From an Access-Reject message.  The RFC's say that an Access-Reject
+#      packet can contain only a few attributes.  We enforce that here.
+#
+DEFAULT
+       EAP-Message =* ANY,
+       State =* ANY,
+       Message-Authenticator =* ANY,
+       Reply-Message =* ANY,
+       Proxy-State =* ANY
diff --git a/raddb/attrs.accounting_response b/raddb/attrs.accounting_response
new file mode 100644 (file)
index 0000000..3746ce4
--- /dev/null
@@ -0,0 +1,15 @@
+#
+#      Configuration file for the rlm_attr_filter module.
+#      Please see rlm_attr_filter(5) manpage for more information.
+#
+#      $Id$
+#
+#      This configuration file is used to remove almost all of the attributes
+#      From an Accounting-Response message.  The RFC's say that an
+#      Accounting-Response packet can contain only a few attributes.
+#      We enforce that here.
+#
+DEFAULT
+       Vendor-Specific =* ANY,
+       Message-Authenticator =* ANY,
+       Proxy-State =* ANY
diff --git a/raddb/attrs.pre-proxy b/raddb/attrs.pre-proxy
new file mode 100644 (file)
index 0000000..fdfb650
--- /dev/null
@@ -0,0 +1,58 @@
+#
+#      Configuration file for the rlm_attr_filter module.
+#      Please see rlm_attr_filter(5) manpage for more information.
+#
+#      $Id$
+#
+#      This file contains security and configuration information
+#      for each realm. It can be used be an rlm_attr_filter module
+#      instance to filter attributes before sending packets to the
+#      home server of a realm.
+#
+#      When a packet is sent to a home server, these attributes
+#      and values are tested. Only the first match is used unless
+#      the "Fall-Through" variable is set to "Yes". In that case
+#      the rules defined in the DEFAULT case are processed as well.
+#
+#      A special realm named "DEFAULT" matches on all realm names.
+#      You can have only one DEFAULT entry. All entries are processed
+#      in the order they appear in this file. The first entry that
+#      matches the login-request will stop processing unless you use
+#      the Fall-Through variable.
+#
+#      The first line indicates the realm to which the rules apply.
+#      Indented (with the tab character) lines following the first
+#      line indicate the filter rules.
+#
+
+# This is a complete entry for 'nochap' realm. It allows to send very
+# basic attributes to the home server. Note that there is no Fall-Through
+# entry so that no DEFAULT entry will be used. Only the listed attributes
+# will be sent in the packet, all other attributes will be filtered out.
+#
+#nochap
+#      User-Name =* ANY,
+#      User-Password =* ANY,
+#      NAS-Ip-Address =* ANY,
+#      NAS-Identifier =* ANY
+
+# The entry for the 'brokenas' realm removes the attribute NAS-Port-Type
+# if its value is different from 'Ethernet'. Then the default rules are
+# applied.
+#
+#brokenas
+#      NAS-Port-Type == Ethernet
+#      Fall-Through = Yes
+
+# The rest of this file contains the DEFAULT entry.
+# DEFAULT matches with all realm names.
+
+DEFAULT
+       User-Name =* ANY,
+       User-Password =* ANY,
+       CHAP-Password =* ANY,
+       CHAP-Challenge =* ANY,
+       State =* ANY,
+       NAS-Ip-Address =* ANY,
+       NAS-Identifier =* ANY,
+       Proxy-State =* ANY
diff --git a/raddb/clients b/raddb/clients
deleted file mode 100644 (file)
index c6e0868..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-#      THIS FILE IS DEPRECATED.
-#
-#      You should NOT be using this file to configure the server.
-#      It is here ONLY for backwards compatibility.
-#
-#      See 'clients.conf' for the new configuration.
index e752e27..f0ed060 100644 (file)
 #  are not going to be permitting RADIUS queries from localhost, we suggest
 #  that you delete, or comment out, this entry.
 #
+#
+#  Rules for Prefixes
+#  ------------------
+#  IPv6 prefixes MUST end with :: or IPv6 Address or hostname
+#  IPv4 Prefixes MUST end with .0 or IPv4 Address or hostname
+#  A hostname is a valid DNS lookup name
+#
+#  Valid Prefixes
+#  --------------
+#  For IPv4:
+#    192.168.1.1/24
+#    10.0/8 = 10.0.0.0/16 = 10.0.0.1/8    != 10/8 
+#    192.168.1.1/32 = 192.168.1.1/0
+#    hostname/32   = hostname/0  = hostname
+#   (32 or 0 or NULL prefix lengths are treated same)
+#
+#  For IPv6:
+#    fec0::/64
+#    fec0::1/100
+#    fec0::1/128  = fec0::1/0 = fec0::1 
+#    hostname/128 = hostname/0 = hostname
+#   (128 or 0 or NULL prefix lengths are treated same)
+#
+#  Invalid prefixes
+#  ----------------
+#  For IPv4:
+#  1) 192.168/16 
+#       (MUST end with .0)
+#       (replace with 192.168.0/16 or 192.168.0.0/16 or 192.168.1.1/16)
+#  2) 192.168
+#       (No Prefix, so it is considered as hostname 
+#         and also returns 192.0.0.168 instead of 192.168.0.0)
+#
+#  For IPv6:
+#  1) fec0/16
+#       (MUST end with ::)
+#       (replace with fec0::/16 or fec0::1/16)
+#  2) fec0::
+#       (No prefix, so it is considered as hostname)
+#
+
 client 127.0.0.1 {
        #
        #  The shared secret use to "encrypt" and "sign" packets between
        #  the NAS and FreeRADIUS.  You MUST change this secret from the
        #  default, otherwise it's not a secret any more!
        #
-       #  The secret can be any string, up to 31 characters in length.
+       #  The secret can be any string, up to 8k characters in length.
+       #
+       #  Control codes can be entered vi octal encoding,
+       #       e.g. "\101\102" == "AB"
+       #  Quotation marks can be entered by escaping them,
+       #       e.g. "foo\"bar"
        #
        secret          = testing123
 
@@ -77,6 +123,18 @@ client 127.0.0.1 {
 #      password    = someadminpas
 }
 
+# IPv6 Client
+#client ::1 {
+#      secret          = testing123
+#      shortname       = localhost
+#}
+#
+# All IPv6 Site-local clients
+#client fe80::/16 {
+#      secret          = testing123
+#      shortname       = localhost
+#}
+
 #client some.host.org {
 #      secret          = testing123
 #      shortname       = localhost
@@ -109,3 +167,16 @@ client 127.0.0.1 {
 #      password    = someadminpas
 #}
 
+#######################################################################
+#
+#  Per-socket client lists.  The configuration entries are exactly
+#  the same as above, but they are nested inside of a section.
+#
+#  You can have as many per-socket client lists as you have "listen"
+#  sections, or you can re-use a list among multiple "listen" sections.
+#
+#per_socket_clients {
+#      client 192.168.3.4 {
+#              secret = testing123
+#        }
+#}
index 95bb8f0..39bb360 100644 (file)
                #
                #  The Perl script to execute on authorize, authenticate,
                #  accounting, xlat, etc.  This is very similar to using
-               #  Exec-Program-Wait = "/path/foo.pl", but it is persistent,
-               #  and therefore faster.
+               #  'rlm_exec' module, but it is persistent, and therefore
+               #  faster.
                #
-                module = /path/to/your/perl_program
+               module = /path/to/your/perl_module.pm
 
                #
                #  The following hashes are given to the module and
                 #  filled with value-pairs (Attribute names and values)
                #
-               #  %RAD_REPLY           Attributes to go into the reply
-               #  %RAD_REQUEST         Attributes from the request
-               #  %RAD_CHECK           Check items
-               #
-               #  Only the %RAD_REPLY hash can be modified.
-               #  All of the other hashes are read only.
-               #
+               #  %RAD_CHECK           Read-only       Check items
+               #  %RAD_REQUEST         Read-only       Attributes from the request
+               #  %RAD_REPLY           Read-write      Attributes for the reply
+               # 
                #  The return codes from functions in the perl_script
                #  are passed directly back to the server.  These
                #  codes are defined in doc/configurable_failover,
                #  and are pre-defined in the 'example.pl' program
                #  which is included.
                #               
-                func_accounting = accounting
-                func_authenticate = authenticate
-               func_authorize = authorize
-                func_preacct = preacct
-                func_checksimul = checksimul
-                func_xlat = xlat
+
+               #
+               #  List of functions in the module to call.
+               #  Uncomment and change if you want to use function
+               #  names other than the defaults.
+               #
+               #func_authenticate = authenticate
+               #func_authorize = authorize
+               #func_preacct = preacct
+               #func_accounting = accounting
+               #func_checksimul = checksimul
+               #func_pre_proxy = pre_proxy
+               #func_post_proxy = post_proxy
+               #func_post_auth = post_auth
+               #func_xlat = xlat
+               #func_detach = detach
+
+               #
+               #  Uncomment the following lines if you wish
+               #  to use separate functions for Start and Stop
+               #  accounting packets. In that case, the 
+               #  func_accounting function is not called.
+               #
+               #func_start_accounting = accounting_start
+               #func_stop_accounting = accounting_stop
+               
+               #  Uncomment the following lines if your perl is 
+               #  compiled with threads support.
+               #  The settings below are the defaults.
+               #
+               #max_clones = 32
+               #start_clones = 32
+               #min_spare_clones = 0
+               #max_spare_clones = 32
+               #cleanup_delay = 5
+               #max_request_per_clone = 0
+
        }
 
        #
                # Reload the hash every 600 seconds (10mins)
                hash_reload = 600
        }
+
+       #
+       #  See also protocol_filter.conf
+       #
+       protocol_filter {
+               #
+               #  Location of the protocol filter configuration file.
+               #
+               filename = ${raddbdir}/protocol_filter.conf
+
+               #
+               #  The key to look up the section with filtering rules.
+               #
+               key = %{Realm:-DEFAULT}
+       }
+
+       # Caching module
+       #
+       # Should be added in the post-auth section (after all other modules)
+       # and in the authorize section (before any other modules)
+       #
+       # authorize {
+       #       caching {
+       #               ok = return
+       #       }
+       #       [... other modules ...]
+       # }
+       # post-auth {
+       #       [... other modules ...]
+       #       caching
+       # }
+       #
+       # The caching module will cache the Auth-Type and reply items
+       # and send them back on any subsequent requests for the same key
+       #
+       # Configuration:
+       #
+       # filename: The gdbm file to use for the cache database
+       #               (can be memory mapped for more speed)
+       #
+       # key: A string to xlat and use as a key. For instance,
+       #       "%{Acct-Unique-Session-Id}"
+       #
+       # post-auth: If we find a cached entry, set the post-auth to that value
+       #
+       # cache-ttl: The time to cache the entry. The same time format
+       #               as the counter module apply here.
+       #         num[hdwm] where:
+       #       h: hours, d: days, w: weeks, m: months
+       #       If the letter is ommited days will be assumed.
+       #       e.g. 1d == one day
+       #
+       # cache-size: The gdbm cache size to request (default 1000)
+       #
+       # hit-ratio: If set to non-zero we print out statistical
+       #       information after so many cache requests
+       #
+       # cache-rejects: Do we also cache rejects, or not? (default 'yes')
+       #
+       caching {
+               filename = ${raddbdir}/db.cache
+               cache-ttl = 1d
+               hit-ratio = 1000
+               key = "%{Acct-Unique-Session-Id}"
+               #post-auth = ""
+               # cache-size = 2000
+               # cache-rejects = yes
+       }
+
+
+       # Simple module for logging of Account packets to radiusd.log
+       # You need to declare it in the accounting section for it to work
+       acctlog {
+               acctlog_update = ""
+               acctlog_start = "Connect: [%{User-Name}] (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} ip %{Framed-IP-Address})"
+               acctlog_stop = "Disconnect: [%{User-Name}] (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} ip %{Framed-IP-Address}) %{Acct-Session-Time} seconds"
+               acctlog_on = "NAS %C (%{NAS-IP-Address}) just came online"
+               acctlog_off = "NAS %C (%{NAS-IP-Address}) just went offline"
+       }
index e686556..912d98f 100644 (file)
@@ -3,12 +3,21 @@
 # to be used by LDAP authentication and authorization module (rlm_ldap)
 #
 # Format:
-#   ItemType   RADIUS-Attribute-Name           ldapAttributeName
+#   ItemType   RADIUS-Attribute-Name           ldapAttributeName  [operator]
 #
 # Where:
 #   ItemType              = checkItem or replyItem 
 #   RADIUS-Attribute-Name = attribute name in RADIUS dictionary
 #   ldapAttributeName     = attribute name in LDAP schema
+#   operator              = optional, and may not be present.
+#                          If not present, defaults to "==" for checkItems,
+#                          and "=" for replyItems.
+#                          If present, the operator here should be one
+#                          of the same operators as defined in the "users"3
+#                          file ("man users", or "man 5 users").
+#                          If an operator is present in the value of the
+#                          LDAP entry (i.e. ":=foo"), then it over-rides
+#                          both the default, and any operator given here.
 #
 # If $GENERIC$ is specified as RADIUS-Attribute-Name, the line specifies
 # a LDAP attribute which can be used to store any RADIUS 
@@ -26,6 +35,8 @@ checkItem     Called-Station-Id               radiusCalledStationId
 checkItem      Calling-Station-Id              radiusCallingStationId
 checkItem      LM-Password                     lmPassword
 checkItem      NT-Password                     ntPassword
+checkItem      LM-Password                     sambaLmPassword
+checkItem      NT-Password                     sambaNtPassword
 checkItem      SMB-Account-CTRL-TEXT           acctFlags
 checkItem      Expiration                      radiusExpiration
 checkItem      NAS-IP-Address                  radiusNASIpAddress
diff --git a/raddb/naslist b/raddb/naslist
deleted file mode 100644 (file)
index ea73423..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-#      THIS FILE IS DEPRECATED.
-#
-#      You should NOT be using this file to configure the server.
-#      It is here ONLY for backwards compatibility.
-#
-#      See 'clients.conf' for the new configuration.
-#
-#
-# naslist      This file contains a list of NASes (Network Access Servers,
-#              also known as terminal servers) which we know.
-#
-#              Description of the fields:
-#
-#              * The first field is a valid hostname or IP address
-#                for the client.
-#              * The second field (seperated by blanks or tabs) is the 
-#                short name we use in the logfiles for this NAS.
-#              * The third field defines what type of device it is. Valid
-#                values are "cisco", "computone", "livingston", "max40xx", 
-#                 "multitech", "netserver", "pathras", "patton", "portslave", 
-#                 "tc", "usrhiper" or "other".
-#
-#              This is used to find out how to detect double logins.
-#
-
-# NAS Name             Short Name      Type
-#----------------      ----------      ----
-#portmaster1.isp.com   pm1.NY          livingston
-#portmaster2.isp.com   pm1.LA          livingston
-localhost              local           portslave
index 3984a7e..3ae59e1 100644 (file)
@@ -10,7 +10,7 @@
 #  management and OTP verification functions; and lsmd or gsmd,
 #  which implements synchronous state management functions.
 #  otpd, lsmd and gsmd are available from TRI-D Systems:
-#              <http://www.TRI-Dsystems.com/>
+#              <http://www.tri-dsystems.com/>
 
 #  You must list this module in BOTH the authorize and authenticate
 #  sections in order to use it.
diff --git a/raddb/policy.txt b/raddb/policy.txt
new file mode 100755 (executable)
index 0000000..a1c6754
--- /dev/null
@@ -0,0 +1,71 @@
+#
+#      Sample of a policy language.
+#      There's no documentation other than this file.
+#      The syntax is odd, but it works.
+#      It's not intended for production use.
+#      Use it if you want obscure error messages and possibly server crashes.
+#
+#      $Id$
+#
+#  Debugging statements
+#
+#debug print_tokens    # as we're parsing this file
+debug print_policy     # once the file has been parsed
+debug evaluate         # print limited information during evaluation
+
+#
+#  A named policy.
+#
+policy 3pm {
+if (Time-Of-Day < "15:00") {
+   reply .= {
+      # Use ARAP-Password for testing because it's an attribute
+      # no one cares about.
+      ARAP-Password = "< 15:00"
+   }
+}
+
+}
+
+#
+#  A named policy, executed during the "authorize" phase,
+#  because it's named "authorize". 
+#
+policy authorize {
+  if (CHAP-Password) {
+     if (!(CHAP-Challenge)) {
+        print "Adding CHAP-Challenge = %{request:Packet-Authentication-Vector}\n"
+
+        #
+        #  Append all attributes to the specified list.
+        #  The per-attribute operators MUST be '='
+        #
+        request .= {
+           CHAP-Challenge = "%{request:Packet-Authentication-Vector}"
+        }
+     }
+
+     #
+     #  Use per-attribute operators to do override, replace, etc.
+     #  It's "control", not "check items", because "check items"
+     #  is a hold-over from the "users" file, and we no longer like that.
+     #
+     control = {
+         Auth-Type := CHAP
+     }
+  }
+
+#
+#  This could just as well be "%{ldap: query...}" =~ ...
+#
+#  if ("%{User-Name}" =~ "^(b)") {
+#     reply .= {
+#         Arap-Password = "Hello, %{1}"
+#     }
+#  }
+
+  #
+  #  Execute "3pm", as if it was in-line here.
+  #
+#  call 3pm
+}
diff --git a/raddb/postgresql.conf b/raddb/postgresql.conf
deleted file mode 100644 (file)
index b6944c2..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-#
-#  $Id$
-#
-#  Configuration for the SQL module, when using Postgresql.
-#
-#  The database schema is available at:
-#
-#      doc/examples/postgresql.sql
-#
-
-sql {
-
-       # Database type
-       # Current supported are: rlm_sql_mysql, rlm_sql_postgresql,
-       # rlm_sql_unixodbc, rlm_sql_oracle.
-       driver = "rlm_sql_postgresql"
-
-       # Connect info
-       server = "localhost"
-
-       # The following credentials will most likely work on a default
-       # install of Postgresql. If they do work however, it means that
-       # you have a HUGE GAPING SECURITY RISK on your server! Please
-       # change the "postgres" users password and setup a separate
-       # radius user.
-       login = "postgres"
-       password = ""
-
-       # Database table configuration
-       radius_db = "radius"
-
-       # If you want both stop and start records logged to the
-       # same SQL table, leave this as is.  If you want them in
-       # different tables, put the start table in acct_table1
-       # and stop table in acct_table2
-       acct_table1 = "radacct"
-       acct_table2 = "radacct"
-
-       # Allow for storing data after authentication
-       postauth_table = "radpostauth"
-
-       authcheck_table = "radcheck"
-       authreply_table = "radreply"
-
-       groupcheck_table = "radgroupcheck"
-       groupreply_table = "radgroupreply"
-
-       # Table to keep group info
-       usergroup_table = "usergroup"
-
-       # Remove stale session if checkrad does not see a double login
-       deletestalesessions = yes
-
-       # Print all SQL statements when in debug mode (-x)
-       sqltrace = yes
-       sqltracefile = ${logdir}/sqltrace.sql
-
-       # number of sql connections to make to server
-       num_sql_socks = 5
-
-       # number of seconds to dely retrying on a failed database
-       # connection (per_socket)
-       #connect_failure_retry_delay = 60
-
-       #######################################################################
-       #  Query config:  Username
-       #######################################################################
-       # This is the username that will get substituted, escaped, and added
-       # as attribute 'SQL-User-Name'.  '%{SQL-User-Name}' should be used
-       # below everywhere a username substitution is needed so you you can
-       # be sure the username passed from the client is escaped properly.
-       #
-       # Uncomment the next line, if you want the sql_user_name to mean:
-       #
-       #    Use Stripped-User-Name, if it's there.
-       #    Else use User-Name, if it's there,
-       #    Else use hard-coded string "none" as the user name.
-       #
-       #sql_user_name = "%{Stripped-User-Name:-%{User-Name:-none}}"
-       #
-       sql_user_name = "%{User-Name}"
-
-
-       #######################################################################
-       #  Authorization Queries
-       #######################################################################
-       #  These queries compare the check items for the user
-       #  in ${authcheck_table} and setup the reply items in
-       #  ${authreply_table}.  You can use any query/tables
-       #  you want, but the return data for each row MUST
-       #  be in the  following order:
-       #
-       #  0. Row ID (currently unused)
-       #  1. UserName/GroupName
-       #  2. Item Attr Name
-       #  3. Item Attr Value
-       #  4. Item Attr Operation
-       #######################################################################
-
-       # Use these for case insensitive usernames. WARNING: Slower queries!
-# authorize_check_query = "SELECT id, UserName, Attribute, Value, Op \
-#   FROM ${authcheck_table} \
-#   WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') \
-#   ORDER BY id"
-# authorize_reply_query = "SELECT id, UserName, Attribute, Value, Op \
-#   FROM ${authreply_table} \
-#   WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') \
-#   ORDER BY id"
-
-       authorize_check_query = "SELECT id, UserName, Attribute, Value, Op \
-               FROM ${authcheck_table} \
-               WHERE Username = '%{SQL-User-Name}' \
-               ORDER BY id"
-
-       authorize_reply_query = "SELECT id, UserName, Attribute, Value, Op \
-               FROM ${authreply_table} \
-               WHERE Username = '%{SQL-User-Name}' \
-               ORDER BY id"
-
-       # Use these for case insensitive usernames. WARNING: Slower queries!
-# authorize_group_check_query = "SELECT ${groupcheck_table}.id, ${groupcheck_table}.GroupName, \
-#   ${groupcheck_table}.Attribute, ${groupcheck_table}.Value, ${groupcheck_table}.Op \
-#   FROM ${groupcheck_table}, ${usergroup_table} \
-#   WHERE LOWER(${usergroup_table}.UserName) = LOWER('%{SQL-User-Name}') AND ${usergroup_table}.GroupName = ${groupcheck_table}.GroupName \
-#   ORDER BY ${groupcheck_table}.id"
-# authorize_group_reply_query = "SELECT ${groupreply_table}.id, ${groupreply_table}.GroupName, \
-#   ${groupreply_table}.Attribute, ${groupreply_table}.Value, ${groupreply_table}.Op \
-#   FROM ${groupreply_table}, ${usergroup_table} \
-#   WHERE LOWER(${usergroup_table}.UserName) = LOWER('%{SQL-User-Name}') AND ${usergroup_table}.GroupName = ${groupreply_table}.GroupName \
-#   ORDER BY ${groupreply_table}.id"
-
-       authorize_group_check_query = "SELECT ${groupcheck_table}.id, ${groupcheck_table}.GroupName, \
-               ${groupcheck_table}.Attribute, ${groupcheck_table}.Value,${groupcheck_table}.Op \
-               FROM ${groupcheck_table}, ${usergroup_table} \
-               WHERE ${usergroup_table}.Username = '%{SQL-User-Name}' AND ${usergroup_table}.GroupName = ${groupcheck_table}.GroupName \
-               ORDER BY ${groupcheck_table}.id"
-
-       authorize_group_reply_query = "SELECT ${groupreply_table}.id, ${groupreply_table}.GroupName, ${groupreply_table}.Attribute, \
-               ${groupreply_table}.Value, ${groupreply_table}.Op \
-               FROM ${groupreply_table},${usergroup_table} \
-               WHERE ${usergroup_table}.Username = '%{SQL-User-Name}' AND ${usergroup_table}.GroupName = ${groupreply_table}.GroupName \
-               ORDER BY ${groupreply_table}.id"
-
-       #######################################################################
-       #  Authentication Query
-       #######################################################################
-       # This query is used only to get the Password for the
-       # user we want to authenticate.  The password MUST
-       # be the first field in the return row data.
-       #######################################################################
-
-       authenticate_query = "SELECT Value,Attribute FROM ${authcheck_table} \
-               WHERE UserName = '%{User-Name}' AND ( Attribute = 'User-Password' OR Attribute = 'Crypt-Password' ) \
-               ORDER BY Attribute DESC"
-
-        #######################################################################
-        # Simultaneous Use Checking Queries
-        #######################################################################
-        # simul_count_query     - query for the number of current connections
-        #                       - If this is not defined, no simultaneouls use checking
-        #                       - will be performed by this module instance
-        # simul_verify_query    - query to return details of current connections for verification
-        #                       - Leave blank or commented out to disable verification step
-        #                       - Note that the returned field order should not be changed.
-        #######################################################################
-
-        # Uncomment simul_count_query to enable simultaneous use checking
-       # simul_count_query = "SELECT COUNT(*) FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime IS NULL"
-        # simul_verify_query = "SELECT RadAcctId, AcctSessionId, UserName, NASIPAddress, NASPortId, FramedIPAddress, CallingStationId, FramedProtocol FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime IS NULL"
-
-
-
-       #######################################################################
-       #  Accounting Queries
-       #######################################################################
-       # accounting_onoff_query        - query for Accounting On/Off packets
-       # accounting_update_query       - query for Accounting update packets
-       # accounting_update_query_alt   - query for Accounting update packets
-       #                               (alternate in case first query fails)
-       # accounting_start_query        - query for Accounting start packets
-       # accounting_start_query_alt    - query for Accounting start packets
-       #                               (alternate in case first query fails)
-       # accounting_stop_query         - query for Accounting stop packets
-       # accounting_stop_query_alt     - query for Accounting start packets
-       #                               (alternate in case first query doesn't
-       #                                affect any existing rows in the table)
-       #######################################################################
-
-       accounting_onoff_query = "UPDATE ${acct_table1} \
-               SET AcctStopTime = ('%S'::timestamp - '%{Acct-Delay-Time:-0}'::interval), \
-               AcctSessionTime = (EXTRACT(EPOCH FROM('%S'::timestamp with time zone - AcctStartTime::timestamp with time zone - '%{Acct-Delay-Time:-0}'::interval)))::BIGINT, \
-               AcctTerminateCause='%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time:-0}' \
-               WHERE AcctSessionTime IS NULL AND AcctStopTime IS NULL AND NASIPAddress= '%{NAS-IP-Address}' AND AcctStartTime <= '%S'::timestamp"
-
-       accounting_update_query = "UPDATE ${acct_table1} \
-               SET FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \
-               AcctSessionTime = (EXTRACT(EPOCH FROM('%S'::timestamp with time zone - AcctStartTime::timestamp with time zone - '%{Acct-Delay-Time:-0}'::interval)))::BIGINT, \
-                AcctInputOctets = (('%{Acct-Input-Gigawords:-0}'::bigint << 32) + '%{Acct-Input-Octets:-0}'::bigint), \
-                AcctOutputOctets = (('%{Acct-Output-Gigawords:-0}'::bigint << 32) + '%{Acct-Output-Octets:-0}'::bigint) \
-               WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' \
-               AND NASIPAddress= '%{NAS-IP-Address}' AND AcctStopTime IS NULL"
-
-       accounting_update_query_alt = "INSERT into ${acct_table1} \
-               (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, \
-               AcctSessionTime, AcctAuthentic, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, \
-               ServiceType, FramedProtocol, FramedIPAddress, XAscendSessionSvrKey) \
-               values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', \
-               '%{NAS-Port}', '%{NAS-Port-Type}', ('%S'::timestamp -  '%{Acct-Delay-Time:-0}'::interval - '%{Acct-Session-Time:-0}'::interval), \
-               '%{Acct-Session-Time}', '%{Acct-Authentic}', \
-               (('%{Acct-Input-Gigawords:-0}'::bigint << 32) + '%{Acct-Input-Octets:-0}'::bigint), \
-               (('%{Acct-Output-Gigawords:-0}'::bigint << 32) + '%{Acct-Output-Octets:-0}'::bigint), '%{Called-Station-Id}', \
-               '%{Calling-Station-Id}', '%{Service-Type}', '%{Framed-Protocol}', \
-               NULLIF('%{Framed-IP-Address}', '')::inet, '%{X-Ascend-Session-Svr-Key}')"
-
-       accounting_start_query = "INSERT into ${acct_table1} \
-               (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctAuthentic, \
-               ConnectInfo_start, CalledStationId, CallingStationId, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, XAscendSessionSvrKey) \
-               values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', \
-               '%{NAS-Port}', '%{NAS-Port-Type}', ('%S'::timestamp - '%{Acct-Delay-Time:-0}'::interval), '%{Acct-Authentic}', '%{Connect-Info}', \
-               '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Service-Type}', '%{Framed-Protocol}', \
-               NULLIF('%{Framed-IP-Address}', '')::inet, '%{Acct-Delay-Time:-0}', '%{X-Ascend-Session-Svr-Key}')"
-
-       accounting_start_query_alt  = "UPDATE ${acct_table1} \
-               SET AcctStartTime = ('%S'::timestamp - '%{Acct-Delay-Time:-0}'::interval), AcctStartDelay = '%{Acct-Delay-Time:-0}', \
-               ConnectInfo_start = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' \
-               AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime IS NULL"
-
-       accounting_stop_query = "UPDATE ${acct_table2} \
-               SET AcctStopTime = ('%S'::timestamp - '%{Acct-Delay-Time:-0}'::interval), \
-               AcctSessionTime = NULLIF('%{Acct-Session-Time}', '')::bigint, \
-               AcctInputOctets = (('%{Acct-Input-Gigawords:-0}'::bigint << 32) + '%{Acct-Input-Octets:-0}'::bigint), \
-               AcctOutputOctets = (('%{Acct-Output-Gigawords:-0}'::bigint << 32) + '%{Acct-Output-Octets:-0}'::bigint), \
-               AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time:-0}', \
-               FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, ConnectInfo_stop = '%{Connect-Info}' \
-               WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' \
-               AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime IS NULL"
-
-       accounting_stop_query_alt = "INSERT into ${acct_table2} \
-               (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, \
-               AcctSessionTime, AcctAuthentic, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, \
-               AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStopDelay, XAscendSessionSvrKey) \
-               values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', \
-               '%{NAS-Port}', '%{NAS-Port-Type}', ('%S'::timestamp -  '%{Acct-Delay-Time:-0}'::interval - '%{Acct-Session-Time:-0}'::interval), \
-               ('%S'::timestamp - '%{Acct-Delay-Time:-0}'::interval), NULLIF('%{Acct-Session-Time}', '')::bigint, \
-               '%{Acct-Authentic}', '%{Connect-Info}', \
-               (('%{Acct-Input-Gigawords:-0}'::bigint << 32) + '%{Acct-Input-Octets:-0}'::bigint), \
-               (('%{Acct-Output-Gigawords:-0}'::bigint << 32) + '%{Acct-Output-Octets:-0}'::bigint), '%{Called-Station-Id}', \
-               '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', '%{Framed-Protocol}', \
-               NULLIF('%{Framed-IP-Address}', '')::inet, '%{Acct-Delay-Time:-0}', '%{X-Ascend-Session-Svr-Key}')"
-
-       #######################################################################
-       # Group Membership Queries
-       #######################################################################
-       # group_membership_query        - Check user group membership
-       #######################################################################
-
-       # Use these for case insensitive usernames. WARNING: Slower queries!
-#      group_membership_query = "SELECT GroupName FROM ${usergroup_table} WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}')"
-
-       group_membership_query = "SELECT GroupName FROM ${usergroup_table} WHERE UserName='%{SQL-User-Name}'"
-
-       #######################################################################
-       # Authentication Logging Queries
-       #######################################################################
-       # postauth_query                - Insert some info after authentication
-       #######################################################################
-       postauth_query = "INSERT INTO ${postauth_table} (username, pass, reply, authdate) VALUES ('%{User-Name}', '%{User-Password:-Chap-Password}', '%{reply:Packet-Type}', NOW())"
-
-}
index b889a77..0f5d15a 100644 (file)
@@ -1,11 +1,26 @@
 #
+#  Configuration file for the rlm_files module.
+#  Please see rlm_files(5) manpage for more information.
+#
+#  $Id$
+#
 #  This file is similar to the "users" file.  The check items
 #  are compared against the request, but the "reply" items are
-#  used to update the proxied packet, not the reply to the NAS>
+#  used to update the proxied packet, not the reply to the NAS.
+#
+#  You can use this file to re-write requests which are about to
+#  be sent to a home server.
+#
+
 #
-#  You can use this file to re-write requests which are about to be
-#  sent to a home server.
+#  Requests destinated to realm "extisp" are sent to a RADIUS
+#  home server hosted by an other company which doesn't know about
+#  the IP addresses of our NASes. Therefore we replace the value of
+#  the NAS-IP-Address attribute by a unique value we communicated
+#  to them.
 #
+#DEFAULT Realm == "extisp"
+#      NAS-IP-Address := 10.1.2.3
 
 #
 #  For all proxied packets, set the User-Name in the proxied packet
diff --git a/raddb/protocol_filter.conf b/raddb/protocol_filter.conf
new file mode 100755 (executable)
index 0000000..1687865
--- /dev/null
@@ -0,0 +1,130 @@
+#
+#      $Id$
+#
+#      Filter protocols by realm (or other key)
+#      The "protocol_filter" module reads this file, and implements
+#      the restrictions contained in it.
+#
+#      The main purpose of this configuration file is to permit the
+#      administrator to control, by realm (or any other key), which
+#      protocols the request is permitted to contain.  This allows
+#      the server to permit users in one realm to use (say) EAP, and
+#      to deny EAP to users in other realms.
+#
+#      The key is used to look up entries by subsection.  Within each
+#      subsection, there is a list of attributes, with value "permit"
+#      or "deny".  When a request comes in, the attributes from the
+#      request packet are looked up in the appropriate section given
+#      by the key.  If the section has an entry which says "permit"
+#      for that attribute, the request is permitted to continue.  If
+#      the section has and entry which says "deny" for that
+#      attribute, the request is immediately rejected.
+#
+#      The default (if the attribute is not listed in the subsection)
+#      is to permit the attribute.
+#
+#      The attribute names MUST be spelled the same way as in
+#      the dictionary files.
+#
+#      The entries can have sub-sections, too.  Each subsection
+#      MUST begin with a "key" entry, which is used to apply
+#      one of the rules in the subsection.  Only one rule from
+#      each subsection is applied, and that rule is the one pointed
+#      to by the key.  The key is dynamically expanded (see doc/variables.txt)
+#      at run time, for each request as it comes in.
+#
+DEFAULT {
+       #
+       #  There is no key here, as the key is always hard-coded to be
+       #  attributes in the request.  For a request to pass the tests
+       #  in this section, ALL of the rules below must permit the
+       #  request to pass.  That is, the rules are logically ANDed
+       #  together.
+       #
+
+       # allow requests to contain a user password attribute.
+       User-Password = permit
+
+       # Deny requests which try to use MS-CHAP, for testing.
+       # just because we can.  Both MS-CHAPv1 and MS-CHAPv2
+       # use MS-CHAP-Challenge, so we just deny that.
+       # If we wanted to deny just MS-CHAPv2, we would deny the
+       # MS-CHAP2-Response attribute.
+       MS-CHAP-Challenge = deny
+
+       #
+       #  Allow some EAP protocols, but not others.
+       #
+       #  The use of the EAP-Type for the key, below, means that the
+       #  protocol_filter module MUST be listed after "eap" in the
+       #  "authorize" section.
+       #
+       EAP-Message {
+               #
+               #  See the dictionary for the names of the EAP-Types.
+               #  e.g. VALUE EAP-Type <name> <number>
+               #
+               #  The names for the EAP types MUST be exactly the same
+               #  as the names in the dictionary file.
+               #
+               key = %{EAP-Type:-DEFAULT}
+
+               #  This is insecure, so we don't allow it.
+               MD5-Challenge = deny
+
+               # Permit one EAP type.  We picked this one at random.
+               EAP-MSCHAP-V2 = permit          
+
+               DEFAULT = deny
+       }
+}
+
+#
+#  A more complicated example.
+#
+example.com {
+       #
+       #  For various reasons, we often would like to use the same
+       #  configuration entries inside, and outside of the TLS tunnel.
+       #  This allows us to keep all of the per-realm configuration in
+       #  one place.
+       #
+       EAP-Message {
+               #
+               #  Define subsections, based on the request being
+               #  inside, or outside, of the TLS tunnel.
+               #
+               key = %{FreeRADIUS-Proxied-To:-Outer}
+
+               #
+               #  Outside of the tunnel.
+               #
+               Outer {
+                       key = %{EAP-Type:-DEFAULT}
+
+                       #  This is insecure, so we don't allow it.
+                       #  It's not necessary, as the DEFAULT below will
+                       #  take care of it, but this is a good example.
+                       MD5-Challenge = deny
+
+                       # We allow TTLS & PEAP as EAP types.
+                       EAP-TTLS = permit
+
+                       PEAP = permit
+
+                       DEFAULT = deny
+               }
+
+               #
+               #  Inside of the tunnel.
+               #
+               127.0.0.1 {
+                       key = %{EAP-Type:-DEFAULT}
+
+                       #  We don't do TLS inside of TTLS.
+                       EAP-TLS = deny
+
+                       DEFAULT = permit
+               }
+       }
+}
index 032b7a0..433178d 100644 (file)
 #  to which it sends proxy requests.
 #
 proxy server {
-
-#
-#  If the NAS re-sends the request to us, we can immediately re-send
-#  the proxy request to the end server.  To do so, use 'yes' here.
-#
-#  If this is set to 'no', then we send the retries on our own schedule,
-#  and ignore any duplicate NAS requests.
-#
-#  If you want to have the server send proxy retries ONLY when the NAS
-#  sends it's retries to the server, then set this to 'yes', and
-#  set the other proxy configuration parameters to 0 (zero).
-#
-#  Additionally, if you want 'failover' to work, the server must manage
-#  retries and timeouts.  Therefore, if this is set to yes, then no
-#  failover functionality is possible.
-#
-       synchronous = no
-
 #
 #  The time (in seconds) to wait for a response from the proxy, before
 #  re-sending the proxied request.
@@ -97,22 +79,6 @@ proxy server {
 #
        default_fallback = yes
 
-#
-#  Older versions of the server would pass proxy requests through the
-#  'authorize' sections twice; once when the packet was received
-#  from the NAS, and again after the reply was received from the home
-#  server.  Now that we have a 'post_proxy' section, the replies from
-#  the home server should be sent through that, instead of through
-#  the 'authorize' section again.
-#
-#  However, for backwards compatibility, this behaviour is configurable.
-#  The default configuration is 'no', because this option is deprecated
-#  and will be removed in the future.
-#
-#  allowed values: {yes, no}
-#
-       post_proxy_authorize = no
-
 }
 
 #######################################################################
index 87ce019..16daa81 100644 (file)
@@ -40,6 +40,19 @@ run_dir = ${localstatedir}/run/radiusd
 log_file = ${logdir}/radius.log
 
 #
+#  Destination for log messages.  This can be one of:
+#
+#      files - log to ${log_file}, as defined above.
+#      syslog - to syslog (see also the log{} section, below)
+#      stdout - standard output
+#      stderr - standard error.
+#
+#  The command-line option "-X" over-rides this option, and forces
+#  logging to go to stdout.
+#
+log_destination = files
+
+#
 # libdir: Where to find the rlm_* modules.
 #
 #   This should be automatically set at configuration time.
@@ -127,15 +140,6 @@ pidfile = ${run_dir}/radiusd.pid
 #
 max_request_time = 30
 
-#  delete_blocked_requests: If the request takes MORE THAN 'max_request_time'
-#  to be handled, then maybe the server should delete it.
-#
-#  If you're running in threaded, or thread pool mode, this setting
-#  should probably be 'no'.  Setting it to 'yes' when using a threaded
-#  server MAY cause the server to crash!
-#
-delete_blocked_requests = no
-
 #  cleanup_delay: The time to wait (in seconds) before cleaning up
 #  a reply which was sent to the NAS.
 #
@@ -174,78 +178,83 @@ cleanup_delay = 5
 #
 max_requests = 1024
 
-#  bind_address:  Make the server listen on a particular IP address, and
-#  send replies out from that address.  This directive is most useful
-#  for machines with multiple IP addresses on one interface.
-#
-#  It can either contain "*", or an IP address, or a fully qualified
-#  Internet domain name.  The default is "*"
-#
-#  As of 1.0, you can also use the "listen" directive.  See below for
-#  more information.
-#
-bind_address = *
-
-#  port: Allows you to bind FreeRADIUS to a specific port.
-#
-#  The default port that most NAS boxes use is 1645, which is historical.
-#  RFC 2138 defines 1812 to be the new port.  Many new servers and
-#  NAS boxes use 1812, which can create interoperability problems.
-#
-#  The port is defined here to be 0 so that the server will pick up
-#  the machine's local configuration for the radius port, as defined
-#  in /etc/services.
+#  listen: Make the server listen on a particular IP address, and send
+#  replies out from that address. This directive is most useful for
+#  hosts with multiple IP addresses on one interface.
 #
-#  If you want to use the default RADIUS port as defined on your server,
-#  (usually through 'grep radius /etc/services') set this to 0 (zero).
+#  If you want the server to listen on additional addresses, or on
+#  additionnal ports, you can use multiple "listen" sections.
 #
-#  A port given on the command-line via '-p' over-rides this one.
-#
-#  As of 1.0, you can also use the "listen" directive.  See below for
-#  more information.
-#
-port = 0
-
+#  Each section make the server listen for only one type of packet,
+#  therefore authentication and accounting have to be configured in
+#  different sections.
 #
-#  By default, the server uses "bind_address" to listen to all IP's
-#  on a machine, or just one IP.  The "port" configuration is used
-#  to select the authentication port used when listening on those
-#  addresses.
+#  The server ignore all "listen" section if you are using '-i' and '-p'
+#  on the command line.
 #
-#  If you want the server to listen on additional addresses, you can
-#  use the "listen" section.  A sample section (commented out) is included
-#  below.  This "listen" section duplicates the functionality of the
-#  "bind_address" and "port" configuration entries, but it only listens
-#  for authentication packets.
-#
-#  If you comment out the "bind_address" and "port" configuration entries,
-#  then it becomes possible to make the server accept only accounting,
-#  or authentication packets.  Previously, it always listened for both
-#  types of packets, and it was impossible to make it listen for only
-#  one type of packet.
-#
-#listen {
+listen {
        #  IP address on which to listen.
        #  Allowed values are:
        #       dotted quad (1.2.3.4)
        #       hostname    (radius.example.com)
        #       wildcard    (*)
-#      ipaddr = *
+       ipaddr = *
+
+       #  OR, you can use an IPv6 address, but not both
+       #  at the same time.
+#      ipv6addr = ::   # any.  ::1 == localhost
 
        #  Port on which to listen.
        #  Allowed values are:
        #       integer port number (1812)
        #       0 means "use /etc/services for the proper port"
-#      port = 0
+       port = 0
 
        #  Type of packets to listen for.
        #  Allowed values are:
        #       auth    listen for authentication packets
        #       acct    listen for accounting packets
        #
-#      type = auth
-#}
+       type = auth
+
+       #  Some systems support binding to an interface, in addition
+       #  to the IP address.  This feature isn't strictly necessary,
+       #  but for sites with many IP addresses on one interface,
+       #  it's useful to say "listen on all addresses for eth0".
+       #
+       #  If your system does not support this feature, you will
+       #  get an error if you try to use it.
+       #
+#      interface = eth0
 
+       #  Per-socket lists of clients.  This is a very useful feature.
+       #
+       #  The name here is a reference to a section elsewhere in
+       #  radiusd.conf, or clients.conf.  Having the name as
+       #  a reference allows multiple sockets to use the same
+       #  set of clients.
+       #
+       #  If this configuration is used, then the global list of clients
+       #  is IGNORED for this "listen" section.  Take care configuring
+       #  this feature, to ensure you don't accidentally disable a
+       #  client you need.
+       #
+       #  See clients.conf for the configuration of "per_socket_clients".
+       #
+#      clients = per_socket_clients
+}
+
+#  This second "listen" section is for listening on the accounting
+#  port, too.
+#
+listen {
+       ipaddr = *
+#      ipv6addr = ::
+       port = 0
+       type = acct
+#      interface = eth0
+#      clients = per_socket_clients
+}
 
 #  hostname_lookups: Log the names of clients or just their IP addresses
 #  e.g., www.freeradius.org (on) or 206.47.27.232 (off).
@@ -283,6 +292,20 @@ allow_core_dumps = no
 regular_expressions    = @REGEX@
 extended_expressions   = @REGEX_EXTENDED@
 
+#
+#  Logging section.  The various "log_*" configuration items
+#  will eventually be moved here.
+#
+log {
+       #
+       #  Which syslog facility to use, if ${log_destination} == "syslog"
+       #
+       #  The exact values permitted here are OS-dependent.  You probably
+       #  don't want to change this.
+       #
+       syslog_facility = daemon
+}
+
 #  Log the full User-Name attribute, as it was found in the request.
 #
 # allowed values: {no, yes}
@@ -304,54 +327,6 @@ log_auth = no
 log_auth_badpass = no
 log_auth_goodpass = no
 
-# usercollide:  Turn "username collision" code on and off.  See the
-# "doc/duplicate-users" file
-#
-#  WARNING
-#  !!!!!!!  Setting this to "yes" may result in the server behaving
-#  !!!!!!!  strangely.  The "username collision" code will ONLY work
-#  !!!!!!!  with clear-text passwords.  Even then, it may not do what
-#  !!!!!!!  you want, or what you expect.
-#  !!!!!!!
-#  !!!!!!!  We STRONGLY RECOMMEND that you do not use this feature,
-#  !!!!!!!  and that you find another way of acheiving the same goal.
-#  !!!!!!!
-#  !!!!!!!  e,g. module fail-over.  See 'doc/configurable_failover'
-#  WARNING
-#
-usercollide = no
-
-# lower_user / lower_pass:  
-# Lower case the username/password "before" or "after"
-# attempting to authenticate.  
-#
-#  If "before", the server will first modify the request and then try
-#  to auth the user.  If "after", the server will first auth using the
-#  values provided by the user.  If that fails it will reprocess the
-#  request after modifying it as you specify below.
-#
-#  This is as close as we can get to case insensitivity.  It is the
-#  admin's job to ensure that the username on the auth db side is
-#  *also* lowercase to make this work
-#
-# Default is 'no' (don't lowercase values)
-# Valid values = "before" / "after" / "no"
-#
-lower_user = no
-lower_pass = no
-
-# nospace_user / nospace_pass:
-#
-#  Some users like to enter spaces in their username or password
-#  incorrectly.  To save yourself the tech support call, you can
-#  eliminate those spaces here:
-#
-# Default is 'no' (don't remove spaces)
-# Valid values = "before" / "after" / "no" (explanation above)
-#
-nospace_user = no
-nospace_pass = no
-
 #  The program to execute to do concurrency checks.
 checkrad = ${sbindir}/checkrad
 
@@ -396,17 +371,19 @@ security {
        #  status_server: Whether or not the server will respond
        #  to Status-Server requests.
        #
-       #  Normally this should be set to "no", because they're useless.
-       #  See: http://www.freeradius.org/rfc/rfc2865.html#Keep-Alives
+       #  When sent a Status-Server message, the server responds with
+       #  an Access-Accept or Accounting-Response packet.
        #
-       #  However, certain NAS boxes may require them. 
+       #  This is mainly useful for administrators who want to "ping"
+       #  the server, without adding test users, or creating fake
+       #  accounting packets.
        #
-       #  When sent a Status-Server message, the server responds with
-       #  an Access-Accept packet, containing a Reply-Message attribute,
-       #  which is a string describing how long the server has been
-       #  running.
+       #  It's also useful when a NAS marks a RADIUS server "dead".
+       #  The NAS can periodically "ping" the server with a Status-Server
+       #  packet.  If the server responds, it must be alive, and the
+       #  NAS can start using it for real requests.
        #
-       status_server = no
+       status_server = yes
 }
 
 # PROXY CONFIGURATION
@@ -559,22 +536,17 @@ modules {
 
        # PAP module to authenticate users based on their stored password
        #
-       #  As of 1.1.4, the "encryption_scheme" configuration should
-       #  no longer be used.  For backwards compatibility, it will still
-       #  work as before, but we recommend that it is not used.
-       # 
-       #  The replacement is "auto_header = yes".
-       #  For backwards compatibility, the default is "auto_header = no",
-       #  but we recommend reviewing your use of the PAP module, based
-       #  on the documentation in "man rlm_pap".
-       #
-       #  The new capability in this module makes it MUCH easier to
-       #  configure the server for multiple crypt/hash schemes, AND
-       #  it supports more methods than before.  Please read "man rlm_pap"
-       #  for more detailed documentation.
-       #
+       #  Supports multiple encryption/hash schemes.  See "man passwd"
+       #  for details.
+       #
+       #  The "auto_header" configuration item can be set to "yes".
+       #  In this case, the module will look inside of the User-Password
+       #  attribute for the headers {crypt}, {clear}, etc., and will
+       #  automatically create the attribute on the right-hand side,
+       #  with the correct value.  It will also automatically handle
+       #  Base-64 encoded data, hex strings, and binary data.
        pap {
-               auto_header = yes
+               auto_header = no
        }
 
        # CHAP module
@@ -610,45 +582,11 @@ modules {
        # Unix /etc/passwd style authentication
        #
        unix {
+               #  As of 1.1.0, the Unix module no longer reads,
+               #  or caches /etc/passwd, /etc/shadow, or /etc/group.
+               #  If you wish to cache those files, see the passwd
+               #  module, above.
                #
-               #  Cache /etc/passwd, /etc/shadow, and /etc/group
-               #
-               #  The default is to NOT cache them.
-               #
-               #  For FreeBSD and NetBSD, you do NOT want to enable
-               #  the cache, as it's password lookups are done via a
-               #  database, so set this value to 'no'.
-               #
-               #  Some systems (e.g. RedHat Linux with pam_pwbd) can
-               #  take *seconds* to check a password, when th passwd
-               #  file containing 1000's of entries.  For those systems,
-               #  you should set the cache value to 'yes', and set
-               #  the locations of the 'passwd', 'shadow', and 'group'
-               #  files, below.
-               #
-               # allowed values: {no, yes}
-               cache = no
-
-               # Reload the cache every 600 seconds (10mins). 0 to disable.
-               cache_reload = 600
-
-               #
-               #  Define the locations of the normal passwd, shadow, and
-               #  group files.
-               #
-               #  'shadow' is commented out by default, because not all
-               #  systems have shadow passwords.
-               #
-               #  To force the module to use the system password functions,
-               #  instead of reading the files, leave the following entries
-               #  commented out.
-               #
-               #  This is required for some systems, like FreeBSD,
-               #  and Mac OSX.
-               #
-               #       passwd = /etc/passwd
-               #       shadow = /etc/shadow
-               #       group = /etc/group
 
                #
                #  The location of the "wtmp" file.
@@ -743,74 +681,109 @@ $INCLUDE ${confdir}/eap.conf
        #       
        ldap {
                server = "ldap.your.domain"
-               # identity = "cn=admin,o=My Org,c=UA"
-               # password = mypass
+               #identity = "cn=admin,o=My Org,c=UA"
+               #password = mypass
                basedn = "o=My Org,c=UA"
                filter = "(uid=%{Stripped-User-Name:-%{User-Name}})"
-               # base_filter = "(objectclass=radiusprofile)"
-
-               # set this to 'yes' to use TLS encrypted connections
-               # to the LDAP database by using the StartTLS extended
-               # operation.
-               # The StartTLS operation is supposed to be used with normal
-               # ldap connections instead of using ldaps (port 689) connections
-               start_tls = no
-
-               # tls_cacertfile        = /path/to/cacert.pem
-               # tls_cacertdir         = /path/to/ca/dir/
-               # tls_certfile          = /path/to/radius.crt
-               # tls_keyfile           = /path/to/radius.key
-               # tls_randfile          = /path/to/rnd
-               # tls_require_cert      = "demand"
+               #base_filter = "(objectclass=radiusprofile)"
+
+               #  How many connections to keep open to the LDAP server.
+               #  This saves time over opening a new LDAP socket for
+               #  every authentication request.
+               ldap_connections_number = 5
+
+               timeout = 4
+               timelimit = 3
+               net_timeout = 1
+
+               #
+               #  This subsection configures the tls related items
+               #  that control how FreeRADIUS connects to an LDAP
+               #  server.  It contains all of the "tls_*" configuration
+               #  entries used in older versions of FreeRADIUS.  Those
+               #  configuration entries can still be used, but we recommend
+               #  using these.
+               #
+               tls {
+                       # Set this to 'yes' to use TLS encrypted connections
+                       # to the LDAP database by using the StartTLS extended
+                       # operation.
+                       #                       
+                       # The StartTLS operation is supposed to be
+                       # used with normal ldap connections instead of
+                       # using ldaps (port 689) connections
+                       start_tls = no
+
+                       # cacertfile    = /path/to/cacert.pem
+                       # cacertdir             = /path/to/ca/dir/
+                       # certfile              = /path/to/radius.crt
+                       # keyfile               = /path/to/radius.key
+                       # randfile              = /path/to/rnd
+                       # require_cert  = "demand"
+               }
 
                # default_profile = "cn=radprofile,ou=dialup,o=My Org,c=UA"
                # profile_attribute = "radiusProfileDn"
-               access_attr = "dialupAccess"
+               access_attr = "dialupAccess"
 
                # Mapping of RADIUS dictionary attributes to LDAP
                # directory attributes.
                dictionary_mapping = ${raddbdir}/ldap.attrmap
 
-               ldap_connections_number = 5
-
-               #
-               # NOTICE: The password_header directive is NOT case insensitive
-               #
-               # password_header = "{clear}"
-               #
-               # Set:
-               #       password_attribute = nspmPassword
-               #
-               # to get the user's password from a Novell eDirectory
-               # backend. This will work *only if* freeRADIUS is
-               # configured to build with --with-edir option.
-               #
-               #
-               #  The server can usually figure this out on its own, and pull
-               #  the correct User-Password or NT-Password from the database.
-               #
-               #  Note that NT-Passwords MUST be stored as a 32-digit hex
-               #  string, and MUST start off with "0x", such as:
-               #
-               #       0x000102030405060708090a0b0c0d0e0f
-               #
-               #  Without the leading "0x", NT-Passwords will not work.
-               #  This goes for NT-Passwords stored in SQL, too.
+               #  Set password_attribute = nspmPassword to get the
+               #  user's password from a Novell eDirectory
+               #  backend. This will work ONLY IF FreeRADIUS has been
+               #  built with the --with-edir configure option.
                #
                # password_attribute = userPassword
-               #
-               # Un-comment the following to disable Novell eDirectory account
-               # policy check and intruder detection. This will work *only if*
-               # FreeRADIUS is configured to build with --with-edir option.
-               #
-               edir_account_policy_check=no
+
+               #  As of 1.1.0, the LDAP module will auto-discover
+               #  the password headers (which are non-standard).
+               #  It will use the following table to map passwords
+               #  to RADIUS attributes.  The PAP module (see above)
+               #  can then automatically determine the hashing
+               #  method to use to authenticate the user.
+               #
+               #       Header          Attribute
+               #       ------          ---------
+               #       {clear}         User-Password
+               #       {cleartext}     User-Password
+               #       {md5}           MD5-Password
+               #       {smd5}          SMD5-Password
+               #       {crypt}         Crypt-Password
+               #       {sha}           SHA-Password
+               #       {ssha}          SSHA-Password
+               #       {nt}            NT-Password
+               #       {ns-mta-md5}    NS-MTA-MD5-Password
+               #               
+               #
+               #  The headers are compared in a case-insensitive manner.
+               #  The format of the password in LDAP (base 64-encoded, hex,
+               #  clear-text, whatever) is not that important.  The PAP
+               #  module will figure it out.
+               #
+               #  The default for "auto_header" is "no", to enable backwards
+               #  compatibility with the "password_header" directive,
+               #  which is now deprecated.  If this is set to "yes",
+               #  then the above table will be used, and the
+               #  "password_header" directive will be ignored.
+
+               #auto_header = yes
+
+               #  Un-comment the following to disable Novell
+               #  eDirectory account policy check and intruder
+               #  detection. This will work *only if* FreeRADIUS is
+               #  configured to build with --with-edir option.
+               #
+               edir_account_policy_check = no
+
+               #
+               #  Group membership checking.  Disabled by default.
                #
                # groupname_attribute = cn
                # groupmembership_filter = "(|(&(objectClass=GroupOfNames)(member=%{Ldap-UserDn}))(&(objectClass=GroupOfUniqueNames)(uniquemember=%{Ldap-UserDn})))"
                # groupmembership_attribute = radiusGroupName
-               timeout = 4
-               timelimit = 3
-               net_timeout = 1
+
                # compare_check_items = yes
                # do_xlat = yes
                # access_attr_used_for_allow = yes
@@ -846,8 +819,6 @@ $INCLUDE ${confdir}/eap.conf
        #
        #            Field marked as ',' may contain a comma separated list
        #            of attributes.
-       #   authtype - if record found this Auth-Type is used to authenticate
-       #            user
        #   hashsize - hashtable size. If 0 or not specified records are not
        #            stored in memory and file is red on every request.
        #   allowmultiplekeys - if few records for every key are allowed
@@ -862,7 +833,6 @@ $INCLUDE ${confdir}/eap.conf
        #passwd etc_smbpasswd {
        #       filename = /etc/smbpasswd
        #       format = "*User-Name::LM-Password:NT-Password:SMB-Account-CTRL-TEXT::"
-       #       authtype = MS-CHAP
        #       hashsize = 100
        #       ignorenislike = no
        #       allowmultiplekeys = no
@@ -888,18 +858,10 @@ $INCLUDE ${confdir}/eap.conf
        #  preacct sections.
        #
        #  Four config options:
-       #       format         -  must be 'prefix' or 'suffix'
+       #       format         -  must be "prefix" or "suffix"
+       #                         The special cases of "DEFAULT"
+       #                         and "NULL" are allowed, too.
        #       delimiter      -  must be a single character
-       #       ignore_default -  set to 'yes' or 'no'
-       #       ignore_null    -  set to 'yes' or 'no'
-       #
-       #  ignore_default and ignore_null can be set to 'yes' to prevent
-       #  the module from matching against DEFAULT or NULL realms.  This
-       #  may be useful if you have have multiple instances of the
-       #  realm module.
-       #
-       #  They both default to 'no'.
-       #
 
        #  'realm/username'
        #
@@ -907,8 +869,6 @@ $INCLUDE ${confdir}/eap.conf
        realm IPASS {
                format = prefix
                delimiter = "/"
-               ignore_default = no
-               ignore_null = no
        }
 
        #  'username@realm'
@@ -916,8 +876,6 @@ $INCLUDE ${confdir}/eap.conf
        realm suffix {
                format = suffix
                delimiter = "@"
-               ignore_default = no
-               ignore_null = no
        }
 
        #  'username%realm'
@@ -925,8 +883,6 @@ $INCLUDE ${confdir}/eap.conf
        realm realmpercent {
                format = suffix
                delimiter = "%"
-               ignore_default = no
-               ignore_null = no
        }
 
        #
@@ -935,8 +891,6 @@ $INCLUDE ${confdir}/eap.conf
        realm ntdomain {
                format = prefix
                delimiter = "\\"
-               ignore_default = no
-               ignore_null = no
        }       
 
        #  A simple value checking module
@@ -1065,6 +1019,11 @@ $INCLUDE ${confdir}/eap.conf
        # Livingston-style 'users' file
        #
        files {
+               # The default key attribute to use for matches.  The content
+               # of this attribute is used to match the "name" of the
+               # entry.
+               #key = "%{Stripped-User-Name:-%{User-Name}}"
+
                usersfile = ${confdir}/users
                acctusersfile = ${confdir}/acct_users
                preproxy_usersfile = ${confdir}/preproxy_users
@@ -1112,6 +1071,17 @@ $INCLUDE ${confdir}/eap.conf
                detailperm = 0600
 
                #
+               #  Every entry in the detail file has a header which
+               #  is a timestamp.  By default, we use the ctime
+               #  format (see "man ctime" for details).
+               #
+               #  The header can be customized by editing this
+               #  string.  See "doc/variables.txt" for a description
+               #  of what can be put here.
+               #
+               header = "%t"
+
+               #
                # Certain attributes such as User-Password may be
                # "sensitive", so they should not be printed in the
                # detail file.  This section lists the attributes
@@ -1122,6 +1092,7 @@ $INCLUDE ${confdir}/eap.conf
                #suppress {
                        # User-Password
                #}
+
        }
 
        #
@@ -1140,6 +1111,11 @@ $INCLUDE ${confdir}/eap.conf
                #  This MUST be 0600, otherwise anyone can read
                #  the users passwords!
                # detailperm = 0600
+
+               # You may also strip out passwords completely
+               #suppress {
+                       # User-Password
+               #}
        # }
 
        #
@@ -1153,9 +1129,6 @@ $INCLUDE ${confdir}/eap.conf
        # detail reply_log {
                # detailfile = ${radacctdir}/%{Client-IP-Address}/reply-detail-%Y%m%d
 
-               #
-               #  This MUST be 0600, otherwise anyone can read
-               #  the users passwords!
                # detailperm = 0600
        # }
 
@@ -1172,6 +1145,11 @@ $INCLUDE ${confdir}/eap.conf
                #  This MUST be 0600, otherwise anyone can read
                #  the users passwords!
                # detailperm = 0600
+
+               # You may also strip out passwords completely
+               #suppress {
+                       # User-Password
+               #}
        # }
 
        #
@@ -1183,9 +1161,6 @@ $INCLUDE ${confdir}/eap.conf
        # detail post_proxy_log {
                # detailfile = ${radacctdir}/%{Client-IP-Address}/post-proxy-detail-%Y%m%d
 
-               #
-               #  This MUST be 0600, otherwise anyone can read
-               #  the users passwords!
                # detailperm = 0600
        # }
 
@@ -1247,17 +1222,11 @@ $INCLUDE ${confdir}/eap.conf
        #  Include another file that has the SQL-related configuration.
        #  This is another file only because it tends to be big.
        #
-       #  The following configuration file is for use with MySQL.
-       #
-       #  For Postgresql, use:         ${confdir}/postgresql.conf
-       #  For MS-SQL, use:             ${confdir}/mssql.conf
-       #  For Oracle, use:             ${confdir}/oraclesql.conf
-       #
        $INCLUDE  ${confdir}/sql.conf
 
 
        #  For Cisco VoIP specific accounting with Postgresql,
-       #  use:         ${confdir}/pgsql-voip.conf
+       #  use:         ${confdir}/sql/postgresql-voip-postpaid.conf
        #
        #  You will also need the sql schema from:
        #        src/billing/cisco_h323_db_schema-postgres.sql
@@ -1331,18 +1300,42 @@ $INCLUDE ${confdir}/eap.conf
        # attr_filter - filters the attributes received in replies from
        # proxied servers, to make sure we send back to our RADIUS client
        # only allowed attributes.
-       attr_filter {
+       attr_filter attr_filter.post-proxy {
                attrsfile = ${confdir}/attrs
        }
 
+       # attr_filter - filters the attributes in the packets we send to
+       # the RADIUS home servers.
+       attr_filter attr_filter.pre-proxy {
+               attrsfile = ${confdir}/attrs.pre-proxy
+       }
+
+       # Enforce RFC requirements on the contents of Access-Reject
+       # packets.  See the comments at the top of the file for
+       # more details.
+       #
+       attr_filter attr_filter.access_reject {
+               key = %{User-Name}
+               attrsfile = ${confdir}/attrs.access_reject
+       }
+
+       #  Enforce RFC requirements on the contents of the
+       #  Accounting-Response packets.  See the comments at the
+       #  top of the file for more details.
+       #
+       attr_filter attr_filter.accounting_response {
+               key = %{User-Name}
+               attrsfile = ${confdir}/attrs.accounting_response
+       }
+
        #  counter module:
        #  This module takes an attribute (count-attribute).
        #  It also takes a key, and creates a counter for each unique
        #  key.  The count is incremented when accounting packets are
        #  received by the server.  The value of the increment depends
        #  on the attribute type.
-       #  If the attribute is Acct-Session-Time or of an integer type we add the
-       #  value of the attribute. If it is anything else we increase the
+       #  If the attribute is Acct-Session-Time or of an integer type we add
+       #  the value of the attribute. If it is anything else we increase the
        #  counter by one.
        #
        #  The 'reset' parameter defines when the counters are all reset to
@@ -1379,6 +1372,8 @@ $INCLUDE ${confdir}/eap.conf
        #  the radius.log
        #  If the count attribute is Acct-Session-Time then on each login
        #  we send back the remaining online time as a Session-Timeout attribute
+       #  ELSE and if the reply-name is set, we send back that attribute.
+       #  The reply-name attribute MUST be of an integer type.
        #
        #  The counter-name can also be used instead of using the check-name
        #  like below:
@@ -1404,6 +1399,7 @@ $INCLUDE ${confdir}/eap.conf
                reset = daily
                counter-name = Daily-Session-Time
                check-name = Max-Daily-Session
+               reply-name = Session-Timeout
                allowed-servicetype = Framed-User
                cache-size = 5000
        }
@@ -1449,11 +1445,6 @@ $INCLUDE ${confdir}/eap.conf
        #  attribute to use to access the counter in the 'users' file
        #  or SQL radcheck or radcheckgroup tables.
        #
-       #  The 'reply-name' parameter is the name the the attribute
-       #  which holds the time remaining for the user.  This is normally
-       #  Session-Timeout, which makes the NAS disconnect the user
-       #  once the session time is up.
-       #
        #  DEFAULT  Max-Daily-Session > 3600, Auth-Type = Reject
        #      Reply-Message = "You've used up more than one hour today"
        #
@@ -1567,6 +1558,8 @@ $INCLUDE ${confdir}/eap.conf
        #  The value of the attribute will be replaced with the output
        #  of the program which is executed.  Due to RADIUS protocol
        #  limitations, any output over 253 bytes will be ignored.
+       #
+       #  The module also registers a few paircompare functions
        expr {
        }
 
@@ -1581,6 +1574,48 @@ $INCLUDE ${confdir}/eap.conf
        }
 
        #
+       # The expiration module. This handles the Expiration attribute
+       # It should be included in the *end* of the authorize section
+       # in order to handle user Expiration. It should also be included
+       # in the instantiate section in order to register the Expiration
+       # compare function
+       #
+       expiration {
+               #
+               # The Reply-Message which will be sent back in case the
+               # account has expired. Dynamic substitution is supported
+               #
+               reply-message = "Password Has Expired\r\n" 
+#              reply-message = "Your account has expired, %{User-Name}\r\n"
+       }
+
+       # The logintime module. This handles the Login-Time,
+       # Current-Time, and Time-Of-Day attributes.  It should be
+       # included in the *end* of the authorize section in order to
+       # handle Login-Time checks. It should also be included in the
+       # instantiate section in order to register the Current-Time
+       # and Time-Of-Day comparison functions.
+       #
+       # When the Login-Time attribute is set to some value, and the
+       # user has bene permitted to log in, a Session-Timeout is
+       # calculated based on the remaining time.  See "doc/README".
+       #
+       logintime {
+               #
+               # The Reply-Message which will be sent back in case
+               # the account is calling outside of the allowed
+               # timespan. Dynamic substitution is supported.
+               #
+               reply-message = "You are calling outside your allowed timespan\r\n"
+#              reply-message = "Outside allowed timespan (%{check:Login-Time}), %{User-Name}\r\n"
+
+               # The minimum timeout (in seconds) a user is allowed
+               # to have. If the calculated timeout is lower we don't
+               # allow the logon. Some NASes do not handle values
+               # lower than 60 seconds well.
+               minimum-timeout = 60
+       }
+       #
        #  Execute external programs
        #
        #  This module is useful only for 'xlat'.  To use it,
@@ -1600,6 +1635,8 @@ $INCLUDE ${confdir}/eap.conf
        exec {
                wait = yes
                input_pairs = request
+               shell_escape = yes
+               output = none
        }
 
        #
@@ -1613,7 +1650,24 @@ $INCLUDE ${confdir}/eap.conf
        #  one section (e.g. 'authorize', 'pre_proxy', etc), then it
        #  is probably best to define a different instance of the
        #  'exec' module for every section.     
-       #       
+       #
+       #  The return value of the program run determines the result
+       #  of the exec instance call as follows:
+       #  (See doc/configurable_failover for details)
+       #
+       #  < 0 : fail      the module failed
+       #  = 0 : ok        the module succeeded
+       #  = 1 : reject    the module rejected the user
+       #  = 2 : fail      the module failed
+       #  = 3 : ok        the module succeeded
+       #  = 4 : handled   the module has done everything to handle the request
+       #  = 5 : invalid   the user's configuration entry was invalid
+       #  = 6 : userlock  the user was locked out
+       #  = 7 : notfound  the user was not found
+       #  = 8 : noop      the module did nothing
+       #  = 9 : updated   the module updated information in the request
+       #  > 9 : fail      the module failed
+       #
        exec echo {
                #
                #  Wait for the program to finish.
@@ -1679,6 +1733,18 @@ $INCLUDE ${confdir}/eap.conf
                #  being sent to the NAS.
                #
                #packet_type = Access-Accept
+
+               #
+               #  Should we escape the environment variables?
+               #  
+               #  If this is set, all the RADIUS attributes
+               #  are capitalised and dashes replaced with
+               #  underscores. Also, RADIUS values are surrounded
+               #  with double-quotes.
+               #
+               #  That is to say: User-Name=BobUser => USER_NAME="BobUser"
+               shell_escape = yes
+
        }
 
        #  Do server side ip pool management. Should be added in post-auth and
@@ -1689,10 +1755,15 @@ $INCLUDE ${confdir}/eap.conf
        #  attribute in the user profiles and use different pools
        #  for different users. The Pool-Name attribute is a *check* item not
        #  a reply item.
+       #  The Pool-Name should be set to the ippool module instance name or to
+       #  DEFAULT to match any module.
        #
        # Example:
        # radiusd.conf: ippool students { [...] }
+       #               ippool teachers { [...] }
        # users file  : DEFAULT Group == students, Pool-Name := "students"
+       #               DEFAULT Group == teachers, Pool-Name := "teachers"
+       #               DEFAULT Group == other, Pool-Name := "DEFAULT"
        #
        # ********* IF YOU CHANGE THE RANGE PARAMETERS YOU MUST *********
        # ********* THEN ERASE THE DB FILES                     *********
@@ -1724,6 +1795,10 @@ $INCLUDE ${confdir}/eap.conf
                # maximum-timeout: If not zero specifies the maximum time in seconds an
                # entry may be active. Default: 0
                maximum-timeout = 0
+
+               # The key to use for the session database (which holds the allocated ip's)
+               # normally it should just be the nas  ip/port (which is the default)
+               #key = "%{NAS-IP-Address} %{NAS-Port}"
        }
 
        # $INCLUDE  ${confdir}/sqlippool.conf
@@ -1731,6 +1806,22 @@ $INCLUDE ${confdir}/eap.conf
        # OTP token support.  Not included by default.
        # $INCLUDE  ${confdir}/otp.conf
 
+       #
+       #  Implements Login-Time, Current-Time, and Time-Of-Day
+       #
+       logintime {
+               #
+               #  Don't worry about anything here for now..
+               #
+       }
+
+       #
+       #  Kerberos.  See doc/rlm_krb5 for minimal docs.
+       #
+#      krb5 {
+#              keytab = /path/to/keytab
+#              service_principal = name_of_principle
+#      }
 }
 
 # Instantiation
@@ -1775,6 +1866,22 @@ instantiate {
        # the check-name attribute before any module which sets
        # it
 #      daily
+       expiration
+       logintime
+
+       # subsections here can be thought of as "virtual" modules.
+       #
+       # e.g. If you have two redundant SQL servers, and you want to
+       # use them in the authorize and accounting sections, you could
+       # place a "redundant" block in each section, containing the
+       # exact same text.  Or, you could uncomment the following
+       # lines, and list "redundant_sql" in the authorize and
+       # accounting sections.
+       #
+       #redundant redundant_sql {
+       #       sql1
+       #       sql2
+       #}
 }
 
 #  Authorization. First preprocess (hints and huntgroups files),
@@ -1802,8 +1909,6 @@ authorize {
        #  un-comment the following line, and the 'detail auth_log'
        #  section, above.
 #      auth_log
-       
-#      attr_filter
 
        #
        #  The chap module will set 'Auth-Type := CHAP' if we are
@@ -1819,6 +1924,14 @@ authorize {
        mschap
 
        #
+       #  Pull crypt'd passwords from /etc/passwd or /etc/shadow,
+       #  using the system API's to get the password.  If you want
+       #  to read /etc/passwd or /etc/shadow directly, see the
+       #  passwd module, above.
+       #
+       unix
+
+       #
        #  If you have a Cisco SIP server authenticating against
        #  FreeRADIUS, uncomment the following line, and the 'digest'
        #  line in the 'authenticate' section.
@@ -1877,9 +1990,20 @@ authorize {
        # Use the checkval module
 #      checkval
 
+       expiration
+       logintime
+
+       #
+       #  If no other module has claimed responsibility for
+       #  authentication, then try to use PAP.  This allows the
+       #  other modules listed above to add a "known good" password
+       #  to the request, and to do nothing else.  The PAP module
+       #  will then see that password, and use it to do PAP
+       #  authentication.
+       #
+       #  This module should be listed last, so that the other modules
+       #  get a chance to set Auth-Type for themselves.
        #
-       # As of 1.1.4, you should list "pap" last in this section.
-       # See "man rlm_pap" for more information.
        pap
 }
 
@@ -2029,6 +2153,8 @@ accounting {
        #  Cisco VoIP specific bulk accounting
 #      pgsql-voip
 
+       #  Filter attributes from the accounting response.
+       attr_filter.accounting_response
 }
 
 
@@ -2039,7 +2165,7 @@ session {
        radutmp
 
        #
-       #  See "Simultaneous Use Checking Querie" in sql.conf
+       #  See "Simultaneous Use Checking Queries" in sql.conf
 #      sql
 }
 
@@ -2075,17 +2201,17 @@ post-auth {
        #  the 'modules' section.
        #
 #      ldap
+
        #
        #  Access-Reject packets are sent through the REJECT sub-section of the
        #  post-auth section.
-       #  Uncomment the following and set the module name to the ldap instance
-       #  name if you have set 'edir_account_policy_check = yes' in the ldap
-       #  module sub-section of the 'modules' section.
        #
-#      Post-Auth-Type REJECT {
-#              insert-module-name-here
-#      }
-
+       #  Add the ldap module name (or instance) if you have set 
+       #  'edir_account_policy_check = yes' in the ldap module configuration
+       #
+       Post-Auth-Type REJECT {
+               attr_filter.access_reject
+       }
 }
 
 #
@@ -2103,6 +2229,11 @@ pre-proxy {
        #  as defined in the preproxy_users file.
 #      files
 
+       #  Uncomment the following line if you want to filter requests
+       #  sent to remote servers based on the rules defined in the
+       #  'attrs.pre-proxy' file.
+#      attr_filter.pre-proxy
+
        #  If you want to have a log of packets proxied to a home
        #  server, un-comment the following line, and the
        #  'detail pre_proxy_log' section, above.
@@ -2125,8 +2256,7 @@ post-proxy {
 
        #  Uncomment the following line if you want to filter replies from
        #  remote proxies based on the rules defined in the 'attrs' file.
-
-#      attr_filter
+#      attr_filter.post-proxy
 
        #
        #  If you are proxying LEAP, you MUST configure the EAP
diff --git a/raddb/radrelay.conf.in b/raddb/radrelay.conf.in
new file mode 100644 (file)
index 0000000..c82fd3d
--- /dev/null
@@ -0,0 +1,595 @@
+##
+## radrelay.conf       -- FreeRADIUS server configuration file.
+##
+##     http://www.freeradius.org/
+##     $Id$
+##
+#
+#      This configuration file is for the "radrelay" personality
+#      of FreeRADIUS.  It contains some of the same configuration
+#      items as "radiusd.conf", but many have been deleted, as they
+#      do not apply to "radrelay".
+#
+#      The server reads this file when it is run as "radiusd -n radrelay".
+#
+#
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+sysconfdir = @sysconfdir@
+localstatedir = @localstatedir@
+sbindir = @sbindir@
+logdir = @logdir@
+raddbdir = @raddbdir@
+radacctdir = @radacctdir@
+
+#  Location of config and logfiles.
+confdir = ${raddbdir}
+run_dir = ${localstatedir}/run/radiusd
+
+#
+#  The logging messages for the server are appended to the
+#  tail of this file.
+#
+log_file = ${logdir}/radius.log
+
+#
+#  Destination for log messages.  This can be one of:
+#
+#      files - log to ${log_file}, as defined above.
+#      syslog - to syslog (see also the log{} section, below)
+#      stdout - standard output
+#      stderr - standard error.
+#
+#  The command-line option "-X" over-rides this option, and forces
+#  logging to go to stdout.
+#
+log_destination = files
+
+#
+# libdir: Where to find the rlm_* modules.
+#
+#   This should be automatically set at configuration time.
+#
+#   If the server builds and installs, but fails at execution time
+#   with an 'undefined symbol' error, then you can use the libdir
+#   directive to work around the problem.
+#
+#   The cause is usually that a library has been installed on your
+#   system in a place where the dynamic linker CANNOT find it.  When
+#   executing as root (or another user), your personal environment MAY
+#   be set up to allow the dynamic linker to find the library.  When
+#   executing as a daemon, FreeRADIUS MAY NOT have the same
+#   personalized configuration.
+#
+#   To work around the problem, find out which library contains that symbol,
+#   and add the directory containing that library to the end of 'libdir',
+#   with a colon separating the directory names.  NO spaces are allowed.
+#
+#   e.g. libdir = /usr/local/lib:/opt/package/lib
+#
+#   You can also try setting the LD_LIBRARY_PATH environment variable
+#   in a script which starts the server.
+#
+#   If that does not work, then you can re-configure and re-build the
+#   server to NOT use shared libraries, via:
+#
+#      ./configure --disable-shared
+#      make
+#      make install
+#
+libdir = @libdir@
+
+#  pidfile: Where to place the PID of the RADIUS server.
+#
+#  The server may be signalled while it's running by using this
+#  file.
+#
+#  This file is written when ONLY running in daemon mode.
+#
+#  e.g.:  kill -HUP `cat /var/run/radiusd/radiusd.pid`
+#
+pidfile = ${run_dir}/radrelay.pid
+
+#
+#  radrelay doesn't need any special permissions to run.
+#
+#user = nobody
+#group = nobody
+
+max_request_time = 30
+delete_blocked_requests = no
+cleanup_delay = 5
+max_requests = 1024
+
+#
+#  You can have as many "listen" sections as you want.
+#
+#  The server CANNOT listen on type "detail" and type "acct"
+#  at the same time.
+#
+listen {
+       type = detail
+
+       # where the detail file is located
+       detail = ${confdir}/detail
+
+       #
+
+       #  Send no more than N requests to the server at once.
+       #  If this is set to 0 (zero), then the requests will be read
+       #  from the detail file as fast as possible, potentially
+       #  overwhelming the server.
+       #
+       max_outstanding = 100
+
+
+       #
+       #  Server identity.  This lets you tell the different "listen"
+       #  sections apart.  When a packet is read from a detail file,
+       #  the Server-Identity attribute will be set to the value below
+       #  for that packet.
+       #
+       identity = radrelay
+}
+
+
+hostname_lookups = no
+
+log {
+       syslog_facility = daemon
+}
+
+# PROXY CONFIGURATION
+#
+#  proxy_requests: Turns proxying of RADIUS requests on or off.
+#
+#  The server has proxying turned on by default.  If your system is NOT
+#  set up to proxy requests to another server, then you can turn proxying
+#  off here.  This will save a small amount of resources on the server.
+#
+#  If you have proxying turned off, and your configuration files say
+#  to proxy a request, then an error message will be logged.
+#
+#  To disable proxying, change the "yes" to "no", and comment the
+#  $INCLUDE line.
+#
+#  allowed values: {no, yes}
+#
+proxy_requests  = yes
+$INCLUDE  ${confdir}/proxy.conf
+
+
+# CLIENTS CONFIGURATION
+#
+#  Client configuration is defined in "clients.conf".  
+#
+#  The "radrelay" personality of the server does not have
+#  any clients, and does not need, or read, "clients.conf".
+
+
+# SNMP CONFIGURATION
+#
+# The "radrelay" personality of the server does not have
+# any SNMP configuration.
+
+
+# THREAD POOL CONFIGURATION
+#
+#  Threads are less useful for radrelay than for radiusd.
+#  This section is here just to remind you that it can be controlled.
+#
+thread pool {
+       start_servers = 5
+       max_servers = 32
+       min_spare_servers = 3
+       max_spare_servers = 10
+}
+
+# MODULE CONFIGURATION
+#
+#  The names and configuration of each module is located in this section.
+#
+#  Some modules have been deleted from this section.  e.g
+#
+#      pap
+#      chap
+#      mschap
+#      eap
+#      detail
+#      unix
+#      radutmp
+#
+#  It doesn't make sense to use these modules when the server is running
+#  as "radrelay".
+#
+modules {
+       # Realm module, for proxying.
+       #
+       #  You can have multiple instances of the realm module to
+       #  support multiple realm syntaxs at the same time.  The
+       #  search order is defined by the order in the authorize and
+       #  preacct sections.
+       #
+       #  Four config options:
+       #       format         -  must be "prefix" or "suffix"
+       #                         The special cases of "DEFAULT"
+       #                         and "NULL" are allowed, too.
+       #       delimiter      -  must be a single character
+
+       #  'realm/username'
+       #
+       #  Using this entry, IPASS users have their realm set to "IPASS".
+       realm IPASS {
+               format = prefix
+               delimiter = "/"
+       }
+
+       #  'username@realm'
+       #
+       realm suffix {
+               format = suffix
+               delimiter = "@"
+       }
+
+       #  'username%realm'
+       #
+       realm realmpercent {
+               format = suffix
+               delimiter = "%"
+       }
+
+       #
+       #  'domain\user'
+       #
+       realm ntdomain {
+               format = prefix
+               delimiter = "\\"
+       }       
+
+       #  A simple value checking module
+       #
+       #  It can be used to check if an attribute value in the request
+       #  matches a (possibly multi valued) attribute in the check
+       #  items This can be used for example for caller-id
+       #  authentication.  For the module to run, both the request
+       #  attribute and the check items attribute must exist
+       #
+       #  i.e.
+       #  A user has an ldap entry with 2 radiusCallingStationId
+       #  attributes with values "12345678" and "12345679".  If we
+       #  enable rlm_checkval, then any request which contains a
+       #  Calling-Station-Id with one of those two values will be
+       #  accepted.  Requests with other values for
+       #  Calling-Station-Id will be rejected.
+       #
+       #  Regular expressions in the check attribute value are allowed
+       #  as long as the operator is '=~'
+       #
+       checkval {
+               # The attribute to look for in the request
+               item-name = Calling-Station-Id
+
+               # The attribute to look for in check items. Can be multi valued
+               check-name = Calling-Station-Id
+
+               # The data type. Can be
+               # string,integer,ipaddr,date,abinary,octets
+               data-type = string
+
+               # If set to yes and we dont find the item-name attribute in the
+               # request then we send back a reject
+               # DEFAULT is no
+               #notfound-reject = no
+       }
+       
+       #  rewrite arbitrary packets.  Useful in accounting and authorization.
+       #
+       #
+       #  The module can also use the Rewrite-Rule attribute. If it
+       #  is set and matches the name of the module instance, then
+       #  that module instance will be the only one which runs.
+       #
+       #  Also if new_attribute is set to yes then a new attribute
+       #  will be created containing the value replacewith and it
+       #  will be added to searchin (packet, reply, proxy, proxy_reply or config).
+       # searchfor,ignore_case and max_matches will be ignored in that case.
+       #
+       # Backreferences are supported: %{0} will contain the string the whole match
+       # and %{1} to %{8} will contain the contents of the 1st to the 8th parentheses
+       #
+       # If max_matches is greater than one the backreferences will correspond to the
+       # first match
+
+       #
+       #attr_rewrite sanecallerid {
+       #       attribute = Called-Station-Id
+               # may be "packet", "reply", "proxy", "proxy_reply" or "config"
+       #       searchin = packet
+       #       searchfor = "[+ ]"
+       #       replacewith = ""
+       #       ignore_case = no
+       #       new_attribute = no
+       #       max_matches = 10
+       #       ## If set to yes then the replace string will be appended to the original string
+       #       append = no
+       #}
+
+       # Preprocess the incoming RADIUS request, before handing it off
+       # to other modules.
+       #
+       #  This module processes the 'huntgroups' and 'hints' files.
+       #  In addition, it re-writes some weird attributes created
+       #  by some NASes, and converts the attributes into a form which
+       #  is a little more standard.
+       #
+       preprocess {
+               huntgroups = ${confdir}/huntgroups
+               hints = ${confdir}/hints
+
+               # This hack changes Ascend's wierd port numberings
+               # to standard 0-??? port numbers so that the "+" works
+               # for IP address assignments.
+               with_ascend_hack = no
+               ascend_channels_per_line = 23
+
+               # Windows NT machines often authenticate themselves as
+               # NT_DOMAIN\username
+               #
+               # If this is set to 'yes', then the NT_DOMAIN portion
+               # of the user-name is silently discarded.
+               #
+               # This configuration entry SHOULD NOT be used.
+               # See the "realms" module for a better way to handle
+               # NT domains.
+               with_ntdomain_hack = no
+
+               # Specialix Jetstream 8500 24 port access server.
+               #
+               # If the user name is 10 characters or longer, a "/"
+               # and the excess characters after the 10th are
+               # appended to the user name.
+               #
+               # If you're not running that NAS, you don't need
+               # this hack.
+               with_specialix_jetstream_hack = no
+
+               # Cisco (and Quintum in Cisco mode) sends it's VSA attributes
+               # with the attribute name *again* in the string, like:
+               #
+               #   H323-Attribute = "h323-attribute=value".
+               #
+               # If this configuration item is set to 'yes', then
+               # the redundant data in the the attribute text is stripped
+               # out.  The result is:
+               #
+               #  H323-Attribute = "value"
+               #
+               # If you're not running a Cisco or Quintum NAS, you don't
+               # need this hack.
+               with_cisco_vsa_hack = no
+       }
+
+       # Livingston-style 'users' file
+       #
+       files {
+               usersfile = ${confdir}/users
+               acctusersfile = ${confdir}/acct_users
+
+               #  If you want to use the old Cistron 'users' file
+               #  with FreeRADIUS, you should change the next line
+               #  to 'compat = cistron'.  You can the copy your 'users'
+               #  file from Cistron.
+               compat = no
+       }
+
+       # Create a unique accounting session Id.  Many NASes re-use or
+       # repeat values for Acct-Session-Id, causing no end of
+       # confusion.
+       #
+       #  This module will add a (probably) unique session id 
+       #  to an accounting packet based on the attributes listed
+       #  below found in the packet.  See doc/rlm_acct_unique for
+       #  more information.
+       #
+       acct_unique {
+               key = "User-Name, Acct-Session-Id, NAS-IP-Address, Client-IP-Address, NAS-Port"
+       }
+
+
+       #  Include another file that has the SQL-related configuration.
+       #  This is another file only because it tends to be big.
+       #
+       #  The following configuration file is for use with MySQL.
+       #
+       #  For Postgresql, use:         ${confdir}/postgresql.conf
+       #  For MS-SQL, use:             ${confdir}/mssql.conf
+       #  For Oracle, use:             ${confdir}/oraclesql.conf
+       #
+#      $INCLUDE  ${confdir}/sql.conf
+
+
+       #  For Cisco VoIP specific accounting with Postgresql,
+       #  use:         ${confdir}/pgsql-voip.conf
+       #
+       #  You will also need the sql schema from:
+       #        src/billing/cisco_h323_db_schema-postgres.sql
+       #  Note: This config can be use AS WELL AS the standard sql
+       #  config if you need SQL based Auth
+
+       # The "always" module is here for debugging purposes. Each
+       # instance simply returns the same result, always, without
+       # doing anything.
+       always fail {
+               rcode = fail
+       }
+       always reject {
+               rcode = reject
+       }
+       always ok {
+               rcode = ok
+               simulcount = 0
+               mpp = no
+       }
+
+       #
+       #  The 'expression' module currently has no configuration.
+       #
+       #  This module is useful only for 'xlat'.  To use it,
+       #  put 'exec' into the 'instantiate' section.  You can then
+       #  do dynamic translation of attributes like:
+       #
+       #  Attribute-Name = `%{expr:2 + 3 + %{exec: uid -u}}`
+       #
+       #  The value of the attribute will be replaced with the output
+       #  of the program which is executed.  Due to RADIUS protocol
+       #  limitations, any output over 253 bytes will be ignored.
+       #
+       #  The module also registers a few paircompare functions
+       expr {
+       }
+
+       #
+       #  Execute external programs
+       #
+       #  This module is useful only for 'xlat'.  To use it,
+       #  put 'exec' into the 'instantiate' section.  You can then
+       #  do dynamic translation of attributes like:
+       #
+       #  Attribute-Name = `%{exec:/path/to/program args}`
+       #
+       #  The value of the attribute will be replaced with the output
+       #  of the program which is executed.  Due to RADIUS protocol
+       #  limitations, any output over 253 bytes will be ignored.
+       #
+       #  The RADIUS attributes from the user request will be placed
+       #  into environment variables of the executed program, as
+       #  described in 'doc/variables.txt'
+       #
+       exec {
+               wait = yes
+               input_pairs = request
+               shell_escape = yes
+       }
+}
+
+# Instantiation
+#
+#  This section orders the loading of the modules.  Modules
+#  listed here will get loaded BEFORE the later sections like
+#  authorize, authenticate, etc. get examined.
+#
+#  This section is not strictly needed.  When a section like
+#  authorize refers to a module, it's automatically loaded and
+#  initialized.  However, some modules may not be listed in any
+#  of the following sections, so they can be listed here.
+#
+#  Also, listing modules here ensures that you have control over
+#  the order in which they are initalized.  If one module needs
+#  something defined by another module, you can list them in order
+#  here, and ensure that the configuration will be OK.
+#
+instantiate {
+       exec
+       expr
+
+       # subsections here can be thought of as "virtual" modules.
+       #
+       # e.g. If you have two redundant SQL servers, and you want to
+       # use them in the authorize and accounting sections, you could
+       # place a "redundant" block in each section, containing the
+       # exact same text.  Or, you could uncomment the following
+       # lines, and list "redundant_sql" in the authorize and
+       # accounting sections.
+       #
+       #redundant redundant_sql {
+       #       sql1
+       #       sql2
+       #}
+}
+
+#
+#  There are no authorize, authenticate, or post-auth sections.
+#
+
+#
+#  Pre-accounting.  Decide which accounting type to use.
+#
+preacct {
+       preprocess
+
+       #
+       #  Ensure that we have a semi-unique identifier for every
+       #  request, and many NAS boxes are broken.
+       acct_unique
+
+       #
+       #  Look for IPASS-style 'realm/', and if not found, look for
+       #  '@realm', and decide whether or not to proxy, based on
+       #  that.
+       #
+       #  Accounting requests are generally proxied to the same
+       #  home server as authentication requests.
+#      IPASS
+       suffix
+#      ntdomain
+
+       #
+       #  Read the 'acct_users' file
+       files
+}
+
+#
+#  Accounting.  Log the accounting data.
+#
+accounting {
+       #
+       #  Log traffic to an SQL database.
+       #
+       #  See "Accounting queries" in sql.conf
+#      sql
+
+
+       #  Cisco VoIP specific bulk accounting
+#      pgsql-voip
+
+}
+
+
+#
+#  When the server decides to proxy a request to a home server,
+#  the proxied request is first passed through the pre-proxy
+#  stage.  This stage can re-write the request, or decide to
+#  cancel the proxy.
+#
+#  Only a few modules currently have this method.
+#
+pre-proxy {
+#      attr_rewrite
+
+       #  If you want to have a log of packets proxied to a home
+       #  server, un-comment the following line, and the
+       #  'detail pre_proxy_log' section, above.
+#      pre_proxy_log
+}
+
+#
+#  When the server receives a reply to a request it proxied
+#  to a home server, the request may be massaged here, in the
+#  post-proxy stage.
+#
+post-proxy {
+       #
+
+       #  If you want to have a log of replies from a home server,
+       #  un-comment the following line, and the 'detail post_proxy_log'
+       #  section, above.
+#      post_proxy_log
+
+#      attr_rewrite
+
+       #  Uncomment the following line if you want to filter replies from
+       #  remote proxies based on the rules defined in the 'attrs' file.
+
+#      attr_filter
+}
index 9c576ab..f5cacd7 100644 (file)
@@ -1,38 +1,42 @@
+#  $Id$
 #
-#  Configuration for the SQL module, when using MySQL.
-#
-#  The database schema is available at:
-#
-#      doc/examples/mysql.sql
+#  Configuration for the SQL module
 #
-#  If you are using PostgreSQL, please use 'postgresql.conf', instead.
-#  If you are using Oracle, please use 'oracle.conf', instead.
-#  If you are using MS-SQL, please use 'mssql.conf', instead.
+#  The database schemas are available at:
 #
-#  $Id$
+#      doc/examples/*.sql
 #
+
 sql {
-       # Database type
-       # Current supported are: rlm_sql_mysql, rlm_sql_postgresql,
-       # rlm_sql_iodbc, rlm_sql_oracle, rlm_sql_unixodbc, rlm_sql_freetds
+
+       ## Database type you wish to connect to:
+       # driver = "rlm_sql_freetds"
+       # driver = "rlm_sql_iodbc"
        driver = "rlm_sql_mysql"
+       # driver = "rlm_sql_oracle"
+       # driver = "rlm_sql_postgresql"
+       # driver = "rlm_sql_unixodbc"
+       
+       ## Also see the bottom of this file to modify which SQL dialect you use
 
-       # Connect info
+       ## Connection info:
        server = "localhost"
-       login = "root"
-       password = "rootpass"
+       login = "radius"
+       password = "radpass"
 
-       # Database table configuration
+       ## Database table configuration for everything except Oracle
        radius_db = "radius"
+       ## If you are using Oracle then use this instead
+        # radius_db = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SID=your_sid)))"
 
-       # If you want both stop and start records logged to the
-       # same SQL table, leave this as is.  If you want them in
-       # different tables, put the start table in acct_table1
-       # and stop table in acct_table2
+       ## If you want both stop and start records logged to the
+       ## same SQL table, leave this as is.  If you want them in
+       ## different tables, put the start table in acct_table1
+       ## and stop table in acct_table2
        acct_table1 = "radacct"
        acct_table2 = "radacct"
 
-       # Allow for storing data after authentication
+       ## Allow for storing data after authentication
        postauth_table = "radpostauth"
 
        authcheck_table = "radcheck"
@@ -41,187 +45,39 @@ sql {
        groupcheck_table = "radgroupcheck"
        groupreply_table = "radgroupreply"
 
-       usergroup_table = "usergroup"
+       ## Table to keep group info
+       usergroup_table = "radusergroup"
 
-       # Table to keep radius client info
+       ## If set to 'yes' (default) we read the group tables
+       ## If set to 'no' the user MUST have Fall-Through = Yes in the radreply table
+       # read_groups = yes
+
+       ## Table to keep radius client info
        nas_table = "nas"
 
-       # Remove stale session if checkrad does not see a double login
+       ## Set to 'yes' to read radius clients from the database ('nas' table)
+       # readclients = yes
+
+       ## Remove stale session if checkrad does not see a double login
        deletestalesessions = yes
 
-       # Print all SQL statements when in debug mode (-x)
+       ## Print all SQL statements when in debug mode (-x)
        sqltrace = no
        sqltracefile = ${logdir}/sqltrace.sql
 
-       # number of sql connections to make to server
+       ## number of sql connections to make to server
        num_sql_socks = 5
 
-       # number of seconds to dely retrying on a failed database
-       # connection (per_socket)
+       ## number of seconds to dely retrying on a failed database
+       ## connection (per_socket)
        connect_failure_retry_delay = 60
 
-       # Safe characters list for sql queries. Everything else is replaced
-       # with their mime-encoded equivalents.
-       # The default list should be ok
-       #safe-characters = "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"
-
-       #######################################################################
-       #  Query config:  Username
-       #######################################################################
-       # This is the username that will get substituted, escaped, and added
-       # as attribute 'SQL-User-Name'.  '%{SQL-User-Name}' should be used below
-       # everywhere a username substitution is needed so you you can be sure
-       # the username passed from the client is escaped properly.
-       #
-       #  Uncomment the next line, if you want the sql_user_name to mean:
-       #
-       #    Use Stripped-User-Name, if it's there.
-       #    Else use User-Name, if it's there,
-       #    Else use hard-coded string "DEFAULT" as the user name.
-       #sql_user_name = "%{Stripped-User-Name:-%{User-Name:-DEFAULT}}"
-       #
-       sql_user_name = "%{User-Name}"
-
-       #######################################################################
-       #  Default profile
-       #######################################################################
-       # This is the default profile. It is found in SQL by group membership.
-       # That means that this profile must be a member of at least one group
-       # which will contain the corresponding check and reply items.
-       # This profile will be queried in the authorize section for every user.
-       # The point is to assign all users a default profile without having to
-       # manually add each one to a group that will contain the profile.
-       # The SQL module will also honor the User-Profile attribute. This
-       # attribute can be set anywhere in the authorize section (ie the users
-       # file). It is found exactly as the default profile is found.
-       # If it is set then it will *overwrite* the default profile setting.
-       # The idea is to select profiles based on checks on the incoming packets,
-       # not on user group membership. For example:
-       # -- users file --
-       # DEFAULT       Service-Type == Outbound-User, User-Profile := "outbound"
-       # DEFAULT       Service-Type == Framed-User, User-Profile := "framed"
-       #
-       # By default the default_user_profile is not set
-       #
-       #default_user_profile = "DEFAULT"
-       #
-       # Determines if we will query the default_user_profile or the User-Profile
-       # if the user is not found. If the profile is found then we consider the user
-       # found. By default this is set to 'no'.
-       #
-       #query_on_not_found = no
-
-       #######################################################################
-       #  Authorization Queries
-       #######################################################################
-       #  These queries compare the check items for the user
-       #  in ${authcheck_table} and setup the reply items in
-       #  ${authreply_table}.  You can use any query/tables
-       #  you want, but the return data for each row MUST
-       #  be in the  following order:
-       #
-       #  0. Row ID (currently unused)
-       #  1. UserName/GroupName
-       #  2. Item Attr Name
-       #  3. Item Attr Value
-       #  4. Item Attr Operation
-       #######################################################################
-       # Use these for case sensitive usernames.
-#      authorize_check_query = "SELECT id, UserName, Attribute, Value, op \
-#         FROM ${authcheck_table} \
-#         WHERE Username = BINARY '%{SQL-User-Name}' \
-#         ORDER BY id"
-#      authorize_reply_query = "SELECT id, UserName, Attribute, Value, op \
-#         FROM ${authreply_table} \
-#         WHERE Username = BINARY '%{SQL-User-Name}' \
-#         ORDER BY id"
-
-       # The default queries are case insensitive. (for compatibility with
-       # older versions of FreeRADIUS)
-       authorize_check_query = "SELECT id, UserName, Attribute, Value, op \
-          FROM ${authcheck_table} \
-          WHERE Username = '%{SQL-User-Name}' \
-          ORDER BY id"
-       authorize_reply_query = "SELECT id, UserName, Attribute, Value, op \
-          FROM ${authreply_table} \
-          WHERE Username = '%{SQL-User-Name}' \
-          ORDER BY id"
-
-       # Use these for case sensitive usernames.
-#      authorize_group_check_query = "SELECT ${groupcheck_table}.id,${groupcheck_table}.GroupName,${groupcheck_table}.Attribute,${groupcheck_table}.Value,${groupcheck_table}.op FROM ${groupcheck_table},${usergroup_table} WHERE ${usergroup_table}.Username = BINARY '%{SQL-User-Name}' AND ${usergroup_table}.GroupName = ${groupcheck_table}.GroupName ORDER BY ${groupcheck_table}.id"
-#      authorize_group_reply_query = "SELECT ${groupreply_table}.id,${groupreply_table}.GroupName,${groupreply_table}.Attribute,${groupreply_table}.Value,${groupreply_table}.op  FROM ${groupreply_table},${usergroup_table} WHERE ${usergroup_table}.Username = BINARY '%{SQL-User-Name}' AND ${usergroup_table}.GroupName = ${groupreply_table}.GroupName ORDER BY ${groupreply_table}.id"
-
-       authorize_group_check_query = "SELECT ${groupcheck_table}.id,${groupcheck_table}.GroupName,${groupcheck_table}.Attribute,${groupcheck_table}.Value,${groupcheck_table}.op  FROM ${groupcheck_table},${usergroup_table} WHERE ${usergroup_table}.Username = '%{SQL-User-Name}' AND ${usergroup_table}.GroupName = ${groupcheck_table}.GroupName ORDER BY ${groupcheck_table}.id"
-       authorize_group_reply_query = "SELECT ${groupreply_table}.id,${groupreply_table}.GroupName,${groupreply_table}.Attribute,${groupreply_table}.Value,${groupreply_table}.op  FROM ${groupreply_table},${usergroup_table} WHERE ${usergroup_table}.Username = '%{SQL-User-Name}' AND ${usergroup_table}.GroupName = ${groupreply_table}.GroupName ORDER BY ${groupreply_table}.id"
-
-       #######################################################################
-       #  Accounting Queries
-       #######################################################################
-       # accounting_onoff_query        - query for Accounting On/Off packets
-       # accounting_update_query       - query for Accounting update packets
-       # accounting_update_query_alt   - query for Accounting update packets
-       #                               (alternate in case first query fails)
-       # accounting_start_query        - query for Accounting start packets
-       # accounting_start_query_alt    - query for Accounting start packets
-       #                               (alternate in case first query fails)
-       # accounting_stop_query         - query for Accounting stop packets
-       # accounting_stop_query_alt     - query for Accounting start packets
-       #                               (alternate in case first query doesn't
-       #                                affect any existing rows in the table)
-       #######################################################################
-       accounting_onoff_query = "UPDATE ${acct_table1} SET AcctStopTime='%S', AcctSessionTime=unix_timestamp('%S') - unix_timestamp(AcctStartTime), AcctTerminateCause='%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time}' WHERE AcctSessionTime=0 AND AcctStopTime=0 AND NASIPAddress= '%{NAS-IP-Address}' AND AcctStartTime <= '%S'"
-
-       accounting_update_query = "UPDATE ${acct_table1} \
-          SET FramedIPAddress = '%{Framed-IP-Address}', \
-          AcctSessionTime = '%{Acct-Session-Time}', \
-          AcctInputOctets = '%{Acct-Input-Octets}', \
-          AcctOutputOctets = '%{Acct-Output-Octets}' \
-          WHERE AcctSessionId = '%{Acct-Session-Id}' \
-          AND UserName = '%{SQL-User-Name}' \
-          AND NASIPAddress= '%{NAS-IP-Address}'"
-
-       accounting_update_query_alt = "INSERT into ${acct_table1} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', '%{NAS-Port-Type}', DATE_SUB('%S',INTERVAL (%{Acct-Session-Time:-0} + %{Acct-Delay-Time:-0}) SECOND), '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0')"
-
-       accounting_start_query = "INSERT into ${acct_table1} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', '%{NAS-Port-Type}', '%S', '0', '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '%{Acct-Delay-Time}', '0')"
-
-       accounting_start_query_alt  = "UPDATE ${acct_table1} SET AcctStartTime = '%S', AcctStartDelay = '%{Acct-Delay-Time}', ConnectInfo_start = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}'"
-
-       accounting_stop_query = "UPDATE ${acct_table2} SET AcctStopTime = '%S', AcctSessionTime = '%{Acct-Session-Time}', AcctInputOctets = '%{Acct-Input-Octets}', AcctOutputOctets = '%{Acct-Output-Octets}', AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time}', ConnectInfo_stop = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}'"
-
-       accounting_stop_query_alt = "INSERT into ${acct_table2} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', '%{NAS-Port-Type}', DATE_SUB('%S', INTERVAL (%{Acct-Session-Time:-0} + %{Acct-Delay-Time:-0}) SECOND), '%S', '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Connect-Info}', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0', '%{Acct-Delay-Time}')"
-
-       #######################################################################
-       # Simultaneous Use Checking Queries
-       #######################################################################
-       # simul_count_query     - query for the number of current connections
-       #                       - If this is not defined, no simultaneouls use checking
-       #                       - will be performed by this module instance
-       # simul_verify_query    - query to return details of current connections for verification
-       #                       - Leave blank or commented out to disable verification step
-       #                       - Note that the returned field order should not be changed.
-       #######################################################################
-
-       # Uncomment simul_count_query to enable simultaneous use checking
-       # simul_count_query = "SELECT COUNT(*) FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime = 0"
-       simul_verify_query = "SELECT RadAcctId, AcctSessionId, UserName, NASIPAddress, NASPortId, FramedIPAddress, CallingStationId, FramedProtocol FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime = 0"
-
-       #######################################################################
-       # Group Membership Queries
-       #######################################################################
-       # group_membership_query        - Check user group membership
-       #######################################################################
-
-       group_membership_query = "SELECT GroupName FROM ${usergroup_table} WHERE UserName='%{SQL-User-Name}'"
-
-       #######################################################################
-       # Authentication Logging Queries
-       #######################################################################
-       # postauth_query                - Insert some info after authentication
-       #######################################################################
-
-       postauth_query = "INSERT into ${postauth_table} (id, user, pass, reply, date) values ('', '%{User-Name}', '%{User-Password:-Chap-Password}', '%{reply:Packet-Type}', NOW())"
-
-       #
-       # Set to 'yes' to read radius clients from the database ('nas' table)
-       #readclients = yes
+
+       ## Uncomment the appropriate config file for your SQL dialect
+
+       # $INCLUDE ${confdir}/sql/mssql-dialup.conf
+       $INCLUDE ${confdir}/sql/mysql-dialup.conf
+       # $INCLUDE ${confdir}/sql/oracle-dialup.conf
+       # $INCLUDE ${confdir}/sql/postgresql-dialup.conf
+
 }
similarity index 80%
rename from raddb/mssql.conf
rename to raddb/sql/mssql-dialup.conf
index 0627627..a3cfe3b 100644 (file)
@@ -7,45 +7,6 @@
 #
 #  $Id$
 #
-sql {
-
-       # Database type
-       # Current supported are: rlm_sql_mysql, rlm_sql_postgresql,
-       # rlm_sql_iodbc, rlm_sql_oracle, rlm_sql_unixodbc
-       driver = "rlm_sql_unixodbc"
-
-       # Connect info
-       server = "localhost"
-       login = "root"
-       password = "rootpass"
-
-       # Database table configuration
-       radius_db = "radius"
-
-       # If you want both stop and start records logged to the
-       # same SQL table, leave this as is.  If you want them in
-       # different tables, put the start table in acct_table1
-       # and stop table in acct_table2
-       acct_table1 = "radacct"
-       acct_table2 = "radacct"
-
-       authcheck_table = "radcheck"
-       authreply_table = "radreply"
-
-       groupcheck_table = "radgroupcheck"
-       groupreply_table = "radgroupreply"
-
-       usergroup_table = "usergroup"
-
-       # Remove stale session if checkrad does not see a double login
-       deletestalesessions = yes
-
-       # Print all SQL statements when in debug mode (-x)
-       sqltrace = no
-       sqltracefile = ${logdir}/sqltrace.sql
-
-       # number of sql connections to make to server
-       num_sql_socks = 5
 
        # Safe characters list for sql queries. Everything else is replaced
        # with their mime-encoded equivalents.
@@ -110,7 +71,7 @@ sql {
        #                               (alternate in case first query doesn't
        #                                affect any existing rows in the table)
        #######################################################################
-       accounting_onoff_query = "UPDATE ${acct_table1} SET AcctStopTime='%S', AcctSessionTime=unix_timestamp('%S') - unix_timestamp(AcctStartTime), AcctTerminateCause='%{Acct-Terminate-Cause}', AcctStopDelay = %{Acct-Delay-Time} WHERE AcctSessionTime=0 AND AcctStopTime=0 AND NASIPAddress= '%{NAS-IP-Address}' AND AcctStartTime <= '%S'"
+       accounting_onoff_query = "UPDATE ${acct_table1} SET AcctStopTime='%S', AcctSessionTime=unix_timestamp('%S') - unix_timestamp(AcctStartTime), AcctTerminateCause='%{Acct-Terminate-Cause}', AcctStopDelay = %{Acct-Delay-Time:-0} WHERE AcctSessionTime=0 AND AcctStopTime=0 AND NASIPAddress= '%{NAS-IP-Address}' AND AcctStartTime <= '%S'"
 
        accounting_update_query = "UPDATE ${acct_table1} SET FramedIPAddress = '%{Framed-IP-Address}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress= '%{NAS-IP-Address}' AND AcctStopTime = 0"
 
@@ -118,14 +79,13 @@ sql {
 
        # accounting_start_query: Inserting of RadAcctId and AcctStopTime was
        # removed. These fields are processing by a database
-       accounting_start_query = "INSERT into ${acct_table1} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPort, NASPortType, AcctStartTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', '%S', '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '%{Acct-Delay-Time}', '0')"
+       accounting_start_query = "INSERT into ${acct_table1} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPort, NASPortType, AcctStartTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', '%S', '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '%{Acct-Delay-Time:-0}', '0')"
 
-       accounting_start_query_alt  = "UPDATE ${acct_table1} SET AcctStartTime = '%S', AcctStartDelay = '%{Acct-Delay-Time}', ConnectInfo_start = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime = 0"
+       accounting_start_query_alt  = "UPDATE ${acct_table1} SET AcctStartTime = '%S', AcctStartDelay = '%{Acct-Delay-Time:-0}', ConnectInfo_start = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime = 0"
 
-       accounting_stop_query = "UPDATE ${acct_table2} SET AcctStopTime = '%S', AcctSessionTime = '%{Acct-Session-Time}', AcctInputOctets = '%{Acct-Input-Octets}', AcctOutputOctets = '%{Acct-Output-Octets}', AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time}', ConnectInfo_stop = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime = 0"
+       accounting_stop_query = "UPDATE ${acct_table2} SET AcctStopTime = '%S', AcctSessionTime = '%{Acct-Session-Time}', AcctInputOctets = '%{Acct-Input-Octets}', AcctOutputOctets = '%{Acct-Output-Octets}', AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time:-0}', ConnectInfo_stop = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime = 0"
 
        # accounting_stop_query_alt: Inserting of RadAcctId and AcctStartTime was
        # removed. These fields are processing by a database
-       accounting_stop_query_alt = "INSERT into ${acct_table2} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPort, NASPortType, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', '%S', '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Connect-Info}', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0', '%{Acct-Delay-Time}')"
+       accounting_stop_query_alt = "INSERT into ${acct_table2} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPort, NASPortType, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', '%S', '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Connect-Info}', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0', '%{Acct-Delay-Time:-0}')"
 
-}
diff --git a/raddb/sql/mysql-dialup.conf b/raddb/sql/mysql-dialup.conf
new file mode 100644 (file)
index 0000000..9418437
--- /dev/null
@@ -0,0 +1,178 @@
+#  $Id$
+#
+# FreeRADIUS "dialup" SQL Queries for the MySQL Dialect
+
+       # Safe characters list for sql queries. Everything else is replaced
+       # with their mime-encoded equivalents.
+       # The default list should be ok
+       #safe-characters = "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"
+
+       #######################################################################
+       #  Query config:  Username
+       #######################################################################
+       # This is the username that will get substituted, escaped, and added
+       # as attribute 'SQL-User-Name'.  '%{SQL-User-Name}' should be used below
+       # everywhere a username substitution is needed so you you can be sure
+       # the username passed from the client is escaped properly.
+       #
+       #  Uncomment the next line, if you want the sql_user_name to mean:
+       #
+       #    Use Stripped-User-Name, if it's there.
+       #    Else use User-Name, if it's there,
+       #    Else use hard-coded string "DEFAULT" as the user name.
+       #sql_user_name = "%{Stripped-User-Name:-%{User-Name:-DEFAULT}}"
+       #
+       sql_user_name = "%{User-Name}"
+
+       #######################################################################
+       #  Default profile
+       #######################################################################
+       # This is the default profile. It is found in SQL by group membership.
+       # That means that this profile must be a member of at least one group
+       # which will contain the corresponding check and reply items.
+       # This profile will be queried in the authorize section for every user.
+       # The point is to assign all users a default profile without having to
+       # manually add each one to a group that will contain the profile.
+       # The SQL module will also honor the User-Profile attribute. This
+       # attribute can be set anywhere in the authorize section (ie the users
+       # file). It is found exactly as the default profile is found.
+       # If it is set then it will *overwrite* the default profile setting.
+       # The idea is to select profiles based on checks on the incoming packets,
+       # not on user group membership. For example:
+       # -- users file --
+       # DEFAULT       Service-Type == Outbound-User, User-Profile := "outbound"
+       # DEFAULT       Service-Type == Framed-User, User-Profile := "framed"
+       #
+       # By default the default_user_profile is not set
+       #
+       #default_user_profile = "DEFAULT"
+
+       #######################################################################
+       #  NAS Query
+       #######################################################################
+       #  This query retrieves the radius clients
+       #
+       #  0. Row ID (currently unused)
+       #  1. Name (or IP address)
+       #  2. Shortname
+       #  3. Type
+       #  4. Secret
+       #######################################################################
+
+       nas_query = "SELECT id, nasname, shortname, type, secret FROM ${nas_table}"
+
+       #######################################################################
+       #  Authorization Queries
+       #######################################################################
+       #  These queries compare the check items for the user
+       #  in ${authcheck_table} and setup the reply items in
+       #  ${authreply_table}.  You can use any query/tables
+       #  you want, but the return data for each row MUST
+       #  be in the  following order:
+       #
+       #  0. Row ID (currently unused)
+       #  1. UserName/GroupName
+       #  2. Item Attr Name
+       #  3. Item Attr Value
+       #  4. Item Attr Operation
+       #######################################################################
+       # Use these for case sensitive usernames.
+#      authorize_check_query = "SELECT id, UserName, Attribute, Value, op \
+#         FROM ${authcheck_table} \
+#         WHERE Username = BINARY '%{SQL-User-Name}' \
+#         ORDER BY id"
+#      authorize_reply_query = "SELECT id, UserName, Attribute, Value, op \
+#         FROM ${authreply_table} \
+#         WHERE Username = BINARY '%{SQL-User-Name}' \
+#         ORDER BY id"
+
+       # The default queries are case insensitive. (for compatibility with
+       # older versions of FreeRADIUS)
+       authorize_check_query = "SELECT id, UserName, Attribute, Value, op \
+          FROM ${authcheck_table} \
+          WHERE Username = '%{SQL-User-Name}' \
+          ORDER BY id"
+       authorize_reply_query = "SELECT id, UserName, Attribute, Value, op \
+          FROM ${authreply_table} \
+          WHERE Username = '%{SQL-User-Name}' \
+          ORDER BY id"
+
+       # Use these for case sensitive usernames.
+#      group_membership_query = "SELECT GroupName \
+#         FROM ${usergroup_table} \
+#         WHERE UserName = BINARY '%{SQL-User-Name}' \
+#         ORDER BY priority"
+
+       group_membership_query = "SELECT GroupName \
+          FROM ${usergroup_table} \
+          WHERE UserName = '%{SQL-User-Name}' \
+          ORDER BY priority"
+
+       authorize_group_check_query = "SELECT id, GroupName, Attribute, Value, op \
+          FROM ${groupcheck_table} \
+          WHERE GroupName = '%{Sql-Group}' \
+          ORDER BY id"
+       authorize_group_reply_query = "SELECT id, GroupName, Attribute, Value, op \
+          FROM ${groupreply_table} \
+          WHERE GroupName = '%{Sql-Group}' \
+          ORDER BY id"
+
+       #######################################################################
+       #  Accounting Queries
+       #######################################################################
+       # accounting_onoff_query        - query for Accounting On/Off packets
+       # accounting_update_query       - query for Accounting update packets
+       # accounting_update_query_alt   - query for Accounting update packets
+       #                               (alternate in case first query fails)
+       # accounting_start_query        - query for Accounting start packets
+       # accounting_start_query_alt    - query for Accounting start packets
+       #                               (alternate in case first query fails)
+       # accounting_stop_query         - query for Accounting stop packets
+       # accounting_stop_query_alt     - query for Accounting start packets
+       #                               (alternate in case first query doesn't
+       #                                affect any existing rows in the table)
+       #######################################################################
+       accounting_onoff_query = "UPDATE ${acct_table1} SET AcctStopTime='%S', AcctSessionTime=unix_timestamp('%S') - unix_timestamp(AcctStartTime), AcctTerminateCause='%{Acct-Terminate-Cause}', AcctStopDelay = %{Acct-Delay-Time:-0} WHERE AcctSessionTime=0 AND AcctStopTime=0 AND NASIPAddress= '%{NAS-IP-Address}' AND AcctStartTime <= '%S'"
+
+       accounting_update_query = "UPDATE ${acct_table1} \
+          SET FramedIPAddress = '%{Framed-IP-Address}', \
+          AcctSessionTime = '%{Acct-Session-Time}', \
+          AcctInputOctets = '%{Acct-Input-Octets}', \
+          AcctOutputOctets = '%{Acct-Output-Octets}' \
+          WHERE AcctSessionId = '%{Acct-Session-Id}' \
+          AND UserName = '%{SQL-User-Name}' \
+          AND NASIPAddress= '%{NAS-IP-Address}'"
+
+       accounting_update_query_alt = "INSERT into ${acct_table1} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', '%{NAS-Port-Type}', DATE_SUB('%S',INTERVAL (%{Acct-Session-Time:-0} + %{Acct-Delay-Time:-0}) SECOND), '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0')"
+
+       accounting_start_query = "INSERT into ${acct_table1} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', '%{NAS-Port-Type}', '%S', '0', '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '%{Acct-Delay-Time:-0}', '0')"
+
+       accounting_start_query_alt  = "UPDATE ${acct_table1} SET AcctStartTime = '%S', AcctStartDelay = '%{Acct-Delay-Time:-0}', ConnectInfo_start = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}'"
+
+       accounting_stop_query = "UPDATE ${acct_table2} SET AcctStopTime = '%S', AcctSessionTime = '%{Acct-Session-Time}', AcctInputOctets = '%{Acct-Input-Octets}', AcctOutputOctets = '%{Acct-Output-Octets}', AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time:-0}', ConnectInfo_stop = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}'"
+
+       accounting_stop_query_alt = "INSERT into ${acct_table2} (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}', '%{NAS-Port-Type}', DATE_SUB('%S', INTERVAL (%{Acct-Session-Time:-0} + %{Acct-Delay-Time:-0}) SECOND), '%S', '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Connect-Info}', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0', '%{Acct-Delay-Time:-0}')"
+
+       #######################################################################
+       # Simultaneous Use Checking Queries
+       #######################################################################
+       # simul_count_query     - query for the number of current connections
+       #                       - If this is not defined, no simultaneouls use checking
+       #                       - will be performed by this module instance
+       # simul_verify_query    - query to return details of current connections for verification
+       #                       - Leave blank or commented out to disable verification step
+       #                       - Note that the returned field order should not be changed.
+       #######################################################################
+
+       # Uncomment simul_count_query to enable simultaneous use checking
+       # simul_count_query = "SELECT COUNT(*) FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime = 0"
+       simul_verify_query = "SELECT RadAcctId, AcctSessionId, UserName, NASIPAddress, NASPortId, FramedIPAddress, CallingStationId, FramedProtocol FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime = 0"
+
+       #######################################################################
+       # Authentication Logging Queries
+       #######################################################################
+       # postauth_query                - Insert some info after authentication
+       #######################################################################
+
+       postauth_query = "INSERT into ${postauth_table} (id, user, pass, reply, date) values ('', '%{User-Name}', '%{User-Password:-Chap-Password}', '%{reply:Packet-Type}', '%S')"
+
similarity index 84%
rename from raddb/oraclesql.conf
rename to raddb/sql/oracle-dialup.conf
index ebbc7b7..35ffe6d 100644 (file)
@@ -7,49 +7,7 @@
 #
 #      $Id$
 #
-sql {
-
-       # Database type
-       # Current supported are: rlm_sql_mysql, rlm_sql_postgresql,
-       # rlm_sql_iodbc, rlm_sql_oracle, rlm_sql_unixodbc, rlm_sql_freetds
-       driver = "rlm_sql_oracle"
-
-       # Connect info
-       server = "localhost"
-       login = "root"
-       password = "rootpass"
-       
-       # Database table configuration
-       radius_db = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SID=your_sid)))"
-               
-       # If you want both stop and start records logged to the
-       # same SQL table, leave this as is.  If you want them in
-       # different tables, put the start table in acct_table1
-       # and stop table in acct_table2
-       acct_table1 = "radacct"
-       acct_table2 = "radacct"
-               
-       authcheck_table = "radcheck"
-       authreply_table = "radreply"
-       
-       groupcheck_table = "radgroupcheck"
-       groupreply_table = "radgroupreply"
-       
-       usergroup_table = "usergroup"
-       
-       # Remove stale session if checkrad does not see a double login
-       deletestalesessions = yes
-
-       # Print all SQL statements when in debug mode (-x)
-       sqltrace = no
-       sqltracefile = ${logdir}/sqltrace.sql
-
-       # number of sql connections to make to server
-       num_sql_socks = 5
-
-       # number of seconds to dely retrying on a failed database
-       # connection (per_socket)
-       connect_failure_retry_delay = 60
+
 
        #######################################################################
        #  Query config:  Username
@@ -143,7 +101,7 @@ sql {
        #                               (alternate in case first query doesn't
        #                                affect any existing rows in the table)
        #######################################################################
-       accounting_onoff_query = "UPDATE ${acct_table1} SET AcctStopTime=TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), AcctSessionTime=((TO_DATE('%S','yyyy-mm-dd hh24:mi:ss') - AcctStartTime)*86400), AcctTerminateCause='%{Acct-Terminate-Cause}', AcctStopDelay = %{Acct-Delay-Time} WHERE AcctSessionTime=0 AND AcctStopTime IS NULL AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStartTime <= TO_DATE('%S','yyyy-mm-dd hh24:mi:ss')"
+       accounting_onoff_query = "UPDATE ${acct_table1} SET AcctStopTime=TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), AcctSessionTime=((TO_DATE('%S','yyyy-mm-dd hh24:mi:ss') - AcctStartTime)*86400), AcctTerminateCause='%{Acct-Terminate-Cause}', AcctStopDelay = %{Acct-Delay-Time:-0} WHERE AcctSessionTime=0 AND AcctStopTime IS NULL AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStartTime <= TO_DATE('%S','yyyy-mm-dd hh24:mi:ss')"
 
 accounting_update_query = "UPDATE ${acct_table1} \
     SET FramedIPAddress = NULLIF('%{Framed-IP-Address}', ''), \
@@ -158,13 +116,16 @@ accounting_update_query = "UPDATE ${acct_table1} \
 
        accounting_update_query_alt = "INSERT into ${acct_table1} (RadAcctId, AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay) values('', '%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', NULL, '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0')"
 
-       accounting_start_query = "INSERT into ${acct_table1} (RadAcctId, AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('', '%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), NULL, '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '%{Acct-Delay-Time}', '0')"
+       accounting_start_query = "INSERT into ${acct_table1} (RadAcctId, AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('', '%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), NULL, '0', '%{Acct-Authentic}', '%{Connect-Info}', '', '0', '0', '%{Called-Station-Id}', '%{Calling-Station-Id}', '', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '%{Acct-Delay-Time:-0}', '0')"
+
+       accounting_start_query_alt  = "UPDATE ${acct_table1} SET AcctStartTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), AcctStartDelay = '%{Acct-Delay-Time:-0}', ConnectInfo_start = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime IS NULL"
 
-       accounting_start_query_alt  = "UPDATE ${acct_table1} SET AcctStartTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), AcctStartDelay = '%{Acct-Delay-Time}', ConnectInfo_start = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime IS NULL"
+       accounting_stop_query = "UPDATE ${acct_table2} SET AcctStopTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), AcctSessionTime = '%{Acct-Session-Time}', AcctInputOctets = '%{Acct-Input-Octets}', AcctOutputOctets = '%{Acct-Output-Octets}', AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time:-0}', ConnectInfo_stop = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime IS NULL"
 
-       accounting_stop_query = "UPDATE ${acct_table2} SET AcctStopTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), AcctSessionTime = '%{Acct-Session-Time}', AcctInputOctets = '%{Acct-Input-Octets}', AcctOutputOctets = '%{Acct-Output-Octets}', AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time}', ConnectInfo_stop = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime IS NULL"
+       # Optional Query - pnixon
+       #accounting_stop_query =3D "UPDATE ${acct_table2} SET AcctStopTime = TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), AcctSessionTime = (substr((sysdate-acctstarttime),instr((sysdate-acctstarttime),' ')+7,2) + substr((sysdate-acctstarttime),instr((sysdate-acctstarttime),' ')+4,2)*60 + substr((sysdate-acctstarttime),instr((sysdate-acctstarttime),' ')+1,2)*3600 + trunc(to_number(substr((sysdate-acctstarttime),1,instr(sysdate-acctstarttime,' '))))*86400), AcctInputOctets = '%{Acct-Input-Octets}', AcctOutputOctets = '%{Acct-Output-Octets}', AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time}', ConnectInfo_stop = '%{Connect-Info}' WHERE AcctSessionId =3D '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime IS NULL" 
 
-       accounting_stop_query_alt = "INSERT into ${acct_table2} (RadAcctId, AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('', '%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', NULL, TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Connect-Info}', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0', '%{Acct-Delay-Time}')"
+       accounting_stop_query_alt = "INSERT into ${acct_table2} (RadAcctId, AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, AcctSessionTime, AcctAuthentic, ConnectInfo_start, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay, AcctStopDelay) values('', '%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port-Id}', '%{NAS-Port-Type}', NULL, TO_DATE('%S','yyyy-mm-dd hh24:mi:ss'), '%{Acct-Session-Time}', '%{Acct-Authentic}', '', '%{Connect-Info}', '%{Acct-Input-Octets}', '%{Acct-Output-Octets}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}', '0', '%{Acct-Delay-Time:-0}')"
 
        #######################################################################
        # Simultaneous Use Checking Queries
@@ -188,4 +149,4 @@ accounting_update_query = "UPDATE ${acct_table1} \
        #######################################################################
 
        group_membership_query = "SELECT GroupName FROM ${usergroup_table} WHERE UserName='%{SQL-User-Name}'"
-}
+
diff --git a/raddb/sql/postgresql-dialup.conf b/raddb/sql/postgresql-dialup.conf
new file mode 100644 (file)
index 0000000..b58e062
--- /dev/null
@@ -0,0 +1,244 @@
+#
+#  $Id$
+#
+#  Configuration for the SQL module, when using Postgresql.
+#
+#  The database schema is available at:
+#
+#      doc/examples/postgresql.sql
+#
+
+
+       # Safe characters list for sql queries. Everything else is replaced
+       # with their mime-encoded equivalents.
+       # The default list should be ok
+#      safe-characters = "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"
+
+       #######################################################################
+       #  Query config:  Username
+       #######################################################################
+       # This is the username that will get substituted, escaped, and added
+       # as attribute 'SQL-User-Name'.  '%{SQL-User-Name}' should be used
+       # below everywhere a username substitution is needed so you you can
+       # be sure the username passed from the client is escaped properly.
+       #
+       # Uncomment the next line, if you want the sql_user_name to mean:
+       #
+       #    Use Stripped-User-Name, if it's there.
+       #    Else use User-Name, if it's there,
+       #    Else use hard-coded string "none" as the user name.
+       #
+       #sql_user_name = "%{Stripped-User-Name:-%{User-Name:-none}}"
+       #
+       sql_user_name = "%{User-Name}"
+
+       #######################################################################
+       #  Default profile
+       #######################################################################
+       # This is the default profile. It is found in SQL by group membership.
+       # That means that this profile must be a member of at least one group
+       # which will contain the corresponding check and reply items.
+       # This profile will be queried in the authorize section for every user.
+       # The point is to assign all users a default profile without having to
+       # manually add each one to a group that will contain the profile.
+       # The SQL module will also honor the User-Profile attribute. This
+       # attribute can be set anywhere in the authorize section (ie the users
+       # file). It is found exactly as the default profile is found.
+       # If it is set then it will *overwrite* the default profile setting.
+       # The idea is to select profiles based on checks on the incoming
+       # packets, not on user group membership. For example:
+       # -- users file --
+       # DEFAULT       Service-Type == Outbound-User, User-Profile := "outbound"
+       # DEFAULT       Service-Type == Framed-User, User-Profile := "framed"
+       #
+       # By default the default_user_profile is not set
+       #
+#      default_user_profile = "DEFAULT"
+
+       #######################################################################
+       #  NAS Query
+       #######################################################################
+       #  This query retrieves the radius clients
+       #
+       #  0. Row ID (currently unused)
+       #  1. Name (or IP address)
+       #  2. Shortname
+       #  3. Type
+       #  4. Secret
+       #######################################################################
+
+       nas_query = "SELECT id, nasname, shortname, type, secret FROM ${nas_table}"
+
+       #######################################################################
+       #  Authorization Queries
+       #######################################################################
+       #  These queries compare the check items for the user
+       #  in ${authcheck_table} and setup the reply items in
+       #  ${authreply_table}.  You can use any query/tables
+       #  you want, but the return data for each row MUST
+       #  be in the  following order:
+       #
+       #  0. Row ID (currently unused)
+       #  1. UserName/GroupName
+       #  2. Item Attr Name
+       #  3. Item Attr Value
+       #  4. Item Attr Operation
+       #######################################################################
+
+       # Use these for case insensitive usernames. WARNING: Slower queries!
+# authorize_check_query = "SELECT id, UserName, Attribute, Value, Op \
+#   FROM ${authcheck_table} \
+#   WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') \
+#   ORDER BY id"
+# authorize_reply_query = "SELECT id, UserName, Attribute, Value, Op \
+#   FROM ${authreply_table} \
+#   WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') \
+#   ORDER BY id"
+
+       authorize_check_query = "SELECT id, UserName, Attribute, Value, Op \
+               FROM ${authcheck_table} \
+               WHERE Username = '%{SQL-User-Name}' \
+               ORDER BY id"
+
+       authorize_reply_query = "SELECT id, UserName, Attribute, Value, Op \
+               FROM ${authreply_table} \
+               WHERE Username = '%{SQL-User-Name}' \
+               ORDER BY id"
+
+       # Use these for case insensitive usernames. WARNING: Slower queries!
+# authorize_group_check_query = "SELECT ${groupcheck_table}.id, ${groupcheck_table}.GroupName, \
+#   ${groupcheck_table}.Attribute, ${groupcheck_table}.Value, ${groupcheck_table}.Op \
+#   FROM ${groupcheck_table}, ${usergroup_table} \
+#   WHERE LOWER(${usergroup_table}.UserName) = LOWER('%{SQL-User-Name}') AND ${usergroup_table}.GroupName = ${groupcheck_table}.GroupName \
+#   ORDER BY ${groupcheck_table}.id"
+# authorize_group_reply_query = "SELECT ${groupreply_table}.id, ${groupreply_table}.GroupName, \
+#   ${groupreply_table}.Attribute, ${groupreply_table}.Value, ${groupreply_table}.Op \
+#   FROM ${groupreply_table}, ${usergroup_table} \
+#   WHERE LOWER(${usergroup_table}.UserName) = LOWER('%{SQL-User-Name}') AND ${usergroup_table}.GroupName = ${groupreply_table}.GroupName \
+#   ORDER BY ${groupreply_table}.id"
+
+  authorize_group_check_query = "SELECT id, GroupName, Attribute, Value, op \
+    FROM ${groupcheck_table} \
+    WHERE GroupName = '%{Sql-Group}' \
+    ORDER BY id"
+
+  authorize_group_reply_query = "SELECT id, GroupName, Attribute, Value, op \
+    FROM ${groupreply_table} \
+    WHERE GroupName = '%{Sql-Group}' \
+    ORDER BY id"
+
+        #######################################################################
+        # Simultaneous Use Checking Queries
+        #######################################################################
+        # simul_count_query     - query for the number of current connections
+        #                       - If this is not defined, no simultaneous use checking
+        #                       - will be performed by this module instance
+        # simul_verify_query    - query to return details of current connections for verification
+        #                       - Leave blank or commented out to disable verification step
+        #                       - Note that the returned field order should not be changed.
+        #######################################################################
+
+        # Uncomment simul_count_query to enable simultaneous use checking
+       # simul_count_query = "SELECT COUNT(*) FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime IS NULL"
+        # simul_verify_query = "SELECT RadAcctId, AcctSessionId, UserName, NASIPAddress, NASPortId, FramedIPAddress, CallingStationId, FramedProtocol FROM ${acct_table1} WHERE UserName='%{SQL-User-Name}' AND AcctStopTime IS NULL"
+
+
+
+       #######################################################################
+       #  Accounting Queries
+       #######################################################################
+       # accounting_onoff_query        - query for Accounting On/Off packets
+       # accounting_update_query       - query for Accounting update packets
+       # accounting_update_query_alt   - query for Accounting update packets
+       #                               (alternate in case first query fails)
+       # accounting_start_query        - query for Accounting start packets
+       # accounting_start_query_alt    - query for Accounting start packets
+       #                               (alternate in case first query fails)
+       # accounting_stop_query         - query for Accounting stop packets
+       # accounting_stop_query_alt     - query for Accounting start packets
+       #                               (alternate in case first query doesn't
+       #                                affect any existing rows in the table)
+       #######################################################################
+
+  accounting_onoff_query = "UPDATE ${acct_table1} \
+    SET AcctStopTime = (now() - '%{Acct-Delay-Time:-0}'::interval), \
+    AcctSessionTime = (EXTRACT(EPOCH FROM (now()::timestamp with time zone - AcctStartTime::timestamp with time zone \
+    - '%{Acct-Delay-Time:-0}'::interval)))::BIGINT, \
+    AcctTerminateCause='%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time:-0}' \
+    WHERE AcctSessionTime IS NULL AND AcctStopTime IS NULL AND NASIPAddress= '%{NAS-IP-Address}' AND AcctStartTime <= now()"
+
+  accounting_update_query = "UPDATE ${acct_table1} \
+    SET FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, \
+    AcctSessionTime = '%{Acct-Session-Time}', \
+    AcctInputOctets = (('%{Acct-Input-Gigawords:-0}'::bigint << 32) + '%{Acct-Input-Octets:-0}'::bigint), \
+    AcctOutputOctets = (('%{Acct-Output-Gigawords:-0}'::bigint << 32) + '%{Acct-Output-Octets:-0}'::bigint) \
+    WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' \
+    AND NASIPAddress= '%{NAS-IP-Address}' AND AcctStopTime IS NULL"
+
+  accounting_update_query_alt = "INSERT INTO ${acct_table1} \
+    (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, \
+    AcctSessionTime, AcctAuthentic, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, \
+    ServiceType, FramedProtocol, FramedIPAddress) \
+    values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', \
+    %{NAS-Port:-NULL}::integer, '%{NAS-Port-Type}', (now() - '%{Acct-Delay-Time:-0}'::interval - '%{Acct-Session-Time:-0}'::interval), \
+    '%{Acct-Session-Time}', '%{Acct-Authentic}', \
+    (('%{Acct-Input-Gigawords:-0}'::bigint << 32) + '%{Acct-Input-Octets:-0}'::bigint), \
+    (('%{Acct-Output-Gigawords:-0}'::bigint << 32) + '%{Acct-Output-Octets:-0}'::bigint), '%{Called-Station-Id}', \
+    '%{Calling-Station-Id}', '%{Service-Type}', '%{Framed-Protocol}', NULLIF('%{Framed-IP-Address}', '')::inet)"
+
+  accounting_start_query = "INSERT INTO ${acct_table1} \
+    (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctAuthentic, \
+    ConnectInfo_start, CalledStationId, CallingStationId, ServiceType, FramedProtocol, FramedIPAddress, AcctStartDelay) \
+    values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', \
+    %{NAS-Port:-NULL}::integer, '%{NAS-Port-Type}', (now() - '%{Acct-Delay-Time:-0}'::interval), '%{Acct-Authentic}', \
+    '%{Connect-Info}', '%{Called-Station-Id}', '%{Calling-Station-Id}', '%{Service-Type}', '%{Framed-Protocol}', \
+    NULLIF('%{Framed-IP-Address}', '')::inet, '%{Acct-Delay-Time:-0}')"
+
+  accounting_start_query_alt  = "UPDATE ${acct_table1} \
+    SET AcctStartTime = (now() - '%{Acct-Delay-Time:-0}'::interval), AcctStartDelay = '%{Acct-Delay-Time:-0}', \
+    ConnectInfo_start = '%{Connect-Info}' WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' \
+    AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime IS NULL"
+
+  accounting_stop_query = "UPDATE ${acct_table2} \
+    SET AcctStopTime = (now() - '%{Acct-Delay-Time:-0}'::interval), \
+    AcctSessionTime = CASE WHEN '%{Acct-Session-Time}' = '' THEN \
+    (EXTRACT(EPOCH FROM (now()::TIMESTAMP WITH TIME ZONE - AcctStartTime::TIMESTAMP WITH TIME ZONE \
+    - '%{Acct-Delay-Time:-0}'::INTERVAL)))::BIGINT ELSE '%{Acct-Session-Time}' END, \
+    AcctInputOctets = (('%{Acct-Input-Gigawords:-0}'::bigint << 32) + '%{Acct-Input-Octets:-0}'::bigint), \
+    AcctOutputOctets = (('%{Acct-Output-Gigawords:-0}'::bigint << 32) + '%{Acct-Output-Octets:-0}'::bigint), \
+    AcctTerminateCause = '%{Acct-Terminate-Cause}', AcctStopDelay = '%{Acct-Delay-Time:-0}', \
+    FramedIPAddress = NULLIF('%{Framed-IP-Address}', '')::inet, ConnectInfo_stop = '%{Connect-Info}' \
+    WHERE AcctSessionId = '%{Acct-Session-Id}' AND UserName = '%{SQL-User-Name}' \
+    AND NASIPAddress = '%{NAS-IP-Address}' AND AcctStopTime IS NULL"
+
+  accounting_stop_query_alt = "INSERT INTO ${acct_table2} \
+    (AcctSessionId, AcctUniqueId, UserName, Realm, NASIPAddress, NASPortId, NASPortType, AcctStartTime, AcctStopTime, \
+    AcctSessionTime, AcctAuthentic, ConnectInfo_stop, AcctInputOctets, AcctOutputOctets, CalledStationId, \
+    CallingStationId, AcctTerminateCause, ServiceType, FramedProtocol, FramedIPAddress, AcctStopDelay) \
+    values('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}', '%{SQL-User-Name}', '%{Realm}', '%{NAS-IP-Address}', \
+    %{NAS-Port:-NULL}::integer, '%{NAS-Port-Type}', (now() - '%{Acct-Delay-Time:-0}'::interval - '%{Acct-Session-Time:-0}'::interval), \
+    (now() - '%{Acct-Delay-Time:-0}'::interval), NULLIF('%{Acct-Session-Time}', '')::bigint, '%{Acct-Authentic}', \
+    '%{Connect-Info}', (('%{Acct-Input-Gigawords:-0}'::bigint << 32) + '%{Acct-Input-Octets:-0}'::bigint), \
+    (('%{Acct-Output-Gigawords:-0}'::bigint << 32) + '%{Acct-Output-Octets:-0}'::bigint), '%{Called-Station-Id}', \
+    '%{Calling-Station-Id}', '%{Acct-Terminate-Cause}', '%{Service-Type}', '%{Framed-Protocol}', \
+    NULLIF('%{Framed-IP-Address}', '')::inet, '%{Acct-Delay-Time:-0}')"
+
+       #######################################################################
+       # Group Membership Queries
+       #######################################################################
+       # group_membership_query        - Check user group membership
+       #######################################################################
+
+       # Use these for case insensitive usernames. WARNING: Slower queries!
+# group_membership_query = "SELECT GroupName FROM ${usergroup_table} WHERE LOWER(UserName) = LOWER('%{SQL-User-Name}') ORDER BY priority"
+
+  group_membership_query = "SELECT GroupName FROM ${usergroup_table} WHERE UserName='%{SQL-User-Name}' ORDER BY priority"
+
+       #######################################################################
+       # Authentication Logging Queries
+       #######################################################################
+       # postauth_query                - Insert some info after authentication
+       #######################################################################
+  postauth_query = "INSERT INTO ${postauth_table} (username, pass, reply, authdate) \
+    VALUES ('%{User-Name}', '%{User-Password:-Chap-Password}', '%{reply:Packet-Type}', NOW())"
+
similarity index 94%
rename from raddb/pgsql-voip.conf
rename to raddb/sql/postgresql-voip-postpaid.conf
index c4c28bd..001a724 100644 (file)
@@ -29,7 +29,7 @@ sql pgsql-voip {
        groupcheck_table = "radgroupcheck"
        groupreply_table = "radgroupreply"
        
-       usergroup_table = "usergroup"
+       usergroup_table = "radusergroup"
        
        # Remove stale session if checkrad does not see a double login
        deletestalesessions = yes
@@ -43,7 +43,7 @@ sql pgsql-voip {
        
        # Radius server name so you can tell which radius server handled a request
        # when you have multiple radius servers and one database.
-       radius_server_name = myservername
+       radius_server_name = FreeRADIUS
 
        #######################################################################
        #  Query config:  Username
@@ -97,11 +97,11 @@ sql pgsql-voip {
        accounting_stop_query = "INSERT into ${acct_table2}%{h323-call-type} \
                (RadiusServerName, UserName, NASIPAddress, AcctTime, \
                AcctSessionTime, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, \
-               AcctDelayTime, H323RemoteAddress, CiscoNASPort, h323callorigin, callid, \
+               AcctDelayTime, H323RemoteAddress, H323VoiceQuality, CiscoNASPort, h323callorigin, callid, \
                h323connecttime, h323disconnectcause, h323disconnecttime, h323gwid, h323setuptime) \
                values('${radius_server_name}', '%{SQL-User-Name}', '%{NAS-IP-Address}', now(), '%{Acct-Session-Time:-0}', \
                '%{Acct-Input-Octets:-0}', '%{Acct-Output-Octets:-0}', '%{Called-Station-Id}', '%{Calling-Station-Id}', \
-               '%{Acct-Delay-Time:-0}', NULLIF('%{h323-remote-address}', '')::inet, NULLIF('%{Cisco-NAS-Port}', ''), \
+               '%{Acct-Delay-Time:-0}', NULLIF('%{h323-remote-address}', '')::inet, NULLIF('%{h323-voice-quality}','')::integer, NULLIF('%{Cisco-NAS-Port}', ''), \
                '%{h323-call-origin}', pick_id('%{h323-conf-id}', '%{call-id}'), strip_dot('%{h323-connect-time}'), '%{h323-disconnect-cause}', \
                strip_dot('%{h323-disconnect-time}'), '%{h323-gw-id}', strip_dot('%{h323-setup-time}'))"
  
index 75d21e6..fdc4a83 100644 (file)
+#  Configuration for the SQL based IPPool module (rlm_sqlippool)
+#
+#  The database schemas are available at:
+#
+#       doc/examples/*.sql
+#
+#  $Id$
 
-sqlippool sqlippool {
+sqlippool {
 
- #
- # SQL connection information
- #
+ ## SQL instance to use (from sql.conf)
  sql-instance-name = "sql"
 
- # lease_duration. fix for lost acc-stop packets
+ ## Table to keep ippool info
+ ippool_table = "radippool"
+
+ ## lease_duration. fix for lost acc-stop packets
  lease-duration = 3600
 
- # Attribute which should be considered unique per NAS
+ ## Attribute which should be considered unique per NAS
+ ## Using NAS-Port gives behaviour similar to rlm_ippool. Calling-Station-Id is for NAS that send fixed NAS-Port
  pool-key = "%{NAS-Port}"
  # pool-key = "%{Calling-Station-Id}"
 
+ ## Logging configuration.
+ sqlippool_log_exists = "Existing IP: %{reply:Framed-IP-Address} \
+  (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
+
+ sqlippool_log_success = "Allocated IP: %{reply:Framed-IP-Address} from %{check:Pool-Name} \
+  (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
+
+ sqlippool_log_clear = "Released IP %{Framed-IP-Address}\
+ (did %{Called-Station-Id} cli %{Calling-Station-Id} user %{User-Name})"
+
+ sqlippool_log_failed = "IP Allocation FAILED from %{check:Pool-Name} \
+  (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
 
- #
- # This series of queries allocates an IP address
- #
- allocate-clear = "UPDATE radippool \
+ sqlippool_log_nopool = "No Pool-Name defined \
+  (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} user %{User-Name})"
+
+ ## This series of queries allocates an IP address
+ allocate-clear = "UPDATE ${ippool_table} \
   SET nasipaddress = '', pool_key = 0, callingstationid = '', \
   expiry_time = 'now'::timestamp(0) - '1 second'::interval \
-  WHERE pool_key = '%{Calling-Station-Id}'"
-
- # note the ORDER BY clause of next query, it'll try to allocate IPs
- # like Cisco internal pools do - it _trys_ to allocate the same IP-address
- # which user had last session...
- allocate-find = "SELECT framedipaddress FROM radippool \
-  WHERE pool_name = '%{reply:Pool-Name}' AND expiry_time < 'now'::timestamp(0) \
-  ORDER BY pool_name, (username <> '%{User-Name}'), (callingstationid <> '%{Calling-Station-Id}'), expiry_time \
+  WHERE pool_key = '${pool-key}'"
+
+ ## The ORDER BY clause of this query tries to allocate the same IP-address
+ ## which user had last session...
+ allocate-find = "SELECT framedipaddress FROM ${ippool_table} \
+  WHERE pool_name = '%{check:Pool-Name}' AND expiry_time < 'now'::timestamp(0) \
+  ORDER BY (username <> '%{SQL-User-Name}'), (callingstationid <> '%{Calling-Station-Id}'), expiry_time \
   LIMIT 1 \
   FOR UPDATE"
 
- allocate-update = "UPDATE radippool \
-  SET nasipaddress = '%{NAS-IP-Address}', pool_key = '%{Calling-Station-Id}', \
-  callingstationid = '%{Calling-Station-Id}', username = '%{User-Name}', \
+ ## If you prefer to allocate a random IP address every time, use this query instead
+ #allocate-find = "SELECT framedipaddress FROM ${ippool_table} \
+ # WHERE pool_name = '%P' AND expiry_time < 'now'::timestamp(0) \
+ # ORDER BY RANDOM() \
+ # 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='%{check:Pool-Name}' LIMIT 1"
+
+ allocate-update = "UPDATE ${ippool_table} \
+  SET nasipaddress = '%{NAS-IP-Address}', pool_key = '${pool-key}', \
+  callingstationid = '%{Calling-Station-Id}', username = '%{SQL-User-Name}', \
   expiry_time = 'now'::timestamp(0) + '${lease-duration} second'::interval \
   WHERE framedipaddress = '%I'"
 
 
+ ## This series of queries frees an IP number when an accounting
+ ## START record arrives
+ start-update = "UPDATE ${ippool_table} \
+  SET expiry_time = 'now'::timestamp(0) + '${lease-duration} second'::interval \
+  WHERE nasipaddress = '%{NAS-IP-Address}' AND  pool_key = '${pool-key}'"
 
- #
- # This series of queries frees an IP number when an accounting
- # START record arrives
- #
- start-update = "UPDATE radippool \
-  SET expiry_time = 'now'::timestamp(0) + '%J second'::interval \
-  WHERE nasipaddress = '%n' AND nas_port = '%p' AND pool_name = '%P'"
-
- #
- # This series of queries frees an IP number when an accounting
- # STOP record arrives
- #
- stop-clear = "UPDATE radippool \
+ ## This series of queries frees an IP number when an accounting
+ ## STOP record arrives
+ stop-clear = "UPDATE ${ippool_table} \
   SET nasipaddress = '', pool_key = 0, callingstationid = '', \
   expiry_time = 'now'::timestamp(0) - '1 second'::interval \
-  WHERE nasipaddress = '%{Nas-IP-Address}' AND pool_key = '${pool-key}' AND username = '%{User-Name}' \
+  WHERE nasipaddress = '%{Nas-IP-Address}' AND pool_key = '${pool-key}' AND username = '%{SQL-User-Name}' \
   AND callingstationid = '%{Calling-Station-Id}' AND framedipaddress = '%{Framed-IP-Address}'"
 
 
 
-
- #
- # This series of queries frees an IP number when an accounting
- # ALIVE record arrives
- #
- alive-update = "UPDATE radippool \
+ ## This series of queries frees an IP number when an accounting
+ ## ALIVE record arrives
+ alive-update = "UPDATE ${ippool_table} \
   SET expiry_time = 'now'::timestamp(0) + '${lease-duration} seconds'::interval \
-  WHERE nasipaddress = '%{Nas-IP-Address}' AND pool_key = '${pool-key}' AND username = '%{User-Name}' \
+  WHERE nasipaddress = '%{Nas-IP-Address}' AND pool_key = '${pool-key}' AND username = '%{SQL-User-Name}' \
   AND callingstationid = '%{Calling-Station-Id}' AND framedipaddress = '%{Framed-IP-Address}'"
 
 
- #
- # This series of queries frees the IP numbers allocate to a
- # NAS when an accounting ON record arrives
- #
- on-clear = "UPDATE radippool \
+ ## This series of queries frees the IP numbers allocate to a
+ ## NAS when an accounting ON record arrives
+ on-clear = "UPDATE ${ippool_table} \
   SET nasipaddress = '', pool_key = 0, callingstationid = '', \
   expiry_time = 'now'::timestamp(0) - '1 second'::interval \
-  WHERE nasipaddress = '%{Nas-IP-Address}' AND username = '%{User-Name}' \
+  WHERE nasipaddress = '%{Nas-IP-Address}' AND username = '%{SQL-User-Name}' \
   AND callingstationid = '%{Calling-Station-Id}' AND framedipaddress = '%{Framed-IP-Address}'"
 
- #
- # This series of queries frees the IP numbers allocate to a
- # NAS when an accounting OFF record arrives
- #
- off-clear = "UPDATE radippool \
+ ## This series of queries frees the IP numbers allocate to a
+ ## NAS when an accounting OFF record arrives
+ off-clear = "UPDATE ${ippool_table} \
   SET nasipaddress = '', pool_key = 0, callingstationid = '', \
   expiry_time = 'now'::timestamp(0) - '1 second'::interval \
-  WHERE nasipaddress = '%{Nas-IP-Address}' AND username = '%{User-Name}' \
+  WHERE nasipaddress = '%{Nas-IP-Address}' AND username = '%{SQL-User-Name}' \
   AND callingstationid = '%{Calling-Station-Id}' AND framedipaddress = '%{Framed-IP-Address}'"
 
-
 }
-
index 2c2586f..f0e1372 100644 (file)
@@ -2,12 +2,6 @@
 #      Please read the documentation file ../doc/processing_users_file,
 #      or 'man 5 users' (after installing the server) for more information.
 #
-#      As of 1.1.4, you SHOULD NOT use Auth-Type.  See "man rlm_pap"
-#      for a much better way of dealing with differing passwords.
-#      If you set Auth-Type, SOME AUTHENTICATION METHODS WILL NOT WORK.
-#      If you don't set Auth-Type, the server will figure out what to do,
-#      and will almost always do the right thing.
-#
 #      This file contains authentication security and configuration
 #      information for each user.  Accounting requests are NOT processed
 #      through this file.  Instead, see 'acct_users', in this directory.
 #      type (perhaps set by the "hints" file), and huntgroup name (set by
 #      the "huntgroups" file).
 #
-#      Indented (with the tab character) lines following the first
-#      line indicate the configuration values to be passed back to
-#      the comm server to allow the initiation of a user session.
-#      This can include things like the PPP configuration values
-#      or the host to log the user onto.
-#
 #      If you are not sure why a particular reply is being sent by the
 #      server, then run the server in debugging mode (radiusd -X), and
 #      you will see which entries in this file are matched.
 #      matches the login-request will stop processing unless you use
 #      the Fall-Through variable.
 #
+#      If you use the database support to turn this file into a .db or .dbm
+#      file, the DEFAULT entries _have_ to be at the end of this file and
+#      you can't have multiple entries for one username.
+#
+#      Indented (with the tab character) lines following the first
+#      line indicate the configuration values to be passed back to
+#      the comm server to allow the initiation of a user session.
+#      This can include things like the PPP configuration values
+#      or the host to log the user onto.
+#
 #      You can include another `users' file with `$INCLUDE users.other'
 #
 
@@ -75,7 +73,7 @@
 # entry so that no DEFAULT entry will be used, and the user will NOT
 # get any attributes in addition to the ones listed here.
 #
-#steve Cleartext-Password := "testing"
+#steve User-Password := "testing"
 #      Service-Type = Framed-User,
 #      Framed-Protocol = PPP,
 #      Framed-IP-Address = 172.16.3.33,
 # This is an entry for a user with a space in their name.
 # Note the double quotes surrounding the name.
 #
-#"John Doe"    Cleartext-Password := "hello"
-#              Reply-Message = "Hello, %u"
+#"John Doe"    User-Password := "hello"
+#              Reply-Message = "Hello, %{User-Name}"
 
 #
 # Dial user back and telnet to the default host for that port
 #
-#Deg   Cleartext-Password := "ge55ged"
+#Deg   User-Password := "ge55ged"
 #      Service-Type = Callback-Login-User,
 #      Login-IP-Host = 0.0.0.0,
 #      Callback-Number = "9,5551212",
 # connection will be broken and the user will be dialed back after which
 # he will get a connection to the host "timeshare1".
 #
-#dialbk        Cleartext-Password := "callme"
+#dialbk        User-Password := "callme"
 #      Service-Type = Callback-Login-User,
 #      Login-IP-Host = timeshare1,
 #      Login-Service = PortMaster,
 # against the system database, give them shell access, and stop processing
 # the rest of the file.
 #
-# Note that authenticating against an /etc/passwd file works ONLY for PAP,
-# and not for CHAP, MS-CHAP, or EAP.
-#
 #DEFAULT       Suffix == ".shell", Auth-Type := System
 #              Service-Type = Login-User,
 #              Login-Service = Telnet,
 #
 
 #
-# First setup all accounts to be checked against the UNIX /etc/passwd.
-# (Unless a password was already given earlier in this file).
-#
-DEFAULT        Auth-Type = System
-       Fall-Through = 1
-
-#
 # Set up different IP address pools for the terminal servers.
 # Note that the "+" behind the IP address means that this is the "base"
 # IP address. The Port-Id (S0, S1 etc) will be added to it.
@@ -167,13 +155,13 @@ DEFAULT   Auth-Type = System
 #              Fall-Through = Yes
 
 #
-# Defaults for all framed connections.
+# Sample defaults for all framed connections.
 #
-DEFAULT        Service-Type == Framed-User
-       Framed-IP-Address = 255.255.255.254,
-       Framed-MTU = 576,
-       Service-Type = Framed-User,
-       Fall-Through = Yes
+#DEFAULT       Service-Type == Framed-User
+#      Framed-IP-Address = 255.255.255.254,
+#      Framed-MTU = 576,
+#      Service-Type = Framed-User,
+#      Fall-Through = Yes
 
 #
 # Default for PPP: dynamic IP address, PPP mode, VJ-compression.
@@ -210,6 +198,6 @@ DEFAULT     Hint == "SLIP"
 # # Last default: shell on the local terminal server.
 # #
 # DEFAULT
-#      Service-Type = Shell-User
+#      Service-Type = Administrative-User
 
 # On no match, the user is denied access.
index c5bacda..12e8deb 100644 (file)
@@ -1,7 +1,7 @@
 Summary: High-performance and highly configurable RADIUS server
 URL: http://www.freeradius.org/
 Name: freeradius
-Version: 1.1.5
+Version: 2.0.0
 Release: 0
 License: GPL
 Group: Networking/Daemons
@@ -114,6 +114,7 @@ fi
 %{_libdir}/*
 %{_mandir}/*/*
 %{_sbindir}/*
+%{_incdir}/freeradius/*
 %attr(0700,radiusd,radiusd) %dir /var/log/radius
 %attr(0700,radiusd,radiusd) %dir /var/log/radius/radacct
 %attr(0700,radiusd,radiusd) %dir /var/run/radiusd
index ac5265a..2bac22d 100755 (executable)
@@ -15,7 +15,7 @@
 #
 #    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 #
 #    Copyright (C) 2001 The FreeRADIUS Project   http://www.freeradius.org
 #
index 4e17270..dcd3cd8 100644 (file)
@@ -4,6 +4,9 @@ include ../Make.inc
 
 all:
 
+radwatch:
+       $(INSTALL) -m 755 radwatch              $(R)$(sbindir)
+
 install:
        $(INSTALL) -m 755 rc.radiusd            $(R)$(sbindir)
        $(INSTALL) -m 755 radsqlrelay           $(R)$(bindir)
index a71350e..73cbb8a 100755 (executable)
@@ -18,7 +18,7 @@ cd certs
 #
 # Generate DH stuff...
 #
-$(SSL)/bin/openssl gendh > dh
+${SSL}/bin/openssl gendh > dh
 
 #
 #  /dev/urandom is not a file, and we can't rely on "test -e" working
diff --git a/scripts/clients.pl b/scripts/clients.pl
new file mode 100755 (executable)
index 0000000..14cd029
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/bin/env perl
+#
+#  Convert old-style "clients" file to new "clients.conf" format.
+#
+#  Usage: clients.pl clients [naslist] new-clients.conf
+#      The "new-clients.conf" will be created if it does not exist.
+#      If it does exist, it will be over-written.
+#
+#
+#      $Id$
+#
+if (($#ARGV < 1) || ($#ARGV > 2)) {
+    print "Usage: clients.pl clients [naslist] new-clients.conf\n";
+    print "       The \"new-clients.conf\" will be created if it does not exist.\n";
+    print "       If it does exist, it will be over-written.\n";
+    exit(1);
+}
+
+$old = shift;
+$new = shift;
+
+if ($new =~ /naslist/) {
+    $naslist = $new;
+    $new = shift;
+}
+
+open OLD, "< $old" or die "Failed to open $old: $!\n";
+
+while (<OLD>) {
+    next if (/^\s*\#/);
+    next if (/^\s*$/);
+
+    split;
+
+    $clients{$_[0]}{"secret"} = $_[1];
+}
+close OLD;
+
+if (defined $naslist) {
+    open OLD, "< $naslist" or die "Failed to open $naslist: $!\n";
+
+    while (<OLD>) {
+       next if (/^\s*\#/);
+       next if (/^\s*$/);
+       
+       split;
+
+       if (!defined $clients{$_[0]}) {
+           print "WARNING! client $_[0] is defined in naslist, but not in clients!";
+           next;
+       }
+
+       $clients{$_[0]}{"shortname"} = $_[1];
+       $clients{$_[0]}{"nastype"} = $_[2];
+    }
+}
+
+open NEW, "> $new" or die "Failed to open $new: $!\n";
+foreach $client (keys %clients) {
+    print NEW "client $client {\n";
+    print NEW "\tsecret = ", $clients{$client}{"secret"}, "\n";
+    if (defined $clients{$client}{"shortname"}) {
+       print NEW "\tshortname = ", $clients{$client}{"shortname"}, "\n";
+       print NEW "\tnastype = ", $clients{$client}{"nastype"}, "\n";
+    }
+    print NEW "}\n";
+    print NEW "\n";
+}
index e9388ad..905442e 100755 (executable)
@@ -14,7 +14,7 @@
 #
 #    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 #
 #    Copyright (C) 2001 The FreeRADIUS Project   http://www.freeradius.org
 #
index 1d388ac..ea303bc 100755 (executable)
@@ -1,20 +1,33 @@
 #!/bin/sh
 #
-# $Id$
-#
-#  Sample script to run when a 'user' file entry is similar to:
-#
-#bob   Password == "bob"
-#      Exec-Program-Wait = "/path/to/program/exec-program-wait"
-#
-#  For 'acct_users':
-#
-#DEFAULT Acct-Status-Type == Start
-#      Exec-Program = "/path/to/exec/acct/start"
-#
-#DEFAULT Acct-Status-Type == Stop
-#      Exec-Program = "/path/to/exec/acct/stop"
-#
+#  $Id$
+#
+#  Sample script to add Attribute/Value pairs in the reply sent to
+#  the NAS.
+#
+#  Before version 2.0 of FreeRADIUS, the script could be run from the
+#  deprecated attributes 'Exec-Program' and 'Exec-Program-Wait'.
+#  However, these attributes are no longer supported and you have to
+#  use the module 'rlm_exec' instead.
+#
+#  An entry for the module 'rlm_exec' must be added to the file
+#  'radiusd.conf' with the path of the script.
+#
+#modules {
+#      exec {
+#              program = "/path/to/program/exec-program-wait"
+#              wait = yes
+#              input_pairs = request
+#              output_pairs = reply
+#      }
+#      ...
+#}
+#
+#authorize {
+#      ...
+#      exec
+#      ...
+#}
 #
 #  Each of the attributes in the request will be available in an
 #  environment variable.  The name of the variable depends on the
 #  to the script.  Then look in the file for a complete list of
 #  variables.
 #
+#  The return value of the program run determines the result
+#  of the exec instance call as follows:
+#  (See doc/configurable_failover for details)
+#  < 0 : fail      the module failed
+#  = 0 : okthe module succeeded
+#  = 1 : reject    the module rejected the user
+#  = 2 : fail      the module failed
+#  = 3 : okthe module succeeded
+#  = 4 : handled   the module has done everything to handle the request
+#  = 5 : invalid   the user's configuration entry was invalid
+#  = 6 : userlock  the user was locked out
+#  = 7 : notfound  the user was not found
+#  = 8 : noop      the module did nothing
+#  = 9 : updated   the module updated information in the request
+#  > 9 : fail      the module failed
+#
 echo "Reply-Message += \"Hello, %u\","
 echo "Reply-Message += \"PATH=$PATH\","
 echo Framed-IP-Address = 255.255.255.255
diff --git a/scripts/min-includes.pl b/scripts/min-includes.pl
new file mode 100755 (executable)
index 0000000..769c01c
--- /dev/null
@@ -0,0 +1,238 @@
+#!/usr/bin/env perl
+######################################################################
+#
+#  This script find duplicates of #include files, ignoring #ifdef's, etc.
+#  from C source files, and (at your command) removes the duplicates.
+#
+#  It is meant to be run ONLY by FreeRADUS developers, and has nothing
+#  whatsoever to do with RADIUS, FreeRADIUS, or confguring a RADIUS server.
+#
+######################################################################
+#
+#  Run as: ./min-includes.pl `find . -name "*.c" -print`
+#              prints out duplicate includes from files.
+#
+#         ./min-includes.pl +n `find . -name "*.c" -print`
+#              removes the duplicate includes from each file.
+#              Remember to check that it still builds!
+#
+#  It has to be run from the TOP of the FreeRADIUS build tree,
+#  i.e. where the top-level "configure" script is located.
+#
+######################################################################
+#
+#  FIXME: We don't handle include files taken from the current
+#  directory...
+#
+#  FIXME: we should take -I <path> from the command line.
+#
+######################################################################
+#
+#  Copyright (C) 2006 Alan DeKok <aland@freeradius.org>
+#
+#  $Id$
+#
+######################################################################
+
+my %processed;
+
+$any_dups = 0;
+$debug = 0;
+
+#
+#  Find the #include's for one file.
+#
+sub process($) {
+    my $file = shift;
+
+    return if ($processed{$file});
+
+    $processed{$file}++;
+
+    open FILE, "<$file" or die "Failed to open $file: $!\n";
+    
+    $line = 0;
+    while (<FILE>) {
+       $line++;
+       
+       next if (!/^\s*\#\s*include\s+/);
+       
+       if (/^\s*\#\s*include\s+"(.+?)"/) {
+           $refs{$file}{$1} = $line;
+
+           # FIXME: local header files?
+           # src/foo/bar.c: #include "foo.h"
+           #   src/foo/foo.h do stuff..
+
+           $include{$1}++;
+       } elsif (/^\s*\#\s*include\s+<(.+?)>/) {
+           $refs{$file}{$1} = $line;
+           $include{$1}++;
+       }
+    }
+    
+    close FILE;
+}
+
+#
+#  Where include files are located.
+#
+#  FIXME: 
+#
+@directories = ("src/lib", "src");
+$do_it = 0;
+
+#
+#  Horrid.
+#
+if ($ARGV[0] eq "+n") {
+    shift;
+    $do_it = 1;
+}
+
+#
+#  Bootstrap the basic C files.
+#
+foreach $file (@ARGV) {
+    process($file);
+}
+
+
+#
+#  Process the include files referenced from the C files, to find out
+#  what they include Note that we create a temporary array, rather
+#  than walking over %include, because the process() function adds
+#  entries to the %include hash.
+#
+@work = sort keys %include;
+foreach $inc (@work) {
+
+    foreach $dir (@directories) {
+       $path = $dir . "/" . $inc;
+
+       # normalize path
+       $path =~ s:/.*?/\.\.::;
+       $path =~ s:/.*?/\.\.::;
+
+       next if (! -e $path);
+       process($path);
+       $forward{$inc} = $path;
+       $reverse{$path} = $inc;
+
+       # ignore system include files
+       next if ((scalar keys %{$refs{$path}}) == 0);
+
+       #  Remember that X includes Y, and push Y onto the list
+       #  of files to scan.
+       foreach $inc2 (sort keys %{$refs{$path}}) {
+           $maps{$inc}{$inc2} = 0;
+           push @work, $inc2;
+       }
+    }
+}
+
+#
+#  Process all of the forward refs, so that we have a complete
+#  list of who's referencing who.
+#
+#  This doesn't find the shortest path from A to B, but it does
+#  find one path.
+#
+foreach $inc (sort keys %maps) {
+    foreach $inc2 (sort keys %{$maps{$inc}}) {
+       foreach $inc3 (sort keys %{$maps{$inc2}}) {
+           # map is already there...
+           next if (defined $maps{$inc}{$inc3});
+
+           $maps{$inc}{$inc3} = $maps{$inc2}{$inc3} + 1;
+       }
+    }
+}
+
+#
+#  Walk through the files again, looking for includes that are
+#  unnecessary.  Note that we process header files, too.
+#
+foreach $file (sort keys %refs) {
+
+    # print out some debugging information.
+    if ($debug > 0) {
+       if (defined $reverse{$file}) {
+           print $file, "\t(", $reverse{$file}, ")\n";
+       } else {
+           print $file, "\n";
+       }
+    }
+
+    #  walk of the list of include's in this file
+    foreach $ref (sort keys %{$refs{$file}}) {
+
+       #  walk over the include files we include, or included by
+       #  files that we include.
+       foreach $inc2 (sort keys %{$maps{$ref}}) {
+           #
+           #  If we include X, and X includes Y, and we include
+           #  Y ourselves *after* X, it's a definite dupe.
+           #
+           #  Note that this is a *guaranteed* duplicate.
+           #
+           #  Sometimes order matters, so we can't always delete X if
+           #  we include Y after X, and Y includes X
+           #
+           if (defined $refs{$file}{$inc2} &&
+               ($refs{$file}{$inc2} > $refs{$file}{$ref})) {
+               $duplicate{$file}{$inc2} = $ref;
+
+               # mark the line to be deleted.
+               $delete_line{$file}{$refs{$file}{$inc2}}++;
+
+               $any_dups++;
+           }
+       }
+       print "\t", $ref, "\n" if ($debug > 0);
+    }
+}
+
+if ($debug > 0) {
+    print "------------------------------------\n";
+}
+
+#
+#  Maybe just print out the dups so that a person can validate them.
+#
+if (!$do_it) {
+    foreach $file (sort keys %duplicate) {
+       print $file, "\n";
+       
+       foreach $inc (sort keys %{$duplicate{$file}}) {
+           print "\t[", $refs{$file}{$inc}, "] ", $inc, " (", $duplicate{$file}{$inc}, " at ", $refs{$file}{$duplicate{$file}{$inc}}, ")\n";
+       }
+    }
+} else {
+    foreach $file (sort keys %duplicate) {
+       open FILE, "<$file" or die "Failed to open $file: $!\n";
+       open OUTPUT, ">$file.tmp" or die "Failed to create $file.tmp: $!\n";
+       
+       $line = 0;
+       while (<FILE>) {
+           $line++;
+
+           # supposed to delete this line, don't print it to the output.
+           next if (defined $delete_line{$file}{$line});
+
+           print OUTPUT;
+       }
+
+       rename "$file.tmp", $file;
+    }
+
+}
+
+#  If we succeeded in re-writing the files, it's OK.
+exit 0 if ($do_it);
+
+#  If there are no duplicates, then we're OK.
+exit 0 if (!$any_dups);
+
+#  Else there are duplicates, complain.
+exit 1
index fea38d0..5644bc3 100755 (executable)
@@ -56,7 +56,7 @@
 #
 #    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 # -----------------------------------------------------------------------
 
 
index 9db1ffa..c21c25c 100755 (executable)
@@ -14,7 +14,7 @@
 #
 #    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 #
 #    Copyright (C) 2001-2002 The FreeRADIUS Project http://www.freeradius.org
 
index 4a1f01f..f422167 100644 (file)
@@ -6,3 +6,15 @@ extendedKeyUsage = 1.3.6.1.5.5.7.3.2
 
 [ xpserver_ext]
 extendedKeyUsage = 1.3.6.1.5.5.7.3.1
+
+#
+#  Add this to the PKCS#7 keybag attributes holding the client's private key
+#  for machine authentication.
+#
+#  the presence of this OID tells Windows XP that the cert is intended
+#  for use by the computer itself, and not by an end-user.
+#
+#  The other solution is to use Microsoft's web certificate server
+#  to generate these certs.
+#
+# 1.3.6.1.4.1.311.17.2 
diff --git a/share/Makefile b/share/Makefile
new file mode 100644 (file)
index 0000000..ab342b4
--- /dev/null
@@ -0,0 +1,15 @@
+#
+#      Scripts to format dictionary files.
+#
+#      $Id$
+#
+.PHONY: format
+
+#
+#  This should only be run by hand, and then sanity checked by hand!
+#
+format: dictionary*
+       @for x in dictionary* ; do \
+               cat $$x | ./format.pl > tmp; \
+               mv tmp $$x; \
+       done
index efa02e6..c18f5b1 100644 (file)
@@ -83,7 +83,6 @@ $INCLUDE dictionary.alteon
 $INCLUDE dictionary.alvarion
 $INCLUDE dictionary.aruba
 $INCLUDE dictionary.ascend
-$INCLUDE dictionary.asn
 $INCLUDE dictionary.bay
 $INCLUDE dictionary.bintec
 $INCLUDE dictionary.cablelabs
@@ -134,7 +133,6 @@ $INCLUDE dictionary.riverstone
 $INCLUDE dictionary.roaringpenguin
 $INCLUDE dictionary.shasta
 $INCLUDE dictionary.shiva
-$INCLUDE dictionary.sofaware
 $INCLUDE dictionary.sonicwall
 $INCLUDE dictionary.springtide
 $INCLUDE dictionary.starent
index 9de40d9..4819471 100644 (file)
@@ -1,15 +1,16 @@
 # -*- text -*-
+##############################################################################
 #
-# Ascend dictionary.
-# $Id$
+#      Ascend dictionary.
 #
-#              Enable by putting the line "$INCLUDE dictionary.ascend" into
-#              the main dictionary file.
+#      $Id$
 #
-# Version:     1.00  21-Jul-1997  Jens Glaser <jens@regio.net>
-#              1.01  22-Jan-1998  Tomas Pospisek <tpo@spin.ch>
-#              1.2   28-Sept-2000 Chris Adams <cmadams@hiwaay.net>
-#              1.3   12-Dec-2000 Miquel van Smoorenburg <miquels@cistron.nl>
+##############################################################################
+
+#
+#      For 16-bit Ascend VSA's, see dictionary.lucent.  Those VSA's
+#      are in the Lucent namespace, and belong in that file, rather
+#      than here.
 #
 #
 #  The Ascend-Data-Filter and Ascend-Call-Filter are case insensitive
diff --git a/share/dictionary.chillispot b/share/dictionary.chillispot
new file mode 100644 (file)
index 0000000..15b3c63
--- /dev/null
@@ -0,0 +1,30 @@
+# -*- text -*-
+##############################################################################
+#
+#      ChilliSpot captive portal
+#      http://www.chillispot.org
+#
+#      $Id$
+#
+##############################################################################
+
+VENDOR         ChilliSpot                      14559
+
+BEGIN-VENDOR   ChilliSpot
+
+ATTRIBUTE      ChilliSpot-Max-Input-Octets             1       integer
+ATTRIBUTE      ChilliSpot-Max-Output-Octets            2       integer
+ATTRIBUTE      ChilliSpot-Max-Total-Octets             3       integer
+
+# Configuration management parameters
+ATTRIBUTE      ChilliSpot-UAM-Allowed                  100     string
+ATTRIBUTE      ChilliSpot-MAC-Allowed                  101     string
+ATTRIBUTE      ChilliSpot-Interval                     102     integer
+
+# Inline with RFC 2882 use of VSE-Authorize-Only for remote config
+# Note that 14559 = 0x38df is used as prefix for the VSE.
+# This is recognized as the best (but bad) way of doing VSEs.
+#
+VALUE  Service-Type                    ChilliSpot-Authorize-Only 0x38df0001
+
+END-VENDOR     ChilliSpot
index ef9377a..08b43a5 100644 (file)
 #
 # http://www.cisco.com/univercd/cc/td/doc/product/access/acs_serv/vapp_dev/vsaig3.htm
 #
+#  For general documentation on Cisco RADIUS configuration, see:
+#
+# http://www.cisco.com/en/US/partner/tech/tk583/tk547/tsd_technology_support_sub-protocol_home.html
+#
 
 VENDOR         Cisco                           9
 
index a58ee06..5d20ad1 100644 (file)
@@ -56,7 +56,8 @@ ATTRIBUTE     EAP-Type                                1018    integer
 ATTRIBUTE      EAP-TLS-Require-Client-Cert             1019    integer
 ATTRIBUTE      EAP-Id                                  1020    integer
 ATTRIBUTE      EAP-Code                                1021    integer
-ATTRIBUTE      EAP-MD5-Password                        1022    string
+# Attribute 1022 unused, was EAP-MD5-Password, which was
+# used only be radeapclient.  It's been replaced by Cleartext-Password
 ATTRIBUTE      PEAP-Version                            1023    integer
 
 #
@@ -350,18 +351,16 @@ VALUE     Packet-Type                     Terminate-Session       31
 VALUE  Packet-Type                     Password-Expired        32
 VALUE  Packet-Type                     Event-Request           33
 VALUE  Packet-Type                     Event-Response          34
+
+#      RFC 3576 allocates packet types 40-45
+
 VALUE  Packet-Type                     Disconnect-Request      40
 VALUE  Packet-Type                     Disconnect-ACK          41
 VALUE  Packet-Type                     Disconnect-NAK          42
-
-# Old names, if no one uses them, they should be deleted.
-VALUE  Packet-Type                     CoF-Request             43
-VALUE  Packet-Type                     CoF-ACK                 44
-VALUE  Packet-Type                     CoF-NAK                 45
-
 VALUE  Packet-Type                     CoA-Request             43
 VALUE  Packet-Type                     CoA-ACK                 44
 VALUE  Packet-Type                     CoA-NAK                 45
+
 VALUE  Packet-Type                     IP-Address-Allocate     50
 VALUE  Packet-Type                     IP-Address-Release      51
 
index 38bbdb6..7341e44 100644 (file)
@@ -320,6 +320,8 @@ ATTRIBUTE   Lucent-User-Login-Level                 307     integer
 ATTRIBUTE      Lucent-First-Level-User                 308     string
 ATTRIBUTE      Lucent-IP-Source-If                     309     string
 ATTRIBUTE      Lucent-Reverse-Path-Check               310     integer
+ATTRIBUTE      Lucent-LCP-Keepalive-Period             321     integer
+ATTRIBUTE      Lucent-LCP-Keepalive-Missed-Limit       322     integer
 ATTRIBUTE      Lucent-Dsl-Atuc-Chan-Uncorrect-Blks     10000   integer
 ATTRIBUTE      Lucent-Dsl-Atuc-Chan-Corrected-Blks     10001   integer
 ATTRIBUTE      Lucent-Dsl-Atuc-Chan-Xmit-Blks          10002   integer
diff --git a/share/dictionary.nortel b/share/dictionary.nortel
new file mode 100644 (file)
index 0000000..88b62a7
--- /dev/null
@@ -0,0 +1,24 @@
+# -*- text -*-
+##############################################################################
+#
+#      Nortel Passport 8600 VSA's.
+#
+#      http://www142.nortelnetworks.com/bvdoc/setips/july04/engineeringtipstricksv12.pdf
+#
+#      $Id$
+#
+##############################################################################
+
+VENDOR         Nortel                          562
+BEGIN-VENDOR   Nortel
+
+ATTRIBUTE      Passport-Command-Scope                  200     integer
+ATTRIBUTE      Passport-Command-Impact                 201     integer
+ATTRIBUTE      Passport-Customer-Identifier            202     integer
+ATTRIBUTE      Passport-Allowed-Access                 203     integer
+ATTRIBUTE      Passport-AllowedOut-Access              204     integer
+ATTRIBUTE      Passport-Login-Directory                205     string
+ATTRIBUTE      Passport-Timeout-Protocol               206     integer
+ATTRIBUTE      Passport-Role                           207     string
+
+END-VENDOR     Nortel
diff --git a/share/dictionary.rfc4590 b/share/dictionary.rfc4590
deleted file mode 100644 (file)
index 0332dd2..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-# -*- text -*-
-#
-#       Attributes and values defined in RFC 4590.
-#       http://www.ietf.org/rfc/rfc4590.txt
-#       Previously defined in draft-sterman-aaa-sip-00.txt
-#
-#       $Id$
-#
-ATTRIBUTE      Digest-Response                         206     string
-ATTRIBUTE      Digest-Attributes                       207     octets  # stupid format
-
-BEGIN-SUB-ATTR Digest-Attributes
-ATTRIBUTE      Digest-Realm                            1       string
-ATTRIBUTE      Digest-Nonce                            2       string
-ATTRIBUTE      Digest-Method                           3       string
-ATTRIBUTE      Digest-URI                              4       string
-ATTRIBUTE      Digest-QOP                              5       string
-ATTRIBUTE      Digest-Algorithm                        6       string
-ATTRIBUTE      Digest-Body-Digest                      7       string
-ATTRIBUTE      Digest-CNonce                           8       string
-ATTRIBUTE      Digest-Nonce-Count                      9       string
-ATTRIBUTE      Digest-User-Name                        10      string
-END-SUB-ATTR
index 9592063..eb31d2d 100644 (file)
@@ -15,13 +15,13 @@ BEGIN-VENDOR        Roaring-Penguin
 ATTRIBUTE      RP-Upstream-Speed-Limit                 1       integer
  # Downstream speed limit in kb/s
 ATTRIBUTE      RP-Downstream-Speed-Limit               2       integer
+
 # Send a HURL
 ATTRIBUTE      RP-HURL                                 3       string
+
 # Send a MOTM
 ATTRIBUTE      RP-MOTM                                 4       string
+
 # Maximum sessions per user
 ATTRIBUTE      RP-Max-Sessions-Per-User                5       integer
 
diff --git a/share/dictionary.schulzrinne-sipping b/share/dictionary.schulzrinne-sipping
deleted file mode 100644 (file)
index 9a32865..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-# http://www.freeradius.org/rfc/draft-schulzrinne-sipping-radius-accounting-00.txt
-#
-# $Id$
-#
-
-
-ATTRIBUTE Sip-Method                   101  integer
-ATTRIBUTE Sip-Response-Code            102  integer
-ATTRIBUTE Sip-Cseq                     103  string
-ATTRIBUTE Sip-To-Tag                   104  string
-ATTRIBUTE Sip-From-Tag                 105  string
-ATTRIBUTE Sip-Branch-ID                106  string
-ATTRIBUTE Sip-Translated-Request-ID    107  string
-ATTRIBUTE Sip-Source-IP-Address        108  ipaddr
-ATTRIBUTE Sip-Source-Port              109  integer
-
-
-### Service-Type Values ###
-VALUE Service-Type       Sip-Session      15
-
-
-### Sip-Method Values ###
-VALUE Sip-Method         INVITE         0
-VALUE Sip-Method         BYE            1
-VALUE Sip-Method         REGISTER       2
-VALUE Sip-Method         CANCEL         3
-VALUE Sip-Method         OPTIONS        4
-VALUE Sip-Method         ACK            5
-VALUE Sip-Method         SUBSCRIBE      6
-VALUE Sip-Method         NOTIFY         7
-
index 56eb275..7228a65 100755 (executable)
 $begin_vendor = 0;
 $blank = 0;
 
-while (<>) {
-    #
-    #  Clear out trailing whitespace
-    #
-    s/[ \t]+$//;
-
-    #
-    #  And CR's
-    #
-    s/\r//g;
-
-    #
-    #  Suppress multiple blank lines
-    #
-    if (/^\s+$/) {
-       next if ($blank == 1);
-       $blank = 1;
-       print "\n";
-       next;
-    }
-    $blank = 0;
-
-    #
-    #  Remember the vendor
-    #
-    if (/^VENDOR\s+([\w-]+)\s+(\w+)(.*)/) {
-       $name=$1;
-       $len = length $name;
-       if ($len < 32) {
-           $lenx = 32 - $len;
-           $lenx += 7;         # round up
-           $lenx /= 8;
-           $lenx = int $lenx;
-           $tabs = "\t" x $lenx;
-       } else {
-           $tabs = " ";
-       }
-       print "VENDOR\t\t$name$tabs$2$3\n";
-       $vendor = $name;
-       next;
-    }
+while (@ARGV) {
+    $filename = shift;
+    
+    open FILE, "<$filename" or die "Failed to open $filename: $!\n";
+    
+    @output = ();
+    
+    while (<FILE>) {
+       #
+       #  Clear out trailing whitespace
+       #
+       s/[ \t]+$//;
 
-    #  
-    #  Remember if we did begin-vendor.
-    #
-    if (/^BEGIN-VENDOR\s+([\w-]+)/) {
-       $begin_vendor = 1;
-       print "BEGIN-VENDOR\t$vendor\n";
-       next;
-    }
+       #
+       #  And CR's
+       #
+       s/\r//g;
 
-    #
-    #  Get attribute.
-    #
-    if (/^ATTRIBUTE\s+([\w-]+)\s+(\w+)\s+(\w+)(.*)/) {
-       $name=$1;
-       $len = length $name;
-       if ($len < 40) {
-           $lenx = 40 - $len;
-           $lenx += 7;         # round up
-           $lenx /= 8;
-           $lenx = int $lenx;
-           $tabs = "\t" x $lenx;
-           if ($tabs eq "") {
-               $tabs = " ";
-           }
-       } else {
-           $tabs = " ";
+       #
+       #  Suppress multiple blank lines
+       #
+       if (/^\s+$/) {
+           next if ($blank == 1);
+           $blank = 1;
+           push @output, "\n";
+           next;
        }
-
-       $value = $2;
-       $type = $3;
-       $stuff = $4;
+       $blank = 0;
 
        #
-       #  See if it's old format, with the vendor at the end of
-       #  the line.  If so, make it the new format.
+       #  Remember the vendor
        #
-       if ($stuff =~ /$vendor/) {
-           if ($begin_vendor == 0) {
-               print "BEGIN-VENDOR\t$vendor\n\n";
-               $begin_vendor = 1;
+       if (/^VENDOR\s+([\w-]+)\s+(\w+)(.*)/) {
+           $name=$1;
+           $len = length $name;
+           if ($len < 32) {
+               $lenx = 32 - $len;
+               $lenx += 7;             # round up
+               $lenx /= 8;
+               $lenx = int $lenx;
+               $tabs = "\t" x $lenx;
+           } else {
+               $tabs = " ";
            }
-           $stuff =~ s/$vendor//;
-           $stuff =~ s/\s+$//;
+           push @output, "VENDOR\t\t$name$tabs$2$3\n";
+           $vendor = $name;
+           next;
        }
 
-       print "ATTRIBUTE\t$name$tabs$value\t$type$stuff\n";
-       next;
-    }
+       #  
+       #  Remember if we did begin-vendor.
+       #
+       if (/^BEGIN-VENDOR\s+([\w-]+)/) {
+           $begin_vendor = 1;
+           if (!defined $vendor) {
+               $vendor = $1;
+           } elsif ($vendor ne $1) {
+               # do something smart
+           }
 
-    #
-    #  Values.
-    #
-    if (/^VALUE\s+([\w-]+)\s+([\w-\/,.]+)\s+(\w+)(.*)/) {
-       $attr=$1;
-       $len = length $attr;
-       if ($len < 32) {
-           $lenx = 32 - $len;
-           $lenx += 7;         # round up
-           $lenx /= 8;
-           $lenx = int $lenx;
-           $tabsa = "\t" x $lenx;
-           if ($tabsa eq "") {
-               $tabsa = " ";
-               $len += 1;
+           push @output, "BEGIN-VENDOR\t$vendor\n";
+           next;
+       }
+
+       #
+       #  Get attribute.
+       #
+       if (/^ATTRIBUTE\s+([\w-]+)\s+(\w+)\s+(\w+)(.*)/) {
+           $name=$1;
+           $len = length $name;
+           if ($len < 40) {
+               $lenx = 40 - $len;
+               $lenx += 7;             # round up
+               $lenx /= 8;
+               $lenx = int $lenx;
+               $tabs = "\t" x $lenx;
+               if ($tabs eq "") {
+                   $tabs = " ";
+               }
            } else {
-               $len -= $len % 8;
-               $len += 8 * length $tabsa;
+               $tabs = " ";
            }
-       } else {
-           $tabsa = " ";
-           $len += 1;
+
+           $value = $2;
+           $type = $3;
+           $stuff = $4;
+
+           #
+           #  See if it's old format, with the vendor at the end of
+           #  the line.  If so, make it the new format.
+           #
+           if ($stuff =~ /$vendor/) {
+               if ($begin_vendor == 0) {
+                   push @output, "BEGIN-VENDOR\t$vendor\n\n";
+                   $begin_vendor = 1;
+               }
+               $stuff =~ s/$vendor//;
+               $stuff =~ s/\s+$//;
+           }
+
+           push @output, "ATTRIBUTE\t$name$tabs$value\t$type$stuff\n";
+           next;
        }
 
        #
-       #  For the code below, we assume that the attribute lengths
+       #  Values.
        #
-       if ($len < 32) {
-           $lena = 0;
-       } else {
-           $lena = $len - 32;
-       }
+       if (/^VALUE\s+([\w-]+)\s+([\w-\/,.]+)\s+(\w+)(.*)/) {
+           $attr=$1;
+           $len = length $attr;
+           if ($len < 32) {
+               $lenx = 32 - $len;
+               $lenx += 7;             # round up
+               $lenx /= 8;
+               $lenx = int $lenx;
+               $tabsa = "\t" x $lenx;
+               if ($tabsa eq "") {
+                   $tabsa = " ";
+                   $len += 1;
+               } else {
+                   $len -= $len % 8;
+                   $len += 8 * length $tabsa;
+               }
+           } else {
+               $tabsa = " ";
+               $len += 1;
+           }
 
-       $name = $2;
-       $len = length $name;
-       if ($len < 24) {
-           $lenx = 24 - $lena - $len;
-           $lenx += 7;         # round up
-           $lenx /= 8;
-           $lenx = int $lenx;
-           $tabsn = "\t" x $lenx;
-           if ($tabsn eq "") {
+           #
+           #  For the code below, we assume that the attribute lengths
+           #
+           if ($len < 32) {
+               $lena = 0;
+           } else {
+               $lena = $len - 32;
+           }
+
+           $name = $2;
+           $len = length $name;
+           if ($len < 24) {
+               $lenx = 24 - $lena - $len;
+               $lenx += 7;             # round up
+               $lenx /= 8;
+               $lenx = int $lenx;
+               $tabsn = "\t" x $lenx;
+               if ($tabsn eq "") {
+                   $tabsn = " ";
+               }
+           } else {
                $tabsn = " ";
            }
-       } else {
-           $tabsn = " ";
+
+           push @output, "VALUE\t$attr$tabsa$name$tabsn$3$4\n";
+           next;
        }
 
-       print "VALUE\t$attr$tabsa$name$tabsn$3$4\n";
-       next;
-    }
+       #
+       #  Remember if we did this.
+       #
+       if (/^END-VENDOR/) {
+           $begin_vendor = 0;
+       }
 
-    #
-    #  Remember if we did this.
-    #
-    if (/^END-VENDOR/) {
-       $begin_vendor = 0;
+       #
+       #  Everything else gets dumped out as-is.
+       #
+       push @output, $_;
     }
 
-    #
-    #  Everything else gets dumped out as-is.
-    #
-    print;
-}
-
 #
 #  If we changed the format, print the end vendor, too.
 #
-if ($begin_vendor) {
-    print "\nEND-VENDOR\t$vendor\n";
+    if ($begin_vendor) {
+       push @output, "\nEND-VENDOR\t$vendor\n";
+    }
+
+    close FILE;
+
+    open FILE, ">$filename" or die "Failed to open $filename: $!\n";
+
+    print FILE @output;
+
+    close FILE;
 }
index 2e8fb1e..bfd5272 100644 (file)
@@ -9,7 +9,7 @@ include ../Make.inc
 SUBDIRS                = include lib modules main
 WHAT_TO_MAKE   = all
 
-all:
+all: freeradius-devel
        @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
 
 clean:
@@ -24,3 +24,6 @@ common:
                echo "Making $(WHAT_TO_MAKE) in $$dir..."; \
                $(MAKE) $(MFLAGS) -C $$dir $(WHAT_TO_MAKE) || exit $$?; \
        done
+
+freeradius-devel:
+       ln -s include freeradius-devel
index c3a91b9..da38d60 100644 (file)
@@ -63,25 +63,18 @@ CONFIGURATION
        "gw-accounting aaa"
        "radius-server vsa send"
 
-* In /etc/raddb/radiusd.conf set "with_cisco_vsa_hack = yes"
-
 * Create a Database to hold your billing records. ie:
        "createdb radius"
-* Add the plperl language to the database. ie:
-       "createlang plpgsql radius"
 
 * Import the SQL schema to your database. ie:
-       "psql radius < h323_db_postgresql.sql"
+       "psql radius < cisco_h323_db_schema-postgres.sql"
 
-* Copy the custom SQL queries to raddb/ ie:
-       "cp pgsql-voip.conf /etc/raddb/"
+* In /etc/raddb/radiusd.conf set "with_cisco_vsa_hack = yes"
 
 * In /etc/raddb/radiusd.conf add "$INCLUDE  ${confdir}/pgsql-voip.conf"
-  You can find the correct section by searching for "sql.conf"
-
+  (You can find the correct section by searching for "sql.conf")
 
-* In /etc/raddb/radiusd.conf add "pgsql-voip" to the "accounting {" section
-  just after the line "detail"
+* In /etc/raddb/radiusd.conf add "pgsql-voip" to the "accounting { }" section.
 
 * (re)Start radiusd
 
index c9cef80..935ee1b 100644 (file)
@@ -1,20 +1,8 @@
-/*
- * Id: postgresql.conf,v 1.8.2.11 2003/07/15 11:15:43 pnixon Exp $
- *
- * Old Function 'strip_dot' Now replaced by one written plpgsql
- *
- * Note: On SuSE Linux 8.0 and 8.1 you need to do the following from the command line before
- *       plperl functions will work.
- *
- * # ln -s /usr/lib/perl5/5.8.0/i586-linux-thread-multi/CORE/libperl.so /usr/lib/libperl.so
- * # createlang -U postgres plperl radius
- *
- *     CREATE OR REPLACE FUNCTION strip_dot_in_perl (text) returns timestamp AS '
- *             my $datetime = $_[0];
- *             $datetime =~ s/^\\.*//;
- *             return $datetime;
- *     ' language 'plperl';
- */
+-- Id: postgresql.conf,v 1.8.2.11 2003/07/15 11:15:43 pnixon Exp $
+
+-- create plpgsql language
+CREATE FUNCTION "plpgsql_call_handler" () RETURNS LANGUAGE_HANDLER AS '$libdir/plpgsql' LANGUAGE C;
+CREATE TRUSTED LANGUAGE "plpgsql" HANDLER "plpgsql_call_handler";
 
 
 CREATE OR REPLACE FUNCTION chop_number(VARCHAR) RETURNS VARCHAR AS '
@@ -93,14 +81,35 @@ CREATE OR REPLACE FUNCTION chop_number_number(VARCHAR) RETURNS VARCHAR AS '
  END;
 ' LANGUAGE 'plpgsql';
 
-/*
- * Some sample database VIEWs to simplify billing queries.
- */
+-- Some sample database VIEWs to simplify billing queries.
+
+CREATE OR REPLACE VIEW StartVoIPd AS
+SELECT DISTINCT ON(h323SetupTime, CallID) * FROM StartVoIP;
+
+CREATE OR REPLACE VIEW StopVoIPd AS
+SELECT DISTINCT ON(h323SetupTime, CallID) * FROM StopVoIP;
+
+
+CREATE OR REPLACE VIEW call_history_csps2 AS
+SELECT StartVoIP.h323ConnectTime, StopVoIP.h323DisconnectTime, (EXTRACT(EPOCH FROM(StopVoIP.h323DisconnectTime - StartVoIP.h323ConnectTime)))::BIGINT AS CallLength, StopVoIP.CalledStationId AS Number, StopVoIP.UserName AS UserName, StopVoIP.CallingStationId AS CallerID, StopVoIP.CallID
+FROM StopVoIPd AS StopVoIP LEFT OUTER JOIN StartVoIPd AS StartVoIP
+ON (StopVoIP.CallID = StartVoIP.CallID)
+WHERE StopVoIP.NASIPAddress = '212.50.54.122'
+ORDER BY StartVoIP.h323ConnectTime;
+
+CREATE OR REPLACE VIEW call_history_csps AS
+SELECT CAST ((h323DisconnectTime::date AT TIME ZONE 'UTC') AS date) AS Date, CAST ((h323DisconnectTime AT TIME ZONE 'UTC') AS time without time zone) AS Time, AcctSessionTime AS Length, CalledStationId AS Number, UserName AS UserName, CallingStationId AS CallerID, CallID
+FROM StopVoIP
+WHERE NASIPAddress = '212.50.54.122';
+
+CREATE OR REPLACE VIEW call_history AS
+SELECT CAST ((h323SetupTime::date AT TIME ZONE 'UTC') AS date) AS Date, CAST ((h323SetupTime AT TIME ZONE 'UTC') AS time without time zone) AS Time, AcctSessionTime AS Length, CalledStationId AS Number, UserName AS UserName, CallingStationId AS CallerID, H323RemoteAddress, NASIPAddress, CallID
+FROM StopVoIP;
 
 CREATE OR REPLACE VIEW call_history AS
 SELECT CAST ((pots.h323SetupTime::date AT TIME ZONE 'UTC') AS date) AS Date, CAST ((pots.h323SetupTime AT TIME ZONE 'UTC') AS time without time zone) AS Time, pots.AcctSessionTime AS Length, pots.CalledStationId AS Number, ip.H323RemoteAddress AS cust_ip, ip.NASIPAddress AS gw_ip
 FROM StopTelephony AS pots LEFT OUTER JOIN StopVoIP AS ip
-ON (pots.h323ConfID = ip.h323ConfID);
+ON (pots.CallID = ip.CallID);
 
 CREATE OR REPLACE VIEW call_history_customer AS
 SELECT Date, Time, Length, Number, cust_ip, gw_ip, CustomerIP.Company AS Company
@@ -113,11 +122,11 @@ FROM customers  AS cust, cust_gw AS gw
 WHERE cust.cust_id = gw.cust_id;
 
 CREATE OR REPLACE VIEW VoIP AS
-SELECT RadAcctId AS ID, NASIPAddress AS GWIP, AcctSessionTime AS Call_Seconds, chop_number_country(CalledStationId) AS Country, chop_number_city(CalledStationId) AS City,chop_number_number(CalledStationId) AS Number, chop_number(CalledStationId) AS Original_Number, EXTRACT(YEAR FROM (h323setuptime AT TIME ZONE 'UTC')) AS Year, EXTRACT(MONTH FROM (h323setuptime AT TIME ZONE 'UTC')) AS Month, EXTRACT(DAY FROM (h323setuptime AT TIME ZONE 'UTC')) AS Day, CAST ((h323SetupTime AT TIME ZONE 'UTC') AS time without time zone) AS Time, h323DisconnectCause AS error_code, H323RemoteAddress AS Remote_IP, h323ConfID AS ConfID
+SELECT RadAcctId AS ID, NASIPAddress AS GWIP, AcctSessionTime AS Call_Seconds, chop_number_country(CalledStationId) AS Country, chop_number_city(CalledStationId) AS City,chop_number_number(CalledStationId) AS Number, chop_number(CalledStationId) AS Original_Number, EXTRACT(YEAR FROM (h323setuptime AT TIME ZONE 'UTC')) AS Year, EXTRACT(MONTH FROM (h323setuptime AT TIME ZONE 'UTC')) AS Month, EXTRACT(DAY FROM (h323setuptime AT TIME ZONE 'UTC')) AS Day, CAST ((h323SetupTime AT TIME ZONE 'UTC') AS time without time zone) AS Time, h323DisconnectCause AS error_code, H323RemoteAddress AS Remote_IP, CallID
 FROM StopVoIP;
 
 CREATE OR REPLACE VIEW Telephony AS
-SELECT RadAcctId AS ID, NASIPAddress AS GWIP, AcctSessionTime AS Call_Seconds, chop_number_country(CalledStationId) AS Country, chop_number_city(CalledStationId) AS City,chop_number_number(CalledStationId) AS Number, chop_number(CalledStationId) AS Original_Number, EXTRACT(YEAR FROM (h323setuptime AT TIME ZONE 'UTC')) AS Year, EXTRACT(MONTH FROM (h323setuptime AT TIME ZONE 'UTC')) AS Month, EXTRACT(DAY FROM (h323setuptime AT TIME ZONE 'UTC')) AS Day, CAST ((h323SetupTime AT TIME ZONE 'UTC') AS time without time zone) AS Time, h323DisconnectCause AS error_code, split_part(split_part(CiscoNASPort,':',1),' ',2) AS PRI, split_part(CiscoNASPort,':',3) AS PRI_channel, CiscoNASPort AS isdn_port, h323ConfID AS ConfID
+SELECT RadAcctId AS ID, NASIPAddress AS GWIP, AcctSessionTime AS Call_Seconds, chop_number_country(CalledStationId) AS Country, chop_number_city(CalledStationId) AS City,chop_number_number(CalledStationId) AS Number, chop_number(CalledStationId) AS Original_Number, EXTRACT(YEAR FROM (h323setuptime AT TIME ZONE 'UTC')) AS Year, EXTRACT(MONTH FROM (h323setuptime AT TIME ZONE 'UTC')) AS Month, EXTRACT(DAY FROM (h323setuptime AT TIME ZONE 'UTC')) AS Day, CAST ((h323SetupTime AT TIME ZONE 'UTC') AS time without time zone) AS Time, h323DisconnectCause AS error_code, split_part(split_part(CiscoNASPort,':',1),' ',2) AS PRI, split_part(CiscoNASPort,':',3) AS PRI_channel, CiscoNASPort AS isdn_port, CallID AS ConfID
 FROM StopTelephony;
 
 CREATE OR REPLACE VIEW calls AS
@@ -141,9 +150,6 @@ ORDER BY H323ConnectTime, CalledStationId, H323RemoteAddress ASC;
 
 
 
-/*
- * # createlang -U postgres plpgsql radius
- */
 CREATE OR REPLACE FUNCTION VoIPInsertRecord(StopVoIP.UserName%TYPE, StopVoIP.NASIPAddress%TYPE, StopVoIP.AcctSessionTime%TYPE,
 StopVoIP.AcctInputOctets%TYPE, StopVoIP.AcctOutputOctets%TYPE, StopVoIP.CalledStationId%TYPE, StopVoIP.CallingStationId%TYPE,
 StopVoIP.AcctDelayTime%TYPE, StopVoIP.h323CallOrigin%TYPE, StopVoIP.h323SetupTime%TYPE, StopVoIP.h323ConnectTime%TYPE, StopVoIP.h323DisconnectTime%TYPE,
@@ -153,12 +159,12 @@ DECLARE
     key2 ALIAS FOR $2;
     key3 ALIAS FOR $16;
 BEGIN
-        PERFORM radacctid FROM StopVoIP WHERE h323SetupTime = $10 AND NASIPAddress = $2 AND h323confid = $16;
+        PERFORM radacctid FROM StopVoIP WHERE h323SetupTime = $10 AND NASIPAddress = $2 AND CallID = $16;
         IF NOT FOUND THEN
                INSERT into StopVoIP (
                 UserName, NASIPAddress, AcctSessionTime, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId,
                 AcctDelayTime, h323callorigin, h323setuptime, h323connecttime, h323disconnecttime, h323disconnectcause,
-               H323RemoteAddress, h323voicequality, h323confid) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16);
+               H323RemoteAddress, h323voicequality, CallID) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16);
        RETURN true;
         END IF;
         RETURN false;
@@ -169,15 +175,15 @@ CREATE OR REPLACE FUNCTION TelephonyInsertRecord(StopTelephony.UserName%TYPE, St
     StopTelephony.AcctInputOctets%TYPE, StopTelephony.AcctOutputOctets%TYPE, StopTelephony.CalledStationId%TYPE, StopTelephony.CallingStationId%TYPE,
     StopTelephony.AcctDelayTime%TYPE, StopTelephony.CiscoNASPort%TYPE, StopTelephony.h323CallOrigin%TYPE, StopTelephony.h323SetupTime%TYPE,
     StopTelephony.h323ConnectTime%TYPE, StopTelephony.h323DisconnectTime%TYPE, StopTelephony.h323DisconnectCause%TYPE, 
-    StopTelephony.H323VoiceQuality%TYPE, StopTelephony.h323ConfID%TYPE) RETURNS BOOLEAN AS '
+    StopTelephony.H323VoiceQuality%TYPE, StopTelephony.CallID%TYPE) RETURNS BOOLEAN AS '
 DECLARE
 BEGIN
-        PERFORM radacctid FROM StopTelephony WHERE h323SetupTime = $11 AND NASIPAddress = $2 AND h323confid = $16;
+        PERFORM radacctid FROM StopTelephony WHERE h323SetupTime = $11 AND NASIPAddress = $2 AND CallID = $16;
         IF NOT FOUND THEN
                INSERT into StopTelephony (
                 UserName, NASIPAddress, AcctSessionTime, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId,
                 AcctDelayTime, CiscoNASPort, h323callorigin, h323setuptime, h323connecttime, h323disconnecttime, h323disconnectcause,
-               h323voicequality, h323confid) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16);
+               h323voicequality, CallID) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16);
        RETURN true;
         END IF;
         RETURN false;
index ac232b1..0da9eb5 100644 (file)
 
 CREATE TABLE StartVoIP (
        RadAcctId               BIGSERIAL PRIMARY KEY,
-       h323SetupTime           TIMESTAMP with time zone NOT NULL,
+       AcctTime                TIMESTAMP with time zone NOT NULL,
+       h323SetupTime           TIMESTAMP with time zone,
        H323ConnectTime         TIMESTAMP with time zone,
        UserName                VARCHAR(64),
        RadiusServerName        VARCHAR(32),
        NASIPAddress            INET NOT NULL,
-       AcctTime                TIMESTAMP with time zone,
        CalledStationId         VARCHAR(80),
        CallingStationId        VARCHAR(80),
        AcctDelayTime           INTEGER,
        H323GWID                VARCHAR(32),
        h323CallOrigin          VARCHAR(10),
-       CallID                  VARCHAR(50) NOT NULL,
+       CallID                  VARCHAR(80) NOT NULL,
        processed               BOOLEAN DEFAULT false
 );
-create index startvoipcombo on startvoip (h323SetupTime, nasipaddress);
+create index startvoipcombo on startvoip (AcctTime, nasipaddress);
 
 
 CREATE TABLE StartTelephony (
        RadAcctId               BIGSERIAL PRIMARY KEY,
-       h323SetupTime           TIMESTAMP with time zone NOT NULL,
+       AcctTime                TIMESTAMP with time zone NOT NULL,
+       h323SetupTime           TIMESTAMP with time zone,
        H323ConnectTime         TIMESTAMP with time zone,
        UserName                VARCHAR(64),
        RadiusServerName        VARCHAR(32),
        NASIPAddress            INET NOT NULL,
-       AcctTime                TIMESTAMP with time zone,
        CalledStationId         VARCHAR(80),
        CallingStationId        VARCHAR(80),
        AcctDelayTime           INTEGER,
        H323GWID                VARCHAR(32),
        h323CallOrigin          VARCHAR(10),
-       CallID                  VARCHAR(35) NOT NULL,
+       CallID                  VARCHAR(80) NOT NULL,
        processed               BOOLEAN DEFAULT false
 );
-create index starttelephonycombo on starttelephony (h323SetupTime, nasipaddress);
+create index starttelephonycombo on starttelephony (AcctTime, nasipaddress);
 
 
 
@@ -65,13 +65,13 @@ create index starttelephonycombo on starttelephony (h323SetupTime, nasipaddress)
  */
 CREATE TABLE StopVoIP (
        RadAcctId               BIGSERIAL PRIMARY KEY,
+       AcctTime                TIMESTAMP with time zone NOT NULL,
        H323SetupTime           TIMESTAMP with time zone,
        H323ConnectTime         TIMESTAMP with time zone,
-       H323DisconnectTime      TIMESTAMP with time zone NOT NULL,
+       H323DisconnectTime      TIMESTAMP with time zone,
        UserName                VARCHAR(32),
        RadiusServerName        VARCHAR(32),
        NASIPAddress            INET NOT NULL,
-       AcctTime                TIMESTAMP with time zone,
        AcctSessionTime         BIGINT,
        AcctInputOctets         BIGINT,
        AcctOutputOctets        BIGINT,
@@ -84,28 +84,21 @@ CREATE TABLE StopVoIP (
        H323DisconnectCause     VARCHAR(20),
        H323RemoteAddress       INET,
        H323VoiceQuality        INTEGER,
-       CallID                  VARCHAR(50) NOT NULL,
+       CallID                  VARCHAR(80) NOT NULL,
        processed               BOOLEAN DEFAULT false
 );
-create UNIQUE index stopvoipcombo on stopvoip (h323SetupTime, nasipaddress, CallID);
-/*
- * Some Cisco CSPS do not have complete VSA details. If you have one of these you will want
- * to use the following index, as the one above will drop records.
- * 
- *  create UNIQUE index stopvoipcombo on stopvoip (h323DisconnectTime, nasipaddress, CallID);
- *
- */
+create UNIQUE index stopvoipcombo on stopvoip (AcctTime, nasipaddress, CallID);
 
 
 CREATE TABLE StopTelephony (
        RadAcctId               BIGSERIAL PRIMARY KEY,
+       AcctTime                TIMESTAMP with time zone NOT NULL,
        H323SetupTime           TIMESTAMP with time zone NOT NULL,
        H323ConnectTime         TIMESTAMP with time zone NOT NULL,
        H323DisconnectTime      TIMESTAMP with time zone NOT NULL,
        UserName                VARCHAR(32) DEFAULT '' NOT NULL,
        RadiusServerName        VARCHAR(32),
        NASIPAddress            INET NOT NULL,
-       AcctTime                TIMESTAMP with time zone,
        AcctSessionTime         BIGINT,
        AcctInputOctets         BIGINT,
        AcctOutputOctets        BIGINT,
@@ -118,12 +111,12 @@ CREATE TABLE StopTelephony (
        H323DisconnectCause     VARCHAR(20),
        H323RemoteAddress       INET,
        H323VoiceQuality        INTEGER,
-       CallID                  VARCHAR(35) NOT NULL,
+       CallID                  VARCHAR(80) NOT NULL,
        processed               BOOLEAN DEFAULT false
 );
--- You can have more than one record that is identical except for CiscoNASPort if you have a VoIP dial peer
+-- You can have more than one record that is identical except for CiscoNASPort if you have a dial peer hungroup
 -- configured for multiple PRIs.
-create UNIQUE index stoptelephonycombo on stoptelephony (h323SetupTime, nasipaddress, CallID, CiscoNASPort);
+create UNIQUE index stoptelephonycombo on stoptelephony (AcctTime, nasipaddress, CallID, CiscoNASPort);
 
 /*
  * Table structure for 'gateways'
@@ -172,6 +165,10 @@ CREATE VIEW customerip AS
     SELECT gw.cust_gw AS ipaddr, cust.company, cust.customer, gw."location" FROM customers cust, cust_gw gw WHERE (cust.cust_id = gw.cust_id);
 
 
+-- create plpgsql language (You need to be a database superuser to be able to do this)
+CREATE FUNCTION "plpgsql_call_handler" () RETURNS LANGUAGE_HANDLER AS '$libdir/plpgsql' LANGUAGE C;
+CREATE TRUSTED LANGUAGE "plpgsql" HANDLER "plpgsql_call_handler";
+
 /*
  * Function 'strip_dot'
  * removes "." from the start of cisco timestamps
index 51a1650..79b9753 100755 (executable)
@@ -1,18 +1,16 @@
 #!/usr/bin/perl
 #
 # Author:       Peter Nixon <codemonkey@peternixon.net>
-# Date:         August 2002 
 # Summary:      Extract information from Radius detail log and
 #              compare/insert/update a Postgresql database.
-# Copy Policy:  GNU Public Licence Version 2 or later
+# Copy Policy:  GNU Public Licence Version 2
 # URL:          http://www.peternixon.net/code/
-# Supported:    PostgreSQL (tested on version 7.2 and 7.3.x) and FreeRadius
-# Copyright:    2002, 2003 Peter Nixon <codemonkey@petenixon.net>
+# Supported:    PostgreSQL (tested on version 7.2, 7.3, 7.4 and 8) and FreeRadius
+# Copyright:    2004 Peter Nixon http://www.petenixon.net
 #
 # 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.
+# it under the terms of Version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
 #
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -23,6 +21,7 @@
 #
 
 
+
 # Modules that we use to get things done.
 require DBI;
 require Getopt::Long;
@@ -46,12 +45,12 @@ $password    = "";
 
 
 #### You should not have to modify anything below here
-$progname = "H323 Detail to DB parser";
-$version = 2;
+$progname = "H323 Detail2DB";
+$version = 2.2;
 
 # Set up some basic variables
-$passno = 0; $double_match_no = 0; $verbose = 0;
-$starttime = time();
+my $passno = 0; my $duplicates = 0; my $verbose = 0; my %duplicate_records = ();
+my $starttime = time();
 
 
 sub db_connect {
@@ -61,28 +60,37 @@ sub db_connect {
        if ($verbose > 1) { print "DEBUG: localhost connection so using UNIX socket instead of network socket.\n" }
                $dbh = DBI->connect("DBI:Pg:dbname=$database", "$user", "$password")
                        or die "Couldn't connect to database: " . DBI->errstr;
-       }
-       else {
+       } else {
                $dbh = DBI->connect("DBI:Pg:dbname=$database;host=$hostname", "$user", "$password")
                        or die "Couldn't connect to database: " . DBI->errstr;
        }
 }
 
 sub db_disconnect {
-       ### Now, disconnect from the database
+       my $hostname = shift;
        if ($verbose > 1) { print "DEBUG: Disconnecting from Database Host: $hostname\n" }
-       $dbh->disconnect
+       $dbh->disconnect                # Disconnect from the database
            or warn "Disconnection failed: $DBI::errstr\n";
 }
 
+sub process_duplicates {
+       if ($verbose > 1) { print "DEBUG: Now processing $duplicates duplicate records\n" }
+       foreach my $a1 ( keys %duplicate_records ) {
+               print "$a1:\n";
+               for my $a2 ( keys %{ $duplicate_records{$a1} } ) {
+                       print "\t$a2 = $duplicate_records{$a1}{$a2}\n";
+               }
+       print "\n";
+       }
+}
+
 
-sub procedure_insert {
-       $passno++;
+sub procedure_insert {         # FIXME: Does not work with current SQL schema. Use standard method
        if ($verbose > 0) { print "Record: $passno) Conf ID: $h323_conf_id   Setup Time: $h323_setup_time  Call Length: $AcctSessionTime   "; }
        if ($h323_call_type eq 'VoIP') { 
         $sth2 = $dbh->prepare("SELECT VoIPInsertRecord('$UserName', '$NasIPAddress', '$AcctSessionTime', '$AcctInputOctets', '$AcctOutputOctets',
                '$Called_Station_Id', '$Calling_Station_Id', '$AcctDelayTime', '$h323_call_origin', '$h323_setup_time',
-               '$h323_connect_time','$h323_disconnect_time', '$h323_disconnect_cause', '$h323_remote_address', '$h323_voice_quality', '$h323_conf_id')");
+               '$h323_connect_time','$h323_disconnect_time', '$h323_disconnect_cause', (NULLIF('$h323_remote_address', '')::inet), '$h323_voice_quality', '$h323_conf_id')");
        }
        elsif ($h323_call_type eq 'Telephony') {
         $sth2 = $dbh->prepare("SELECT TelephonyInsertRecord('$UserName', '$NasIPAddress', '$AcctSessionTime', '$AcctInputOctets', '$AcctOutputOctets',
@@ -97,35 +105,42 @@ sub procedure_insert {
 
 sub db_insert {
        if ($h323_call_type eq 'VoIP') { 
-        $sth2 = $dbh->prepare("INSERT into Stop$h323_call_type (
-               UserName, NASIPAddress, AcctSessionTime, AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId,
-               AcctDelayTime, H323RemoteAddress, h323callorigin, h323confid,
-               h323connecttime, h323disconnectcause, h323disconnecttime, h323setuptime, h323voicequality)
-               values('$UserName', '$NasIPAddress', '$AcctSessionTime', '$AcctInputOctets', '$AcctOutputOctets',
-               '$Called_Station_Id', '$Calling_Station_Id', '$AcctDelayTime', '$h323_remote_address',
-               '$h323_call_origin', '$h323_conf_id', '$h323_connect_time', '$h323_disconnect_cause', '$h323_disconnect_time', '$h323_setup_time', '$h323_voice_quality')");
+        $sth2 = $dbh->prepare("INSERT into StopVoIP (
+               AcctTime, UserName, NASIPAddress, AcctSessionTime, AcctInputOctets, AcctOutputOctets,
+               CalledStationId, CallingStationId, AcctDelayTime, H323RemoteAddress, h323gwid, h323callorigin,
+               callid, h323connecttime, h323disconnectcause, h323disconnecttime, h323setuptime, h323voicequality)
+               values(($Timestamp)::abstime, '$UserName', '$NasIPAddress', '$AcctSessionTime', '$AcctInputOctets',
+               '$AcctOutputOctets', '$Called_Station_Id', '$Calling_Station_Id', '$AcctDelayTime',
+               NULLIF('$h323_remote_address', '')::INET, '$h323_gw_id','$h323_call_origin', '$h323_conf_id',
+               NULLIF('$h323_connect_time', '')::TIMESTAMPTZ, '$h323_disconnect_cause',
+               NULLIF('$h323_disconnect_time', '')::TIMESTAMPTZ, NULLIF('$h323_setup_time', '')::TIMESTAMPTZ,
+               NULLIF('$h323_voice_quality','')::INT4)");
+
        }
        elsif ($h323_call_type eq 'Telephony') {
-        $sth2 = $dbh->prepare("INSERT into StopTelephony (UserName, NASIPAddress, AcctSessionTime,
+        $sth2 = $dbh->prepare("INSERT into StopTelephony (
+               AcctTime, UserName, NASIPAddress, AcctSessionTime,
                 AcctInputOctets, AcctOutputOctets, CalledStationId, CallingStationId, AcctDelayTime,
-                CiscoNASPort, h323callorigin, h323confid, h323connecttime, h323disconnectcause, h323disconnecttime, h323setuptime, h323voicequality)
-                values('$UserName', '$NasIPAddress', '$AcctSessionTime', '$AcctInputOctets', '$AcctOutputOctets',
+                CiscoNASPort, h323callorigin, callid, h323connecttime, h323disconnectcause, h323disconnecttime, h323setuptime, h323voicequality)
+                values(($Timestamp)::abstime, '$UserName', '$NasIPAddress', '$AcctSessionTime', '$AcctInputOctets', '$AcctOutputOctets',
                 '$Called_Station_Id', '$Calling_Station_Id', '$AcctDelayTime', '$Cisco_NAS_Port', '$h323_call_origin', '$h323_conf_id',
                '$h323_connect_time', '$h323_disconnect_cause', '$h323_disconnect_time', '$h323_setup_time', '$h323_voice_quality')");
-       } else { print "ERROR: Unsupported h323calltype \"$h323_call_type\"\n" }
-
+       } else { 
+               if ($h323_call_type) { print "ERROR: Unsupported h323calltype: \"$h323_call_type\"\n"; }
+               else { print "ERROR: Missing \"h323calltype\". This doesn't appear to be a VoIP record."; }
+               return;         # Not a VoIP record. Bailout
+        }
        $sth2->execute();
        #my $returned_rows = $sth2->rows;
        if ($verbose > 0) { print "added to DB\n"; }
        $sth2->finish();
-
 }
 
 ## This sub can be used to update data in an existing database if you have some fields not in the Database.
 sub db_update {
        my $sth2= $dbh->prepare("UPDATE radacct SET CalledStationId = '$Called_Station_Id', 
                AcctTerminateCause = '$AcctTerminateCause', H323RemoteAddress = '$h323_remote_address',
-               AcctStatusType = '$AcctStatusType', h323confid = '$h323_conf_id', h323calltype = '$h323_call_type',
+               AcctStatusType = '$AcctStatusType', callid = '$h323_conf_id', h323calltype = '$h323_call_type',
                CiscoNASPort = '$Cisco_NAS_Port', h323disconnectcause = '$h323_disconnect_cause',
                h323connecttime = '$h323_connect_time', h323disconnecttime = '$h323_disconnect_time',
                h323setuptime = '$h323_setup_time' WHERE AcctSessionId = 'AcctSessionId' AND UserName = '$UserName'
@@ -138,77 +153,61 @@ sub db_update {
 }
 
 sub db_read {
-       $passno++;
-       if ($verbose > 0) { print "Record: $passno) Conf ID: $h323_conf_id   Setup Time: $h323_setup_time  Call Length: $AcctSessionTime   "; }
+       if ($verbose > 0) { print "Record: $passno) ConfID: $h323_conf_id Timestamp: $radius_record_timestamp Length: $AcctSessionTime "; }
        my $sth = $dbh->prepare("SELECT RadAcctId FROM Stop$h323_call_type
-               WHERE h323SetupTime = '$h323_setup_time'
+               WHERE AcctTime = ($Timestamp)::abstime
                AND NASIPAddress = '$NasIPAddress'
-               AND h323confid = '$h323_conf_id'")
-                or die "Couldn't prepare statement: " . $dbh->errstr;
+               AND callid = '$h323_conf_id'")
+                or die "\nCouldn't prepare statement: " . $dbh->errstr . "\n";
 
-          my @data;
-          $sth->execute()             # Execute the query
-            or die "Couldn't execute statement: " . $sth->errstr;
-           my $returned_rows = $sth->rows;
+       my @data;
+       $sth->execute()             # Execute the query
+               or die "\nCouldn't execute statement: " . $sth->errstr . "\n";
+       my $returned_rows = $sth->rows;
 
           if ($sth->rows == 0) {
-               &db_insert;
+               &db_insert;     # It's a new record. All systems go.
           } elsif ($sth->rows == 1) {
-                if ($verbose > 0) { print "Exists in DB.\n"; }
+                if ($verbose > 0) { print "already in DB.\n"; }
                # FIXME: Make updates an option!
                 #while (@data = $sth->fetchrow_array()) {
                 #my $dbAcctSessionId = $data[1];
                ##&db_update;
                 #}
           } else {
-               $double_match_no++;
-               # FIXME: Log this somewhere!
+               $duplicates++;   # FIXME: Log this somewhere!
                 print "********* More than One Match! We have a problem!\n";
           }
 
-        $sth->finish;
-
-}
-
-sub read_record {
-       my $keepreading = 1;
-       @record = ();
-       while ($keepreading) {
-               $_ = <DETAIL>;
-               print "$_" if ($verbose > 1);
-               if ( /^$/ ) {
-                       $keepreading = 0;
-               } else {
-                       $record[++$#record] = $_;
-               }
-       }
+       $sth->finish;
 }
 
 sub process_record {
-       if ($verbose > 1) { print "DEBUG: Processing Record\n"; }
-       # Clear the variable we use.
-       $UserName = ""; $NasPort=""; $NasPortType="";
-        $NasIPAddress = ""; $AcctStatusType=""; $AcctSessionTime="";
+       $radius_record_timestamp = @record[0];
+       chomp $radius_record_timestamp;
+       if ($verbose > 1) { print "DEBUG: Processing new record with time: $radius_record_timestamp \n"; }
+       # Clear the variables we use so that we don't have rubbish from the last loop
+       $UserName=""; $NasPort=""; $NasPortType="";
+       $NasIPAddress = ""; $AcctStatusType=""; $AcctSessionTime="";
        $AcctInputOctets=""; $AcctOutputOctets=""; $AcctTerminateCause="";
        $ServiceType=""; $FramedProtocol=""; $FramedIPAddress="";
-       $Timestamp=""; $AcctDelayTime=""; $ConnectInfo=""; $Called_Station_Id="";
+       $Timestamp=""; $AcctDelayTime=0; $ConnectInfo=""; $Called_Station_Id="";
        $SQL_User_Name=""; $Cisco_NAS_Port=""; $Client_IP_Address="";
        $h323_remote_address=""; $h323_disconnect_cause=""; $h323_gw_id="";
        $h323_conf_id=""; $h323_call_type=""; $h323_disconnect_time="";
        $h323_connect_time=""; $h323_setup_time=""; $Calling_Station_Id="";
-       $h323_call_origin=""; $h323_voice_quality="";
+       $h323_call_origin=""; $h323_voice_quality=""; $h323_gw_id="";
 
-       foreach (@record) {             # Collect data
+       foreach (@record) {             # Parse the lines of data into variables.
 
        # Initial cleanup of junk from the line of data
        s/^\s+//;       # Strip leading spaces.
+       s/^Quintum-//;  # Strip leading "Quintum-".
        chomp;          # Strip trailing CR
 
-       # Parse the line of data into variables.
        $AcctStatusType = $_ if s/Acct-Status-Type = //;
-
-       # All the data we need is in Stop records.
-       if ($AcctStatusType eq "Start") {
+       if ($AcctStatusType eq "Stop") {                # All the data we need is in Stop records.
+       } elsif ($AcctStatusType eq "Start") {
                if ($verbose > 1) { print "DEBUG: Skipping \"Start\" record\n"; }
                return;
        } elsif ($AcctStatusType eq "Alive"){
@@ -216,12 +215,6 @@ sub process_record {
                return;
        };
 
-       if (s/h323-call-type = \"h323-call-type=//) {
-                        $h323_call_type = substr($_, 0, -1);
-                } elsif (s/h323-call-type = //) {
-                        $h323_call_type = $_;
-            };
-
        $UserName = $_ if s/User-Name = //;
        $NasIPAddress = $_ if s/NAS-IP-Address = //;
        $AcctSessionTime = $_ if s/Acct-Session-Time = //;
@@ -231,6 +224,12 @@ sub process_record {
        $Called_Station_Id = $_ if s/Called-Station-Id = //;
        $Calling_Station_Id = $_ if s/Calling-Station-Id = //;
        $Cisco_NAS_Port = $_ if s/Cisco-NAS-Port = //;
+       $Timestamp = $_ if s/Timestamp = //;
+       if (s/h323-call-type = \"h323-call-type=//) {
+                        $h323_call_type = substr($_, 0, -1);
+                } elsif (s/h323-call-type = //) {
+                        $h323_call_type = $_;
+            };
        if (s/h323-remote-address = \"h323-remote-address=//) {
                        $h323_remote_address = $_;
                } elsif (s/h323-remote-address = //) {
@@ -266,6 +265,11 @@ sub process_record {
                 } elsif (s/h323-call-origin = //) {
                         $h323_call_origin = $_;
             };
+        if (s/h323-gw-id = \"h323-gw-id=//) {
+                        $h323_gw_id = substr($_, 0, -1);
+                } elsif (s/h323-gw-id = //) {
+                        $h323_gw_id = $_;
+            };
         if (s/h323-voice-quality = \"h323-voice-quality=//) {
                         $h323_voice_quality = substr($_, 0, -1);
                 } elsif (s/h323-voice-quality = //) {
@@ -295,23 +299,43 @@ sub process_record {
        $h323_connect_time =~ s/^\.*//;
        $h323_disconnect_time =~ s/^\.*//;
 
+       # Ignore broken fields from some stupid, non-cisco gateways (They shall remain nameless)
+       if ($h323_connect_time eq "0") { $h323_connect_time = "" };
+       if ($h323_disconnect_time eq "0") { $h323_disconnect_time = "" };
+
        # If its a valid record continue onto the database functions
        # FIXME: More checks needed here.
        if ($h323_call_type) { 
+               $passno++;
+               #@duplicate_records{$passno} += @record;
                if (&procedure_get()) { &procedure_insert; }
                else { &db_read; }
        } else { if ($verbose > 1) { print "DEBUG: Skipping non-h323 record\n"; } }
 }
 
+sub read_record {
+       my $keepreading = 1;
+       @record = ();
+       while ($keepreading) {
+               $_ = <DETAIL>;
+               print "$_" if ($verbose > 1);
+               if ( /^$/ ) {
+                       $keepreading = 0;       # End of record
+               } else {
+                       $record[++$#record] = $_;
+               }
+       }
+       &process_record;
+}
+
 sub read_detailfile {
-       my $filename = shift; my @record = ();
+       my $file_starttime = time(); my $filename = shift; my @record = (); my $record_no = 0;
        if ($verbose > 1) { print "DEBUG: Reading detail file: $filename\n" }
-       # test if the file exists and is readable
-       if ((-r $filename) != 1) { 
+       if ((-r $filename) != 1) {              # test if the file exists and is readable
                if ($verbose >= 0) { print "INFO: Skipping file \"$filename\" as it is not readable or does not exist.\n" }
                return;
         }
-       if ( $filename =~ /.gz$/ ) {
+       if ( $filename =~ /.gz$/ ) {            # Deal with compressed files
                open (DETAIL, "$GZCAT $filename |") || warn "read_detailfile(\"$filename\"): $!\n";
        } elsif ( $filename =~ /.Z$/ ) {
                open (DETAIL, "$ZCAT $filename |") || warn "read_detailfile(\"$filename\"): $!\n";
@@ -326,13 +350,12 @@ sub read_detailfile {
                $valid_input = 0 if (eof(DETAIL));
                if ($verbose > 1) { print "DEBUG: Reading Record\n"; }
                &read_record;
-               &process_record;
+               $record_no++;
        }
-       my $runtime = (time() - $starttime);
-       if ($runtime > 0) { 
-       } else { $runtime = 1; }
-       my $speed = ($passno / $runtime); 
-        if ($verbose >= 0) { print "\n $passno records from $filename were processed in $runtime seconds ($speed records/sec) \n"; }
+       my $file_runtime = (time() - $file_starttime);
+       if ($file_runtime < 1) { $file_runtime = 1; }
+       my $file_speed = ($record_no / $file_runtime); 
+        if ($verbose >= 0) { print "\n $record_no total records read from $filename were processed in $file_runtime seconds ($file_speed records/sec) \n"; }
 }
 
 sub print_usage_info {
@@ -342,14 +365,16 @@ sub print_usage_info {
        $underbar =~ s/./-/g;
        print "$leader\n$underbar\n";
        print "\n";
-       print "  Syntax:   h323detail2db.pl [ options ] file\n";
+       print "  Syntax:   h323detail2db.pl [ options ] detailfile(s)\n";
        print "\n";
+       print "    -d --database                    Database to use\n";
        print "    -h --help                        Show this usage information\n";
+       print "    -H --host                        Database host to connect to (Default: localhost)\n";
+       print "    -p --procedure                   Use Postgresql stored procedure (BROKEN!)\n";
+       print "    -q --quiet                       Turn on quiet mode (No Output)\n";
        print "    -v --verbose                     Turn on verbose\n";
-       print "    -x --debug                       Turn on debugging\n";
-       print "    -p --procedure                   Use Postgresql stored procedure (faster!)\n";
        print "    -V --version                     Show version and copyright\n";
-       print "    -H --host                        Database host to connect to (Default: localhost)\n";
+       print "    -x --debug                       Turn on debugging\n";
        print "\n";
 }
 
@@ -370,7 +395,7 @@ sub main {
        };
 
        # See the Getopt::Long man page for details on the syntax of this line
-       @valid_opts = ("h|help", "V|version", "f|file=s", "x|debug", "v|verbose+" => \$verbose, "q|quiet+" => \$quiet, "D|date=s", "H|host=s", "p|procedure");
+       @valid_opts = ("h|help", "V|version", "f|file=s", "x|debug", "d|database=s", "v|verbose+" => \$verbose, "q|quiet+" => \$quiet, "D|date=s", "H|host=s", "p|procedure");
        Getopt::Long::Configure("no_getopt_compat", "bundling", "no_ignore_case");
        Getopt::Long::GetOptions(@valid_opts);
 
@@ -385,8 +410,8 @@ sub main {
                $rcs_info =~ s/\$\s*Author: (\S+) \$ /$1/;
 
                print "\n";
-               print "$progname Version $version by Peter Nixon <codemonkey\@peternixon.net>\n";
-               print "Copyright (c) 2002-2003, 2003 Peter Nixon\n";
+               print "$progname Version $version by Peter Nixon - http://www.peternixon.net/\n";
+               print "Copyright (c) 2002-2004 Peter Nixon\n";
                print "  ($rcs_info)\n";
                print "\n";
                return SUCCESS;
@@ -400,17 +425,28 @@ sub main {
                $verbose = 2;
        } elsif ($quiet) { $verbose -= $quiet; }
        &procedure_set($opt_p);
+       if ($opt_d) { 
+               if ($verbose > 0) { print "Using database \"$opt_d\" instead of default database \"$database\"\n"; }
+               $database = $opt_d;
+       }
 
        if (@ARGV) {
-               if ($opt_H) { &db_connect($opt_H);
-               } else { &db_connect(localhost); }
+               my $db_host;
+               if ($opt_H) { $db_host = $opt_H; }
+               else { $db_host = "localhost"; }
+               &db_connect($db_host);
 
                # Loop through the defined files
                foreach $file (@ARGV) {
                        &read_detailfile($file);
                }
+               &process_duplicates;
+               &db_disconnect($db_host);
 
-               &db_disconnect;
+               my $runtime = (time() - $starttime);
+               if ($runtime < 1) { $runtime = 1; }
+               my $speed = ($passno / $runtime); 
+               if ($verbose >= 0) { print "\n $passno valid records were processed in $runtime seconds ($speed records/sec) \n"; }
        } else {
                print "ERROR: Please specify one or more detail file(s) to import.\n";
                exit(FAILURE);
index f34ea64..80a5721 100644 (file)
@@ -18,3 +18,16 @@ distclean:
 clean:
 
 install:
+       $(INSTALL) -d -m 755 $(R)$(includedir)/freeradius
+       $(INSTALL) -m 644 hash.h $(R)$(includedir)/freeradius
+       $(INSTALL) -m 644 libradius.h $(R)$(includedir)/freeradius
+       $(INSTALL) -m 644 md4.h $(R)$(includedir)/freeradius
+       $(INSTALL) -m 644 md5.h $(R)$(includedir)/freeradius
+       $(INSTALL) -m 644 missing.h $(R)$(includedir)/freeradius
+       $(INSTALL) -m 644 packet.h $(R)$(includedir)/freeradius
+       $(INSTALL) -m 644 radius.h $(R)$(includedir)/freeradius
+       $(INSTALL) -m 644 radpaths.h $(R)$(includedir)/freeradius
+       $(INSTALL) -m 644 sha1.h $(R)$(includedir)/freeradius
+       $(INSTALL) -m 644 token.h $(R)$(includedir)/freeradius
+       $(INSTALL) -m 644 udpfromto.h $(R)$(includedir)/freeradius
+       sed -i 's/^#include <freeradius-devel/#include <freeradius/' $(R)$(includedir)/freeradius/libradius.h
index fb4cc17..36f1250 100644 (file)
-/* src/include/autoconf.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
-/*
+/* src/include/autoconf.h.in.  Generated from configure.in by autoheader.  */
 
-acconfig.h - template used by autoheader to create config.h.in
-config.h.in - used by autoconf to create config.h
-config.h - created by autoconf; contains defines generated by autoconf
+/* Include support for Ascend binary filter attributes */
+#undef ASCEND_BINARY
 
-*/
+/* BSD-Style get*byaddr_r */
+#undef BSDSTYLE
 
+/* style of ctime_r function */
+#undef CTIMERSTYLE
 
-/* Define if on AIX 3.
-   System headers sometimes define this.
-   We just want to avoid a redefinition error message.  */
-#ifndef _ALL_SOURCE
-#undef _ALL_SOURCE
-#endif
+/* style of gethostbyaddr_r functions */
+#undef GETHOSTBYADDRRSTYLE
 
-/* Define to empty if the keyword does not work.  */
-#undef const
+/* style of gethostbyname_r functions */
+#undef GETHOSTBYNAMERSTYLE
 
-/* Define to `int' if <sys/types.h> doesn't define.  */
-#undef gid_t
+/* GNU-Style get*byaddr_r */
+#undef GNUSTYLE
 
-/* Define if you have <sys/wait.h> that is POSIX.1 compatible.  */
-#undef HAVE_SYS_WAIT_H
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
 
-/* Define to `long' if <sys/types.h> doesn't define.  */
-#undef off_t
+/* Define if you have the <asn1.h>, <snmp_impl.h> and <snmp.h> header file. */
+#undef HAVE_ASN1_SNMP_SNMPIMPL_H
 
-/* Define to `int' if <sys/types.h> doesn't define.  */
-#undef pid_t
+/* Define to 1 if you have the `closefrom' function. */
+#undef HAVE_CLOSEFROM
 
-/* Define as the return type of signal handlers (int or void).  */
-#undef RETSIGTYPE
+/* Do we have the crypt function */
+#undef HAVE_CRYPT
 
-/* Define to `unsigned' if <sys/types.h> doesn't define.  */
-#undef size_t
+/* Define to 1 if you have the <crypt.h> header file. */
+#undef HAVE_CRYPT_H
 
-/* Define if you have the ANSI C header files.  */
-#undef STDC_HEADERS
+/* Define to 1 if you have the `ctime_r' function. */
+#undef HAVE_CTIME_R
 
-/* Define if you can safely include both <sys/time.h> and <time.h>.  */
-#undef TIME_WITH_SYS_TIME
+/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_DIRENT_H
 
-/* Define to `int' if <sys/types.h> doesn't define.  */
-#undef uid_t
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
 
-/* Define if your processor stores words with the most significant
-   byte first (like Motorola and SPARC, unlike Intel and VAX).  */
-#undef WORDS_BIGENDIAN
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
 
-/* style of gethost*_r functions */
-#define GNUSTYLE 1
-#define SYSVSTYLE 2
-#define BSDSTYLE 3
-#undef GETHOSTBYADDRRSTYLE
-#undef GETHOSTBYNAMERSTYLE
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
 
-/* style of ctime_r function */
-#define POSIXSTYLE 1
-#define SOLARISSTYLE 2
-#undef CTIMERSTYLE
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
 
-/* Do we have the crypt function ? */
-#undef HAVE_CRYPT
+/* Define to 1 if you have the `gethostname' function. */
+#undef HAVE_GETHOSTNAME
 
-/* Include support for Ascend binary filter attributes */
-#undef ASCEND_BINARY
+/* Define to 1 if you have the `getnameinfo' function. */
+#undef HAVE_GETNAMEINFO
 
-/* socklen_t is generally 'int' on systems which don't use it */
-#undef socklen_t
+/* Define to 1 if you have the <getopt.h> header file. */
+#undef HAVE_GETOPT_H
 
-/* uint8_t should be the canonical 'octet' for network traffic */
-#undef uint8_t
+/* Define to 1 if you have the `getopt_long' function. */
+#undef HAVE_GETOPT_LONG
 
-/* uint16_t should be the canonical '2 octets' for network traffic */
-#undef uint16_t
+/* Define to 1 if you have the `getusershell' function. */
+#undef HAVE_GETUSERSHELL
 
-/* uint32_t should be the canonical 'network integer' */
-#undef uint32_t
+/* Define to 1 if you have the `gmtime_r' function. */
+#undef HAVE_GMTIME_R
 
-/* Include SNMP subagent */
-#undef WITH_SNMP
+/* define if you have IN6_PKTINFO (Linux) */
+#undef HAVE_IN6_PKTINFO
 
-/* Define if you have the <ucd-snmp/asn1.h>, <ucd-snmp/snmp_impl.h> and <ucd-snmp/snmp.h> header file.  */
-#undef HAVE_UCD_SNMP_ASN1_SNMP_SNMPIMPL_H
+/* Define to 1 if you have the `inet_aton' function. */
+#undef HAVE_INET_ATON
 
-/* Define if you have the <asn1.h>, <snmp_impl.h> and <snmp.h> header file.  */
-#undef HAVE_ASN1_SNMP_SNMPIMPL_H
+/* Define to 1 if you have the `inet_ntop' function. */
+#undef HAVE_INET_NTOP
 
-/* Define if you have the snmp library (-lsnmp).  */
-#undef HAVE_LIBSNMP
+/* Define to 1 if you have the `inet_pton' function. */
+#undef HAVE_INET_PTON
 
-/* define this if we have the <regex.h> header file */
-#undef HAVE_REGEX_H
+/* Define to 1 if you have the `initgroups' function. */
+#undef HAVE_INITGROUPS
 
-/* define this if we have REG_EXTENDED (from <regex.h>) */
-#undef HAVE_REG_EXTENDED
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
 
-/* define to something if you don't have ut_xtime in struct utmpx */
-#undef ut_xtime
+/* define if you have IP_PKTINFO (Linux) */
+#undef HAVE_IP_PKTINFO
 
-/* define if you have OSFC2 authentication */
-#undef OSFC2
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+#undef HAVE_LIBCRYPTO
 
-/* define if you have OSFSIA authentication */
-#undef OSFSIA
+/* Define to 1 if you have the `nsl' library (-lnsl). */
+#undef HAVE_LIBNSL
 
-/* define if you have IP_PKTINFO (Linux) */
-#undef HAVE_IP_PKTINFO
+/* Define to 1 if you have the `pcap' library (-lpcap). */
+#undef HAVE_LIBPCAP
 
-/* define if you want udpfromto */
-#undef WITH_UDPFROMTO
+/* Define to 1 if you have the `resolv' library (-lresolv). */
+#undef HAVE_LIBRESOLV
 
-/* Define if you have the closefrom function.  */
-#undef HAVE_CLOSEFROM
+/* Define if you have the snmp library (-lsnmp). */
+#undef HAVE_LIBSNMP
 
-/* Define if you have the ctime_r function.  */
-#undef HAVE_CTIME_R
+/* Define to 1 if you have the `socket' library (-lsocket). */
+#undef HAVE_LIBSOCKET
 
-/* Define if you have the gethostname function.  */
-#undef HAVE_GETHOSTNAME
+/* Define to 1 if you have the `ssl' library (-lssl). */
+#undef HAVE_LIBSSL
 
-/* Define if you have the getopt_long function.  */
-#undef HAVE_GETOPT_LONG
+/* Define to 1 if you have the `localtime_r' function. */
+#undef HAVE_LOCALTIME_R
 
-/* Define if you have the getusershell function.  */
-#undef HAVE_GETUSERSHELL
+/* Define to 1 if you have the `lockf' function. */
+#undef HAVE_LOCKF
 
-/* Define if you have the gmtime_r function.  */
-#undef HAVE_GMTIME_R
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
 
-/* Define if you have the inet_aton function.  */
-#undef HAVE_INET_ATON
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
 
-/* Define if you have the inet_ntop function.  */
-#undef HAVE_INET_NTOP
+/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
+#undef HAVE_NDIR_H
 
-/* Define if you have the inet_pton function.  */
-#undef HAVE_INET_PTON
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
 
-/* Define if you have the initgroups function.  */
-#undef HAVE_INITGROUPS
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
 
-/* Define if you have the localtime_r function.  */
-#undef HAVE_LOCALTIME_R
+/* Define to 1 if you have the <net/if.h> header file. */
+#undef HAVE_NET_IF_H
 
-/* Define if you have the lockf function.  */
-#undef HAVE_LOCKF
+/* Define to 1 if you have the <openssl/crypto.h> header file. */
+#undef HAVE_OPENSSL_CRYPTO_H
 
-/* Define if you have the pthread_sigmask function.  */
+/* Define to 1 if you have the <openssl/engine.h> header file. */
+#undef HAVE_OPENSSL_ENGINE_H
+
+/* Define to 1 if you have the <openssl/err.h> header file. */
+#undef HAVE_OPENSSL_ERR_H
+
+/* Define to 1 if you have the <openssl/ssl.h> header file. */
+#undef HAVE_OPENSSL_SSL_H
+
+/* Define to 1 if you have the <pcap.h> header file. */
+#undef HAVE_PCAP_H
+
+/* Define to 1 if you have the <prot.h> header file. */
+#undef HAVE_PROT_H
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
+
+/* Define to 1 if you have the `pthread_sigmask' function. */
 #undef HAVE_PTHREAD_SIGMASK
 
-/* Define if you have the setlinebuf function.  */
+/* define this if we have the <regex.h> header file */
+#undef HAVE_REGEX_H
+
+/* define this if we have REG_EXTENDED (from <regex.h>) */
+#undef HAVE_REG_EXTENDED
+
+/* Define to 1 if you have the <resource.h> header file. */
+#undef HAVE_RESOURCE_H
+
+/* Define to 1 if you have the <semaphore.h> header file. */
+#undef HAVE_SEMAPHORE_H
+
+/* Define to 1 if you have the `setlinebuf' function. */
 #undef HAVE_SETLINEBUF
 
-/* Define if you have the setsid function.  */
+/* Define to 1 if you have the `setsid' function. */
 #undef HAVE_SETSID
 
-/* Define if you have the setvbuf function.  */
+/* Define to 1 if you have the `setvbuf' function. */
 #undef HAVE_SETVBUF
 
-/* Define if you have the sigaction function.  */
+/* Define to 1 if you have the <siad.h> header file. */
+#undef HAVE_SIAD_H
+
+/* Define to 1 if you have the <sia.h> header file. */
+#undef HAVE_SIA_H
+
+/* Define to 1 if you have the `sigaction' function. */
 #undef HAVE_SIGACTION
 
-/* Define if you have the sigprocmask function.  */
+/* Define to 1 if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* Define to 1 if you have the `sigprocmask' function. */
 #undef HAVE_SIGPROCMASK
 
-/* Define if you have the snprintf function.  */
+/* Define to 1 if you have the `snprintf' function. */
 #undef HAVE_SNPRINTF
 
-/* Define if you have the strcasecmp function.  */
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
 #undef HAVE_STRCASECMP
 
-/* Define if you have the strncasecmp function.  */
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcat' function. */
+#undef HAVE_STRLCAT
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the `strncasecmp' function. */
 #undef HAVE_STRNCASECMP
 
-/* Define if you have the strsep function.  */
+/* Define to 1 if you have the `strsep' function. */
 #undef HAVE_STRSEP
 
-/* Define if you have the strsignal function.  */
+/* Define to 1 if you have the `strsignal' function. */
 #undef HAVE_STRSIGNAL
 
-/* Define if you have the vsnprintf function.  */
-#undef HAVE_VSNPRINTF
+/* Generic DNS lookups */
+#undef HAVE_STRUCT_ADDRINFO
 
-/* Define if you have the <arpa/inet.h> header file.  */
-#undef HAVE_ARPA_INET_H
+/* IPv6 address structure */
+#undef HAVE_STRUCT_IN6_ADDR
 
-/* Define if you have the <crypt.h> header file.  */
-#undef HAVE_CRYPT_H
+/* IPv6 socket addresses */
+#undef HAVE_STRUCT_SOCKADDR_IN6
 
-/* Define if you have the <dirent.h> header file.  */
-#undef HAVE_DIRENT_H
+/* Generic socket addresses */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE
 
-/* Define if you have the <dlfcn.h> header file.  */
-#undef HAVE_DLFCN_H
+/* Define to 1 if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
 
-/* Define if you have the <errno.h> header file.  */
-#undef HAVE_ERRNO_H
+/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_SYS_DIR_H
 
-/* Define if you have the <fcntl.h> header file.  */
-#undef HAVE_FCNTL_H
+/* Define to 1 if you have the <sys/fcntl.h> header file. */
+#undef HAVE_SYS_FCNTL_H
 
-/* Define if you have the <getopt.h> header file.  */
-#undef HAVE_GETOPT_H
+/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
+   */
+#undef HAVE_SYS_NDIR_H
 
-/* Define if you have the <inttypes.h> header file.  */
-#undef HAVE_INTTYPES_H
+/* Define to 1 if you have the <sys/security.h> header file. */
+#undef HAVE_SYS_SECURITY_H
 
-/* Define if you have the <malloc.h> header file.  */
-#undef HAVE_MALLOC_H
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
 
-/* Define if you have the <ndir.h> header file.  */
-#undef HAVE_NDIR_H
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
 
-/* Define if you have the <netdb.h> header file.  */
-#undef HAVE_NETDB_H
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
 
-/* Define if you have the <netinet/in.h> header file.  */
-#undef HAVE_NETINET_IN_H
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
 
-/* Define if you have the <openssl/crypto.h> header file.  */
-#undef HAVE_OPENSSL_CRYPTO_H
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
 
-/* Define if you have the <openssl/engine.h> header file.  */
-#undef HAVE_OPENSSL_ENGINE_H
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#undef HAVE_SYS_WAIT_H
 
-/* Define if you have the <openssl/err.h> header file.  */
-#undef HAVE_OPENSSL_ERR_H
+/* Define if you have the <ucd-snmp/asn1.h>, <ucd-snmp/snmp_impl.h> and
+   <ucd-snmp/snmp.h> header file. */
+#undef HAVE_UCD_SNMP_ASN1_SNMP_SNMPIMPL_H
 
-/* Define if you have the <openssl/ssl.h> header file.  */
-#undef HAVE_OPENSSL_SSL_H
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
 
-/* Define if you have the <prot.h> header file.  */
-#undef HAVE_PROT_H
+/* Define to 1 if you have the <utmpx.h> header file. */
+#undef HAVE_UTMPX_H
 
-/* Define if you have the <pthread.h> header file.  */
-#undef HAVE_PTHREAD_H
+/* Define to 1 if you have the <utmp.h> header file. */
+#undef HAVE_UTMP_H
 
-/* Define if you have the <resource.h> header file.  */
-#undef HAVE_RESOURCE_H
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
 
-/* Define if you have the <semaphore.h> header file.  */
-#undef HAVE_SEMAPHORE_H
+/* define if you have OSFC2 authentication */
+#undef OSFC2
 
-/* Define if you have the <sia.h> header file.  */
-#undef HAVE_SIA_H
+/* define if you have OSFSIA authentication */
+#undef OSFSIA
 
-/* Define if you have the <siad.h> header file.  */
-#undef HAVE_SIAD_H
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
 
-/* Define if you have the <signal.h> header file.  */
-#undef HAVE_SIGNAL_H
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
 
-/* Define if you have the <stdint.h> header file.  */
-#undef HAVE_STDINT_H
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
 
-/* Define if you have the <stdio.h> header file.  */
-#undef HAVE_STDIO_H
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
 
-/* Define if you have the <sys/dir.h> header file.  */
-#undef HAVE_SYS_DIR_H
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
 
-/* Define if you have the <sys/fcntl.h> header file.  */
-#undef HAVE_SYS_FCNTL_H
+/* Posix-Style ctime_r */
+#undef POSIXSTYLE
 
-/* Define if you have the <sys/ndir.h> header file.  */
-#undef HAVE_SYS_NDIR_H
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
 
-/* Define if you have the <sys/prctl.h> header file.  */
-#undef HAVE_SYS_PRCTL_H
+/* Solaris-Style ctime_r */
+#undef SOLARISSTYLE
 
-/* Define if you have the <sys/security.h> header file.  */
-#undef HAVE_SYS_SECURITY_H
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
 
-/* Define if you have the <sys/select.h> header file.  */
-#undef HAVE_SYS_SELECT_H
+/* SYSV-Style get*byaddr_r */
+#undef SYSVSTYLE
 
-/* Define if you have the <sys/socket.h> header file.  */
-#undef HAVE_SYS_SOCKET_H
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
 
-/* Define if you have the <sys/stat.h> header file.  */
-#undef HAVE_SYS_STAT_H
+/* Include SNMP subagent */
+#undef WITH_SNMP
 
-/* Define if you have the <sys/time.h> header file.  */
-#undef HAVE_SYS_TIME_H
+/* define if you want udpfromto */
+#undef WITH_UDPFROMTO
 
-/* Define if you have the <sys/types.h> header file.  */
-#undef HAVE_SYS_TYPES_H
+/* Define to 1 if your processor stores words with the most significant byte
+   first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
 
-/* Define if you have the <sys/wait.h> header file.  */
-#undef HAVE_SYS_WAIT_H
+/* Define to 1 if on AIX 3.
+   System headers sometimes define this.
+   We just want to avoid a redefinition error message.  */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
 
-/* Define if you have the <syslog.h> header file.  */
-#undef HAVE_SYSLOG_H
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
 
-/* Define if you have the <unistd.h> header file.  */
-#undef HAVE_UNISTD_H
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
 
-/* Define if you have the <utmp.h> header file.  */
-#undef HAVE_UTMP_H
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
 
-/* Define if you have the <utmpx.h> header file.  */
-#undef HAVE_UTMPX_H
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
 
-/* Define if you have the nsl library (-lnsl).  */
-#undef HAVE_LIBNSL
+/* Define to `long' if <sys/types.h> does not define. */
+#undef off_t
 
-/* Define if you have the resolv library (-lresolv).  */
-#undef HAVE_LIBRESOLV
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
 
-/* Define if you have the socket library (-lsocket).  */
-#undef HAVE_LIBSOCKET
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
 
-/* Define to 1 if you have the crypto library (-lcrypto). */
-#undef HAVE_LIBCRYPTO
+/* socklen_t is generally 'int' on systems which don't use it */
+#undef socklen_t
 
-/* Define to 1 if you have the ssl library (-lssl). */
-#undef HAVE_LIBSSL
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* uint16_t should be the canonical '2 octets' for network traffic */
+#undef uint16_t
 
-/* Some versions of glibc need this defined for pread/pwrite. */
-#undef _GNU_SOURCE
+/* uint32_t should be the canonical 'network integer */
+#undef uint32_t
 
+/* uint8_t should be the canonical 'octet' for network traffic */
+#undef uint8_t
+
+/* define to something if you don't have ut_xtime in struct utmpx */
+#undef ut_xtime
index 4e9e9f6..ddda6e6 100644 (file)
@@ -8,8 +8,11 @@
  *
  */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(conffile_h, "$Id$")
+
 #include <stddef.h>
-#include "token.h"
+#include <freeradius-devel/token.h>
 
 /*
  * Export the minimum amount of information about these structs
@@ -17,6 +20,7 @@
 typedef struct conf_item CONF_ITEM;
 typedef struct conf_pair CONF_PAIR;
 typedef struct conf_part CONF_SECTION;
+typedef struct conf_data CONF_DATA;
 
 /*
  *  Instead of putting the information into a configuration structure,
@@ -26,6 +30,7 @@ typedef struct conf_part CONF_SECTION;
 #define PW_TYPE_STRING_PTR     100
 #define PW_TYPE_BOOLEAN                101
 #define PW_TYPE_SUBSECTION     102
+#define PW_TYPE_FILENAME       103
 
 typedef struct CONF_PARSER {
   const char *name;
@@ -45,22 +50,27 @@ typedef struct CONF_PARSER {
 
 void           cf_pair_free(CONF_PAIR **cp);
 void           cf_section_free(CONF_SECTION **cp);
-int            cf_section_parse(CONF_SECTION *cs, void *base, const CONF_PARSER *variables);
-
-CONF_SECTION *conf_read(const char *fromfile, int fromline,
-                       const char *conffile, CONF_SECTION *parent);
+int            cf_item_parse(CONF_SECTION *cs, const char *name,
+                             int type, void *data, const char *dflt);
+int            cf_section_parse(CONF_SECTION *, void *base,
+                                const CONF_PARSER *variables);
+CONF_SECTION   *cf_file_read(const char *file);
+int            cf_file_include(const char *file, CONF_SECTION *cs);
 
-
-CONF_PAIR      *cf_pair_find(CONF_SECTION *section, const char *name);
-CONF_PAIR      *cf_pair_find_next(CONF_SECTION *section, CONF_PAIR *pair, const char *name);
+CONF_PAIR      *cf_pair_find(const CONF_SECTION *, const char *name);
+CONF_PAIR      *cf_pair_find_next(const CONF_SECTION *, const CONF_PAIR *, const char *name);
 CONF_SECTION   *cf_section_find(const char *name);
-CONF_SECTION   *cf_section_sub_find(CONF_SECTION *section, const char *name);
-char           *cf_section_value_find(CONF_SECTION *section, const char *attr);
+CONF_SECTION   *cf_section_sub_find(const CONF_SECTION *, const char *name);
+CONF_SECTION   *cf_section_sub_find_name2(const CONF_SECTION *, const char *name1, const char *name2);
+char           *cf_section_value_find(const CONF_SECTION *, const char *attr);
+
+void *cf_data_find(CONF_SECTION *, const char *);
+int cf_data_add(CONF_SECTION *, const char *, void *, void (*)(void *));
 
 char *cf_pair_attr(CONF_PAIR *pair);
 char *cf_pair_value(CONF_PAIR *pair);
-char *cf_section_name1(CONF_SECTION *section);
-char *cf_section_name2(CONF_SECTION *section);
+const char *cf_section_name1(const CONF_SECTION *);
+const char *cf_section_name2(const CONF_SECTION *);
 int dump_config(void);
 CONF_SECTION *cf_subsection_find_next(CONF_SECTION *section,
                                      CONF_SECTION *subsection,
@@ -74,4 +84,10 @@ CONF_PAIR *cf_itemtopair(CONF_ITEM *item);
 CONF_SECTION *cf_itemtosection(CONF_ITEM *item);
 CONF_ITEM *cf_pairtoitem(CONF_PAIR *cp);
 CONF_ITEM *cf_sectiontoitem(CONF_SECTION *cs);
+
+/*
+ *     Big magic.
+ */
+int cf_section_migrate(CONF_SECTION *dst, CONF_SECTION *src);
+
 #endif /* _CONFFILE_H */
diff --git a/src/include/hash.h b/src/include/hash.h
new file mode 100644 (file)
index 0000000..4f21954
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef LRAD_HASH_H
+#define LRAD_HASH_H
+
+/*
+ * hash.h      Structures and prototypes
+ *             for fast hashing.
+ *
+ * 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 2005,2006  The FreeRADIUS server project
+ */
+
+#include <freeradius-devel/ident.h>
+RCSIDH(hash_h, "$Id$")
+
+/*
+ *     Fast hash, which isn't too bad.  Don't use for cryptography,
+ *     just for hashing internal data.
+ */
+uint32_t lrad_hash(const void *, size_t);
+uint32_t lrad_hash_update(const void *data, size_t size, uint32_t hash);
+uint32_t lrad_hash_string(const char *p);
+
+/*
+ *     If you need fewer than 32-bits of hash, use this macro to get
+ *     the number of bits in the hash you need.  The upper bits of the
+ *     hash will be set to zero.
+ */
+uint32_t lrad_hash_fold(uint32_t hash, int bits);
+
+typedef struct lrad_hash_table_t lrad_hash_table_t;
+typedef void (*lrad_hash_table_free_t)(void *);
+typedef uint32_t (*lrad_hash_table_hash_t)(const void *);
+typedef int (*lrad_hash_table_cmp_t)(const void *, const void *);
+typedef int (*lrad_hash_table_walk_t)(void * /* ctx */, void * /* data */);
+
+lrad_hash_table_t *lrad_hash_table_create(lrad_hash_table_hash_t hashNode,
+                                         lrad_hash_table_cmp_t cmpNode,
+                                         lrad_hash_table_free_t freeNode);
+void           lrad_hash_table_free(lrad_hash_table_t *ht);
+int            lrad_hash_table_insert(lrad_hash_table_t *ht, void *data);
+int            lrad_hash_table_delete(lrad_hash_table_t *ht, const void *data);
+void           *lrad_hash_table_yank(lrad_hash_table_t *ht, const void *data);
+int            lrad_hash_table_replace(lrad_hash_table_t *ht, void *data);
+void           *lrad_hash_table_finddata(lrad_hash_table_t *ht, const void *data);
+int            lrad_hash_table_num_elements(lrad_hash_table_t *ht);
+int            lrad_hash_table_walk(lrad_hash_table_t *ht,
+                                    lrad_hash_table_walk_t callback,
+                                    void *ctx);
+#endif /* LRAD_HASH_H */
index bcefff0..0b0d831 100644 (file)
@@ -7,9 +7,25 @@
  *
  * 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,2002,2003,2004,2005,2006  The FreeRADIUS server project
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSIDH(libradius_h, "$Id$")
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #include <errno.h>
 #endif
 
+#ifdef HAVE_NETINET_IN_H
+#include       <netinet/in.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include       <arpa/inet.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include       <sys/socket.h>
+#endif
+
 #include <stdio.h>
+#include <stdarg.h>
 
 /*
  *  Check for inclusion of <time.h>, versus <sys/time.h>
@@ -44,8 +73,9 @@
 # endif
 #endif
 
-#include "radius.h"
-#include "token.h"
+#include <freeradius-devel/radius.h>
+#include <freeradius-devel/token.h>
+#include <freeradius-devel/hash.h>
 
 #ifdef SIZEOF_UNSIGNED_INT
 #if SIZEOF_UNSIGNED_INT != 4
@@ -56,8 +86,8 @@
 /*
  *  Include for modules.
  */
-#include <sha1.h>
-#include <md4.h>
+#include <freeradius-devel/sha1.h>
+#include <freeradius-devel/md4.h>
 
 #define EAP_START               2
 
@@ -65,7 +95,7 @@
 #define CHAP_VALUE_LENGTH       16
 #define MAX_STRING_LEN         254     /* RFC2138: string 0-253 octets */
 
-#  define VENDOR(x)            ((x >> 16) & 0xffff)
+#  define VENDOR(x)            ((x >> 16) & 0x7fff)
 
 #ifdef _LIBRADIUS
 #  define AUTH_HDR_LEN         20
                                     } \
                                } while(0)
 #  define TAG_VALID(x)          ((x) > 0 && (x) < 0x20)
-#  define TAG_VALID_ZERO(x)     ((x) >= 0 && (x) < 0x20)
+#  define TAG_VALID_ZERO(x)     ((x) < 0x20)
 #  define TAG_ANY               -128   /* minimum signed char */
 #endif
 
 #endif
 
 typedef struct attr_flags {
-       char                    addport;        /* Add port to IP address */
-       char                    has_tag;        /* attribute allows tags */
-       signed char             len_disp;       /* length displacement */
-       char                    do_xlat;
-       signed char             tag;
-       uint8_t                 encrypt;        /* encryption method */
+       unsigned int            addport : 1;  /* add NAS-Port to IP address */
+       unsigned int            has_tag : 1;  /* tagged attribute */
+       unsigned int            do_xlat : 1;  /* strvalue is dynamic */
+       unsigned int            caseless : 1; /* case insensitive compares */
+       unsigned int            array : 1; /* pack multiples into 1 attr */
+       unsigned int            has_value : 1; /* has a value */
+       unsigned int            has_value_alias : 1; /* has a value alias */
+
+       int8_t                  tag;          /* tag for tunneled attributes */
+       uint8_t                 encrypt;      /* encryption method */
 } ATTR_FLAGS;
 
 /*
@@ -137,14 +171,44 @@ typedef struct dict_vendor {
 typedef struct value_pair {
        char                    name[40];
        int                     attribute;
+       int                     vendor;
        int                     type;
-       int                     length; /* of strvalue */
-       uint32_t                lvalue;
+       int                     length; /* of data */
        LRAD_TOKEN              operator;
-       uint8_t                 strvalue[MAX_STRING_LEN];
+       uint32_t                lvalue; /* DELETE ME ASAP */
         ATTR_FLAGS              flags;
        struct value_pair       *next;
+       union {
+               char                    strvalue[MAX_STRING_LEN];
+               uint8_t                 octets[MAX_STRING_LEN];
+               struct in_addr          ipaddr;
+               struct in6_addr         ipv6addr;
+               uint32_t                date;
+               uint32_t                integer;
+               uint8_t                 filter[32];
+               uint8_t                 ifid[8]; /* struct? */
+               uint8_t                 ipv6prefix[18]; /* struct? */
+       } data;
 } VALUE_PAIR;
+#define vp_strvalue   data.strvalue
+#define vp_octets     data.octets
+#define vp_ipaddr     lvalue
+#define vp_ipv6addr   data.ipv6addr
+#define vp_data       lvalue
+#define vp_integer    lvalue
+#define vp_ifid       data.ifid
+#define vp_ipv6prefix data.ipv6prefix
+#define vp_filter     data.filter
+
+
+typedef struct lrad_ipaddr_t {
+       int             af;     /* address family */
+       union {
+               struct in_addr  ip4addr;
+               struct in6_addr ip6addr; /* maybe defined in missing.h */
+       } ipaddr;
+} lrad_ipaddr_t;
+
 
 /*
  *     vector:         Request authenticator from access-request packet
@@ -157,10 +221,10 @@ typedef struct value_pair {
  */
 typedef struct radius_packet {
        int                     sockfd;
-       uint32_t                src_ipaddr;
-       uint32_t                dst_ipaddr;
-       u_short                 src_port;
-       u_short                 dst_port;
+       lrad_ipaddr_t           src_ipaddr;
+        lrad_ipaddr_t          dst_ipaddr;
+       uint16_t                src_port;
+       uint16_t                dst_port;
        int                     id;
        unsigned int            code;
        uint8_t                 vector[AUTH_VECTOR_LEN];
@@ -169,6 +233,7 @@ typedef struct radius_packet {
        uint8_t                 *data;
        int                     data_len;
        VALUE_PAIR              *vps;
+       uint32_t                hash;
 } RADIUS_PACKET;
 
 /*
@@ -196,13 +261,6 @@ DICT_VALUE *dict_valbyname(int attr, const char *val);
 int            dict_vendorbyname(const char *name);
 DICT_VENDOR    *dict_vendorbyvalue(int vendor);
 
-/*
- *  Compatibility
- */
-#define dict_vendorcode
-#define dict_vendorpec
-
-
 #if 1 /* FIXME: compat */
 #define dict_attrget   dict_attrbyvalue
 #define dict_attrfind  dict_attrbyname
@@ -223,39 +281,50 @@ DICT_VENDOR       *dict_vendorbyvalue(int vendor);
 
 /* md5.c */
 
-void           librad_md5_calc(u_char *, u_char *, u_int);
+void           librad_md5_calc(uint8_t *, const uint8_t *, unsigned int);
 
 /* hmac.c */
 
-void lrad_hmac_md5(const unsigned char *text, int text_len,
-                  const unsigned char *key, int key_len,
+void lrad_hmac_md5(const uint8_t *text, int text_len,
+                  const uint8_t *key, int key_len,
                   unsigned char *digest);
 
 /* hmacsha1.c */
 
-void lrad_hmac_sha1(const unsigned char *text, int text_len,
-                   const unsigned char *key, int key_len,
-                   unsigned char *digest);
+void lrad_hmac_sha1(const uint8_t *text, int text_len,
+                   const uint8_t *key, int key_len,
+                   uint8_t *digest);
 
 /* radius.c */
 int            rad_send(RADIUS_PACKET *, const RADIUS_PACKET *, const char *secret);
+int            rad_packet_ok(RADIUS_PACKET *packet);
 RADIUS_PACKET  *rad_recv(int fd);
-int            rad_verify(RADIUS_PACKET *packet, RADIUS_PACKET *original, const char *secret);
+int            rad_verify(RADIUS_PACKET *packet, RADIUS_PACKET *original,
+                          const char *secret);
 int            rad_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original, const char *secret);
+int            rad_encode(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
+                          const char *secret);
+int            rad_sign(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
+                        const char *secret);
+
 RADIUS_PACKET  *rad_alloc(int newvector);
 void           rad_free(RADIUS_PACKET **);
-int            rad_pwencode(char *encpw, int *len, const char *secret, const char *vector);
-int            rad_pwdecode(char *encpw, int len, const char *secret, const char *vector);
-int            rad_tunnel_pwencode(char *encpw, int *len, const char *secret, const char *vector);
-int            rad_tunnel_pwdecode(uint8_t *encpw, int *len, const char *secret, const char *vector);
-int            rad_chap_encode(RADIUS_PACKET *packet, char *output, int id, VALUE_PAIR *password);
+int            rad_pwencode(char *encpw, int *len, const char *secret,
+                            const uint8_t *vector);
+int            rad_pwdecode(char *encpw, int len, const char *secret,
+                            const uint8_t *vector);
+int            rad_tunnel_pwencode(char *encpw, int *len, const char *secret,
+                                   const uint8_t *vector);
+int            rad_tunnel_pwdecode(uint8_t *encpw, int *len,
+                                   const char *secret, const uint8_t *vector);
+int            rad_chap_encode(RADIUS_PACKET *packet, uint8_t *output,
+                               int id, VALUE_PAIR *password);
+VALUE_PAIR     *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET *original,
+                            const char *secret, int attribute, int length,
+                            const uint8_t *data);
 int            rad_vp2attr(const RADIUS_PACKET *packet,
                            const RADIUS_PACKET *original, const char *secret,
                            const VALUE_PAIR *vp, uint8_t *ptr);
-int            rad_encode(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
-                          const char *secret);
-int            rad_sign(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
-                        const char *secret);
 
 /* valuepair.c */
 VALUE_PAIR     *paircreate(int attr, int type);
@@ -265,6 +334,7 @@ VALUE_PAIR  *pairfind(VALUE_PAIR *, int);
 void           pairdelete(VALUE_PAIR **, int);
 void           pairadd(VALUE_PAIR **, VALUE_PAIR *);
 void            pairreplace(VALUE_PAIR **first, VALUE_PAIR *add);
+int            paircmp(VALUE_PAIR *check, VALUE_PAIR *data);
 VALUE_PAIR     *paircopy(VALUE_PAIR *vp);
 VALUE_PAIR     *paircopy2(VALUE_PAIR *vp, int attr);
 void           pairmove(VALUE_PAIR **to, VALUE_PAIR **from);
@@ -298,41 +368,34 @@ extern int        librad_max_attributes; /* per incoming packet */
 /*
  *     Several handy miscellaneous functions.
  */
-char *         ip_hostname (char *buf, size_t buflen, uint32_t ipaddr);
-uint32_t       ip_getaddr (const char *);
-char *         ip_ntoa(char *, uint32_t);
-uint32_t       ip_addr(const char *);
+const char *   ip_ntoa(char *, uint32_t);
 char           *ifid_ntoa(char *buffer, size_t size, uint8_t *ifid);
 uint8_t                *ifid_aton(const char *ifid_str, uint8_t *ifid);
-const char     *ipv6_ntoa(char *buffer, size_t size, void *ip6addr);
-int            ipv6_addr(const char *ip6_str, void *ip6addr);
-char           *strNcpy(char *dest, const char *src, int n);
-void           rad_lowercase(char *str);
-void           rad_rmspace(char *str);
 int            rad_lockfd(int fd, int lock_len);
 int            rad_lockfd_nonblock(int fd, int lock_len);
 int            rad_unlockfd(int fd, int lock_len);
 void           lrad_bin2hex(const uint8_t *bin, char *hex, int len);
 int            lrad_hex2bin(const char *hex, uint8_t *bin, int len);
+#ifndef HAVE_INET_PTON
+int            inet_pton(int af, const char *src, void *dst);
+#endif
+#ifndef HAVE_INET_NTOP
+const char     *inet_ntop(int af, const void *src, char *dst, size_t cnt);
+#endif
 #ifndef HAVE_CLOSEFROM
 int            closefrom(int fd);
 #endif
 
+int            ip_hton(const char *src, int af, lrad_ipaddr_t *dst);
+const char     *ip_ntoh(const lrad_ipaddr_t *src, char *dst, size_t cnt);
+
+
 #ifdef ASCEND_BINARY
 /* filters.c */
 int            ascend_parse_filter(VALUE_PAIR *pair);
-void           print_abinary(VALUE_PAIR *vp, u_char *buffer, int len);
+void           print_abinary(VALUE_PAIR *vp, char *buffer, int len);
 #endif /*ASCEND_BINARY*/
 
-/* snprintf.c */
-#ifndef HAVE_VSNPRINTF
-#include <stdarg.h>
-int vsnprintf(char *str, size_t count, const char *fmt, va_list arg);
-#endif
-#ifndef HAVE_SNPRINTF
-int snprintf(char *str, size_t count, const char *fmt, ...);
-#endif
-
 /* random numbers in isaac.c */
 /* context of random number generator */
 typedef struct lrad_randctx {
@@ -349,6 +412,7 @@ void lrad_randinit(lrad_randctx *ctx, int flag);
 uint32_t lrad_rand(void);      /* like rand(), but better. */
 void lrad_rand_seed(const void *, size_t ); /* seed the random pool */
 
+
 /* crypt wrapper from crypt.c */
 int lrad_crypt_check(const char *key, const char *salt);
 
@@ -362,48 +426,38 @@ rbtree_t       *rbtree_create(int (*Compare)(const void *, const void *),
 void           rbtree_free(rbtree_t *tree);
 int            rbtree_insert(rbtree_t *tree, void *Data);
 void           rbtree_delete(rbtree_t *tree, rbnode_t *Z);
+int            rbtree_deletebydata(rbtree_t *tree, const void *data);
 rbnode_t       *rbtree_find(rbtree_t *tree, const void *Data);
 void          *rbtree_finddata(rbtree_t *tree, const void *Data);
 int            rbtree_num_elements(rbtree_t *tree);
 void          *rbtree_node2data(rbtree_t *tree, rbnode_t *node);
-int            rbtree_deletebydata(rbtree_t *tree, const void *data);
 
 /* callback order for walking  */
 typedef enum { PreOrder, InOrder, PostOrder } RBTREE_ORDER;
-int rbtree_walk(rbtree_t *tree, RBTREE_ORDER order, int (*callback)(void *, void *), void *context);
 
 /*
- *     Fast hash, which isn't too bad.  Don't use for cryptography,
- *     just for hashing internal data.
+ *     The callback should be declared as:
+ *     int callback(void *context, void *data)
+ *
+ *     The "context" is some user-defined context.
+ *     The "data" is the pointer to the user data in the node,
+ *       NOT the node itself.
+ *
+ *     It should return 0 if all is OK, and !0 for any error.
+ *     The walking will stop on any error.
  */
-uint32_t lrad_hash(const void *, size_t);
-uint32_t lrad_hash_update(const void *data, size_t size, uint32_t hash);
-uint32_t lrad_hash_string(const char *p);
+int rbtree_walk(rbtree_t *tree, RBTREE_ORDER order, int (*callback)(void *, void *), void *context);
 
 /*
- *     If you need fewer than 32-bits of hash, use this macro to get
- *     the number of bits in the hash you need.  The upper bits of the
- *     hash will be set to zero.
+ *     FIFOs
  */
-uint32_t lrad_hash_fold(uint32_t hash, int bits);
-
-typedef struct lrad_hash_table_t lrad_hash_table_t;
-typedef void (*lrad_hash_table_free_t)(void *);
-typedef uint32_t (*lrad_hash_table_hash_t)(const void *);
-typedef int (*lrad_hash_table_cmp_t)(const void *, const void *);
-typedef int (*lrad_hash_table_walk_t)(void * /* ctx */, void * /* data */);
-
-lrad_hash_table_t *lrad_hash_table_create(lrad_hash_table_hash_t hashNode,
-                                         lrad_hash_table_cmp_t cmpNode,
-                                         lrad_hash_table_free_t freeNode);
-void           lrad_hash_table_free(lrad_hash_table_t *ht);
-int            lrad_hash_table_insert(lrad_hash_table_t *ht, void *data);
-int            lrad_hash_table_delete(lrad_hash_table_t *ht, const void *data);
-void           *lrad_hash_table_yank(lrad_hash_table_t *ht, const void *data);
-int            lrad_hash_table_replace(lrad_hash_table_t *ht, void *data);
-void           *lrad_hash_table_finddata(lrad_hash_table_t *ht, const void *data);
-int            lrad_hash_table_num_elements(lrad_hash_table_t *ht);
-int            lrad_hash_table_walk(lrad_hash_table_t *ht,
-                                    lrad_hash_table_walk_t callback,
-                                    void *ctx);
+typedef struct lrad_fifo_t lrad_fifo_t;
+typedef void (*lrad_fifo_free_t)(void *);
+lrad_fifo_t *lrad_fifo_create(int max_entries, lrad_fifo_free_t freeNode);
+void lrad_fifo_free(lrad_fifo_t *fi);
+int lrad_fifo_push(lrad_fifo_t *fi, void *data);
+void *lrad_fifo_pop(lrad_fifo_t *fi);
+
+#include <freeradius-devel/packet.h>
+
 #endif /*LIBRADIUS_H*/
index 9d17a47..f26b513 100644 (file)
@@ -6,11 +6,11 @@
  *
  */
 
-
 #ifndef _LRAD_MD4_H
 #define _LRAD_MD4_H
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSIDH(md4_h, "$Id$")
 
 #ifdef HAVE_INTTYPES_H
 #include <inttypes.h>
index 8a5ed05..0e15b0c 100644 (file)
@@ -9,7 +9,8 @@
 #ifndef _LRAD_MD5_H
 #define _LRAD_MD5_H
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSIDH(md5_h, "$Id$")
 
 #ifdef HAVE_INTTYPES_H
 #include <inttypes.h>
  *  FreeRADIUS defines to ensure globally unique MD5 function names,
  *  so that we don't pick up vendor-specific broken MD5 libraries.
  */
-#define MD5_CTX                librad_MD5_CTX
-#define MD5Init                librad_MD5Init
-#define MD5Update      librad_MD5Update
-#define MD5Final       librad_MD5Final
-#define MD5Transform   librad_MD5Transform
+#define MD5_CTX                lrad_MD5_CTX
+#define MD5Init                lrad_MD5Init
+#define MD5Update      lrad_MD5Update
+#define MD5Final       lrad_MD5Final
+#define MD5Transform   lrad_MD5Transform
+
 
 /*  The below was retrieved from
  *  http://www.openbsd.org/cgi-bin/cvsweb/~checkout~/src/sys/crypto/md5.h?rev=1.1
 #define        MD5_BLOCK_LENGTH                64
 #define        MD5_DIGEST_LENGTH               16
 
-typedef struct MD5Context {
+typedef struct lrad_MD5Context {
        uint32_t state[4];                      /* state */
        uint32_t count[2];                      /* number of bits, mod 2^64 */
        uint8_t buffer[MD5_BLOCK_LENGTH];       /* input buffer */
-} MD5_CTX;
+} lrad_MD5_CTX;
 
 /* include <sys/cdefs.h> */
 
 /* __BEGIN_DECLS */
-void    MD5Init(MD5_CTX *);
-void    MD5Update(MD5_CTX *, const uint8_t *, size_t)
+void    lrad_MD5Init(lrad_MD5_CTX *);
+void    lrad_MD5Update(lrad_MD5_CTX *, const uint8_t *, size_t)
 /*             __attribute__((__bounded__(__string__,2,3)))*/;
-void    MD5Final(uint8_t [MD5_DIGEST_LENGTH], MD5_CTX *)
+void    lrad_MD5Final(uint8_t [MD5_DIGEST_LENGTH], lrad_MD5_CTX *)
 /*             __attribute__((__bounded__(__minbytes__,1,MD5_DIGEST_LENGTH)))*/;
-void    MD5Transform(uint32_t [4], const uint8_t [MD5_BLOCK_LENGTH])
+void    lrad_MD5Transform(uint32_t [4], const uint8_t [MD5_BLOCK_LENGTH])
 /*             __attribute__((__bounded__(__minbytes__,1,4)))*/
 /*             __attribute__((__bounded__(__minbytes__,2,MD5_BLOCK_LENGTH)))*/;
 /* __END_DECLS */
index caa7d3f..054f5d6 100644 (file)
@@ -8,6 +8,22 @@
  * Version:    $Id$
  *
  */
+
+#include <freeradius-devel/ident.h>
+RCSIDH(missing_h, "$Id$")
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+/*
+ *     Functions from missing.c
+ */
+
 #ifndef HAVE_STRNCASECMP
 extern int strncasecmp(char *s1, char *s2, int n);
 #endif
@@ -21,6 +37,7 @@ extern char *strsep(char **stringp, const char *delim);
 #endif
 
 #ifndef HAVE_LOCALTIME_R
+struct tm;
 struct tm *localtime_r(const time_t *l_clock, struct tm *result);
 #endif
 
@@ -81,4 +98,201 @@ void endusershell(void);
 #define INADDR_NONE     ((uint32_t) 0xffffffff)
 #endif
 
+#ifndef INADDRSZ
+#define INADDRSZ 4
+#endif
+
+#ifndef INET_ADDRSTRLEN
+#define INET_ADDRSTRLEN 16
+#endif
+
+#ifndef AF_UNSPEC
+#define AF_UNSPEC 0
+#endif
+
+#ifndef AF_INET6
+#define AF_INET6 10
+
+#ifndef HAVE_STRUCT_IN6_ADDR
+struct in6_addr
+{
+       union {
+               uint8_t u6_addr8[16];
+               uint16_t u6_addr16[8];
+               uint32_t u6_addr32[4];
+       } in6_u;
+#define s6_addr                        in6_u.u6_addr8
+#define s6_addr16              in6_u.u6_addr16
+#define s6_addr32              in6_u.u6_addr32
+};
+
+#ifndef IN6ADDRSZ
+#define IN6ADDRSZ 16
+#endif
+
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 46
+#endif
+
+#ifndef IN6ADDR_ANY_INIT
+#define IN6ADDR_ANY_INIT       {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }}}
+#endif
+
+#ifndef IN6ADDR_LOOPBACK_INIT
+#define IN6ADDR_LOOPBACK_INIT  {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}}
+#endif
+
+#ifndef IN6_IS_ADDR_UNSPECIFIED
+#define IN6_IS_ADDR_UNSPECIFIED(a) \
+       (((__const uint32_t *) (a))[0] == 0                                   \
+        && ((__const uint32_t *) (a))[1] == 0                                \
+        && ((__const uint32_t *) (a))[2] == 0                                \
+        && ((__const uint32_t *) (a))[3] == 0)
+#endif
+
+#ifndef IN6_IS_ADDR_LOOPBACK
+#define IN6_IS_ADDR_LOOPBACK(a) \
+       (((__const uint32_t *) (a))[0] == 0                                   \
+        && ((__const uint32_t *) (a))[1] == 0                                \
+        && ((__const uint32_t *) (a))[2] == 0                                \
+        && ((__const uint32_t *) (a))[3] == htonl (1))
+#endif
+
+#ifndef IN6_IS_ADDR_MULTICAST
+#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff)
+#endif
+
+#ifndef IN6_IS_ADDR_LINKLOCAL
+#define IN6_IS_ADDR_LINKLOCAL(a) \
+       ((((__const uint32_t *) (a))[0] & htonl (0xffc00000))                 \
+        == htonl (0xfe800000))
+#endif
+
+#ifndef IN6_IS_ADDR_SITELOCAL
+#define IN6_IS_ADDR_SITELOCAL(a) \
+       ((((__const uint32_t *) (a))[0] & htonl (0xffc00000))                 \
+        == htonl (0xfec00000))
+#endif
+
+#ifndef IN6_IS_ADDR_V4MAPPED
+#define IN6_IS_ADDR_V4MAPPED(a) \
+       ((((__const uint32_t *) (a))[0] == 0)                                 \
+        && (((__const uint32_t *) (a))[1] == 0)                              \
+        && (((__const uint32_t *) (a))[2] == htonl (0xffff)))
+#endif
+
+#ifndef IN6_IS_ADDR_V4COMPAT
+#define IN6_IS_ADDR_V4COMPAT(a) \
+       ((((__const uint32_t *) (a))[0] == 0)                                 \
+        && (((__const uint32_t *) (a))[1] == 0)                              \
+        && (((__const uint32_t *) (a))[2] == 0)                              \
+        && (ntohl (((__const uint32_t *) (a))[3]) > 1))
+#endif
+
+#ifndef IN6_ARE_ADDR_EQUAL
+#define IN6_ARE_ADDR_EQUAL(a,b) \
+       ((((__const uint32_t *) (a))[0] == ((__const uint32_t *) (b))[0])     \
+        && (((__const uint32_t *) (a))[1] == ((__const uint32_t *) (b))[1])  \
+        && (((__const uint32_t *) (a))[2] == ((__const uint32_t *) (b))[2])  \
+        && (((__const uint32_t *) (a))[3] == ((__const uint32_t *) (b))[3]))
+#endif
+
+#endif /* HAVE_STRUCT_IN6_ADDR */
+#endif
+
+/*
+ *     Functions from getaddrinfo.c
+ */
+
+#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
+struct sockaddr_storage
+{
+    uint16_t ss_family;        /* Address family, etc.  */
+    char ss_padding[128 - (sizeof(uint16_t))];
+};
+#endif /* HAVE_STRUCT_SOCKADDR_STORAGE */
+
+#ifndef HAVE_STRUCT_ADDRINFO
+
+/* for old netdb.h */
+#ifndef EAI_SERVICE
+#define EAI_MEMORY      2
+#define EAI_FAMILY      5    /* ai_family not supported */
+#define EAI_NONAME      8    /* hostname nor servname provided, or not known */
+#define EAI_SERVICE     9   /* servname not supported for ai_socktype */
+#endif
+
+/* dummy value for old netdb.h */
+#ifndef AI_PASSIVE
+#define AI_PASSIVE      1
+#define AI_CANONNAME    2
+#define AI_NUMERICHOST  4
+#define NI_NUMERICHOST  2
+#define NI_NAMEREQD     4
+#define NI_NUMERICSERV  8
+
+struct addrinfo
+{
+  int ai_flags;                        /* Input flags.  */
+  int ai_family;               /* Protocol family for socket.  */
+  int ai_socktype;             /* Socket type.  */
+  int ai_protocol;             /* Protocol for socket.  */
+  socklen_t ai_addrlen;                /* Length of socket address.  */
+  struct sockaddr *ai_addr;    /* Socket address for socket.  */
+  char *ai_canonname;          /* Canonical name for service location.  */
+  struct addrinfo *ai_next;    /* Pointer to next in list.  */
+};
+
+#endif /* AI_PASSIVE */
+
+#endif /* HAVE_STRUCT_ADDRINFO */
+
+/* Translate name of a service location and/or a service name to set of
+   socket addresses. */
+#ifndef HAVE_GETADDRINFO
+extern int getaddrinfo (const char *__name,
+                       const char *__service,
+                       const struct addrinfo *__req,
+                       struct addrinfo **__pai);
+
+/* Free `addrinfo' structure AI including associated storage.  */
+extern void freeaddrinfo (struct addrinfo *__ai);
+
+/* Convert error return from getaddrinfo() to a string.  */
+extern char *gai_strerror (int __ecode);
+#endif
+
+/* Translate a socket address to a location and service name. */
+#ifndef HAVE_GETNAMEINFO
+extern int getnameinfo (const struct sockaddr *__sa,
+                       socklen_t __salen, char *__host,
+                       socklen_t __hostlen, char *__serv,
+                       socklen_t __servlen, unsigned int __flags);
+#endif
+
+/*
+ *     Functions from snprintf.c
+ */
+
+#ifndef HAVE_VSNPRINTF
+#include <stdarg.h>
+extern int vsnprintf(char *str, size_t count, const char *fmt, va_list arg);
+#endif
+
+#ifndef HAVE_SNPRINTF
+extern int snprintf(char *str, size_t count, const char *fmt, ...);
+#endif
+
+/*
+ *     Functions from strl{cat,cpy}.c
+ */
+
+#ifndef HAVE_STRLCPY
+extern size_t strlcpy(char *dst, const char *src, size_t siz);
+#endif
+
+#ifndef HAVE_STRLCAT
+extern size_t strlcat(char *dst, const char *src, size_t siz);
+#endif
+
 #endif /* _FR_MISSING_H */
index adb472f..daf63a8 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Version: $Id$ */
 
-#include "conffile.h" /* Need CONF_* definitions */
+#include <freeradius-devel/conffile.h> /* Need CONF_* definitions */
 
 /*
  *     For each authorize/authtype/etc, we have an ordered
@@ -17,18 +17,19 @@ int modcall(int component, modcallable *c, REQUEST *request);
 
 /* Parse a module-method's config section (e.g. authorize{}) into a tree that
  * may be called with modcall() */
-modcallable *compile_modgroup(int component, CONF_SECTION *cs,
-               const char *filename);
+modcallable *compile_modgroup(modcallable *parent,
+                             int component, CONF_SECTION *cs,
+                             const char *filename);
 
 /* Create a single modcallable node that references a module instance. This
  * may be a CONF_SECTION containing action specifiers like "notfound = return"
  * or a simple CONF_PAIR, in which case the default actions are used. */
-modcallable *compile_modsingle(int component, CONF_ITEM *ci,
-               const char *filename, const char **modname);
+modcallable *compile_modsingle(modcallable *parent, int component, CONF_ITEM *ci,
+                              const char *filename, const char **modname);
 
 /* Add an entry to the end of a modgroup, creating it first if necessary */
 void add_to_modcallable(modcallable **parent, modcallable *this,
-               int component, char *name);
+                       int component, const char *name);
 
 /* Free a tree returned by compile_modgroup or compile_modsingle */
 void modcallable_free(modcallable **pc);
index 0aef7ff..a85c5ff 100644 (file)
@@ -2,19 +2,18 @@
  * accessed from anywhere else.
  *
  * Version: $Id$ */
-#include "radiusd.h"
-#include "modules.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 #include "ltdl.h"
 
 /*
  *     Keep track of which modules we've loaded.
  */
-typedef struct module_list_t {
-       struct module_list_t    *next;
+typedef struct module_entry_t {
        char                    name[MAX_STRING_LEN];
-       module_t                *module;
+       const module_t          *module;
        lt_dlhandle             handle;
-} module_list_t;
+} module_entry_t;
 
 /*
  *     Per-instance data structure, to correlate the modules
@@ -22,13 +21,12 @@ typedef struct module_list_t {
  *     and the per-instance data structures.
  */
 typedef struct module_instance_t {
-       struct module_instance_t *next;
        char                    name[MAX_STRING_LEN];
-       module_list_t           *entry;
+       module_entry_t          *entry;
        void                    *insthandle;
 #ifdef HAVE_PTHREAD_H
        pthread_mutex_t         *mutex;
 #endif
 } module_instance_t;
 
-module_instance_t *find_module_instance(const char *instname);
+module_instance_t *find_module_instance(CONF_SECTION *, const char *instname);
index 0d65f98..0b3942b 100644 (file)
@@ -7,7 +7,11 @@
 
 #ifndef RADIUS_MODULES_H
 #define RADIUS_MODULES_H
-#include "conffile.h"
+
+#include <freeradius-devel/ident.h>
+RCSIDH(modules_h, "$Id$")
+
+#include <freeradius-devel/conffile.h>
 
 typedef int (*packetmethod)(void *instance, REQUEST *request);
 
@@ -26,18 +30,18 @@ enum {
 #define RLM_TYPE_THREAD_SAFE   (0 << 0)
 #define RLM_TYPE_THREAD_UNSAFE (1 << 0)
 
+#define RLM_MODULE_MAGIC_NUMBER ((uint32_t) (0xf4ee4ad2))
+#define RLM_MODULE_INIT RLM_MODULE_MAGIC_NUMBER
+
 typedef struct module_t {
+       uint32_t        magic;  /* may later be opaque struct */
        const char      *name;
-       int     type;                   /* reserved */
-       int     (*init)(void);
-       int     (*instantiate)(CONF_SECTION *mod_cs, void **instance);
+       int             type;
+       int             (*instantiate)(CONF_SECTION *mod_cs, void **instance);
+       int             (*detach)(void *instance);
        packetmethod    methods[RLM_COMPONENT_COUNT];
-       int     (*detach)(void *instance);
-       int     (*destroy)(void);
 } module_t;
 
-extern const char *component_names[RLM_COMPONENT_COUNT];
-
 enum {
        RLM_MODULE_REJECT,      /* immediately reject the request */
        RLM_MODULE_FAIL,        /* module failed, don't reply */
@@ -51,7 +55,7 @@ enum {
        RLM_MODULE_NUMCODES     /* How many return codes there are */
 };
 
-int setup_modules(void);
+int setup_modules(int);
 int detach_modules(void);
 int module_authorize(int type, REQUEST *request);
 int module_authenticate(int type, REQUEST *request);
diff --git a/src/include/packet.h b/src/include/packet.h
new file mode 100644 (file)
index 0000000..120dd68
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef LRAD_PACKET_H
+#define LRAD_PACKET_H
+
+/*
+ * packet.h    Structures and prototypes
+ *             for packet manipulation
+ *
+ * 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,2002,2003,2004,2005,2006  The FreeRADIUS server project
+ */
+
+#include <freeradius-devel/ident.h>
+RCSIDH(packet_h, "$Id$")
+
+uint32_t lrad_request_packet_hash(const RADIUS_PACKET *packet);
+uint32_t lrad_reply_packet_hash(const RADIUS_PACKET *packet);
+int lrad_packet_cmp(const RADIUS_PACKET *a, const RADIUS_PACKET *b);
+void lrad_request_from_reply(RADIUS_PACKET *request,
+                            const RADIUS_PACKET *reply);
+int lrad_socket(lrad_ipaddr_t *ipaddr, int port);
+
+typedef struct lrad_packet_list_t lrad_packet_list_t;
+
+lrad_packet_list_t *lrad_packet_list_create(int alloc_id);
+void lrad_packet_list_free(lrad_packet_list_t *pl);
+int lrad_packet_list_insert(lrad_packet_list_t *pl,
+                           RADIUS_PACKET **request_p);
+
+RADIUS_PACKET **lrad_packet_list_find(lrad_packet_list_t *pl,
+                                     RADIUS_PACKET *request);
+RADIUS_PACKET **lrad_packet_list_find_byreply(lrad_packet_list_t *pl,
+                                             RADIUS_PACKET *reply);
+RADIUS_PACKET **lrad_packet_list_yank(lrad_packet_list_t *pl,
+                                     RADIUS_PACKET *request);
+int lrad_packet_list_num_elements(lrad_packet_list_t *pl);
+int lrad_packet_list_id_alloc(lrad_packet_list_t *pl,
+                             RADIUS_PACKET *request);
+int lrad_packet_list_id_free(lrad_packet_list_t *pl,
+                            RADIUS_PACKET *request);
+int lrad_packet_list_socket_add(lrad_packet_list_t *pl, int sockfd);
+int lrad_packet_list_socket_remove(lrad_packet_list_t *pl, int sockfd);
+int lrad_packet_list_walk(lrad_packet_list_t *pl, void *ctx,
+                         lrad_hash_table_walk_t callback);
+int lrad_packet_list_fd_set(lrad_packet_list_t *pl, fd_set *set);
+RADIUS_PACKET *lrad_packet_list_recv(lrad_packet_list_t *pl, fd_set *set);
+
+int lrad_packet_list_num_incoming(lrad_packet_list_t *pl);
+int lrad_packet_list_num_outgoing(lrad_packet_list_t *pl);
+
+
+#ifndef offsetof
+# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+/*
+ *     "find" returns a pointer to the RADIUS_PACKET* member in the
+ *     caller's structure.  In order to get the pointer to the *top*
+ *     of the caller's structure, you have to subtract the offset to
+ *     the member from the returned pointer, and cast it to the
+ *     required type.
+ */
+# define lrad_packet2myptr(TYPE, MEMBER, PTR) (TYPE *) (((char *)PTR) - offsetof(TYPE, MEMBER))
+#endif /* LRAD_PACKET_H */
index 91e361e..e477c32 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000,2001  The FreeRADIUS server project
+ * Copyright 2000,2001,2006  The FreeRADIUS server project
  */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(rad_assert_h, "$Id$")
+
 extern void rad_assert_fail (const char *file, unsigned int line);
 
 #ifdef NDEBUG
index 188df8f..a519668 100644 (file)
@@ -15,6 +15,8 @@
 #define PW_TYPE_IFID                   6
 #define PW_TYPE_IPV6ADDR               7
 #define PW_TYPE_IPV6PREFIX             8
+#define PW_TYPE_BYTE                   9
+#define PW_TYPE_SHORT                  10
 
 #define        PW_AUTHENTICATION_REQUEST       1
 #define        PW_AUTHENTICATION_ACK           2
 #define PW_FRAMED_POOL                 88
 #define PW_NAS_IPV6_ADDRESS            95
 
+#define PW_EXTENDED_ATTRIBUTE          192
+
 #define PW_DIGEST_RESPONSE             206
 #define PW_DIGEST_ATTRIBUTES           207
 
 #define PW_FALL_THROUGH                        500
-#define PW_ADD_PORT_TO_IP_ADDRESS      501
 #define PW_EXEC_PROGRAM                        502
 #define PW_EXEC_PROGRAM_WAIT           503
 
 #define PW_PACKET_DST_PORT             1087
 #define PW_PACKET_AUTHENTICATION_VECTOR        1088
 #define PW_TIME_OF_DAY                 1089
+#define PW_REQUEST_PROCESSING_STAGE    1090
+#define PW_CACHE_NO_CACHING            1091
+#define PW_CACHE_DELETE_CACHE          1092
 
 #define PW_SHA_PASSWORD                        1093
 #define PW_SSHA_PASSWORD               1094
 #define PW_MD5_PASSWORD                        1095
 #define PW_SMD5_PASSWORD               1096
+
+#define PW_PACKET_SRC_IPV6_ADDRESS     1097
+#define PW_PACKET_DST_IPV6_ADDRESS     1098
+#define PW_SERVER_IDENTITY             1099
 #define PW_CLEARTEXT_PASSWORD          1100
 #define PW_PASSWORD_WITH_HEADER                1101
 
-
 /*
  *     Integer Translations
  */
index 1ef2b85..6440b3e 100644 (file)
@@ -3,6 +3,10 @@
 /*
  * Version:    $Id$
  */
+
+#include <freeradius-devel/ident.h>
+RCSIDH(radius_snmp_h, "$Id$")
+
 #ifdef WITH_SNMP
 
 typedef enum smux_event_t {
@@ -41,7 +45,7 @@ typedef struct rad_snmp_server_t {
 typedef struct rad_snmp_t {
        rad_snmp_server_t auth;
        rad_snmp_server_t acct;
-       smux_event_t      smux_event;
+       smux_event_t      smux_event;
        const char        *smux_password;
        int               snmp_write_access;
        int               smux_fd;
index a966950..7e7f323 100644 (file)
@@ -7,12 +7,16 @@
  * Version:    $Id$
  *
  */
-#include "libradius.h"
-#include "radpaths.h"
-#include "conf.h"
-#include "conffile.h"
 
-#include <stdarg.h>
+#include <freeradius-devel/ident.h>
+RCSIDH(radiusd_h, "$Id$")
+
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
+#include <freeradius-devel/radpaths.h>
+#include <freeradius-devel/conf.h>
+#include <freeradius-devel/conffile.h>
+
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
@@ -28,15 +32,8 @@ typedef pid_t child_pid_t;
 #endif
 
 #ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
 #endif
 
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-
-#include "missing.h"
-
 #define NO_SUCH_CHILD_PID (child_pid_t) (0)
 
 #ifndef NDEBUG
@@ -48,6 +45,16 @@ typedef pid_t child_pid_t;
  */
 typedef struct request_data_t request_data_t;
 
+/*
+ *     For listening on multiple IP's and ports.
+ */
+typedef struct rad_listen_t rad_listen_t;
+
+/*
+ *     For request lists.
+ */
+typedef struct request_list_t request_list_t;
+
 #define REQUEST_DATA_REGEX (0xadbeef00)
 #define REQUEST_MAX_REGEX (8)
 
@@ -62,12 +69,16 @@ typedef struct auth_req {
        VALUE_PAIR              *config_items;
        VALUE_PAIR              *username;
        VALUE_PAIR              *password;
+
        request_data_t          *data;
        char                    secret[32];
        child_pid_t             child_pid;
        time_t                  timestamp;
        int                     number; /* internal server number */
 
+       rad_listen_t            *listener;
+       rad_listen_t            *proxy_listener;
+
        /*
         *      We could almost keep a const char here instead of a
         *      _copy_ of the secret... but what if the RADCLIENT
@@ -77,7 +88,7 @@ typedef struct auth_req {
        char                    proxysecret[32];
        int                     proxy_try_count;
        int                     proxy_outstanding;
-       time_t                  proxy_next_try;
+       time_t                  proxy_start_time;
 
        int                     simul_max;
        int                     simul_count;
@@ -85,6 +96,8 @@ typedef struct auth_req {
 
        int                     finished;
        int                     options; /* miscellanous options */
+       const char              *module; /* for debugging unresponsive children */
+       const char              *component; /* ditto */
        void                    *container;
 } REQUEST;
 
@@ -95,6 +108,8 @@ typedef struct auth_req {
 #define RAD_REQUEST_OPTION_FAKE_REQUEST    (1 << 3)
 #define RAD_REQUEST_OPTION_REJECTED        (1 << 4)
 #define RAD_REQUEST_OPTION_PROXIED         (1 << 5)
+#define RAD_REQUEST_OPTION_STOP_NOW        (1 << 6)
+#define RAD_REQUEST_OPTION_REPROCESS       (1 << 7)
 
 /*
  *  Function handler for requests.
@@ -102,32 +117,26 @@ typedef struct auth_req {
 typedef                int (*RAD_REQUEST_FUNP)(REQUEST *);
 
 typedef struct radclient {
-       uint32_t                ipaddr;
-       uint32_t                netmask;
-       char                    longname[256];
-       u_char                  secret[32];
-       char                    shortname[32];
-       char                    nastype[32];
-       char                    login[32];
-       char                    password[32];
-       struct radclient        *next;
+       lrad_ipaddr_t           ipaddr;
+       int                     prefix;
+       char                    *longname;
+       char                    *secret;
+       char                    *shortname;
+       char                    *nastype;
+       char                    *login;
+       char                    *password;
+       int                     number; /* internal use only */
 } RADCLIENT;
 
-typedef struct nas {
-       uint32_t                ipaddr;
-       char                    longname[256];
-       char                    shortname[32];
-       char                    nastype[32];
-       struct nas              *next;
-} NAS;
+typedef struct radclient_list RADCLIENT_LIST;
 
 typedef struct _realm {
        char                    realm[64];
        char                    server[64];
        char                    acct_server[64];
-       uint32_t                ipaddr; /* authentication */
-       uint32_t                acct_ipaddr;
-       u_char                  secret[32];
+       lrad_ipaddr_t           ipaddr; /* authentication */
+       lrad_ipaddr_t           acct_ipaddr;
+       char                    secret[32];
        time_t                  last_reply; /* last time we saw a packet */
        int                     auth_port;
        int                     acct_port;
@@ -147,6 +156,7 @@ typedef struct pair_list {
        VALUE_PAIR              *check;
        VALUE_PAIR              *reply;
        int                     lineno;
+       int                     order;
        struct pair_list        *next;
        struct pair_list        *lastdefault;
 } PAIR_LIST;
@@ -154,68 +164,94 @@ typedef struct pair_list {
 
 /*
  *     Types of listeners.
+ *
+ *     FIXME: Separate ports for proxy auth/acct?
  */
 typedef enum RAD_LISTEN_TYPE {
        RAD_LISTEN_NONE = 0,
        RAD_LISTEN_AUTH,
        RAD_LISTEN_ACCT,
-       RAD_LISTEN_PROXY
+       RAD_LISTEN_PROXY,
+       RAD_LISTEN_DETAIL,
+       RAD_LISTEN_MAX
 } RAD_LISTEN_TYPE;
 
+typedef int (*rad_listen_recv_t)(rad_listen_t *, RAD_REQUEST_FUNP *, REQUEST **);
+typedef int (*rad_listen_send_t)(rad_listen_t *, REQUEST *);
+typedef int (*rad_listen_update_t)(rad_listen_t *, time_t);
+typedef int (*rad_listen_print_t)(rad_listen_t *, char *, size_t);
 
-/*
- *     For listening on multiple IP's and ports.
- */
-typedef struct rad_listen_t {
-       struct rad_listen_t *next; /* could be rbtree stuff */
-       uint32_t        ipaddr;
+struct rad_listen_t {
+       struct rad_listen_t *next; /* should be rbtree stuff */
+
+       /*
+        *      For normal sockets.
+        */
        RAD_LISTEN_TYPE type;
-       int             port;
        int             fd;
-} rad_listen_t;
+       const char      *identity;
+       request_list_t  *rl;
+
+       rad_listen_recv_t recv;
+       rad_listen_send_t send;
+       rad_listen_update_t update;
+       rad_listen_print_t print;
+
+       void            *data;
+};
+
 
+typedef enum radlog_dest_t {
+  RADLOG_STDOUT = 0,
+  RADLOG_FILES,
+  RADLOG_SYSLOG,
+  RADLOG_STDERR,
+  RADLOG_NULL,
+  RADLOG_NUM_DEST
+} radlog_dest_t;
 
 typedef struct main_config_t {
        struct main_config *next;
        time_t          config_dead_time;
-       uint32_t        myip;
+       lrad_ipaddr_t   myip;   /* from the command-line only */
+       int             port;   /* from the command-line only */
        int             log_auth;
        int             log_auth_badpass;
        int             log_auth_goodpass;
-       int             do_usercollide;
 #ifdef WITH_SNMP
        int             do_snmp;
 #endif
        int             allow_core_dumps;
        int             debug_level;
        int             proxy_requests;
-       int             post_proxy_authorize;
        int             wake_all_if_all_dead;
        int             proxy_synchronous;
        int             proxy_dead_time;
        int             proxy_retry_count;
        int             proxy_retry_delay;
        int             proxy_fallback;
+       const char      *proxy_fail_type;
        int             reject_delay;
        int             status_server;
        int             max_request_time;
        int             cleanup_delay;
        int             max_requests;
+#ifdef DELETE_BLOCKED_REQUESTS
        int             kill_unresponsive_children;
-       char            *do_lower_user;
-       char            *do_lower_pass;
-       char            *do_nospace_user;
-       char            *do_nospace_pass;
-       char            *nospace_time;
+#endif
        char            *log_file;
        char            *checkrad;
        const char      *pid_file;
        const char      *uid_name;
        const char      *gid_name;
        rad_listen_t    *listen;
+       int             syslog_facility;
+       int             radlog_fd;
+       radlog_dest_t   radlog_dest;
        CONF_SECTION    *config;
-       RADCLIENT       *clients;
+       RADCLIENT_LIST  *clients;
        REALM           *realms;
+       const char      *radiusd_conf;
 } MAIN_CONFIG_T;
 
 #define DEBUG  if(debug_flag)log_debug
@@ -235,6 +271,7 @@ typedef struct main_config_t {
 #define L_INFO                 3
 #define L_ERR                  4
 #define L_PROXY                        5
+#define L_ACCT                 6
 #define L_CONS                 128
 
 #ifndef FALSE
@@ -252,13 +289,19 @@ typedef struct main_config_t {
 /* for paircompare_register */
 typedef int (*RAD_COMPARE_FUNC)(void *instance, REQUEST *,VALUE_PAIR *, VALUE_PAIR *, VALUE_PAIR *, VALUE_PAIR **);
 
-typedef enum radlog_dest_t {
-  RADLOG_FILES = 0,
-  RADLOG_SYSLOG,
-  RADLOG_STDOUT,
-  RADLOG_STDERR,
-  RADLOG_NULL
-} radlog_dest_t;
+typedef enum request_fail_t {
+  REQUEST_FAIL_UNKNOWN = 0,
+  REQUEST_FAIL_NO_THREADS,     /* no threads to handle it */
+  REQUEST_FAIL_DECODE,         /* rad_decode didn't like it */
+  REQUEST_FAIL_PROXY,          /* call to proxy modules failed */
+  REQUEST_FAIL_PROXY_SEND,     /* proxy_send didn't like it */
+  REQUEST_FAIL_NO_RESPONSE,    /* we weren't told to respond, so we reject */
+  REQUEST_FAIL_HOME_SERVER,    /* the home server didn't respond */
+  REQUEST_FAIL_HOME_SERVER2,   /* another case of the above */
+  REQUEST_FAIL_HOME_SERVER3,   /* another case of the above */
+  REQUEST_FAIL_NORMAL_REJECT,  /* authentication failure */
+  REQUEST_FAIL_SERVER_TIMEOUT  /* the server took too long to process the request */
+} request_fail_t;
 
 /*
  *     Global variables.
@@ -267,17 +310,14 @@ typedef enum radlog_dest_t {
  */
 extern const char      *progname;
 extern int             debug_flag;
-extern int             syslog_facility;
 extern const char      *radacct_dir;
 extern const char      *radlog_dir;
 extern const char      *radlib_dir;
 extern const char      *radius_dir;
 extern const char      *radius_libdir;
-extern radlog_dest_t   radlog_dest;
 extern uint32_t                expiration_seconds;
 extern int             log_stripped_names;
 extern int             log_auth_detail;
-extern int             acct_port;
 extern const char      *radiusd_version;
 
 /*
@@ -293,14 +333,13 @@ int               rad_check_ts(uint32_t nasaddr, unsigned int port, const char *user,
 int            session_zap(REQUEST *request, uint32_t nasaddr,
                            unsigned int port, const char *user,
                            const char *sessionid, uint32_t cliaddr,
-                           char proto);
+                           char proto,int session_time);
 
 /* radiusd.c */
 #ifndef _LIBRADIUS
 void           debug_pair(FILE *, VALUE_PAIR *);
 #endif
 int            log_err (char *);
-int            rad_respond(REQUEST *, RAD_REQUEST_FUNP fun);
 
 /* util.c */
 void (*reset_signal(int signo, void (*func)(int)))(int);
@@ -308,7 +347,6 @@ void                request_free(REQUEST **request);
 int            rad_mkdir(char *directory, int mode);
 int            rad_checkfilename(const char *filename);
 void           *rad_malloc(size_t size); /* calls exit(1) on error! */
-void           xfree(const char *ptr);
 REQUEST                *request_alloc(void);
 REQUEST                *request_alloc_fake(REQUEST *oldreq);
 int            request_data_add(REQUEST *request,
@@ -316,34 +354,41 @@ int               request_data_add(REQUEST *request,
                                 void *opaque, void (*free_opaque)(void *));
 void           *request_data_get(REQUEST *request,
                                  void *unique_ptr, int unique_int);
-void           request_reject(REQUEST *request);
-void           rfc_clean(RADIUS_PACKET *packet);
+void           *request_data_reference(REQUEST *request,
+                                 void *unique_ptr, int unique_int);
+int            rad_copy_string(char *dst, const char *src);
+int            rad_copy_variable(char *dst, const char *from);
+
+/* request_process.c */
+int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun);
+void           request_reject(REQUEST *request, request_fail_t reason);
 
 /* client.c */
-int            read_clients_file(const char *file);
-RADCLIENT      *client_find(uint32_t ipno);
-const char     *client_name(uint32_t ipno);
-void           client_walk(void);
-void           clients_free(RADCLIENT *cl);
+RADCLIENT_LIST *clients_init(void);
+void           clients_free(RADCLIENT_LIST *clients);
+RADCLIENT_LIST *clients_parse_section(const char *filename,
+                                      CONF_SECTION *section);
+void           client_free(RADCLIENT *client);
+int            client_add(RADCLIENT_LIST *clients, RADCLIENT *client);
+RADCLIENT      *client_find(const RADCLIENT_LIST *clients,
+                            const lrad_ipaddr_t *ipaddr);
+const char     *client_name(const RADCLIENT_LIST *clients,
+                            const lrad_ipaddr_t *ipaddr);
+RADCLIENT      *client_findbynumber(const RADCLIENT_LIST *clients,
+                                    int number);
+RADCLIENT      *client_find_old(const lrad_ipaddr_t *ipaddr);
+const char     *client_name_old(const lrad_ipaddr_t *ipaddr);
 
 /* files.c */
 REALM          *realm_find(const char *, int);
 REALM          *realm_findbyaddr(uint32_t ipno, int port);
 void           realm_free(REALM *cl);
-void           realm_disable(uint32_t ipno, int port);
+void           realm_disable(REQUEST *);
 int            pairlist_read(const char *file, PAIR_LIST **list, int complain);
 void           pairlist_free(PAIR_LIST **);
 int            read_config_files(void);
 int            read_realms_file(const char *file);
 
-/* nas.c */
-int            read_naslist_file(char *);
-NAS            *nas_find(uint32_t ipno);
-const char     *nas_name(uint32_t ipno);
-const char     *nas_name2(RADIUS_PACKET *r);
-char  *                nas_name3(char *buf, size_t buflen, uint32_t ipno);
-NAS            *nas_findbyname(char *nasname);
-
 /* version.c */
 void           version(void);
 
@@ -368,14 +413,14 @@ int proxy_send(REQUEST *request);
 /* auth.c */
 char   *auth_name(char *buf, size_t buflen, REQUEST *request, int do_cli);
 int            rad_authenticate (REQUEST *);
-int            rad_check_password(REQUEST *request);
 int            rad_postauth(REQUEST *);
 
 /* exec.c */
 int            radius_exec_program(const char *,  REQUEST *, int,
                                    char *user_msg, int msg_len,
                                    VALUE_PAIR *input_pairs,
-                                   VALUE_PAIR **output_pairs);
+                                   VALUE_PAIR **output_pairs,
+                                       int shell_escape);
 
 /* timestr.c */
 int            timestr_match(char *, time_t);
@@ -385,8 +430,8 @@ int         paircompare_register(int attr, int otherattr,
                                     RAD_COMPARE_FUNC func,
                                     void *instance);
 void           paircompare_unregister(int attr, RAD_COMPARE_FUNC func);
-int            paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,
-                       VALUE_PAIR **reply);
+int            paircompare(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,
+                           VALUE_PAIR **reply);
 int            simplepaircmp(REQUEST *, VALUE_PAIR *, VALUE_PAIR *);
 void           pair_builtincompare_init(void);
 void           pairxlatmove(REQUEST *, VALUE_PAIR **to, VALUE_PAIR **from);
@@ -402,7 +447,7 @@ void                xlat_unregister(const char *module, RAD_XLAT_FUNC func);
 
 
 /* threads.c */
-extern         int thread_pool_init(void);
+extern         int thread_pool_init(int spawn_flag);
 extern         int thread_pool_clean(time_t now);
 extern         int thread_pool_addrequest(REQUEST *, RAD_REQUEST_FUNP);
 extern         pid_t rad_fork(void);
@@ -411,14 +456,19 @@ extern          int total_active_threads(void);
 
 #ifndef HAVE_PTHREAD_H
 #define rad_fork(n) fork()
-#define rad_waitpid(a,b) waitpid(a,b,0)
+#define rad_waitpid(a,b) waitpid(a,b, 0)
 #endif
 
-/* mainconfig.h */
+/* mainconfig.c */
 /* Define a global config structure */
 extern struct main_config_t mainconfig;
 
 int read_mainconfig(int reload);
 int free_mainconfig(void);
-CONF_SECTION *read_radius_conf_file(void); /* for radwho and friends. */
+
+/* listen.c */
+void listen_free(rad_listen_t **head);
+int listen_init(const char *filename, rad_listen_t **head);
+rad_listen_t *proxy_new_listener(void);
+
 #endif /*RADIUSD_H*/
diff --git a/src/include/radsniff.h b/src/include/radsniff.h
new file mode 100644 (file)
index 0000000..22adaa0
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *  radsniff.h Structures and defines for the RADIUS sniffer.
+ *
+ *  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 2006  The FreeRADIUS server project
+ *  Copyright 2006  Nicolas Baradakis <nicolas.baradakis@cegetel.net>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSIDH(radsniff_h, "$Id$")
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+/*
+ *     The number of bytes in an ethernet (MAC) address.
+ */
+#define ETHER_ADDR_LEN         6
+
+/*
+ *     Structure of a DEC/Intel/Xerox or 802.3 Ethernet header.
+ */
+struct  ethernet_header {
+        u_int8_t       ethernet_dhost[ETHER_ADDR_LEN];
+        u_int8_t       ethernet_shost[ETHER_ADDR_LEN];
+        u_int16_t      ethernet_type;
+};
+
+/*
+ *     Length of a DEC/Intel/Xerox or 802.3 Ethernet header.
+ *     Note that some compilers may pad "struct ether_header" to
+ *     a multiple of 4 *bytes, for example, so "sizeof (struct
+ *     ether_header)" may not give the right answer.
+ */
+#define ETHER_HDRLEN           14
+
+/*
+ *     Structure of an internet header, naked of options.
+ */
+struct ip_header {
+        u_int8_t        ip_vhl;         /* header length, version */
+#define IP_V(ip)        (((ip)->ip_vhl & 0xf0) >> 4)
+#define IP_HL(ip)       ((ip)->ip_vhl & 0x0f)
+        u_int8_t        ip_tos;         /* type of service */
+        u_int16_t       ip_len;         /* total length */
+        u_int16_t       ip_id;          /* identification */
+        u_int16_t       ip_off;         /* fragment offset field */
+#define IP_DF 0x4000                    /* dont fragment flag */
+#define IP_MF 0x2000                    /* more fragments flag */
+#define IP_OFFMASK 0x1fff               /* mask for fragmenting bits */
+        u_int8_t        ip_ttl;         /* time to live */
+        u_int8_t        ip_p;           /* protocol */
+        u_int16_t       ip_sum;         /* checksum */
+        struct in_addr  ip_src,ip_dst;  /* source and dest address */
+};
+
+/*
+ *     UDP protocol header.
+ *     Per RFC 768, September, 1981.
+ */
+struct udp_header {
+        u_int16_t       udp_sport;               /* source port */
+        u_int16_t       udp_dport;               /* destination port */
+        u_int16_t       udp_ulen;                /* udp length */
+        u_int16_t       udp_sum;                 /* udp checksum */
+};
+
+/*
+ *     RADIUS packet length.
+ *     RFC 2865, Section 3., subsection 'length' says:
+ *     " ... and maximum length is 4096."
+ */
+#define MAX_RADIUS_LEN 4096
+#define MIN_RADIUS_LEN 20
+#define SNAPLEN (sizeof(struct ethernet_header) + sizeof(struct ip_header) + sizeof(struct udp_header) + MAX_RADIUS_LEN)
+
+typedef struct radius_packet_t {
+       uint8_t       code;
+       uint8_t       id;
+       uint8_t       length[2];
+       uint8_t       vector[AUTH_VECTOR_LEN];
+       uint8_t       data[1];
+} radius_packet_t;
+
+#define AUTH_HDR_LEN 20
index 3b9c015..997c9ea 100644 (file)
@@ -7,6 +7,9 @@
 #ifndef _RADUTMP_H
 #define _RADUTMP_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(radutmp_h, "$Id$")
+
 /*
  *      Types of connection.
  */
index c639867..3ab2d73 100644 (file)
@@ -8,21 +8,21 @@
  *
  */
 
-extern int rl_init(void);
-extern void rl_delete(REQUEST *request);
-extern void rl_add(REQUEST *request);
-extern REQUEST *rl_find(RADIUS_PACKET *packet);
-extern int rl_add_proxy(REQUEST *request);
-extern REQUEST *rl_find_proxy(RADIUS_PACKET *packet);
-extern REQUEST *rl_next(REQUEST *request);
-extern int rl_num_requests(void);
-
-#define RL_WALK_CONTINUE (0)
-#define RL_WALK_STOP     (-1)
+#include <freeradius-devel/ident.h>
+RCSIDH(request_list_h, "$Id$")
 
-typedef int (*RL_WALK_FUNC)(REQUEST *, void *);
+extern request_list_t *rl_init(void);
+extern void rl_deinit(request_list_t *);
+extern void rl_yank(request_list_t *, REQUEST *);
+extern void rl_delete(request_list_t *, REQUEST *);
+extern int rl_add(request_list_t *, REQUEST *);
+extern REQUEST *rl_find(request_list_t *, RADIUS_PACKET *);
 
-extern int rl_walk(RL_WALK_FUNC walker, void *data);
-extern struct timeval *rl_clean_list(time_t now);
+extern int rl_init_proxy(void);
+extern int rl_add_proxy(REQUEST *request);
+extern REQUEST *rl_find_proxy(RADIUS_PACKET *packet);
+extern REQUEST *rl_next(request_list_t *, REQUEST *);
+extern int rl_num_requests(request_list_t *);
+extern int rl_clean_list(request_list_t *, time_t now);
 
 #endif /* _REQUEST_LIST_H */
index 0b29e9f..cfb6995 100644 (file)
@@ -2,15 +2,27 @@
  * Copyright (C) 2000 Jochen Friedrich <jochen@scram.de>
  * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
  *
+ * 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 GNU Zebra; see the file COPYING.  If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 #ifndef _SMUX_H
 #define _SMUX_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(smux_h, "$Id$")
+
 #ifdef HAVE_ASN1_SNMP_SNMPIMPL_H
 #include <asn1.h>
 #include <snmp.h>
index 8243714..f56e5d6 100644 (file)
@@ -7,6 +7,9 @@
 #ifndef SYSUTMP_H_INCLUDED
 #define SYSUTMP_H_INCLUDED
 
+#include <freeradius-devel/ident.h>
+RCSIDH(sysutmp_h, "$Id$")
+
 /*
  *  If we have BOTH utmp.h and utmpx.h, then
  *  we prefer to use utmp.h, but only on systems other than Solaris.
index 1cda314..1c77147 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2001  The FreeRADIUS server project
+ * Copyright 2001,2006  The FreeRADIUS server project
  */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(token_h, "$Id$")
+
 typedef enum lrad_token_t {
-  T_INVALID = 0,               /* invalid token */
+  T_OP_INVALID = 0,            /* invalid token */
   T_EOL,                       /* end of line */
   T_LCBRACE,                   /* { */
   T_RCBRACE,                   /* } */
   T_LBRACE,                    /* ( */
-  T_RBRACE,                    /* ) */
+  T_RBRACE,                    /* )             5 */
   T_COMMA,                     /* , */
   T_SEMICOLON,                 /* ; */
 
   T_OP_ADD,                    /* += */
   T_OP_SUB,                    /* -= */
-  T_OP_SET,                    /* := */
+  T_OP_SET,                    /* :=           10 */
   T_OP_EQ,                     /* = */
   T_OP_NE,                     /* != */
   T_OP_GE,                     /* >= */
   T_OP_GT,                     /* > */
-  T_OP_LE,                     /* <= */
+  T_OP_LE,                     /* <=           15 */
   T_OP_LT,                     /* < */
   T_OP_REG_EQ,                 /* =~ */
   T_OP_REG_NE,                 /* !~ */
   T_OP_CMP_TRUE,                /* =* */
-  T_OP_CMP_FALSE,               /* !* */
+  T_OP_CMP_FALSE,               /* !*          20 */
   T_OP_CMP_EQ,                 /* == */
   T_HASH,                      /* # */
   T_BARE_WORD,                 /* bare word */
   T_DOUBLE_QUOTED_STRING,      /* "foo" */
-  T_SINGLE_QUOTED_STRING,      /* 'foo' */
+  T_SINGLE_QUOTED_STRING,      /* 'foo'        25 */
   T_BACK_QUOTED_STRING,                /* `foo` */
   T_TOKEN_LAST
 } LRAD_TOKEN;
index a95e055..b93c8a3 100644 (file)
@@ -5,6 +5,9 @@
  *
  */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(udpfromtoh, "$Id$")
+
 #include <sys/socket.h>
 
 int udpfromto_init(int s);
diff --git a/src/lib/LICENSE b/src/lib/LICENSE
new file mode 100644 (file)
index 0000000..8add30a
--- /dev/null
@@ -0,0 +1,504 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
index 7339fdf..e975982 100644 (file)
@@ -6,17 +6,18 @@
 
 include ../../Make.inc
 
-SRCS           = crypt.c 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 token.c udpfromto.c \
-                 valuepair.c
+SRCS           = 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
 
 LT_OBJS                = $(SRCS:.c=.lo)
 
 INCLUDES       = ../include/radius.h ../include/libradius.h \
-                 ../include/missing.h ../include/autoconf.h
+                 ../include/missing.h ../include/autoconf.h \
+                 ../include/ident.h
 
-CFLAGS         += -D_LIBRADIUS -I../include
+CFLAGS         += -D_LIBRADIUS -I$(top_builddir)/src
 
 # if you have problems with things that need SHA1-HMAC, this will
 # dump the key and the input to the hash so you can compare to what
@@ -39,7 +40,7 @@ all: $(TARGET).la
 
 $(TARGET).la: $(LT_OBJS)
        $(LIBTOOL) --mode=link $(CC) -release $(RADIUSD_VERSION) \
-       $(LDFLAGS) $(LINK_MODE) -o $@ -rpath $(libdir) $^ $(LCRYPT)
+       $(LDFLAGS) $(LINK_MODE) -o $@ -rpath $(libdir) $^
 
 $(LT_OBJS): $(INCLUDES)
 
diff --git a/src/lib/README b/src/lib/README
new file mode 100644 (file)
index 0000000..1c1da3a
--- /dev/null
@@ -0,0 +1,2 @@
+  The files in this directory are placed under the LGPL, as given
+in the LICENSE file in this directory.
index 74e5c2d..d04b0d0 100644 (file)
  *   License along with this library; if not, write to the Free Software
  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
-static const char rcsid[] = "$Id$";
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include       "autoconf.h"
+#include       <freeradius-devel/autoconf.h>
 
 #include       <stdlib.h>
 #include       <ctype.h>
@@ -38,8 +39,8 @@ static const char rcsid[] = "$Id$";
 
 #include       <unistd.h>
 
-#include       "missing.h"
-#include       "libradius.h"
+#include       <freeradius-devel/missing.h>
+#include       <freeradius-devel/libradius.h>
 
 #define DICT_VALUE_MAX_NAME_LEN (128)
 #define DICT_VENDOR_MAX_NAME_LEN (128)
@@ -91,6 +92,8 @@ static const LRAD_NAME_NUMBER type_table[] = {
        { "ifid",       PW_TYPE_IFID },
        { "ipv6addr",   PW_TYPE_IPV6ADDR },
        { "ipv6prefix", PW_TYPE_IPV6PREFIX },
+       { "byte",       PW_TYPE_BYTE },
+       { "short",      PW_TYPE_SHORT },
        { NULL, 0 }
 };
 
@@ -138,8 +141,11 @@ static int dict_attr_name_cmp(const void *one, const void *two)
 
 static uint32_t dict_attr_value_hash(const void *data)
 {
-       return lrad_hash(&((const DICT_ATTR *)data)->attr,
-                        sizeof(((const DICT_ATTR *)data)->attr));
+       uint32_t hash;
+       const DICT_ATTR *attr = data;
+
+       hash = lrad_hash(&attr->vendor, sizeof(attr->vendor));
+       return lrad_hash_update(&attr->attr, sizeof(attr->attr), hash);
 }
 
 static int dict_attr_value_cmp(const void *one, const void *two)
@@ -147,6 +153,9 @@ static int dict_attr_value_cmp(const void *one, const void *two)
        const DICT_ATTR *a = one;
        const DICT_ATTR *b = two;
 
+       if (a->vendor < b->vendor) return -1;
+       if (a->vendor > b->vendor) return +1;
+
        return a->attr - b->attr;
 }
 
@@ -332,7 +341,7 @@ int dict_addvendor(const char *name, int value)
        size_t length;
        DICT_VENDOR *dv;
 
-       if (value >= (1 << 16)) {
+       if (value >= 32767) {
                librad_log("dict_addvendor: Cannot handle vendor ID larger than 65535");
                return -1;
        }
@@ -447,9 +456,8 @@ int dict_addattr(const char *name, int vendor, int type, int value,
                }
 
                /*
-                *      With a few exceptions, attributes can only be
-                *      1..255.  The check above catches the less than
-                *      zero case.
+                *      FIXME: Switch over dv->type, and limit things
+                *      properly.
                 */
                if ((dv->type == 1) && (value >= 256)) {
                        librad_log("dict_addattr: ATTRIBUTE has invalid number (larger than 255).");
@@ -468,6 +476,7 @@ int dict_addattr(const char *name, int vendor, int type, int value,
        strcpy(attr->name, name);
        attr->attr = value;
        attr->attr |= (vendor << 16); /* FIXME: hack */
+       attr->vendor = vendor;
        attr->type = type;
        attr->flags = flags;
        attr->vendor = vendor;
@@ -498,6 +507,7 @@ int dict_addattr(const char *name, int vendor, int type, int value,
                         */
                }
 
+
                lrad_hash_table_delete(attributes_byvalue, a);
 
                if (!lrad_hash_table_replace(attributes_byname, attr)) {
@@ -534,6 +544,11 @@ int dict_addvalue(const char *namestr, const char *attrstr, int value)
        DICT_ATTR       *dattr;
        DICT_VALUE      *dval;
 
+       if (!*namestr) {
+               librad_log("dict_addvalue: empty names are not permitted");
+               return -1;
+       }
+
        if ((length = strlen(namestr)) >= DICT_VALUE_MAX_NAME_LEN) {
                librad_log("dict_addvalue: value name too long");
                return -1;
@@ -554,18 +569,48 @@ int dict_addvalue(const char *namestr, const char *attrstr, int value)
         */
        dattr = dict_attrbyname(attrstr);
        if (dattr) {
+               if (dattr->flags.has_value_alias) {
+                       librad_log("dict_addvalue: Cannot add VALUE for ATTRIBUTE \"%s\": It already has a VALUE-ALIAS", attrstr);
+                       return -1;
+               }
+
                dval->attr = dattr->attr;
 
                /*
-                *      Octets is allowed as a work-around for the
-                *      fact that branch_1_1 doesn't have BYTE or SHORT
+                *      Enforce valid values
+                *
+                *      Don't worry about fixups...
                 */
-               if ((dattr->type != PW_TYPE_INTEGER) &&
-                   (dattr->type != PW_TYPE_OCTETS)) {
-                       librad_log("dict_addvalue: VALUEs can only be defined for'integer' types");
-                       return -1;
+               switch (dattr->type) {
+                       case PW_TYPE_BYTE:
+                               if (value > 255) {
+                                       librad_log("dict_addvalue: ATTRIBUTEs of type 'byte' cannot have VALUEs larger than 255");
+                                       return -1;
+                               }
+                               break;
+                       case PW_TYPE_SHORT:
+                               if (value > 65535) {
+                                       librad_log("dict_addvalue: ATTRIBUTEs of type 'short' cannot have VALUEs larger than 65535");
+                                       return -1;
+                               }
+                               break;
+
+                               /*
+                                *      Allow octets for now, because
+                                *      of dictionary.cablelabs
+                                */
+                       case PW_TYPE_OCTETS:
+
+                       case PW_TYPE_INTEGER:
+                               break;
+
+                       default:
+                               librad_log("dict_addvalue: VALUEs cannot be defined for attributes of type '%s'",
+                                          lrad_int2str(type_table, dattr->type, "?Unknown?"));
+                               return -1;
                }
 
+               dattr->flags.has_value = 1;
        } else {
                value_fixup_t *fixup;
                
@@ -576,7 +621,7 @@ int dict_addvalue(const char *namestr, const char *attrstr, int value)
                }
                memset(fixup, 0, sizeof(*fixup));
 
-               strNcpy(fixup->attrstr, attrstr, sizeof(fixup->attrstr));
+               strlcpy(fixup->attrstr, attrstr, sizeof(fixup->attrstr));
                fixup->dval = dval;
                
                /*
@@ -668,6 +713,9 @@ static int process_attribute(const char* fn, const int line,
         */
        memset(&flags, 0, sizeof(flags));
        if (argc == 4) {
+               /*
+                *      FIXME: replace strtok with str2argv
+                */
                s = strtok(argv[3], ",");
                while (s) {
                        if (strcmp(s, "has_tag") == 0 ||
@@ -687,6 +735,29 @@ static int process_attribute(const char* fn, const int line,
                                                    fn, line, s);
                                        return -1;
                                }
+
+                       } else if (strncmp(s, "array", 8) == 0) {
+                               flags.array = 1;
+
+                               switch (type) {
+                                       case PW_TYPE_IPADDR:
+                                       case PW_TYPE_BYTE:
+                                       case PW_TYPE_SHORT:
+                                       case PW_TYPE_INTEGER:
+                                       case PW_TYPE_DATE:
+                                               break;
+                                       
+                                       default:
+                                               librad_log( "dict_init: %s[%d] Only IP addresses can have the \"array\" flag set.",
+                                                           fn, line);
+                                               return -1;
+                               }
+
+                       } else if (block_vendor) {
+                               librad_log( "dict_init: %s[%d]: unknown option \"%s\"",
+                                           fn, line, s);
+                               return -1;
+
                        } else {
                                /* Must be a vendor 'flag'... */
                                if (strncmp(s, "vendor=", 7) == 0) {
@@ -696,7 +767,7 @@ static int process_attribute(const char* fn, const int line,
                                
                                vendor = dict_vendorbyname(s);
                                if (!vendor) {
-                                       librad_log( "dict_init: %s[%d]: unknown vendor %s",
+                                       librad_log( "dict_init: %s[%d]: unknown vendor \"%s\"",
                                                    fn, line, s);
                                        return -1;
                                }
@@ -788,6 +859,89 @@ static int process_value(const char* fn, const int line, char **argv,
 
 
 /*
+ *     Process the VALUE-ALIAS command
+ *
+ *     This allows VALUE mappings to be shared among multiple
+ *     attributes.
+ */
+static int process_value_alias(const char* fn, const int line, char **argv,
+                              int argc)
+{
+       DICT_ATTR *my_da, *da;
+       DICT_VALUE *dval;
+
+       if (argc != 2) {
+               librad_log("dict_init: %s[%d]: invalid VALUE-ALIAS line",
+                       fn, line);
+               return -1;
+       }
+
+       my_da = dict_attrbyname(argv[0]);
+       if (!my_da) {
+               librad_log("dict_init: %s[%d]: ATTRIBUTE \"%s\" does not exist",
+                          fn, line, argv[1]);
+               return -1;
+       }
+
+       if (my_da->flags.has_value) {
+               librad_log("dict_init: %s[%d]: Cannot add VALUE-ALIAS to ATTRIBUTE \"%s\" with pre-existing VALUE",
+                          fn, line, argv[0]);
+               return -1;
+       }
+
+       if (my_da->flags.has_value_alias) {
+               librad_log("dict_init: %s[%d]: Cannot add VALUE-ALIAS to ATTRIBUTE \"%s\" with pre-existing VALUE-ALIAS",
+                          fn, line, argv[0]);
+               return -1;
+       }
+
+       da = dict_attrbyname(argv[1]);
+       if (!da) {
+               librad_log("dict_init: %s[%d]: Cannot find ATTRIBUTE \"%s\" for alias",
+                          fn, line, argv[1]);
+               return -1;
+       }
+
+       if (!da->flags.has_value) {
+               librad_log("dict_init: %s[%d]: VALUE-ALIAS cannot refer to ATTRIBUTE %s: It has no values",
+                          fn, line, argv[1]);
+               return -1;
+       }
+
+       if (da->flags.has_value_alias) {
+               librad_log("dict_init: %s[%d]: Cannot add VALUE-ALIAS to ATTRIBUTE \"%s\" which itself has a VALUE-ALIAS",
+                          fn, line, argv[1]);
+               return -1;
+       }
+
+       if (my_da->type != da->type) {
+               librad_log("dict_init: %s[%d]: Cannot add VALUE-ALIAS between attributes of differing type",
+                          fn, line);
+               return -1;
+       }
+
+       if ((dval = malloc(sizeof(*dval))) == NULL) {
+               librad_log("dict_addvalue: out of memory");
+               return -1;
+       }
+       memset(dval, 0, sizeof(*dval));
+
+       dval->name[0] = '\0';   /* empty name */
+       dval->attr = my_da->attr;
+       dval->value = da->attr;
+
+       if (!lrad_hash_table_insert(values_byname, dval)) {
+               librad_log("dict_init: %s[%d]: Error create alias",
+                          fn, line);
+               free(dval);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/*
  *     Process the VENDOR command
  */
 static int process_vendor(const char* fn, const int line, char **argv,
@@ -1069,6 +1223,15 @@ static int my_dict_init(const char *dir, const char *fn,
                        continue;
                }
 
+               if (strcasecmp(argv[0], "VALUE-ALIAS") == 0) {
+                       if (process_value_alias(fn, line,
+                                               argv + 1, argc - 1) == -1) {
+                               fclose(fp);
+                               return -1;
+                       }
+                       continue;
+               }
+
                /*
                 *      Process VENDOR lines.
                 */
@@ -1317,6 +1480,7 @@ DICT_ATTR *dict_attrbyvalue(int attr)
        DICT_ATTR dattr;
 
        dattr.attr = attr;
+       dattr.vendor = VENDOR(attr) & 0x7fff;
 
        return lrad_hash_table_finddata(attributes_byvalue, &dattr);
 }
@@ -1330,7 +1494,7 @@ DICT_ATTR *dict_attrbyname(const char *name)
 
        if (!name) return NULL;
 
-       strNcpy(dattr.name, name, sizeof(dattr.name));
+       strlcpy(dattr.name, name, sizeof(dattr.name));
 
        return lrad_hash_table_finddata(attributes_byname, &dattr);
 }
@@ -1340,9 +1504,21 @@ DICT_ATTR *dict_attrbyname(const char *name)
  */
 DICT_VALUE *dict_valbyattr(int attr, int value)
 {
-       DICT_VALUE dval;
+       DICT_VALUE dval, *dv;
 
+       /*
+        *      First, look up aliases.
+        */
        dval.attr = attr;
+       dval.name[0] = '\0';
+
+       /*
+        *      Look up the attribute alias target, and use
+        *      the correct attribute number if found.
+        */
+       dv = lrad_hash_table_finddata(values_byname, &dval);
+       if (dv) dval.attr = dv->value;
+
        dval.value = value;
        
        return lrad_hash_table_finddata(values_byvalue, &dval);
@@ -1353,16 +1529,25 @@ DICT_VALUE *dict_valbyattr(int attr, int value)
  */
 DICT_VALUE *dict_valbyname(int attr, const char *name)
 {
-       DICT_VALUE *dv;
-       uint32_t buffer[(sizeof(*dv) + DICT_VALUE_MAX_NAME_LEN + 3)/4];
+       DICT_VALUE *my_dv, *dv;
+       uint32_t buffer[(sizeof(*my_dv) + DICT_VALUE_MAX_NAME_LEN + 3)/4];
 
        if (!name) return NULL;
 
-       dv = (DICT_VALUE *) buffer;
-       dv->attr = attr;
-       strNcpy(dv->name, name, DICT_VALUE_MAX_NAME_LEN);
+       my_dv = (DICT_VALUE *) buffer;
+       my_dv->attr = attr;
+       my_dv->name[0] = '\0';
+
+       /*
+        *      Look up the attribute alias target, and use
+        *      the correct attribute number if found.
+        */
+       dv = lrad_hash_table_finddata(values_byname, my_dv);
+       if (dv) my_dv->attr = dv->value;
+
+       strlcpy(my_dv->name, name, DICT_VALUE_MAX_NAME_LEN);
 
-       return lrad_hash_table_finddata(values_byname, dv);
+       return lrad_hash_table_finddata(values_byname, my_dv);
 }
 
 /*
@@ -1378,7 +1563,7 @@ int dict_vendorbyname(const char *name)
        if (!name) return 0;
 
        dv = (DICT_VENDOR *) buffer;
-       strNcpy(dv->name, name, DICT_VENDOR_MAX_NAME_LEN);
+       strlcpy(dv->name, name, DICT_VENDOR_MAX_NAME_LEN);
        
        dv = lrad_hash_table_finddata(vendors_byname, dv);
        if (!dv) return 0;
diff --git a/src/lib/fifo.c b/src/lib/fifo.c
new file mode 100644 (file)
index 0000000..f03f667
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * fifo.c      Non-thread-safe fifo (FIFO) implementation, based
+ *             on hash tables.
+ *
+ * Version:    $Id$
+ *
+ *   This library is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU Lesser General Public
+ *   License as published by the Free Software Foundation; either
+ *   version 2.1 of the License, or (at your option) any later version.
+ *
+ *   This library 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
+ *   Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ *  Copyright 2005,2006  The FreeRADIUS server project
+ *  Copyright 2005  Alan DeKok <aland@ox.org>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
+
+typedef struct lrad_fifo_entry_t {
+       struct lrad_fifo_entry_t *next;
+       void                    *data;
+} lrad_fifo_entry_t;
+
+struct lrad_fifo_t {
+       lrad_fifo_entry_t *head, **tail;
+       lrad_fifo_entry_t *freelist;
+
+       int num_elements;
+       int max_entries;
+       lrad_fifo_free_t freeNode;
+};
+
+
+lrad_fifo_t *lrad_fifo_create(int max_entries, lrad_fifo_free_t freeNode)
+{
+       lrad_fifo_t *fi;
+
+       if ((max_entries < 2) || (max_entries > (1024 * 1024))) return NULL;
+
+       fi = malloc(sizeof(*fi));
+       if (!fi) return NULL;
+
+       memset(fi, 0, sizeof(*fi));
+
+       fi->max_entries = max_entries;
+       fi->freeNode = freeNode;
+
+       return fi;
+}
+
+static void lrad_fifo_free_entries(lrad_fifo_t *fi, lrad_fifo_entry_t *head)
+{
+       lrad_fifo_entry_t *next;
+
+       while (head) {
+               next = head->next;
+
+               if (fi->freeNode && head->data) fi->freeNode(head->data);
+               free(head);
+
+               head = next;
+       }
+}
+
+void lrad_fifo_free(lrad_fifo_t *fi)
+{
+       if (!fi) return;
+
+       lrad_fifo_free_entries(fi, fi->head);
+       lrad_fifo_free_entries(fi, fi->freelist);
+
+       free(fi);
+}
+
+static lrad_fifo_entry_t *lrad_fifo_alloc_entry(lrad_fifo_t *fi)
+{
+       lrad_fifo_entry_t *entry;
+
+       if (fi->freelist) {
+               entry = fi->freelist;
+               fi->freelist = entry->next;
+       } else {
+               entry = malloc(sizeof(*entry));
+               if (!entry) return NULL;
+       }
+
+       memset(entry, 0, sizeof(*entry));
+       return entry;
+}
+
+int lrad_fifo_push(lrad_fifo_t *fi, void *data)
+{
+       lrad_fifo_entry_t *entry;
+
+       if (!fi || !data) return 0;
+
+       if (fi->num_elements >= fi->max_entries) return 0;
+
+       entry = lrad_fifo_alloc_entry(fi);
+       if (!entry) return 0;
+       entry->data = data;
+
+       if (!fi->head) {
+               fi->head = entry;
+       } else {
+               *fi->tail = entry;
+       }
+       fi->tail = &(entry->next);
+
+       fi->num_elements++;
+
+       return 1;
+}
+
+static void lrad_fifo_free_entry(lrad_fifo_t *fi, lrad_fifo_entry_t *entry)
+{
+       entry->data = NULL;
+       entry->next = fi->freelist;
+       fi->freelist = entry->next;
+}
+
+
+void *lrad_fifo_pop(lrad_fifo_t *fi)
+{
+       void *data;
+       lrad_fifo_entry_t *entry;
+
+       if (!fi || !fi->head) return 0;
+
+       entry = fi->head;
+       fi->head = entry->next;
+
+       data = entry->data;
+       lrad_fifo_free_entry(fi, entry);
+
+       fi->num_elements--;
+
+       if (!fi->head) {
+               fi->tail = NULL;
+               fi->num_elements = 0;
+       }
+
+       return data;
+}
+
+#ifdef TESTING
+
+/*
+ *  cc -DTESTING -I .. fifo.c -o fifo
+ *
+ *  ./fifo
+ */
+
+#define MAX 1024
+int main(int argc, char **argv)
+{
+       int i, array[MAX];
+       lrad_fifo_t *fi;
+
+       fi = lrad_fifo_create(MAX, NULL);
+       if (!fi) exit(1);
+       
+       for (i = 0; i < MAX; i++) {
+               array[i] = i;
+
+               if (!lrad_fifo_push(fi, &array[i])) exit(2);
+       }
+
+       for (i = 0; i < MAX; i++) {
+               int *p;
+
+               p = lrad_fifo_pop(fi);
+               if (!p) {
+                       fprintf(stderr, "No pop at %d\n", i);
+                       exit(3);
+               }
+
+               if (*p != i) exit(4);
+       }
+
+       exit(0);
+}
+#endif
index 57f737a..4ce2f48 100644 (file)
  *   License along with this library; if not, write to the Free Software
  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2003  The FreeRADIUS server project
+ * Copyright 2003,2006  The FreeRADIUS server project
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <string.h>
 #include <ctype.h>
 #include <stdlib.h>
 
-#include "libradius.h"
 
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
 
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
+
 /*
  * Two types of filters are supported, GENERIC and IP.  The identifiers
  * are:
@@ -58,6 +63,7 @@ static const char rcsid[] = "$Id$";
 # define TRUE          (! FALSE)
 #endif
 
+
 /*
  *     ascend_ip_filter_t
  *
@@ -212,9 +218,16 @@ typedef struct ascend_filter_t {
                ascend_ip_filter_t       ip;
                ascend_ipx_filter_t      ipx;
                ascend_generic_filter_t generic;
+               uint8_t                 data[28]; /* ensure it's 32 bytes */
        } u;
 } ascend_filter_t;
-#define SIZEOF_RADFILTER 32
+
+/*
+ *     This is a wild C hack...
+ */
+typedef struct _cpp_hack {
+       char data[(sizeof(ascend_filter_t) == 32) ? 1 : -1 ];
+} _cpp_hack;
 
 /*
  * FilterPortType:
@@ -372,49 +385,6 @@ static int str2argv(char *str, char **argv, int max_argc)
 
 
 /*
- *     hex2bin converts hexadecimal strings into binary
- *
- *     Hmm... there are a number of such functions in the source.
- *     maybe we want to make a library function?
- */
-static int hex2bin(const char *str, uint8_t *bin, size_t length)
-{
-       unsigned int            len;
-       const           char *letters = "0123456789ABCDEFabcdef";
-
-       /*
-        *      Must be byte aligned, not nibble aligned.
-        */
-       len = strlen(str);
-       if ((len & 0x01) != 0) return -1;
-
-       /*
-        *      Input string is too long to fit.  Don't even bother
-        *      trying.
-        */
-       if ((len / 2) > length) return -1;
-
-       /*
-        *      Input string contains non-hex characters, die.
-        */
-       if (strspn(str, letters) != len) return -1;
-
-       len = 0;
-       while (*str) {
-               char    *c1, *c2;
-
-               c1 = memchr(letters, toupper((int) *(str++)), 16);
-               c2 = memchr(letters, toupper((int) *(str++)), 16);
-
-               *(bin++) = ((c1-letters)<<4) + (c2-letters);
-               len++;
-       }
-
-        return len;
-}
-
-
-/*
  *     ascend_parse_ipx_net
  *
  *     srcipxnet nnnn srcipxnode mmmmm [srcipxsoc cmd value ]
@@ -455,7 +425,7 @@ static int ascend_parse_ipx_net(int argc, char **argv,
        /*
         *      Node must be 6 octets long.
         */
-       token = hex2bin(p, net->node, IPX_NODE_ADDR_LEN);
+       token = lrad_hex2bin(p, net->node, IPX_NODE_ADDR_LEN);
        if (token != IPX_NODE_ADDR_LEN) return -1;
 
        /*
@@ -742,6 +712,17 @@ static int ascend_parse_port(uint16_t *port, char *compare, char *str)
 }
 
 
+#define IP_SRC_ADDR_FLAG    (1 << 0)
+#define IP_DEST_ADDR_FLAG   (1 << 1)
+#define IP_SRC_PORT_FLAG    (1 << 2)
+#define IP_DEST_PORT_FLAG   (1 << 3)
+#define IP_PROTO_FLAG       (1 << 4)
+#define IP_EST_FLAG         (1 << 5)
+
+#define DONE_FLAGS     (IP_SRC_ADDR_FLAG | IP_DEST_ADDR_FLAG | \
+                       IP_SRC_PORT_FLAG | IP_DEST_PORT_FLAG | \
+                       IP_PROTO_FLAG | IP_EST_FLAG)
+       
 /*
  *     ascend_parse_ip:
  *
@@ -788,72 +769,37 @@ static int ascend_parse_ip(int argc, char **argv, ascend_ip_filter_t *filter)
         *      There may, or may not, be src & dst IP's in the string.
         */
        flags = 0;
-       while ((argc > 0) && (flags != 7)) {
+       while ((argc > 0) && (flags != DONE_FLAGS)) {
                token = lrad_str2int(filterKeywords, argv[0], -1);
                switch (token) {
                case FILTER_IP_SRC:
-                       if (flags & 0x01) return -1;
+                       if (flags & IP_SRC_ADDR_FLAG) return -1;
                        if (argc < 2) return -1;
 
                        rcode = ascend_parse_ipaddr(&filter->srcip, argv[1]);
                        if (rcode < 0) return rcode;
 
                        filter->srcmask = rcode;
-                       flags |= 0x01;
+                       flags |= IP_SRC_ADDR_FLAG;
                        argv += 2;
                        argc -= 2;
                        break;
 
                case FILTER_IP_DST:
-                       if (flags & 0x02) return -1;
+                       if (flags & IP_DEST_ADDR_FLAG) return -1;
                        if (argc < 2) return -1;
 
                        rcode = ascend_parse_ipaddr(&filter->dstip, argv[1]);
                        if (rcode < 0) return rcode;
 
                        filter->dstmask = rcode;
-                       flags |= 0x02;
+                       flags |= IP_DEST_ADDR_FLAG;
                        argv += 2;
                        argc -= 2;
                        break;
 
-                       /*
-                        *      Should be protocol, ASCII or otherwise.
-                        */
-               default:
-                       if (strspn(argv[0], "0123456789") == strlen(argv[0])) {
-                               token = atoi(argv[0]);
-                       } else {
-                               token = lrad_str2int(filterProtoName, argv[0], -1);
-                               if (token == -1) {
-                                       librad_log("Unknown IP protocol \"%s\" in IP data filter",
-                                                  argv[0]);
-                                       return -1;
-                               }
-                       }
-                       filter->proto = token;
-                       flags = 0x07; /* MUST have parsed everything. */
-
-                       argv++;
-                       argc--;
-                       break;
-               }
-       } /* looking for src/dst IP, and proto */
-
-       /*
-        *      Done looking for everything, return.
-        */
-       if (argc == 0) return 0;
-
-       /*
-        *      There may, or may not, be src & dst ports in the string.
-        */
-       flags = 0;
-       while ((argc > 0) && (flags != 7)) {
-               token = lrad_str2int(filterKeywords, argv[0], -1);
-               switch (token) {
                case FILTER_IP_SRC_PORT:
-                       if (flags & 0x01) return -1;
+                       if (flags & IP_SRC_PORT_FLAG) return -1;
                        if (argc < 3) return -1;
 
                        rcode = ascend_parse_port(&filter->srcport,
@@ -861,13 +807,13 @@ static int ascend_parse_ip(int argc, char **argv, ascend_ip_filter_t *filter)
                        if (rcode < 0) return rcode;
                        filter->srcPortComp = rcode;
 
-                       flags |= 0x01;
+                       flags |= IP_SRC_PORT_FLAG;
                        argv += 3;
                        argc -= 3;
                        break;
 
                case FILTER_IP_DST_PORT:
-                       if (flags & 0x02) return -1;
+                       if (flags & IP_DEST_PORT_FLAG) return -1;
                        if (argc < 3) return -1;
 
                        rcode = ascend_parse_port(&filter->dstport,
@@ -875,31 +821,39 @@ static int ascend_parse_ip(int argc, char **argv, ascend_ip_filter_t *filter)
                        if (rcode < 0) return rcode;
                        filter->dstPortComp = rcode;
 
-                       flags |= 0x02;
+                       flags |= IP_DEST_PORT_FLAG;
                        argv += 3;
                        argc -= 3;
                        break;
 
-                       /*
-                        *      Look for established connections.
-                        */
                case FILTER_EST:
+                       if (flags & IP_EST_FLAG) return -1;
                        filter->established = 1;
                        argv++;
                        argc--;
-                       flags = 0x07;
+                       flags |= IP_EST_FLAG;
                        break;
 
-                       /*
-                        *      Unknown thingy.
-                        */
                default:
-                       librad_log("Unknown string \"%s\" in IP data filter",
-                                  argv[0]);
-                       return -1;
+                       if (flags & IP_PROTO_FLAG) return -1;
+                       if (strspn(argv[0], "0123456789") == strlen(argv[0])) {
+                               token = atoi(argv[0]);
+                       } else {
+                               token = lrad_str2int(filterProtoName, argv[0], -1);
+                               if (token == -1) {
+                                       librad_log("Unknown IP protocol \"%s\" in IP data filter",
+                                                  argv[0]);
+                                       return -1;
+                               }
+                       }
+                       filter->proto = token;
+                       flags |= IP_PROTO_FLAG;
+
+                       argv++;
+                       argc--;
                        break;
                }
-       } /* looking for src/dst port */
+       }
 
        /*
         *      We should have parsed everything by now.
@@ -970,11 +924,11 @@ static int ascend_parse_generic(int argc, char **argv,
        filter->offset = rcode;
        filter->offset = htons(filter->offset);
 
-       rcode = hex2bin(argv[1], filter->mask, sizeof(filter->mask));
-       if (rcode < 0) return -1;
+       rcode = lrad_hex2bin(argv[1], filter->mask, sizeof(filter->mask));
+       if (rcode != sizeof(filter->mask)) return -1;
 
-       token = hex2bin(argv[2], filter->value, sizeof(filter->value));
-       if (token < 0) return -1;
+       token = lrad_hex2bin(argv[2], filter->value, sizeof(filter->value));
+       if (token != sizeof(filter->value)) return -1;
 
        /*
         *      The mask and value MUST be the same length.
@@ -1049,7 +1003,7 @@ ascend_parse_filter(VALUE_PAIR *pair)
        ascend_filter_t filter;
 
        rcode = -1;
-       
+
        /*
         *      Rather than printing specific error messages, we create
         *      a general one here, which won't be used if the function
@@ -1060,10 +1014,10 @@ ascend_parse_filter(VALUE_PAIR *pair)
        /*
         *      Tokenize the input string in the VP.
         *
-        *      Once the filter is *completely* parsed, then we will
+        *      Once the filter is *completelty* parsed, then we will
         *      over-write it with the final binary filter.
         */
-       argc = str2argv(pair->strvalue, argv, 32);
+       argc = str2argv(pair->vp_strvalue, argv, 32);
        if (argc < 3) return -1;
 
        /*
@@ -1149,8 +1103,8 @@ ascend_parse_filter(VALUE_PAIR *pair)
         *      Touch the VP only if everything was OK.
         */
        if (rcode == 0) {
-               pair->length = SIZEOF_RADFILTER;
-               memcpy(pair->strvalue, &filter, sizeof(filter));
+               pair->length = sizeof(filter);
+               memcpy(pair->vp_filter, &filter, sizeof(filter));
        }
 
        return rcode;
@@ -1163,7 +1117,7 @@ ascend_parse_filter(VALUE_PAIR *pair)
      * previous 'more'
      */
     if( prevRadPair ) {
-       filt = ( RadFilter * )prevRadPair->strvalue;
+       filt = ( RadFilter * )prevRadPair->vp_strvalue;
        if(( tok != FILTER_GENERIC_TYPE ) || (rc == -1 ) ||
           ( prevRadPair->attribute != pair->attribute ) ||
           ( filt->indirection != radFil.indirection ) ||
@@ -1182,7 +1136,7 @@ ascend_parse_filter(VALUE_PAIR *pair)
     }
 
     if( rc != -1 ) {
-       memcpy( pair->strvalue, (char *) &radFil, pair->length );
+       memcpy( pair->vp_strvalue, &radFil, pair->length );
     }
     return(rc);
 
@@ -1197,40 +1151,40 @@ ascend_parse_filter(VALUE_PAIR *pair)
  *     Note we don't bother checking 'len' after the snprintf's.
  *     This function should ONLY be called with a large (~1k) buffer.
  */
-void print_abinary(VALUE_PAIR *vp, u_char *buffer, int len)
+void print_abinary(VALUE_PAIR *vp, char *buffer, int len)
 {
   int                  i;
   char                 *p;
-  ascend_filter_t      filter;
+  ascend_filter_t      *filter;
 
   static const char *action[] = {"drop", "forward"};
   static const char *direction[] = {"out", "in"};
 
-  p = (char *)buffer;
+  p = buffer;
 
   /*
    *  Just for paranoia: wrong size filters get printed as octets
    */
-  if (vp->length > SIZEOF_RADFILTER) {
-    strcpy(p, "0x");
-    p += 2;
-    len -= 2;
-    for (i = 0; i < vp->length; i++) {
-      snprintf(p, len, "%02x", vp->strvalue[i]);
-      p += 2;
-      len -= 2;
-    }
-    return;
+  if (vp->length != sizeof(*filter)) {
+         strcpy(p, "0x");
+         p += 2;
+         len -= 2;
+         for (i = 0; i < vp->length; i++) {
+                 snprintf(p, len, "%02x", vp->vp_octets[i]);
+                 p += 2;
+                 len -= 2;
+         }
+         return;
   }
 
-  memcpy(&filter, vp->strvalue, SIZEOF_RADFILTER); /* alignment issues */
   *(p++) = '"';
   len -= 3;                    /* account for leading & trailing quotes */
 
+  filter = (ascend_filter_t *) &(vp->vp_filter);
   i = snprintf(p, len, "%s %s %s",
-              lrad_int2str(filterType, filter.type, "??"),
-              direction[filter.direction & 0x01],
-              action[filter.forward & 0x01]);
+              lrad_int2str(filterType, filter->type, "??"),
+              direction[filter->direction & 0x01],
+              action[filter->forward & 0x01]);
 
   p += i;
   len -= i;
@@ -1238,52 +1192,52 @@ void print_abinary(VALUE_PAIR *vp, u_char *buffer, int len)
   /*
    *   Handle IP filters
    */
-  if (filter.type == RAD_FILTER_IP) {
+  if (filter->type == RAD_FILTER_IP) {
 
-    if (filter.u.ip.srcip) {
+    if (filter->u.ip.srcip) {
       i = snprintf(p, len, " srcip %d.%d.%d.%d/%d",
-                  ((u_char *) &filter.u.ip.srcip)[0],
-                  ((u_char *) &filter.u.ip.srcip)[1],
-                  ((u_char *) &filter.u.ip.srcip)[2],
-                  ((u_char *) &filter.u.ip.srcip)[3],
-                  filter.u.ip.srcmask);
+                  ((uint8_t *) &filter->u.ip.srcip)[0],
+                  ((uint8_t *) &filter->u.ip.srcip)[1],
+                  ((uint8_t *) &filter->u.ip.srcip)[2],
+                  ((uint8_t *) &filter->u.ip.srcip)[3],
+                  filter->u.ip.srcmask);
       p += i;
       len -= i;
     }
 
-    if (filter.u.ip.dstip) {
+    if (filter->u.ip.dstip) {
       i = snprintf(p, len, " dstip %d.%d.%d.%d/%d",
-                  ((u_char *) &filter.u.ip.dstip)[0],
-                  ((u_char *) &filter.u.ip.dstip)[1],
-                  ((u_char *) &filter.u.ip.dstip)[2],
-                  ((u_char *) &filter.u.ip.dstip)[3],
-                  filter.u.ip.dstmask);
+                  ((uint8_t *) &filter->u.ip.dstip)[0],
+                  ((uint8_t *) &filter->u.ip.dstip)[1],
+                  ((uint8_t *) &filter->u.ip.dstip)[2],
+                  ((uint8_t *) &filter->u.ip.dstip)[3],
+                  filter->u.ip.dstmask);
       p += i;
       len -= i;
     }
 
     i =  snprintf(p, len, " %s",
-                 lrad_int2str(filterProtoName, filter.u.ip.proto, "??"));
+                 lrad_int2str(filterProtoName, filter->u.ip.proto, "??"));
     p += i;
     len -= i;
 
-    if (filter.u.ip.srcPortComp > RAD_NO_COMPARE) {
+    if (filter->u.ip.srcPortComp > RAD_NO_COMPARE) {
       i = snprintf(p, len, " srcport %s %d",
-                  lrad_int2str(filterCompare, filter.u.ip.srcPortComp, "??"),
-                  ntohs(filter.u.ip.srcport));
+                  lrad_int2str(filterCompare, filter->u.ip.srcPortComp, "??"),
+                  ntohs(filter->u.ip.srcport));
       p += i;
       len -= i;
     }
 
-    if (filter.u.ip.dstPortComp > RAD_NO_COMPARE) {
+    if (filter->u.ip.dstPortComp > RAD_NO_COMPARE) {
       i = snprintf(p, len, " dstport %s %d",
-                  lrad_int2str(filterCompare, filter.u.ip.dstPortComp, "??"),
-                  ntohs(filter.u.ip.dstport));
+                  lrad_int2str(filterCompare, filter->u.ip.dstPortComp, "??"),
+                  ntohs(filter->u.ip.dstport));
       p += i;
       len -= i;
     }
 
-    if (filter.u.ip.established) {
+    if (filter->u.ip.established) {
       i = snprintf(p, len, " est");
       p += i;
       len -= i;
@@ -1292,56 +1246,56 @@ void print_abinary(VALUE_PAIR *vp, u_char *buffer, int len)
     /*
      * Handle IPX filters
      */
-  } else if (filter.type == RAD_FILTER_IPX) {
+  } else if (filter->type == RAD_FILTER_IPX) {
     /* print for source */
-    if (filter.u.ipx.src.net) {
+    if (filter->u.ipx.src.net) {
       i = snprintf(p, len, " srcipxnet 0x%04x srcipxnode 0x%02x%02x%02x%02x%02x%02x",
-                 (unsigned int)ntohl(filter.u.ipx.src.net),
-                 filter.u.ipx.src.node[0], filter.u.ipx.src.node[1],
-                 filter.u.ipx.src.node[2], filter.u.ipx.src.node[3],
-                 filter.u.ipx.src.node[4], filter.u.ipx.src.node[5]);
+                 (unsigned int)ntohl(filter->u.ipx.src.net),
+                 filter->u.ipx.src.node[0], filter->u.ipx.src.node[1],
+                 filter->u.ipx.src.node[2], filter->u.ipx.src.node[3],
+                 filter->u.ipx.src.node[4], filter->u.ipx.src.node[5]);
       p += i;
       len -= i;
 
-      if (filter.u.ipx.srcSocComp > RAD_NO_COMPARE) {
+      if (filter->u.ipx.srcSocComp > RAD_NO_COMPARE) {
        i = snprintf(p, len, " srcipxsock %s 0x%04x",
-                    lrad_int2str(filterCompare, filter.u.ipx.srcSocComp, "??"),
-                    ntohs(filter.u.ipx.src.socket));
+                    lrad_int2str(filterCompare, filter->u.ipx.srcSocComp, "??"),
+                    ntohs(filter->u.ipx.src.socket));
        p += i;
        len -= i;
       }
     }
 
     /* same for destination */
-    if (filter.u.ipx.dst.net) {
+    if (filter->u.ipx.dst.net) {
       i = snprintf(p, len, " dstipxnet 0x%04x dstipxnode 0x%02x%02x%02x%02x%02x%02x",
-                 (unsigned int)ntohl(filter.u.ipx.dst.net),
-                 filter.u.ipx.dst.node[0], filter.u.ipx.dst.node[1],
-                 filter.u.ipx.dst.node[2], filter.u.ipx.dst.node[3],
-                 filter.u.ipx.dst.node[4], filter.u.ipx.dst.node[5]);
+                 (unsigned int)ntohl(filter->u.ipx.dst.net),
+                 filter->u.ipx.dst.node[0], filter->u.ipx.dst.node[1],
+                 filter->u.ipx.dst.node[2], filter->u.ipx.dst.node[3],
+                 filter->u.ipx.dst.node[4], filter->u.ipx.dst.node[5]);
       p += i;
       len -= i;
 
-      if (filter.u.ipx.dstSocComp > RAD_NO_COMPARE) {
+      if (filter->u.ipx.dstSocComp > RAD_NO_COMPARE) {
        i = snprintf(p, len, " dstipxsock %s 0x%04x",
-                    lrad_int2str(filterCompare, filter.u.ipx.dstSocComp, "??"),
-                    ntohs(filter.u.ipx.dst.socket));
+                    lrad_int2str(filterCompare, filter->u.ipx.dstSocComp, "??"),
+                    ntohs(filter->u.ipx.dst.socket));
        p += i;
        len -= i;
       }
     }
 
 
-  } else if (filter.type == RAD_FILTER_GENERIC) {
+  } else if (filter->type == RAD_FILTER_GENERIC) {
     int count;
 
-    i = snprintf(p, len, " %u ", (unsigned int) ntohs(filter.u.generic.offset));
+    i = snprintf(p, len, " %u ", (unsigned int) ntohs(filter->u.generic.offset));
     p += i;
     i -= len;
 
     /* show the mask */
-    for (count = 0; count < ntohs(filter.u.generic.len); count++) {
-      i = snprintf(p, len, "%02x", filter.u.generic.mask[count]);
+    for (count = 0; count < ntohs(filter->u.generic.len); count++) {
+      i = snprintf(p, len, "%02x", filter->u.generic.mask[count]);
       p += i;
       len -= i;
     }
@@ -1351,17 +1305,17 @@ void print_abinary(VALUE_PAIR *vp, u_char *buffer, int len)
     len--;
 
     /* show the value */
-    for (count = 0; count < ntohs(filter.u.generic.len); count++) {
-      i = snprintf(p, len, "%02x", filter.u.generic.value[count]);
+    for (count = 0; count < ntohs(filter->u.generic.len); count++) {
+      i = snprintf(p, len, "%02x", filter->u.generic.value[count]);
       p += i;
       len -= i;
     }
 
-    i = snprintf(p, len, " %s", (filter.u.generic.compNeq) ? "!=" : "==");
+    i = snprintf(p, len, " %s", (filter->u.generic.compNeq) ? "!=" : "==");
     p += i;
     len -= i;
 
-    if (filter.u.generic.more != 0) {
+    if (filter->u.generic.more != 0) {
       i = snprintf(p, len, " more");
       p += i;
       len -= i;
diff --git a/src/lib/getaddrinfo.c b/src/lib/getaddrinfo.c
new file mode 100644 (file)
index 0000000..0ad79de
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ * These functions are defined and used only if the configure 
+ * cannot detect the standard getaddrinfo(), freeaddrinfo(),
+ * gai_strerror() and getnameinfo(). This avoids sprinkling of ifdefs.
+ *
+ * FIXME: getaddrinfo() & getnameinfo() should 
+ *        return all IPv4 addresses provided by DNS lookup.
+ */
+
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include       <freeradius-devel/autoconf.h>
+
+#include       <stdio.h>
+#include       <string.h>
+#include       <stdlib.h>
+#include       <netdb.h>
+#include       <sys/types.h>
+#include       <sys/socket.h>
+#include       <netinet/in.h>
+#include       <arpa/inet.h>
+#include       <ctype.h>
+#include       <sys/param.h>
+
+#include       <freeradius-devel/missing.h>
+
+#ifdef HAVE_PTHREAD_H
+#include       <pthread.h>
+
+/* Thread safe DNS lookups */
+/* TODO There are some systems that use the same hostent structure
+    to return for gethostbyname() & gethostbyaddr(), if that is the
+    case then use only one mutex instead of seperate mutexes
+ */
+static int lrad_hostbyname = 0;
+static int lrad_hodtbyaddr = 0;
+static pthread_mutex_t lrad_hostbyname_mutex;
+static pthread_mutex_t lrad_hodtbyaddr_mutex;
+#endif
+
+#ifndef GETHOSTBYNAMERSTYLE 
+#define LOCAL_GETHOSTBYNAMERSTYLE 1
+#elif (GETHOSTBYNAMERSTYLE != SYSVSTYLE) && (GETHOSTBYNAMERSTYLE != GNUSTYLE)
+#define LOCAL_GETHOSTBYNAMERSTYLE 1
+#endif /* GETHOSTBYNAMERSTYLE */
+
+#ifndef GETHOSTBYADDRRSTYLE
+#define LOCAL_GETHOSTBYADDRR 1
+#elif (GETHOSTBYADDRRSTYLE != SYSVSTYLE) && (GETHOSTBYADDRRSTYLE != GNUSTYLE)
+#define LOCAL_GETHOSTBYADDRR 1
+#endif /* GETHOSTBYADDRRSTYLE */
+
+/*
+ * gethostbyaddr() & gethostbyname() return hostent structure
+ * To make these functions thread safe, we need to
+ * copy the data and not pointers
+ *
+ * struct hostent {
+ *    char    *h_name;        * official name of host *
+ *    char    **h_aliases;    * alias list *
+ *    int     h_addrtype;     * host address type *
+ *    int     h_length;       * length of address *
+ *    char    **h_addr_list;  * list of addresses *
+ * }
+ * This struct contains 3 pointers as members.
+ * The data from these pointers is copied into a buffer.
+ * The buffer is formatted as below to store the data
+ *  ---------------------------------------------------------------
+ * | h_name\0alias_array\0h_aliases\0..\0addr_array\0h_addr_list\0 |
+ *  ---------------------------------------------------------------
+ */
+#if (LOCAL_GETHOSTBYNAMER == 1) || (LOCAL_GETHOSTBYADDRR == 1)
+#define BUFFER_OVERFLOW 255
+int copy_hostent(struct hostent *from, struct hostent *to,
+           char *buffer, int buflen, int *error)
+{
+    int i, len;
+    char *ptr = buffer;
+    
+    *error = 0;
+    to->h_addrtype = from->h_addrtype;
+    to->h_length = from->h_length;
+    to->h_name = (char *)ptr;
+
+    /* copy hostname to buffer */
+    len=strlen(from->h_name)+1;
+    strcpy(ptr, from->h_name);
+    ptr += len;
+
+    /* copy aliases to buffer */
+    to->h_aliases = (char**)ptr;
+    for(i = 0; from->h_aliases[i]; i++);
+    ptr += (i+1) * sizeof(char *);
+
+    for(i = 0; from->h_aliases[i]; i++) {
+       len = strlen(from->h_aliases[i])+1;
+       if ((ptr-buffer)+len < buflen) {
+           to->h_aliases[i] = ptr;
+              strcpy(ptr, from->h_aliases[i]);
+           ptr += len;
+       } else {
+           *error = BUFFER_OVERFLOW;
+           return *error;
+       }
+    }
+    to->h_aliases[i] = NULL;
+
+    /* copy addr_list to buffer */
+    to->h_addr_list = (char**)ptr;
+    for(i = 0; (int *)from->h_addr_list[i] != 0; i++);
+    ptr += (i+1) * sizeof(int *);
+     
+    for(i = 0; (int *)from->h_addr_list[i] != 0; i++) {
+       len = sizeof(int);
+       if ((ptr-buffer)+len < buflen) {
+           to->h_addr_list[i] = ptr;
+           memcpy(ptr, from->h_addr_list[i], len);
+           ptr += len;
+       } else {
+           *error = BUFFER_OVERFLOW;
+            return *error;
+       }
+    }
+    to->h_addr_list[i] = 0;
+    return *error;
+}
+#endif /* (LOCAL_GETHOSTBYNAMER == 1) || (LOCAL_GETHOSTBYADDRR == 1) */
+
+#ifdef LOCAL_GETHOSTBYNAMERSTYLE
+static struct hostent *
+gethostbyname_r(const char *hostname, struct hostent *result, 
+           char *buffer, int buflen, int *error)
+{
+    struct hostent *hp;
+
+#ifdef HAVE_PTHREAD_H
+    if (lrad_hostbyname == 0) {
+       pthread_mutex_init(&lrad_hostbyname_mutex, NULL);
+       lrad_hostbyname = 1;
+    }
+    pthread_mutex_lock(&lrad_hostbyname_mutex);
+#endif
+
+    hp = gethostbyname(name);
+    if ((!hp) || (hp->h_addrtype != AF_INET) || (hp->h_length != 4)) {
+        *error = h_errno;
+         hp = NULL;
+    } else {
+         copy_hostent(hp, result, buffer, buflen, error);
+         hp = result;
+    }
+
+#ifdef HAVE_PTHREAD_H
+    pthread_mutex_unlock(&lrad_hostbyname_mutex);
+#endif
+
+    return hp;
+}
+#endif /* GETHOSTBYNAMERSTYLE */
+
+
+#ifdef LOCAL_GETHOSTBYADDRRSTYLE
+static struct hostent *
+gethostbyaddr_r(const char *addr, int len, int type, struct hostent *result,
+           char *buffer, int buflen, int *error)
+{
+    struct hostent *hp;
+
+#ifdef HAVE_PTHREAD_H
+    if (lrad_hodtbyaddr == 0) {
+       pthread_mutex_init(&lrad_hodtbyaddr_mutex, NULL);
+       lrad_hodtbyaddr = 1;
+    }
+    pthread_mutex_lock(&lrad_hodtbyaddr_mutex);
+#endif
+
+    hp = gethostbyaddr(addr, len, type);
+    if ((!hp) || (hp->h_addrtype != AF_INET) || (hp->h_length != 4)) {
+        *error = h_errno;
+         hp = NULL;
+    } else {
+        copy_hostent(hp, result, buffer, buflen, error);
+         hp = result;
+    }
+
+#ifdef HAVE_PTHREAD_H
+    pthread_mutex_unlock(&lrad_hodtbyaddr_mutex);
+#endif
+
+    return hp;
+}
+#endif /* GETHOSTBYADDRRSTYLE */
+
+/*
+ * Mar  8, 2000 by Hajimu UMEMOTO <ume@mahoroba.org>
+ *
+ * Below code is based on ssh-1.2.27-IPv6-1.5 written by
+ * KIKUCHI Takahiro <kick@kyoto.wide.ad.jp>
+ */
+
+#ifndef HAVE_GETADDRINFO
+static struct addrinfo *
+malloc_ai(int port, u_long addr, int socktype, int proto)
+{
+    struct addrinfo *ai;
+
+    ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) +
+                                   sizeof(struct sockaddr_in));
+    if (ai) {
+        memset(ai, 0, sizeof(struct addrinfo) + sizeof(struct sockaddr_in));
+        ai->ai_addr = (struct sockaddr *)(ai + 1);
+        ai->ai_addrlen = sizeof(struct sockaddr_in);
+#ifdef HAVE_SOCKADDR_SA_LEN
+        ai->ai_addr->sa_len = sizeof(struct sockaddr_in);
+#endif
+        ai->ai_addr->sa_family = ai->ai_family = AF_INET;
+        ((struct sockaddr_in *)(ai)->ai_addr)->sin_port = port;
+        ((struct sockaddr_in *)(ai)->ai_addr)->sin_addr.s_addr = addr;
+        ai->ai_socktype = socktype;
+        ai->ai_protocol = proto;
+        return ai;
+    } else {
+        return NULL;
+    }
+}
+
+char *
+gai_strerror(int ecode)
+{
+    switch (ecode) {
+    case EAI_MEMORY:
+        return "memory allocation failure.";
+    case EAI_FAMILY:
+        return "ai_family not supported.";
+    case EAI_NONAME:
+        return "hostname nor servname provided, or not known.";
+    case EAI_SERVICE:
+        return "servname not supported for ai_socktype.";
+    default:
+        return "unknown error.";
+    }
+}
+
+void
+freeaddrinfo(struct addrinfo *ai)
+{
+    struct addrinfo *next;
+
+    if (ai->ai_canonname)
+        free(ai->ai_canonname);
+    do {
+        next = ai->ai_next;
+        free(ai);
+    } while ((ai = next) != NULL);
+}
+
+int
+getaddrinfo(const char *hostname, const char *servname,
+            const struct addrinfo *hints, struct addrinfo **res)
+{
+    struct addrinfo *cur, *prev = NULL;
+    struct hostent *hp;
+    struct hostent result;
+    struct in_addr in;
+    int i, port = 0, socktype, proto;
+    int error;
+    char buffer[2048];
+
+    if (hints && hints->ai_family != PF_INET && hints->ai_family != PF_UNSPEC)
+        return EAI_FAMILY;
+
+    socktype = (hints && hints->ai_socktype) ? hints->ai_socktype
+                                             : SOCK_STREAM;
+    if (hints && hints->ai_protocol)
+        proto = hints->ai_protocol;
+    else {
+        switch (socktype) {
+        case SOCK_DGRAM:
+            proto = IPPROTO_UDP;
+            break;
+        case SOCK_STREAM:
+            proto = IPPROTO_TCP;
+            break;
+        default:
+            proto = 0;
+            break;
+        }
+    }
+    if (servname) {
+        if (isdigit((int)*servname))
+            port = htons(atoi(servname));
+        else {
+            struct servent *se;
+            char *pe_proto;
+
+            switch (socktype) {
+            case SOCK_DGRAM:
+                pe_proto = "udp";
+                break;
+            case SOCK_STREAM:
+                pe_proto = "tcp";
+                break;
+            default:
+                pe_proto = NULL;
+                break;
+            }
+            if ((se = getservbyname(servname, pe_proto)) == NULL)
+                return EAI_SERVICE;
+            port = se->s_port;
+        }
+    }
+    if (!hostname) {
+        if (hints && hints->ai_flags & AI_PASSIVE)
+            *res = malloc_ai(port, htonl(0x00000000), socktype, proto);
+        else
+            *res = malloc_ai(port, htonl(0x7f000001), socktype, proto);
+        if (*res)
+            return 0;
+        else
+            return EAI_MEMORY;
+    }
+    /* Numeric IP Address */
+    if (inet_aton(hostname, &in)) {
+        *res = malloc_ai(port, in.s_addr, socktype, proto);
+        if (*res)
+            return 0;
+        else
+            return EAI_MEMORY;
+    }
+    if (hints && hints->ai_flags & AI_NUMERICHOST)
+        return EAI_NONAME;
+
+    /* DNS Lookup */
+#ifdef GETHOSTBYNAMERSTYLE
+#if GETHOSTBYNAMERSTYLE == SYSVSTYLE
+    hp = gethostbyname_r(hostname, &result, buffer, sizeof(buffer), &error);
+#elif GETHOSTBYNAMERSTYLE == GNUSTYLE
+    if (gethostbyname_r(hostname, &result, buffer, 
+         sizeof(buffer), &hp, &error) != 0) {
+               hp = NULL;
+       }
+#else
+    hp = gethostbyname_r(hostname, &result, buffer, sizeof(buffer), &error);
+#endif
+#else
+    hp = gethostbyname_r(hostname, &result, buffer, sizeof(buffer), &error);
+#endif
+    if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
+        for (i = 0; hp->h_addr_list[i]; i++) {
+            if ((cur = malloc_ai(port,
+                                ((struct in_addr *)hp->h_addr_list[i])->s_addr,
+                                socktype, proto)) == NULL) {
+                if (*res)
+                    freeaddrinfo(*res);
+                return EAI_MEMORY;
+            }
+            if (prev)
+                prev->ai_next = cur;
+            else
+                *res = cur;
+            prev = cur;
+        }
+        if (hints && hints->ai_flags & AI_CANONNAME && *res) {
+            if (((*res)->ai_canonname = strdup(hp->h_name)) == NULL) {
+                freeaddrinfo(*res);
+                return EAI_MEMORY;
+            }
+        }
+        return 0;
+    }
+    return EAI_NONAME;
+}
+#endif /* HAVE_GETADDRINFO */
+
+
+#ifndef HAVE_GETNAMEINFO
+int
+getnameinfo(const struct sockaddr *sa, socklen_t salen, 
+               char *host, size_t hostlen, 
+               char *serv, size_t servlen, 
+               unsigned int flags)
+{
+    struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+    struct hostent *hp;
+    struct hostent result;
+    char tmpserv[16];
+    char buffer[2048];
+    int error;
+  
+    if (serv) {
+        snprintf(tmpserv, sizeof(tmpserv), "%d", ntohs(sin->sin_port));
+        if (strlen(tmpserv) > servlen)
+            return EAI_MEMORY;
+        else
+            strcpy(serv, tmpserv);
+    }
+    if (host) {
+        if (flags & NI_NUMERICHOST) {
+            /*  No Reverse DNS lookup */
+            if (flags & NI_NAMEREQD)
+                return EAI_NONAME;
+            if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen)
+                return EAI_MEMORY;
+            else {
+                strcpy(host, inet_ntoa(sin->sin_addr));
+                return 0;
+            }
+        } else {
+        /*  Reverse DNS lookup required */
+#ifdef GETHOSTBYADDRRSTYLE
+#if GETHOSTBYADDRRSTYLE == SYSVSTYLE
+            hp = gethostbyaddr_r((char *)&sin->sin_addr,
+                               sizeof(struct in_addr), AF_INET,
+                              &result, buffer, sizeof(buffer), &error);
+#elif GETHOSTBYADDRRSTYLE == GNUSTYLE
+            if (gethostbyaddr_r((char *)&sin->sin_addr,
+                               sizeof(struct in_addr), AF_INET,
+                                   &result, buffer, sizeof(buffer),
+                                   &hp, &error) != 0) {
+                       hp = NULL;
+            }
+#else
+            hp = gethostbyaddr_r((char *)&sin->sin_addr,
+                               sizeof(struct in_addr), AF_INET, 
+                              &result, buffer, sizeof(buffer), &error);
+#endif
+#else
+            hp = gethostbyaddr_r((char *)&sin->sin_addr,
+                               sizeof(struct in_addr), AF_INET,
+                              &result, buffer, sizeof(buffer), &error);
+#endif
+            if (hp)
+                if (strlen(hp->h_name) >= hostlen)
+                    return EAI_MEMORY;
+                else {
+                    strcpy(host, hp->h_name);
+                    return 0;
+                }
+            else if (flags & NI_NAMEREQD)
+                return EAI_NONAME;
+            else if (strlen(inet_ntoa(sin->sin_addr)) >= hostlen)
+                return EAI_MEMORY;
+            else {
+                strcpy(host, inet_ntoa(sin->sin_addr));
+                return 0;
+            }
+        }
+    }
+    return 0;
+}
+#endif /* HAVE_GETNAMEINFO */
index 3ec180f..381c675 100644 (file)
@@ -6,10 +6,10 @@
  *  modifications so that they're not lock-free. :(
  *
  *  However, the split-order idea allows a fast & easy splitting of the
- *  hash bucket chain when the hash table is resized.
- *
- *  This implementation can do ~10^6 lookups/s, which should be fast
- *  enough for most people.
+ *  hash bucket chain when the hash table is resized.  Without it, we'd
+ *  have to check & update the pointers for every node in the buck chain,
+ *  rather than being able to move 1/2 of the entries in the chain with
+ *  one update.
  *
  * Version:    $Id$
  *
  *   License along with this library; if not, write to the Free Software
  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- *  Copyright 2005  The FreeRADIUS server project
+ *  Copyright 2005,2006  The FreeRADIUS server project
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdlib.h>
 #include <string.h>
 
-#include "missing.h"
-#include "libradius.h"
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/hash.h>
 
 /*
  *     A reasonable number of buckets to start off with.
@@ -70,6 +71,8 @@ struct lrad_hash_table_t {
 };
 
 #ifdef TESTING
+#include <stdio.h>
+
 static int grow = 0;
 #endif
 
index 48a48ec..787b907 100644 (file)
  *   License along with this library; if not, write to the Free Software
  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
 /*
 ** Function: hmac_md5
 */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
 #include <string.h>
-#include "md5.h"
-#include "libradius.h"
+#include <freeradius-devel/md5.h>
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
 
 /*
 unsigned char*  text;                pointer to data stream
@@ -38,27 +44,27 @@ unsigned char*  digest;              caller digest to be filled in
 */
 
 void
-lrad_hmac_md5(const unsigned char *text, int text_len,
-             const unsigned char *key, int key_len,
-             unsigned char *digest)
+lrad_hmac_md5(const uint8_t *text, int text_len,
+             const uint8_t *key, int key_len,
+             uint8_t *digest)
 {
-        MD5_CTX context;
-        unsigned char k_ipad[65];    /* inner padding -
+        lrad_MD5_CTX context;
+        uint8_t k_ipad[65];    /* inner padding -
                                       * key XORd with ipad
                                       */
-        unsigned char k_opad[65];    /* outer padding -
+        uint8_t k_opad[65];    /* outer padding -
                                       * key XORd with opad
                                       */
-        unsigned char tk[16];
+        uint8_t tk[16];
         int i;
         /* if key is longer than 64 bytes reset it to key=MD5(key) */
         if (key_len > 64) {
 
-                MD5_CTX      tctx;
+               lrad_MD5_CTX      tctx;
 
-                MD5Init(&tctx);
-                MD5Update(&tctx, key, key_len);
-                MD5Final(tk, &tctx);
+                lrad_MD5Init(&tctx);
+                lrad_MD5Update(&tctx, key, key_len);
+                lrad_MD5Final(tk, &tctx);
 
                 key = tk;
                 key_len = 16;
@@ -90,20 +96,20 @@ lrad_hmac_md5(const unsigned char *text, int text_len,
         /*
          * perform inner MD5
          */
-        MD5Init(&context);                   /* init context for 1st
+        lrad_MD5Init(&context);                   /* init context for 1st
                                               * pass */
-        MD5Update(&context, k_ipad, 64);      /* start with inner pad */
-        MD5Update(&context, text, text_len); /* then text of datagram */
-        MD5Final(digest, &context);          /* finish up 1st pass */
+        lrad_MD5Update(&context, k_ipad, 64);      /* start with inner pad */
+        lrad_MD5Update(&context, text, text_len); /* then text of datagram */
+        lrad_MD5Final(digest, &context);          /* finish up 1st pass */
         /*
          * perform outer MD5
          */
-        MD5Init(&context);                   /* init context for 2nd
+        lrad_MD5Init(&context);                   /* init context for 2nd
                                               * pass */
-        MD5Update(&context, k_opad, 64);     /* start with outer pad */
-        MD5Update(&context, digest, 16);     /* then results of 1st
+        lrad_MD5Update(&context, k_opad, 64);     /* start with outer pad */
+        lrad_MD5Update(&context, digest, 16);     /* then results of 1st
                                               * hash */
-        MD5Final(digest, &context);          /* finish up 2nd pass */
+        lrad_MD5Final(digest, &context);          /* finish up 2nd pass */
 }
 
 /*
@@ -139,12 +145,11 @@ Test Vectors (Trailing '\0' of a character string not included in test):
  *  ./hmac Jefe "what do ya want for nothing?"
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 
 int main(int argc, char **argv)
 {
-  unsigned char digest[16];
+  uint8_t digest[16];
   char *key;
   int key_len;
   char *text;
index ba45a9d..639b980 100644 (file)
@@ -8,19 +8,29 @@
 ** Function: hmac_sha1
 */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <string.h>
 #include <sys/types.h>
-#include "libradius.h"
-#include "sha1.h"
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include <freeradius-devel/sha1.h>
+
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
 
 /*
-unsigned char*  text;                pointer to data stream
+uint8_t*  text;                pointer to data stream
 int             text_len;            length of data stream
-unsigned char*  key;                 pointer to authentication key
+uint8_t*  key;                 pointer to authentication key
 int             key_len;             length of authentication key
-unsigned char*  digest;              caller digest to be filled in
+uint8_t*  digest;              caller digest to be filled in
 */
 
 #ifdef HMAC_SHA1_DATA_PROBLEMS
@@ -28,18 +38,18 @@ unsigned int sha1_data_problems = 0;
 #endif
 
 void
-lrad_hmac_sha1(const unsigned char *text, int text_len,
-              const unsigned char *key, int key_len,
-              unsigned char *digest)
+lrad_hmac_sha1(const uint8_t *text, int text_len,
+              const uint8_t *key, int key_len,
+              uint8_t *digest)
 {
         SHA1_CTX context;
-        unsigned char k_ipad[65];    /* inner padding -
+        uint8_t k_ipad[65];    /* inner padding -
                                       * key XORd with ipad
                                       */
-        unsigned char k_opad[65];    /* outer padding -
+        uint8_t k_opad[65];    /* outer padding -
                                       * key XORd with opad
                                       */
-        unsigned char tk[20];
+        uint8_t tk[20];
         int i;
         /* if key is longer than 64 bytes reset it to key=SHA1(key) */
         if (key_len > 64) {
@@ -161,7 +171,7 @@ Test Vectors (Trailing '\0' of a character string not included in test):
   key =         "Jefe"
   data =        "what do ya want for nothing?"
   data_len =    28 bytes
-  digest =
+  digest =     effcdf6ae5eb2fa2d27416d5f184df9c259a7c79
 
   key =         0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 
@@ -177,17 +187,16 @@ Test Vectors (Trailing '\0' of a character string not included in test):
 
 #ifdef TESTING
 /*
- *  cc -DTESTING -I ../include/ hmac.c md5.c -o hmac
+ *  cc -DTESTING -I ../include/ hmac.c sha1.c -o hmac
  *
  *  ./hmac Jefe "what do ya want for nothing?"
  */
 
-#include <stdio.h>
 #include <stdlib.h>
 
 int main(int argc, char **argv)
 {
-  unsigned char digest[20];
+  uint8_t digest[20];
   char *key;
   int key_len;
   char *text;
index e19dc05..56ef22f 100644 (file)
@@ -10,8 +10,12 @@ MODIFIED:
 ------------------------------------------------------------------------------
 */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
 
 #define RANDSIZL   (8)  /* I recommend 8 for crypto, 4 for simulations */
 #define RANDSIZ    (1<<RANDSIZL)
index 84d54b5..ffdb666 100644 (file)
  *   License along with this library; if not, write to the Free Software
  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdarg.h>
 #include <string.h>
 
-#include "libradius.h"
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
 
 char librad_errstr[1024];
 
index 5610b42..64520d9 100644 (file)
@@ -1,18 +1,20 @@
 /*
- * md4c.c      MD4 message-digest algorithm
+ *  md4c.c     MD4 message-digest algorithm
  *
- * Version:    $Id$
+ *  Version:   $Id$
  *
- * This file is licensed under the LGPL, but is largely derived
- * from public domain source code.
+ *  This file is licensed under the LGPL, but is largely derived
+ *  from public domain source code.
  */
 
-/*#include "global.h"*/
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
 /*
  *  FORCE MD4 TO USE OUR MD4 HEADER FILE!
- *
  *  If we don't do this, it might pick up the systems broken MD4.
- *  - Paul Hampson, (cf Alan DeKok <aland@ox.org> in md5.c)
  */
 #include "../include/md4.h"
 
@@ -75,7 +77,7 @@ unsigned int inlen;                     /* length of input block */
  (((((uint32_t)x) & 0xff000000) >> 24) | \
  ((((uint32_t)x) & 0x00ff0000) >> 8) | \
  ((((uint32_t)x) & 0x0000ff00) << 8) | \
- ((((uint32_t)x) & 0x000000ff) << 24)) 
+ ((((uint32_t)x) & 0x000000ff) << 24))
 
 #define htole32_4(buf) do {                                            \
        (buf)[ 0] = htole32((buf)[ 0]);                                 \
@@ -187,7 +189,7 @@ MD4Update(MD4_CTX *ctx, const unsigned char *buf, size_t len)
 }
 
 /*
- * Final wrapup - pad to 64-byte boundary with the bit pattern 
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
  * 1 0* (64-bit count of bits processed, MSB-first)
  */
 void
index 1f2a94d..43043c4 100644 (file)
@@ -1,28 +1,33 @@
-/* MD5 message-digest algorithm */
-
-/* This file is licensed under the LGPL, but is largely derived from
- * public domain source code
+/*
+ *  md5.c      MD5 message-digest algorithm
+ *
+ *  Version:   $Id$
+ *
+ *  This file is licensed under the LGPL, but is largely derived
+ *  from public domain source code.
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
+
 /*
  *  FORCE MD5 TO USE OUR MD5 HEADER FILE!
- *
  *  If we don't do this, it might pick up the systems broken MD5.
- *  - Alan DeKok <aland@ox.org>
  */
 #include "../include/md5.h"
 
-void librad_md5_calc(unsigned char *output, unsigned char *input,
-                    unsigned int inputlen);
-
-void librad_md5_calc(unsigned char *output, unsigned char *input,
+void librad_md5_calc(uint8_t *output, const uint8_t *input,
                     unsigned int inlen)
 {
-       MD5_CTX context;
+       lrad_MD5_CTX    context;
 
-       MD5Init(&context);
-       MD5Update(&context, input, inlen);
-       MD5Final(output, &context);
+       lrad_MD5Init(&context);
+       lrad_MD5Update(&context, input, inlen);
+       lrad_MD5Final(output, &context);
 }
 
 /*     The below was retrieved from
@@ -70,7 +75,7 @@ void librad_md5_calc(unsigned char *output, unsigned char *input,
        (cp)[1] = (value) >> 8;                                         \
        (cp)[0] = (value); } while (0)
 
-static uint8_t PADDING[MD5_BLOCK_LENGTH] = {
+static const uint8_t PADDING[MD5_BLOCK_LENGTH] = {
        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
@@ -81,7 +86,7 @@ static uint8_t PADDING[MD5_BLOCK_LENGTH] = {
  * initialization constants.
  */
 void
-MD5Init(MD5_CTX *ctx)
+lrad_MD5Init(lrad_MD5_CTX *ctx)
 {
        ctx->count[0] = 0;
        ctx->count[1] = 0;
@@ -96,7 +101,7 @@ MD5Init(MD5_CTX *ctx)
  * of bytes.
  */
 void
-MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
+lrad_MD5Update(lrad_MD5_CTX *ctx, const unsigned char *input, size_t len)
 {
        size_t have, need;
 
@@ -112,12 +117,10 @@ MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
        }
        ctx->count[1] += ((uint32_t)len >> 29);
 
-       
-
        if (len >= need) {
                if (have != 0) {
                        memcpy(ctx->buffer + have, input, need);
-                       MD5Transform(ctx->state, ctx->buffer);
+                       lrad_MD5Transform(ctx->state, ctx->buffer);
                        input += need;
                        len -= need;
                        have = 0;
@@ -125,7 +128,7 @@ MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
 
                /* Process data in MD5_BLOCK_LENGTH-byte chunks. */
                while (len >= MD5_BLOCK_LENGTH) {
-                       MD5Transform(ctx->state, input);
+                       lrad_MD5Transform(ctx->state, input);
                        input += MD5_BLOCK_LENGTH;
                        len -= MD5_BLOCK_LENGTH;
                }
@@ -141,7 +144,7 @@ MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
  * 1 0* (64-bit count of bits processed, MSB-first)
  */
 void
-MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
+lrad_MD5Final(uint8_t digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
 {
        uint8_t count[8];
        size_t padlen;
@@ -155,14 +158,14 @@ MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
            ((ctx->count[0] >> 3) & (MD5_BLOCK_LENGTH - 1));
        if (padlen < 1 + 8)
                padlen += MD5_BLOCK_LENGTH;
-       MD5Update(ctx, PADDING, padlen - 8);            /* padlen - 8 <= 64 */
-       MD5Update(ctx, count, 8);
+       lrad_MD5Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */
+       lrad_MD5Update(ctx, count, 8);
 
        if (digest != NULL) {
                for (i = 0; i < 4; i++)
                        PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
        }
-       bzero(ctx, sizeof(*ctx));       /* in case it's sensitive */
+       memset(ctx, 0, sizeof(*ctx));   /* in case it's sensitive */
 }
 
 
@@ -184,7 +187,7 @@ MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
  * the data and converts bytes into longwords for this routine.
  */
 void
-MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_LENGTH])
+lrad_MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_LENGTH])
 {
        uint32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
 
index 7865d7f..8864fa0 100644 (file)
  *   License along with this library; if not, write to the Free Software
  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
-static const char rcsid[] =
-"$Id$";
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include       "autoconf.h"
+#include       <freeradius-devel/autoconf.h>
 
 #include       <stdio.h>
 #include       <sys/types.h>
@@ -39,117 +39,19 @@ static const char rcsid[] =
 #include       <fcntl.h>
 #include       <unistd.h>
 
-#include       "libradius.h"
-#include       "missing.h"
+#include       <freeradius-devel/missing.h>
+#include       <freeradius-devel/libradius.h>
 
 int            librad_dodns = 0;
 int            librad_debug = 0;
 
 
 /*
- *     Return a printable host name (or IP address in dot notation)
- *     for the supplied IP address.
- */
-char * ip_hostname(char *buf, size_t buflen, uint32_t ipaddr)
-{
-       struct          hostent *hp;
-#ifdef GETHOSTBYADDRRSTYLE
-#if (GETHOSTBYADDRRSTYLE == SYSVSTYLE) || (GETHOSTBYADDRRSTYLE == GNUSTYLE)
-       char buffer[2048];
-       struct hostent result;
-       int error;
-#endif
-#endif
-
-       /*
-        *      No DNS: don't look up host names
-        */
-       if (librad_dodns == 0) {
-               ip_ntoa(buf, ipaddr);
-               return buf;
-       }
-
-#ifdef GETHOSTBYADDRRSTYLE
-#if GETHOSTBYADDRRSTYLE == SYSVSTYLE
-       hp = gethostbyaddr_r((char *)&ipaddr, sizeof(struct in_addr), AF_INET, &result, buffer, sizeof(buffer), &error);
-#elif GETHOSTBYADDRRSTYLE == GNUSTYLE
-       if (gethostbyaddr_r((char *)&ipaddr, sizeof(struct in_addr),
-                           AF_INET, &result, buffer, sizeof(buffer),
-                           &hp, &error) != 0) {
-               hp = NULL;
-       }
-#else
-       hp = gethostbyaddr((char *)&ipaddr, sizeof(struct in_addr), AF_INET);
-#endif
-#else
-       hp = gethostbyaddr((char *)&ipaddr, sizeof(struct in_addr), AF_INET);
-#endif
-       if ((hp == NULL) ||
-           (strlen((char *)hp->h_name) >= buflen)) {
-               ip_ntoa(buf, ipaddr);
-               return buf;
-       }
-
-       strNcpy(buf, (char *)hp->h_name, buflen);
-       return buf;
-}
-
-
-/*
- *     Return an IP address from a host
- *     name or address in dot notation.
- */
-uint32_t ip_getaddr(const char *host)
-{
-       struct hostent  *hp;
-       uint32_t         a;
-#ifdef GETHOSTBYNAMERSTYLE
-#if (GETHOSTBYNAMERSTYLE == SYSVSTYLE) || (GETHOSTBYNAMERSTYLE == GNUSTYLE)
-       struct hostent result;
-       int error;
-       char buffer[2048];
-#endif
-#endif
-
-       if ((a = ip_addr(host)) != htonl(INADDR_NONE))
-               return a;
-
-#ifdef GETHOSTBYNAMERSTYLE
-#if GETHOSTBYNAMERSTYLE == SYSVSTYLE
-       hp = gethostbyname_r(host, &result, buffer, sizeof(buffer), &error);
-#elif GETHOSTBYNAMERSTYLE == GNUSTYLE
-       if (gethostbyname_r(host, &result, buffer, sizeof(buffer),
-                           &hp, &error) != 0) {
-               return htonl(INADDR_NONE);
-       }
-#else
-       hp = gethostbyname(host);
-#endif
-#else
-       hp = gethostbyname(host);
-#endif
-       if (hp == NULL) {
-               return htonl(INADDR_NONE);
-       }
-
-       /*
-        *      Paranoia from a Bind vulnerability.  An attacker
-        *      can manipulate DNS entries to change the length of the
-        *      address.  If the length isn't 4, something's wrong.
-        */
-       if (hp->h_length != 4) {
-               return htonl(INADDR_NONE);
-       }
-
-       memcpy(&a, hp->h_addr, sizeof(uint32_t));
-       return a;
-}
-
-
-/*
  *     Return an IP address in standard dot notation
+ *
+ *     FIXME: DELETE THIS
  */
-char *ip_ntoa(char *buffer, uint32_t ipaddr)
+const char *ip_ntoa(char *buffer, uint32_t ipaddr)
 {
        ipaddr = ntohl(ipaddr);
 
@@ -162,63 +64,6 @@ char *ip_ntoa(char *buffer, uint32_t ipaddr)
 }
 
 
-/*
- *     Return an IP address from
- *     one supplied in standard dot notation.
- */
-uint32_t ip_addr(const char *ip_str)
-{
-       struct in_addr  in;
-
-       if (inet_aton(ip_str, &in) == 0)
-               return htonl(INADDR_NONE);
-       return in.s_addr;
-}
-
-
-/*
- *     Like strncpy, but always adds \0
- */
-char *strNcpy(char *dest, const char *src, int n)
-{
-       char *p = dest;
-
-       while ((n > 1) && (*src)) {
-               *(p++) = *(src++);
-
-               n--;
-       }
-       *p = '\0';
-
-       return dest;
-}
-
-/*
- * Lowercase a string
- */
-void rad_lowercase(char *str) {
-       char *s;
-
-       for (s=str; *s; s++)
-               if (isupper((int) *s)) *s = tolower((int) *s);
-}
-
-/*
- * Remove spaces from a string
- */
-void rad_rmspace(char *str) {
-       char *s = str;
-       char *ptr = str;
-
-  while(ptr && *ptr!='\0') {
-    while(isspace((int) *ptr))
-      ptr++;
-    *s = *ptr;
-    ptr++;
-    s++;
-  }
-  *s = '\0';
-}
 
 /*
  *     Internal wrapper for locking, to minimize the number of ifdef's
@@ -346,87 +191,330 @@ uint8_t *ifid_aton(const char *ifid_str, uint8_t *ifid)
        }
        return ifid;
 }
+
+
+#ifndef HAVE_INET_PTON
+static int inet_pton4(const char *src, struct in_addr *dst)
+{
+       int octet;
+       unsigned int num;
+       const char *p, *off;
+       uint8_t tmp[4];
+       static const char digits[] = "0123456789";
+       
+       octet = 0;
+       p = src;
+       while (1) {
+               num = 0;
+               while (*p && ((off = strchr(digits, *p)) != NULL)) {
+                       num *= 10;
+                       num += (off - digits);
+                       
+                       if (num > 255) return 0;
+                       
+                       p++;
+               }
+               if (!*p) break;
+               
+               /*
+                *      Not a digit, MUST be a dot, else we
+                *      die.
+                */
+               if (*p != '.') {
+                       return 0;
+               }
+
+               tmp[octet++] = num;
+               p++;
+       }
+       
+       /*
+        *      End of the string.  At the fourth
+        *      octet is OK, anything else is an
+        *      error.
+        */
+       if (octet != 3) {
+               return 0;
+       }
+       tmp[3] = num;
+       
+       memcpy(dst, &tmp, sizeof(tmp));
+       return 1;
+}
+
+
+/* int
+ * inet_pton6(src, dst)
+ *     convert presentation level address to network order binary form.
+ * return:
+ *     1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ *     (1) does not touch `dst' unless it's returning 1.
+ *     (2) :: in a full address is silently ignored.
+ * credit:
+ *     inspired by Mark Andrews.
+ * author:
+ *     Paul Vixie, 1996.
+ */
+static int
+inet_pton6(const char *src, unsigned char *dst)
+{
+       static const char xdigits_l[] = "0123456789abcdef",
+                         xdigits_u[] = "0123456789ABCDEF";
+       u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
+       const char *xdigits, *curtok;
+       int ch, saw_xdigit;
+       u_int val;
+
+       memset((tp = tmp), 0, IN6ADDRSZ);
+       endp = tp + IN6ADDRSZ;
+       colonp = NULL;
+       /* Leading :: requires some special handling. */
+       if (*src == ':')
+               if (*++src != ':')
+                       return (0);
+       curtok = src;
+       saw_xdigit = 0;
+       val = 0;
+       while ((ch = *src++) != '\0') {
+               const char *pch;
+
+               if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+                       pch = strchr((xdigits = xdigits_u), ch);
+               if (pch != NULL) {
+                       val <<= 4;
+                       val |= (pch - xdigits);
+                       if (val > 0xffff)
+                               return (0);
+                       saw_xdigit = 1;
+                       continue;
+               }
+               if (ch == ':') {
+                       curtok = src;
+                       if (!saw_xdigit) {
+                               if (colonp)
+                                       return (0);
+                               colonp = tp;
+                               continue;
+                       }
+                       if (tp + INT16SZ > endp)
+                               return (0);
+                       *tp++ = (u_char) (val >> 8) & 0xff;
+                       *tp++ = (u_char) val & 0xff;
+                       saw_xdigit = 0;
+                       val = 0;
+                       continue;
+               }
+               if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
+                   inet_pton4(curtok, tp) > 0) {
+                       tp += INADDRSZ;
+                       saw_xdigit = 0;
+                       break;  /* '\0' was seen by inet_pton4(). */
+               }
+               return (0);
+       }
+       if (saw_xdigit) {
+               if (tp + INT16SZ > endp)
+                       return (0);
+               *tp++ = (u_char) (val >> 8) & 0xff;
+               *tp++ = (u_char) val & 0xff;
+       }
+       if (colonp != NULL) {
+               /*
+                * Since some memmove()'s erroneously fail to handle
+                * overlapping regions, we'll do the shift by hand.
+                */
+               const int n = tp - colonp;
+               int i;
+
+               for (i = 1; i <= n; i++) {
+                       endp[- i] = colonp[n - i];
+                       colonp[n - i] = 0;
+               }
+               tp = endp;
+       }
+       if (tp != endp)
+               return (0);
+       /* bcopy(tmp, dst, IN6ADDRSZ); */
+       memcpy(dst, tmp, IN6ADDRSZ);
+       return (1);
+}
+
 /*
- *     Return an IPv6 address in standard colon notation
+ *     Utility function, so that the rest of the server doesn't
+ *     have ifdef's around IPv6 support
  */
-const char *ipv6_ntoa(char *buffer, size_t size, void *ip6addr)
+int inet_pton(int af, const char *src, void *dst)
 {
-#if defined(HAVE_INET_NTOP) && defined(AF_INET6)
-       return inet_ntop(AF_INET6, (struct in6_addr *) ip6addr, buffer, size);
-#else
+       if (af == AF_INET) {
+               return inet_pton4(src, dst);
+       }
+
+       if (af == AF_INET6) {
+               return inet_pton6(src, dst);
+       }
+
+       return -1;
+}
+#endif
+
+
+#ifndef HAVE_INET_NTOP
+/*
+ *     Utility function, so that the rest of the server doesn't
+ *     have ifdef's around IPv6 support
+ */
+const char *inet_ntop(int af, const void *src, char *dst, size_t cnt)
+{
+       if (af == AF_INET) {
+               const uint8_t *ipaddr = src;
+
+               if (cnt <= INET_ADDRSTRLEN) return NULL;
+               
+               snprintf(dst, cnt, "%d.%d.%d.%d",
+                        ipaddr[0], ipaddr[1],
+                        ipaddr[2], ipaddr[3]);
+               return dst;
+       }
+
        /*
-        *      Do it really stupidly.
+        *      If the system doesn't define this, we define it
+        *      in missing.h
         */
-       snprintf(buffer, size, "%x:%x:%x:%x:%x:%x:%x:%x",
-                (((uint8_t *) ip6addr)[0] << 8) | ((uint8_t *) ip6addr)[1],
-                (((uint8_t *) ip6addr)[2] << 8) | ((uint8_t *) ip6addr)[3],
-                (((uint8_t *) ip6addr)[4] << 8) | ((uint8_t *) ip6addr)[5],
-                (((uint8_t *) ip6addr)[6] << 8) | ((uint8_t *) ip6addr)[7],
-                (((uint8_t *) ip6addr)[8] << 8) | ((uint8_t *) ip6addr)[9],
-                (((uint8_t *) ip6addr)[10] << 8) | ((uint8_t *) ip6addr)[11],
-                (((uint8_t *) ip6addr)[12] << 8) | ((uint8_t *) ip6addr)[13],
-                (((uint8_t *) ip6addr)[14] << 8) | ((uint8_t *) ip6addr)[15]);
-       return buffer;
-#endif
+       if (af == AF_INET6) {
+               const struct in6_addr *ipaddr = src;
+               
+               if (cnt <= INET6_ADDRSTRLEN) return NULL;
+
+               snprintf(dst, cnt, "%x:%x:%x:%x:%x:%x:%x:%x",
+                        (ipaddr->s6_addr[0] << 8) | ipaddr->s6_addr[1],
+                        (ipaddr->s6_addr[2] << 8) | ipaddr->s6_addr[3],
+                        (ipaddr->s6_addr[4] << 8) | ipaddr->s6_addr[5],
+                        (ipaddr->s6_addr[6] << 8) | ipaddr->s6_addr[7],
+                        (ipaddr->s6_addr[8] << 8) | ipaddr->s6_addr[9],
+                        (ipaddr->s6_addr[10] << 8) | ipaddr->s6_addr[11],
+                        (ipaddr->s6_addr[12] << 8) | ipaddr->s6_addr[13],
+                        (ipaddr->s6_addr[14] << 8) | ipaddr->s6_addr[15]);
+               return dst;
+       }
+
+       return NULL;            /* don't support IPv6 */
 }
+#endif
 
 
 /*
- *     Return an IPv6 address from
- *     one supplied in standard colon notation.
+ *     Wrappers for IPv4/IPv6 host to IP address lookup.
+ *     This API returns only one IP address, of the specified
+ *     address family, or the first address (of whatever family),
+ *     if AF_UNSPEC is used.
  */
-int ipv6_addr(const char *ip6_str, void *ip6addr)
+int ip_hton(const char *src, int af, lrad_ipaddr_t *dst)
 {
-#if defined(HAVE_INET_PTON) && defined(AF_INET6)
-       if (inet_pton(AF_INET6, ip6_str, (struct in6_addr *) ip6addr) != 1)
+       int error;
+       struct addrinfo hints, *ai = NULL, *res = NULL;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = af;
+
+       if ((error = getaddrinfo(src, NULL, &hints, &res)) != 0) {
+               librad_log("ip_nton: %s", gai_strerror(error));
                return -1;
-#else
+       }
+
+       for (ai = res; ai; ai = ai->ai_next) {
+               if ((af == ai->ai_family) || (af == AF_UNSPEC))
+                       break;
+       }
+
+       if (!ai) {
+               librad_log("ip_hton failed to find requested information for host %.100s", src);
+               freeaddrinfo(ai);
+               return -1;
+       }
+
+       switch (ai->ai_family) {
+       case AF_INET :
+               dst->af = AF_INET;
+               memcpy(&dst->ipaddr, 
+                      &((struct sockaddr_in*)ai->ai_addr)->sin_addr, 
+                      sizeof(struct in_addr));
+               break;
+               
+       case AF_INET6 :
+               dst->af = AF_INET6;
+               memcpy(&dst->ipaddr, 
+                      &((struct sockaddr_in6*)ai->ai_addr)->sin6_addr, 
+                      sizeof(struct in6_addr));
+               break;
+               
+               /* Flow should never reach here */
+       case AF_UNSPEC :
+       default :
+               librad_log("ip_hton found unusable information for host %.100s", src);
+               freeaddrinfo(ai);
+               return -1;
+       }
+       
+       freeaddrinfo(ai);
+       return 0;
+}
+
+/*
+ *     Look IP addreses up, and print names (depending on DNS config)
+ */
+const char *ip_ntoh(const lrad_ipaddr_t *src, char *dst, size_t cnt)
+{
+       struct sockaddr_storage ss;
+       struct sockaddr_in  *s4;
+       int error, len;
+
        /*
-        *      Copied from the 'ifid' code above, with minor edits.
+        *      No DNS lookups
         */
-       static const char xdigits[] = "0123456789abcdef";
-       const char *p, *pch;
-       int num_id = 0, val = 0, idx = 0;
-       uint8_t *addr = ip6addr;
+       if (!librad_dodns) {
+               return inet_ntop(src->af, &(src->ipaddr), dst, cnt);
+       }
 
-       for (p = ip6_str; ; ++p) {
-               if (*p == ':' || *p == '\0') {
-                       if (num_id <= 0)
-                               return -1;
 
-                       /*
-                        *      Drop 'val' into the array.
-                        */
-                       addr[idx] = (val >> 8) & 0xff;
-                       addr[idx + 1] = val & 0xff;
-                       if (*p == '\0') {
-                               /*
-                                *      Must have all entries before
-                                *      end of the string.
-                                */
-                               if (idx != 14)
-                                       return -1;
-                               break;
-                       }
-                       val = 0;
-                       num_id = 0;
-                       if ((idx += 2) > 14)
-                               return -1;
-               } else if ((pch = strchr(xdigits, tolower(*p))) != NULL) {
-                       if (++num_id > 8) /* no more than 8 16-bit numbers */
-                               return -1;
-                       /*
-                        *      Dumb version of 'scanf'
-                        */
-                       val <<= 4;
-                       val |= (pch - xdigits);
-               } else
-                       return -1;
-       }
+       memset(&ss, 0, sizeof(ss));
+        switch (src->af) {
+        case AF_INET :
+                s4 = (struct sockaddr_in *)&ss;
+                len    = sizeof(struct sockaddr_in);
+                s4->sin_family = AF_INET;
+                s4->sin_port = 0;
+                memcpy(&s4->sin_addr, &src->ipaddr.ip4addr, 4);
+                break;
+
+#ifdef HAVE_STRUCT_SOCKADDR_IN6
+        case AF_INET6 :
+               {
+               struct sockaddr_in6 *s6;
+
+                s6 = (struct sockaddr_in6 *)&ss;
+                len    = sizeof(struct sockaddr_in6);
+                s6->sin6_family = AF_INET6;
+                s6->sin6_flowinfo = 0;
+                s6->sin6_port = 0;
+                memcpy(&s6->sin6_addr, &src->ipaddr.ip6addr, 16);
+                break;
+               }
 #endif
-       return 0;
+
+        default :
+                return NULL;
+        }
+
+       if ((error = getnameinfo((struct sockaddr *)&ss, len, dst, cnt, NULL, 0,
+                                NI_NUMERICHOST | NI_NUMERICSERV)) != 0) {
+               librad_log("ip_ntoh: %s", gai_strerror(error));
+               return NULL;
+       }
+       return dst;
 }
 
+
 static const char *hextab = "0123456789abcdef";
 
 /*
@@ -469,6 +557,7 @@ void lrad_bin2hex(const uint8_t *bin, char *hex, int len)
        return;
 }
 
+
 /*
  *     So we don't have ifdef's in the rest of the code
  */
index 4ea562e..b07f35b 100644 (file)
  *   License along with this library; if not, write to the Free Software
  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
-static const char rcsid[] = "$Id$";
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include       "autoconf.h"
+#include       <freeradius-devel/autoconf.h>
 
 #include       <stdio.h>
 #include       <stdlib.h>
@@ -33,8 +34,8 @@ static const char rcsid[] = "$Id$";
 #include       <arpa/inet.h>
 #include       <ctype.h>
 
-#include       "libradius.h"
-#include       "missing.h"
+#include       <freeradius-devel/missing.h>
+#include       <freeradius-devel/libradius.h>
 
 #ifndef HAVE_CRYPT
 char *crypt(char *key, char *salt)
diff --git a/src/lib/packet.c b/src/lib/packet.c
new file mode 100644 (file)
index 0000000..105c45c
--- /dev/null
@@ -0,0 +1,849 @@
+/*
+ * packet.c    Generic packet manipulation functions.
+ *
+ * Version:    $Id$
+ *
+ *   This library is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU Lesser General Public
+ *   License as published by the Free Software Foundation; either
+ *   version 2.1 of the License, or (at your option) any later version.
+ *
+ *   This library 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
+ *   Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2000-2006  The FreeRADIUS server project
+ */
+
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include       <freeradius-devel/autoconf.h>
+#include       <freeradius-devel/missing.h>
+#include       <freeradius-devel/libradius.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+
+/*
+ *     Take the key fields of a request packet, and convert it to a
+ *     hash.
+ */
+uint32_t lrad_request_packet_hash(const RADIUS_PACKET *packet)
+{
+       uint32_t hash;
+
+       if (packet->hash) return packet->hash;
+
+       hash = lrad_hash(&packet->sockfd, sizeof(packet->sockfd));
+       hash = lrad_hash_update(&packet->id, sizeof(packet->id), hash);
+       hash = lrad_hash_update(&packet->src_port, sizeof(packet->src_port),
+                               hash);
+       hash = lrad_hash_update(&packet->dst_port,
+                               sizeof(packet->dst_port), hash);
+       hash = lrad_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 = lrad_hash_update(&packet->src_ipaddr.ipaddr.ip4addr,
+                                       sizeof(packet->src_ipaddr.ipaddr.ip4addr),
+                                       hash);
+               hash = lrad_hash_update(&packet->dst_ipaddr.ipaddr.ip4addr,
+                                       sizeof(packet->dst_ipaddr.ipaddr.ip4addr),
+                                       hash);
+               break;
+       case AF_INET6:
+               hash = lrad_hash_update(&packet->src_ipaddr.ipaddr.ip6addr,
+                                       sizeof(packet->src_ipaddr.ipaddr.ip6addr),
+                                       hash);
+               hash = lrad_hash_update(&packet->dst_ipaddr.ipaddr.ip6addr,
+                                       sizeof(packet->dst_ipaddr.ipaddr.ip6addr),
+                                       hash);
+               break;
+       default:
+               break;
+       }
+
+       return lrad_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 lrad_reply_packet_hash(const RADIUS_PACKET *packet)
+{
+       uint32_t hash;
+       
+       hash = lrad_hash(&packet->sockfd, sizeof(packet->sockfd));
+       hash = lrad_hash_update(&packet->id, sizeof(packet->id), hash);
+       hash = lrad_hash_update(&packet->src_port, sizeof(packet->src_port),
+                               hash);
+       hash = lrad_hash_update(&packet->dst_port,
+                               sizeof(packet->dst_port), hash);
+       hash = lrad_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 = lrad_hash_update(&packet->dst_ipaddr.ipaddr.ip4addr,
+                                       sizeof(packet->dst_ipaddr.ipaddr.ip4addr),
+                                       hash);
+               hash = lrad_hash_update(&packet->src_ipaddr.ipaddr.ip4addr,
+                                       sizeof(packet->src_ipaddr.ipaddr.ip4addr),
+                                       hash);
+               break;
+       case AF_INET6:
+               hash = lrad_hash_update(&packet->dst_ipaddr.ipaddr.ip6addr,
+                                       sizeof(packet->dst_ipaddr.ipaddr.ip6addr),
+                                       hash);
+               hash = lrad_hash_update(&packet->src_ipaddr.ipaddr.ip6addr,
+                                       sizeof(packet->src_ipaddr.ipaddr.ip6addr),
+                                       hash);
+               break;
+       default:
+               break;
+       }
+
+       return lrad_hash_update(&packet->id, sizeof(packet->id), hash);
+}
+
+
+static int lrad_ipaddr_cmp(const lrad_ipaddr_t *a, const lrad_ipaddr_t *b)
+{
+       if (a->af < b->af) return -1;
+       if (a->af > b->af) return +1;
+
+       switch (a->af) {
+       case AF_INET:
+               return memcmp(&a->ipaddr.ip4addr,
+                             &b->ipaddr.ip4addr,
+                             sizeof(a->ipaddr.ip4addr));
+               break;
+       case AF_INET6:
+               return memcmp(&a->ipaddr.ip6addr,
+                             &b->ipaddr.ip6addr,
+                             sizeof(a->ipaddr.ip6addr));
+               break;
+       default:
+               break;
+       }
+       
+       return -1;
+}
+
+
+/*
+ *     See if two packets are identical.
+ *
+ *     Note that we do NOT compare the authentication vectors.
+ *     That's because if the authentication vector is different,
+ *     it means that the NAS has given up on the earlier request.
+ */
+int lrad_packet_cmp(const RADIUS_PACKET *a, const RADIUS_PACKET *b)
+{
+       int rcode;
+
+       if (a->sockfd < b->sockfd) return -1;
+       if (a->sockfd > b->sockfd) return +1;
+
+       if (a->id < b->id) return -1;
+       if (a->id > b->id) return +1;
+
+       if (a->src_port < b->src_port) return -1;
+       if (a->src_port > b->src_port) return +1;
+
+       if (a->dst_port < b->dst_port) return -1;
+       if (a->dst_port > b->dst_port) return +1;
+
+       rcode = lrad_ipaddr_cmp(&a->dst_ipaddr, &b->dst_ipaddr);
+       if (rcode != 0) return rcode;
+       return lrad_ipaddr_cmp(&a->src_ipaddr, &b->src_ipaddr);
+}
+
+
+/*
+ *     Create a fake "request" from a reply, for later lookup.
+ */
+void lrad_request_from_reply(RADIUS_PACKET *request,
+                            const RADIUS_PACKET *reply)
+{
+       request->sockfd = reply->sockfd;
+       request->id = reply->id;
+       request->src_port = reply->dst_port;
+       request->dst_port = reply->src_port;
+       request->src_ipaddr = reply->dst_ipaddr;
+       request->dst_ipaddr = reply->src_ipaddr;
+}
+
+
+/*
+ *     Open a socket on the given IP and port.
+ */
+int lrad_socket(lrad_ipaddr_t *ipaddr, int port)
+{
+       int sockfd;
+       struct sockaddr_storage salocal;
+       socklen_t       salen;
+
+       if ((port < 0) || (port > 65535)) {
+               librad_log("Port %d is out of allowed bounds", port);
+               return -1;
+       }
+
+       sockfd = socket(ipaddr->af, SOCK_DGRAM, 0);
+       if (sockfd < 0) {
+               return sockfd;
+       }
+
+#ifdef WITH_UDPFROMTO
+       /*
+        *      Initialize udpfromto for all sockets.
+        */
+       if (udpfromto_init(sockfd) != 0) {
+               close(sockfd);
+               return -1;
+       }
+#endif
+
+       memset(&salocal, 0, sizeof(salocal));
+       if (ipaddr->af == AF_INET) {
+               struct sockaddr_in *sa;
+               
+               sa = (struct sockaddr_in *) &salocal;
+               sa->sin_family = AF_INET;
+               sa->sin_addr = ipaddr->ipaddr.ip4addr;
+               sa->sin_port = htons((uint16_t) port);
+               salen = sizeof(*sa);
+               
+#ifdef HAVE_STRUCT_SOCKADDR_IN6
+       } else if (ipaddr->af == AF_INET6) {
+               struct sockaddr_in6 *sa;
+               
+               sa = (struct sockaddr_in6 *) &salocal;
+               sa->sin6_family = AF_INET6;
+               sa->sin6_addr = ipaddr->ipaddr.ip6addr;
+               sa->sin6_port = htons((uint16_t) port);
+               salen = sizeof(*sa);
+
+#if 1
+               /*
+                *      Listening on '::' does NOT get you IPv4 to
+                *      IPv6 mapping.  You've got to listen on an IPv4
+                *      address, too.  This makes the rest of the server
+                *      design a little simpler.
+                */
+#ifdef IPV6_V6ONLY
+
+               if (IN6_IS_ADDR_UNSPECIFIED(&ipaddr->ipaddr.ip6addr)) {
+                       int on = 1;
+                       
+                       setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY,
+                                  (char *)&on, sizeof(on));
+               }
+#endif /* IPV6_V6ONLY */
+#endif
+#endif /* HAVE_STRUCT_SOCKADDR_IN6 */
+       } else {
+               return sockfd;  /* don't bind it */
+       }
+
+       if (bind(sockfd, (struct sockaddr *) &salocal, salen) < 0) {
+               close(sockfd);
+               return -1;
+       }
+
+       return sockfd;
+}
+
+
+/*
+ *     We need to keep track of the socket & it's IP/port.
+ */
+typedef struct lrad_packet_socket_t {
+       int             sockfd;
+
+       int             num_outgoing;
+
+       int             offset; /* 0..31 */
+       int             inaddr_any;
+       lrad_ipaddr_t   ipaddr;
+       int             port;
+} lrad_packet_socket_t;
+
+
+#define FNV_MAGIC_PRIME (0x01000193)
+#define MAX_SOCKETS (32)
+#define SOCKOFFSET_MASK (MAX_SOCKETS - 1)
+#define SOCK2OFFSET(sockfd) ((sockfd * FNV_MAGIC_PRIME) & SOCKOFFSET_MASK)
+
+#define MAX_QUEUES (8)
+
+/*
+ *     Structure defining a list of packets (incoming or outgoing)
+ *     that should be managed.
+ */
+struct lrad_packet_list_t {
+       lrad_hash_table_t *ht;
+
+       lrad_hash_table_t *dst2id_ht;
+
+       int             alloc_id;
+       int             num_outgoing;
+
+       uint32_t mask;
+       int last_recv;
+       lrad_packet_socket_t sockets[MAX_SOCKETS];
+};
+
+
+/*
+ *     Ugh.  Doing this on every sent/received packet is not nice.
+ */
+static lrad_packet_socket_t *lrad_socket_find(lrad_packet_list_t *pl,
+                                            int sockfd)
+{
+       int i, start;
+
+       i = start = SOCK2OFFSET(sockfd);
+
+       do {                    /* make this hack slightly more efficient */
+               if (pl->sockets[i].sockfd == sockfd) return &pl->sockets[i];
+
+               i = (i + 1) & SOCKOFFSET_MASK;
+       } while (i != start);
+
+       return NULL;
+}
+
+int lrad_packet_list_socket_remove(lrad_packet_list_t *pl, int sockfd)
+{
+       lrad_packet_socket_t *ps;
+
+       if (!pl) return 0;
+
+       ps = lrad_socket_find(pl, sockfd);
+       if (!ps) return 0;
+
+       /*
+        *      FIXME: Allow the caller forcibly discard these?
+        */
+       if (ps->num_outgoing != 0) return 0;
+
+       ps->sockfd = -1;
+       pl->mask &= ~(1 << ps->offset);
+
+
+       return 1;
+}
+
+int lrad_packet_list_socket_add(lrad_packet_list_t *pl, int sockfd)
+{
+       int i, start;
+       struct sockaddr_storage src;
+       socklen_t               sizeof_src = sizeof(src);
+       lrad_packet_socket_t    *ps;
+
+       if (!pl) return 0;
+
+       ps = NULL;
+       i = start = SOCK2OFFSET(sockfd);
+
+       do {
+               if (pl->sockets[i].sockfd == -1) {
+                       ps =  &pl->sockets[i];
+                       start = i;
+                       break;
+               }
+
+               i = (i + 1) & SOCKOFFSET_MASK;
+       } while (i != start);
+
+       if (!ps) {
+               return 0;
+       }
+
+       memset(ps, 0, sizeof(*ps));
+       ps->sockfd = sockfd;
+       ps->offset = start;
+
+       /*
+        *      Get address family, etc. first, so we know if we
+        *      need to do udpfromto.
+        *
+        *      FIXME: udpfromto also does this, but it's not
+        *      a critical problem.
+        */
+       memset(&src, 0, sizeof_src);
+       if (getsockname(sockfd, (struct sockaddr *) &src,
+                       &sizeof_src) < 0) {
+               return 0;
+       }
+
+       /*
+        *      Grab IP addresses & ports from the sockaddr.
+        */
+       ps->ipaddr.af = src.ss_family;
+       if (src.ss_family == AF_INET) {
+               struct sockaddr_in      *s4;
+
+               s4 = (struct sockaddr_in *)&src;
+               ps->ipaddr.ipaddr.ip4addr = s4->sin_addr;
+               ps->port = ntohs(s4->sin_port);
+
+               if (ps->ipaddr.ipaddr.ip4addr.s_addr == INADDR_ANY) {
+                       ps->inaddr_any = 1;
+               }
+
+#ifdef HAVE_STRUCT_SOCKADDR_IN6
+       } else if (src.ss_family == AF_INET6) {
+               struct sockaddr_in6     *s6;
+
+               s6 = (struct sockaddr_in6 *)&src;
+               ps->ipaddr.ipaddr.ip6addr = s6->sin6_addr;
+               ps->port = ntohs(s6->sin6_port);
+
+               if (IN6_IS_ADDR_UNSPECIFIED(&ps->ipaddr.ipaddr.ip6addr)) {
+                       ps->inaddr_any = 1;
+               }
+#endif
+       } else {
+               return 0;
+       }
+
+       pl->mask |= (1 << ps->offset);
+       return 1;
+}
+
+static uint32_t packet_entry_hash(const void *data)
+{
+       return lrad_request_packet_hash(*(const RADIUS_PACKET * const *) data);
+}
+
+static int packet_entry_cmp(const void *one, const void *two)
+{
+       const RADIUS_PACKET * const *a = one;
+       const RADIUS_PACKET * const *b = two;
+
+       return lrad_packet_cmp(*a, *b);
+}
+
+/*
+ *     A particular socket can have 256 RADIUS ID's outstanding to
+ *     any one destination IP/port.  So we have a structure that
+ *     manages destination IP & port, and has an array of 256 ID's.
+ *
+ *     The only magic here is that we map the socket number (0..256)
+ *     into an "internal" socket number 0..31, that we use to set
+ *     bits in the ID array.  If a bit is 1, then that ID is in use
+ *     for that socket, and the request MUST be in the packet hash!
+ *
+ *     Note that as a minor memory leak, we don't have an API to free
+ *     this structure, except when we discard the whole packet list.
+ *     This means that if destinations are added and removed, they
+ *     won't be removed from this tree.
+ */
+typedef struct lrad_packet_dst2id_t {
+       lrad_ipaddr_t   dst_ipaddr;
+       int             dst_port;
+       uint32_t        id[1];  /* really id[256] */
+} lrad_packet_dst2id_t;
+
+
+static uint32_t packet_dst2id_hash(const void *data)
+{
+       uint32_t hash;
+       const lrad_packet_dst2id_t *pd = data;
+
+       hash = lrad_hash(&pd->dst_port, sizeof(pd->dst_port));
+       
+       switch (pd->dst_ipaddr.af) {
+       case AF_INET:
+               hash = lrad_hash_update(&pd->dst_ipaddr.ipaddr.ip4addr,
+                                       sizeof(pd->dst_ipaddr.ipaddr.ip4addr),
+                                       hash);
+               break;
+       case AF_INET6:
+               hash = lrad_hash_update(&pd->dst_ipaddr.ipaddr.ip6addr,
+                                       sizeof(pd->dst_ipaddr.ipaddr.ip6addr),
+                                       hash);
+               break;
+       default:
+               break;
+       }
+
+       return hash;
+}
+
+static int packet_dst2id_cmp(const void *one, const void *two)
+{
+       const lrad_packet_dst2id_t *a = one;
+       const lrad_packet_dst2id_t *b = two;
+
+       if (a->dst_port < b->dst_port) return -1;
+       if (a->dst_port > b->dst_port) return +1;
+
+       return lrad_ipaddr_cmp(&a->dst_ipaddr, &b->dst_ipaddr);
+}
+
+static void packet_dst2id_free(void *data)
+{
+       free(data);
+}
+
+
+void lrad_packet_list_free(lrad_packet_list_t *pl)
+{
+       if (!pl) return;
+
+       lrad_hash_table_free(pl->ht);
+       lrad_hash_table_free(pl->dst2id_ht);
+       free(pl);
+}
+
+
+/*
+ *     Caller is responsible for managing the packet entries.
+ */
+lrad_packet_list_t *lrad_packet_list_create(int alloc_id)
+{
+       int i;
+       lrad_packet_list_t      *pl;
+
+       pl = malloc(sizeof(*pl));
+       if (!pl) return NULL;
+       memset(pl, 0, sizeof(*pl));
+
+       pl->ht = lrad_hash_table_create(packet_entry_hash,
+                                       packet_entry_cmp,
+                                       NULL);
+       if (!pl->ht) {
+               lrad_packet_list_free(pl);
+               return NULL;
+       }
+
+       for (i = 0; i < MAX_SOCKETS; i++) {
+               pl->sockets[i].sockfd = -1;
+       }
+
+       if (alloc_id) {
+               pl->alloc_id = 1;
+
+               pl->dst2id_ht = lrad_hash_table_create(packet_dst2id_hash,
+                                                      packet_dst2id_cmp,
+                                                      packet_dst2id_free);
+               if (!pl->dst2id_ht) {
+                       lrad_packet_list_free(pl);
+                       return NULL;
+               }
+       }
+
+       return pl;
+}
+
+
+/*
+ *     If pl->alloc_id is set, then lrad_packet_list_id_alloc() MUST
+ *     be called before inserting the packet into the list!
+ */
+int lrad_packet_list_insert(lrad_packet_list_t *pl,
+                           RADIUS_PACKET **request_p)
+{
+       if (!pl || !request_p || !*request_p) return 0;
+
+       (*request_p)->hash = lrad_request_packet_hash(*request_p);
+
+       return lrad_hash_table_insert(pl->ht, request_p);
+}
+
+RADIUS_PACKET **lrad_packet_list_find(lrad_packet_list_t *pl,
+                                     RADIUS_PACKET *request)
+{
+       if (!pl || !request) return 0;
+
+       return lrad_hash_table_finddata(pl->ht, &request);
+}
+
+
+/*
+ *     This presumes that the reply has dst_ipaddr && dst_port set up
+ *     correctly (i.e. real IP, or "*").
+ */
+RADIUS_PACKET **lrad_packet_list_find_byreply(lrad_packet_list_t *pl,
+                                             RADIUS_PACKET *reply)
+{
+       RADIUS_PACKET my_request, *request;
+       lrad_packet_socket_t *ps;
+
+       if (!pl || !reply) return NULL;
+
+       ps = lrad_socket_find(pl, reply->sockfd);
+       if (!ps) return NULL;
+
+       /*
+        *      Initialize request from reply, AND from the source
+        *      IP & port of this socket.  The client may have bound
+        *      the socket to 0, in which case it's some random port,
+        *      that is NOT in the original request->src_port.
+        */
+       my_request.sockfd = reply->sockfd;
+       my_request.id = reply->id;
+
+       if (ps->inaddr_any) {
+               my_request.src_ipaddr = ps->ipaddr;
+       } else {
+               my_request.src_ipaddr = reply->dst_ipaddr;
+       }
+       my_request.src_port = ps->port;;
+
+       my_request.dst_ipaddr = reply->src_ipaddr;
+       my_request.dst_port = reply->src_port;
+       my_request.hash = 0;
+       
+       request = &my_request;
+
+       return lrad_hash_table_finddata(pl->ht, &request);
+}
+
+
+RADIUS_PACKET **lrad_packet_list_yank(lrad_packet_list_t *pl,
+                                     RADIUS_PACKET *request)
+{
+       if (!pl || !request) return NULL;
+
+       return lrad_hash_table_yank(pl->ht, &request);
+}
+
+int lrad_packet_list_num_elements(lrad_packet_list_t *pl)
+{
+       if (!pl) return 0;
+
+       return lrad_hash_table_num_elements(pl->ht);
+}
+
+
+/*
+ *     1 == ID was allocated & assigned
+ *     0 == error allocating memory
+ *     -1 == all ID's are used, caller should open a new socket.
+ *
+ *     Note that this ALSO assigns a socket to use, and updates
+ *     packet->request->src_ipaddr && packet->request->src_port
+ *
+ *     In multi-threaded systems, the calls to id_alloc && id_free
+ *     should be protected by a mutex.  This does NOT have to be
+ *     the same mutex as the one protecting the insert/find/yank
+ *     calls!
+ */
+int lrad_packet_list_id_alloc(lrad_packet_list_t *pl,
+                             RADIUS_PACKET *request)
+{
+       int i, id, start;
+       uint32_t free_mask;
+       lrad_packet_dst2id_t my_pd, *pd;
+       lrad_packet_socket_t *ps;
+       
+       if (!pl || !pl->alloc_id || !request) return 0;
+
+       my_pd.dst_ipaddr = request->dst_ipaddr;
+       my_pd.dst_port = request->dst_port;
+       
+       pd = lrad_hash_table_finddata(pl->dst2id_ht, &my_pd);
+       if (!pd) {
+               pd = malloc(sizeof(*pd) + 255 * sizeof(pd->id[0]));
+               if (!pd) return 0;
+
+               memset(pd, 0, sizeof(*pd) + 255 * sizeof(pd->id[0]));
+
+               pd->dst_ipaddr = request->dst_ipaddr;
+               pd->dst_port = request->dst_port;
+
+               if (!lrad_hash_table_insert(pl->dst2id_ht, pd)) {
+                       free(pd);
+                       return 0;
+               }
+       }
+       
+       /*
+        *      FIXME: Go to an LRU system.  This prevents ID re-use
+        *      for as long as possible.  The main problem with that
+        *      approach is that it requires us to populate the
+        *      LRU/FIFO when we add a new socket, or a new destination,
+        *      which can be expensive.
+        *
+        *      The LRU can be avoided if the caller takes care to free
+        *      Id's only when all responses have been received, OR after
+        *      a timeout.
+        */
+       id = start = (int) lrad_rand() & 0xff;
+
+       while (pd->id[id] == pl->mask) { /* all sockets are using this ID */
+               id++;
+               id &= 0xff;
+               if (id == start) return 0;
+       }
+
+       free_mask = ~((~pd->id[id]) & pl->mask);
+
+       start = -1;
+       for (i = 0; i < MAX_SOCKETS; i++) {
+               if (pl->sockets[i].sockfd == -1) continue; /* paranoia */
+
+               if ((free_mask & (1 << i)) == 0) {
+                       start = i;
+                       break;
+               }
+       }
+
+       if (start < 0) return 0; /* bad error */
+
+       pd->id[id] |= (1 << start);
+       ps = &pl->sockets[start];
+
+       ps->num_outgoing++;
+       pl->num_outgoing++;
+
+       /*
+        *      Set the ID, source IP, and source port.
+        */
+       request->id = id;
+
+       request->sockfd = ps->sockfd;
+       request->src_ipaddr = ps->ipaddr;
+       request->src_port = ps->port;
+
+       return 1;
+}
+
+/*
+ *     Should be called AFTER yanking it from the list, so that
+ *     any newly inserted entries don't collide with this one.
+ */
+int lrad_packet_list_id_free(lrad_packet_list_t *pl,
+                            RADIUS_PACKET *request)
+{
+       lrad_packet_socket_t *ps;
+       lrad_packet_dst2id_t my_pd, *pd;
+
+       if (!pl || !request) return 0;
+
+       ps = lrad_socket_find(pl, request->sockfd);
+       if (!ps) return 0;
+
+       my_pd.dst_ipaddr = request->dst_ipaddr;
+       my_pd.dst_port = request->dst_port;
+       
+       pd = lrad_hash_table_finddata(pl->dst2id_ht, &my_pd);
+       if (!pd) return 0;
+
+       pd->id[request->id] &= ~(1 << ps->offset);
+       request->hash = 0;      /* invalidate the cached hash */
+
+       ps->num_outgoing--;
+       pl->num_outgoing--;
+
+       return 1;
+}
+
+int lrad_packet_list_walk(lrad_packet_list_t *pl, void *ctx,
+                         lrad_hash_table_walk_t callback)
+{
+       if (!pl || !callback) return 0;
+
+       return lrad_hash_table_walk(pl->ht, callback, ctx);
+}
+
+int lrad_packet_list_fd_set(lrad_packet_list_t *pl, fd_set *set)
+{
+       int i, maxfd;
+
+       if (!pl || !set) return 0;
+
+       maxfd = -1;
+
+       for (i = 0; i < MAX_SOCKETS; i++) {
+               if (pl->sockets[i].sockfd == -1) continue;
+               FD_SET(pl->sockets[i].sockfd, set);
+               if (pl->sockets[i].sockfd > maxfd) {
+                       maxfd = pl->sockets[i].sockfd;
+               }
+       }
+
+       if (maxfd < 0) return -1;
+
+       return maxfd + 1;
+}
+
+/*
+ *     Round-robins the receivers, without priority.
+ *
+ *     FIXME: Add sockfd, if -1, do round-robin, else do sockfd
+ *             IF in fdset.
+ */
+RADIUS_PACKET *lrad_packet_list_recv(lrad_packet_list_t *pl, fd_set *set)
+{
+       int start;
+       RADIUS_PACKET *packet;
+
+       if (!pl || !set) return NULL;
+
+       start = pl->last_recv;
+       do {
+               start++;
+               start &= SOCKOFFSET_MASK;
+
+               if (pl->sockets[start].sockfd == -1) continue;
+
+               if (!FD_ISSET(pl->sockets[start].sockfd, set)) continue;
+
+               packet = rad_recv(pl->sockets[start].sockfd);
+               if (!packet) continue;
+
+               /*
+                *      Call lrad_packet_list_find_byreply().  If it
+                *      doesn't find anything, discard the reply.
+                */
+
+               pl->last_recv = start;
+               return packet;
+       } while (start != pl->last_recv);
+
+       return NULL;
+}
+
+int lrad_packet_list_num_incoming(lrad_packet_list_t *pl)
+{
+       int num_elements;
+
+       if (!pl) return 0;
+
+       num_elements = lrad_hash_table_num_elements(pl->ht);
+       if (num_elements < pl->num_outgoing) return 0; /* panic! */
+
+       return num_elements - pl->num_outgoing;
+}
+
+int lrad_packet_list_num_outgoing(lrad_packet_list_t *pl)
+{
+       if (!pl) return 0;
+
+       return pl->num_outgoing;
+}
index 54959e1..be6e39e 100644 (file)
  *   License along with this library; if not, write to the Free Software
  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
-static const char rcsid[] = "$Id$";
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include       "autoconf.h"
+#include       <freeradius-devel/autoconf.h>
 
 #include       <stdio.h>
 #include       <stdlib.h>
@@ -30,7 +31,8 @@ static const char rcsid[] = "$Id$";
 #include       <ctype.h>
 #include       <string.h>
 
-#include       "libradius.h"
+#include       <freeradius-devel/missing.h>
+#include       <freeradius-devel/libradius.h>
 
 /*
  *     Convert a string to something printable.
@@ -69,8 +71,11 @@ void librad_safeprint(char *in, int inlen, char *out, int outlen)
                        case '\t':
                                sp = 't';
                                break;
+                       case '"':
+                               sp = '"';
+                               break;
                        default:
-                               if (*str < 32 || (*str >= 128)){
+                         if (*str < 32 || (*str >= 128)){
                                        snprintf(out, outlen, "\\%03o", *str);
                                        done += 4;
                                        out  += 4;
@@ -101,41 +106,39 @@ int vp_prints_value(char * out, int outlen, VALUE_PAIR *vp, int delimitst)
 {
        DICT_VALUE  *v;
        char        buf[1024];
-       char        *a;
+       const char  *a = NULL;
+       size_t      len;
        time_t      t;
        struct tm   s_tm;
 
-       out[0] = 0;
+       out[0] = '\0';
        if (!vp) return 0;
 
        switch (vp->type) {
                case PW_TYPE_STRING:
-                       /*
-                        *  NAS-Port may have multiple integer values?
-                        *  This is an internal server extension...
-                        */
-                       if (vp->attribute == PW_NAS_PORT)
-                               a = (char *)vp->strvalue;
-                       else {
-                               if (delimitst && vp->flags.has_tag) {
-                                       /* Tagged attribute: print delimter and ignore tag */
-                                       buf[0] = '"';
-                                       librad_safeprint((char *)(vp->strvalue),
-                                                        vp->length, buf + 1, sizeof(buf) - 2);
-                                       strcat(buf, "\"");
-                               } else if (delimitst) {
-                                       /* Non-tagged attribute: print delimter */
-                                       buf[0] = '"';
-                                       librad_safeprint((char *)vp->strvalue,
-                                                        vp->length, buf + 1, sizeof(buf) - 2);
-                                       strcat(buf, "\"");
-                               } else {
-                                       /* Non-tagged attribute: no delimiter */
-                                       librad_safeprint((char *)vp->strvalue,
-                                                        vp->length, buf, sizeof(buf));
-                               }
-                               a = buf;
+                       if ((delimitst == 1) && vp->flags.has_tag) {
+                               /* Tagged attribute: print delimter and ignore tag */
+                               buf[0] = '"';
+                               librad_safeprint((char *)(vp->vp_strvalue),
+                                                vp->length, buf + 1, sizeof(buf) - 2);
+                               strcat(buf, "\"");
+                       } else if (delimitst == 1) {
+                               /* Non-tagged attribute: print delimter */
+                               buf[0] = '"';
+                               librad_safeprint((char *)vp->vp_strvalue,
+                                                vp->length, buf + 1, sizeof(buf) - 2);
+                               strcat(buf, "\"");
+
+                       } else if (delimitst < 0) {
+                               strlcpy(out, vp->vp_strvalue, outlen);
+                               return strlen(out);
+
+                       } else {
+                               /* Non-tagged attribute: no delimiter */
+                               librad_safeprint((char *)vp->vp_strvalue,
+                                                vp->length, buf, sizeof(buf));
                        }
+                       a = buf;
                        break;
                case PW_TYPE_INTEGER:
                        if ( vp->flags.has_tag ) {
@@ -148,6 +151,8 @@ int vp_prints_value(char * out, int outlen, VALUE_PAIR *vp, int delimitst)
                                        a = buf;
                                }
                        } else {
+                       case PW_TYPE_BYTE:
+                       case PW_TYPE_SHORT:
                                /* Normal, non-tagged attribute */
                                if ((v = dict_valbyattr(vp->attribute, vp->lvalue))
                                    != NULL)
@@ -161,48 +166,68 @@ int vp_prints_value(char * out, int outlen, VALUE_PAIR *vp, int delimitst)
                case PW_TYPE_DATE:
                        t = vp->lvalue;
                        if (delimitst) {
-                         strftime(buf, sizeof(buf), "\"%b %e %Y %H:%M:%S %Z\"",
-                                  localtime_r(&t, &s_tm));
+                         len = strftime(buf, sizeof(buf), "\"%b %e %Y %H:%M:%S %Z\"",
+                                        localtime_r(&t, &s_tm));
                        } else {
-                         strftime(buf, sizeof(buf), "%b %e %Y %H:%M:%S %Z",
-                                  localtime_r(&t, &s_tm));
+                         len = strftime(buf, sizeof(buf), "%b %e %Y %H:%M:%S %Z",
+                                        localtime_r(&t, &s_tm));
                        }
-                       a = buf;
+                       if (len > 0) a = buf;
                        break;
                case PW_TYPE_IPADDR:
-                       a = ip_ntoa(buf, vp->lvalue);
+                       a = inet_ntop(AF_INET, &(vp->lvalue),
+                                     buf, sizeof(buf));
                        break;
                case PW_TYPE_ABINARY:
 #ifdef ASCEND_BINARY
-                 a = buf;
-                 print_abinary(vp, (unsigned char *)buf, sizeof(buf));
-                 break;
+                       a = buf;
+                       print_abinary(vp, buf, sizeof(buf));
+                       break;
 #else
                  /* FALL THROUGH */
 #endif
                case PW_TYPE_OCTETS:
-                 strcpy(buf, "0x");
-                 a = buf + 2;
-                 for (t = 0; t < vp->length; t++) {
-                       sprintf(a, "%02x", vp->strvalue[t]);
-                       a += 2;
-                 }
-                 a = buf;
+                       if (outlen <= (2 * (vp->length + 1))) return 0;
+
+                       strcpy(buf, "0x");
+                       
+                       lrad_bin2hex(vp->vp_octets, buf + 2, vp->length);
+                       a = buf;
                  break;
 
                case PW_TYPE_IFID:
-                       a = ifid_ntoa(buf, sizeof(buf), vp->strvalue);
+                       a = ifid_ntoa(buf, sizeof(buf), vp->vp_octets);
                        break;
 
                case PW_TYPE_IPV6ADDR:
-                       a = ipv6_ntoa(buf, sizeof(buf), vp->strvalue);
+                       a = inet_ntop(AF_INET6,
+                                     (const struct in6_addr *) vp->vp_strvalue,
+                                     buf, sizeof(buf));
+                       break;
+
+               case PW_TYPE_IPV6PREFIX:
+               {
+                       struct in6_addr addr;
+
+                       /*
+                        *      Alignment issues.
+                        */
+                       memcpy(&addr, vp->vp_strvalue + 2, sizeof(addr));
+
+                       a = inet_ntop(AF_INET6, &addr, buf, sizeof(buf));
+                       if (a) {
+                               char *p = buf + strlen(buf);
+                               sprintf(p, "/%u", (unsigned int) vp->vp_strvalue[1]);
+                       }
+               }
                        break;
 
                default:
-                       a = 0;
+                       a = "UNKNOWN-TYPE";
                        break;
        }
-       strNcpy(out, a?a:"UNKNOWN-TYPE", outlen);
+
+       if (a != NULL) strlcpy(out, a, outlen);
 
        return strlen(out);
 }
@@ -211,7 +236,7 @@ int vp_prints_value(char * out, int outlen, VALUE_PAIR *vp, int delimitst)
  *  This is a hack, and has to be kept in sync with tokens.h
  */
 static const char *vp_tokens[] = {
-  "?",                         /* T_INVALID */
+  "?",                         /* T_OP_INVALID */
   "EOL",                       /* T_EOL */
   "{",
   "}",
@@ -248,15 +273,24 @@ int vp_prints(char *out, int outlen, VALUE_PAIR *vp)
 {
        int             len;
        const char      *token = NULL;
+       const char      *name;
 
        out[0] = 0;
        if (!vp) return 0;
+       name = vp->name;
+
+       if (!*name) {
+               DICT_ATTR *da = dict_attrbyvalue(vp->attribute);
+               if (!da) return 0;
+
+               name = da->name;
+       }
 
-       if (strlen(vp->name) + 3 > (size_t)outlen) {
+       if (strlen(name) + 3 > (size_t)outlen) {
                return 0;
        }
 
-       if ((vp->operator > T_INVALID) &&
+       if ((vp->operator > T_OP_INVALID) &&
            (vp->operator < T_TOKEN_LAST)) {
                token = vp_tokens[vp->operator];
        } else {
@@ -265,7 +299,7 @@ int vp_prints(char *out, int outlen, VALUE_PAIR *vp)
 
        if( vp->flags.has_tag ) {
 
-               snprintf(out, outlen, "%s:%d %s ", vp->name, vp->flags.tag,
+               snprintf(out, outlen, "%s:%d %s ", name, vp->flags.tag,
                         token);
 
                len = strlen(out);
@@ -273,7 +307,7 @@ int vp_prints(char *out, int outlen, VALUE_PAIR *vp)
 
        } else {
 
-               snprintf(out, outlen, "%s %s ", vp->name, token);
+               snprintf(out, outlen, "%s %s ", name, token);
                len = strlen(out);
                vp_prints_value(out + len, outlen - len, vp, 1);
 
index 044ed8f..a7c5170 100644 (file)
  *   License along with this library; if not, write to the Free Software
  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000-2003  The FreeRADIUS server project
+ * Copyright 2000-2003,2006  The FreeRADIUS server project
  */
 
-static const char rcsid[] = "$Id$";
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include       "autoconf.h"
-#include       "md5.h"
+#include       <freeradius-devel/autoconf.h>
+#include       <freeradius-devel/md5.h>
 
 #include       <stdlib.h>
 
@@ -32,23 +33,12 @@ static const char rcsid[] = "$Id$";
 #endif
 
 #include       <fcntl.h>
-#include       <string.h>
 #include       <ctype.h>
 
-#include       "libradius.h"
 #ifdef WITH_UDPFROMTO
-#include       "udpfromto.h"
+#include       <freeradius-devel/udpfromto.h>
 #endif
 
-#ifdef HAVE_NETINET_IN_H
-#include       <netinet/in.h>
-#endif
-
-#include       <sys/socket.h>
-
-#ifdef HAVE_ARPA_INET_H
-#include       <arpa/inet.h>
-#endif
 
 #ifdef HAVE_MALLOC_H
 #include       <malloc.h>
@@ -58,6 +48,9 @@ static const char rcsid[] = "$Id$";
 #include       <process.h>
 #endif
 
+#include       <freeradius-devel/missing.h>
+#include       <freeradius-devel/libradius.h>
+
 /*
  *  The RFC says 4096 octets max, and most packets are less than 256.
  */
@@ -85,9 +78,11 @@ typedef struct radius_packet_t {
 } radius_packet_t;
 
 static lrad_randctx lrad_rand_pool;    /* across multiple calls */
-static volatile int lrad_rand_index = -1;
+static int lrad_rand_initialized = 0;
 static unsigned int salt_offset = 0;
 
+
+#define MAX_PACKET_CODE (52)
 static const char *packet_codes[] = {
   "",
   "Access-Request",
@@ -144,6 +139,247 @@ static const char *packet_codes[] = {
 };
 
 
+/*
+ *     Wrapper for sendto which handles sendfromto, IPv6, and all
+ *     possible combinations.
+ */
+static int rad_sendto(int sockfd, void *data, size_t data_len, int flags,
+                     lrad_ipaddr_t *src_ipaddr, lrad_ipaddr_t *dst_ipaddr,
+                     int dst_port)
+{
+       struct sockaddr_storage dst;
+       socklen_t               sizeof_dst = sizeof(dst);
+
+#ifdef WITH_UDPFROMTO
+       struct sockaddr_storage src;
+       socklen_t               sizeof_src = sizeof(src);
+
+       memset(&src, 0, sizeof(src));
+#endif
+       memset(&dst, 0, sizeof(dst));
+
+       /*
+        *      IPv4 is supported.
+        */
+       if (dst_ipaddr->af == AF_INET) {
+               struct sockaddr_in      *s4;
+
+               s4 = (struct sockaddr_in *)&dst;
+               sizeof_dst = sizeof(struct sockaddr_in);
+
+               s4->sin_family = AF_INET;
+               s4->sin_addr = dst_ipaddr->ipaddr.ip4addr;
+               s4->sin_port = htons(dst_port);
+
+#ifdef WITH_UDPFROMTO
+               s4 = (struct sockaddr_in *)&src;
+               sizeof_src = sizeof(struct sockaddr_in);
+
+               s4->sin_family = AF_INET;
+               s4->sin_addr = src_ipaddr->ipaddr.ip4addr;
+#endif
+
+       /*
+        *      IPv6 MAY be supported.
+        */
+#ifdef HAVE_STRUCT_SOCKADDR_IN6
+       } else if (dst_ipaddr->af == AF_INET6) {
+               struct sockaddr_in6     *s6;
+
+               s6 = (struct sockaddr_in6 *)&dst;
+               sizeof_dst = sizeof(struct sockaddr_in6);
+               
+               s6->sin6_family = AF_INET6;
+               s6->sin6_addr = dst_ipaddr->ipaddr.ip6addr;
+               s6->sin6_port = htons(dst_port);
+
+#ifdef WITH_UDPFROMTO
+               return -1;      /* UDPFROMTO && IPv6 are not supported */
+#if 0
+               s6 = (struct sockaddr_in6 *)&src;
+               sizeof_src = sizeof(struct sockaddr_in6);
+
+               s6->sin6_family = AF_INET6;
+               s6->sin6_addr = src_ipaddr->ipaddr.ip6addr;
+#endif /* #if 0 */
+#endif /* WITH_UDPFROMTO */
+#endif /* HAVE_STRUCT_SOCKADDR_IN6 */
+       } else return -1;   /* Unknown address family, Die Die Die! */
+
+#ifdef WITH_UDPFROMTO
+       /*
+        *      Only IPv4 is supported for udpfromto.
+        *
+        *      And if they don't specify a source IP address, don't
+        *      use udpfromto.
+        */
+       if ((dst_ipaddr->af == AF_INET) ||
+           (src_ipaddr->af != AF_UNSPEC)) {
+               return sendfromto(sockfd, data, data_len, flags,
+                                 (struct sockaddr *)&src, sizeof_src, 
+                                 (struct sockaddr *)&dst, sizeof_dst);
+       }
+#else
+       src_ipaddr = src_ipaddr; /* -Wunused */
+#endif
+
+       /*
+        *      No udpfromto, OR an IPv6 socket, fail gracefully.
+        */
+       return sendto(sockfd, data, data_len, flags, 
+                     (struct sockaddr *)&dst, sizeof_dst);
+}
+
+
+/*
+ *     Wrapper for recvfrom, which handles recvfromto, IPv6, and all
+ *     possible combinations.
+ */
+static ssize_t rad_recvfrom(int sockfd, uint8_t **pbuf, int flags,
+                           lrad_ipaddr_t *src_ipaddr, uint16_t *src_port,
+                           lrad_ipaddr_t *dst_ipaddr, uint16_t *dst_port)
+{
+       struct sockaddr_storage src;
+       struct sockaddr_storage dst;
+       socklen_t               sizeof_src = sizeof(src);
+       socklen_t               sizeof_dst = sizeof(dst);
+       ssize_t                 data_len;
+       uint8_t                 header[4];
+       void                    *buf;
+       size_t                  len;
+
+       memset(&src, 0, sizeof_src);
+       memset(&dst, 0, sizeof_dst);
+
+       /*
+        *      Get address family, etc. first, so we know if we
+        *      need to do udpfromto.
+        *
+        *      FIXME: udpfromto also does this, but it's not
+        *      a critical problem.
+        */
+       if (getsockname(sockfd, (struct sockaddr *)&dst,
+                       &sizeof_dst) < 0) return -1;
+
+       /*
+        *      Read the length of the packet, from the packet.
+        *      This lets us allocate the buffer to use for
+        *      reading the rest of the packet.
+        */
+       data_len = recvfrom(sockfd, header, sizeof(header), MSG_PEEK,
+                           (struct sockaddr *)&src, &sizeof_src);
+       if (data_len < 0) return -1;
+
+       /*
+        *      Too little data is available, discard the packet.
+        */
+       if (data_len < 4) {
+               recvfrom(sockfd, header, sizeof(header), flags, 
+                        (struct sockaddr *)&src, &sizeof_src);
+               return 0;
+
+       } else {                /* we got 4 bytes of data. */
+               /*
+                *      See how long the packet says it is.
+                */
+               len = (header[2] * 256) + header[3];
+
+               /*
+                *      The length in the packet says it's less than
+                *      a RADIUS header length: discard it.
+                */
+               if (len < AUTH_HDR_LEN) {
+                       recvfrom(sockfd, header, sizeof(header), flags, 
+                                (struct sockaddr *)&src, &sizeof_src);
+                       return 0;
+
+                       /*
+                        *      Enforce RFC requirements, for sanity.
+                        *      Anything after 4k will be discarded.
+                        */
+               } else if (len > MAX_PACKET_LEN) {
+                       recvfrom(sockfd, header, sizeof(header), flags, 
+                                (struct sockaddr *)&src, &sizeof_src);
+                       return len;
+               }
+       }
+
+       buf = malloc(len);
+       if (!buf) return -1;
+
+       /*
+        *      Receive the packet.  The OS will discard any data in the
+        *      packet after "len" bytes.
+        */
+#ifdef WITH_UDPFROMTO
+       if (dst.ss_family == AF_INET) {
+               data_len = recvfromto(sockfd, buf, len, flags,
+                                     (struct sockaddr *)&src, &sizeof_src, 
+                                     (struct sockaddr *)&dst, &sizeof_dst);
+       } else
+#endif
+               /*
+                *      No udpfromto, OR an IPv6 socket.  Fail gracefully.
+                */
+               data_len = recvfrom(sockfd, buf, len, flags, 
+                                   (struct sockaddr *)&src, &sizeof_src);
+       if (data_len < 0) {
+               free(buf);
+               return data_len;
+       }
+
+       /*
+        *      Check address families, and update src/dst ports, etc.
+        */
+       if (src.ss_family == AF_INET) {
+               struct sockaddr_in      *s4;
+
+               s4 = (struct sockaddr_in *)&src;
+               src_ipaddr->af = AF_INET;
+               src_ipaddr->ipaddr.ip4addr = s4->sin_addr;
+               *src_port = ntohs(s4->sin_port);
+
+               s4 = (struct sockaddr_in *)&dst;
+               dst_ipaddr->af = AF_INET;
+               dst_ipaddr->ipaddr.ip4addr = s4->sin_addr;
+               *dst_port = ntohs(s4->sin_port);
+
+#ifdef HAVE_STRUCT_SOCKADDR_IN6
+       } else if (src.ss_family == AF_INET6) {
+               struct sockaddr_in6     *s6;
+
+               s6 = (struct sockaddr_in6 *)&src;
+               src_ipaddr->af = AF_INET6;
+               src_ipaddr->ipaddr.ip6addr = s6->sin6_addr;
+               *src_port = ntohs(s6->sin6_port);
+
+               s6 = (struct sockaddr_in6 *)&dst;
+               dst_ipaddr->af = AF_INET6;
+               dst_ipaddr->ipaddr.ip6addr = s6->sin6_addr;
+               *dst_port = ntohs(s6->sin6_port);
+#endif
+       } else {
+               free(buf);
+               return -1;      /* Unknown address family, Die Die Die! */
+       }
+       
+       /*
+        *      Different address families should never happen.
+        */
+       if (src.ss_family != dst.ss_family) {
+               free(buf);
+               return -1;
+       }
+
+       /*
+        *      Tell the caller about the data
+        */
+       *pbuf = buf;
+
+       return data_len;
+}
+
+
 #define AUTH_PASS_LEN (AUTH_VECTOR_LEN)
 /*************************************************************************
  *
@@ -159,13 +395,13 @@ static const char *packet_codes[] = {
 static void make_secret(uint8_t *digest, const uint8_t *vector,
                        const char *secret, const uint8_t *value)
 {
-       MD5_CTX context;
+       lrad_MD5_CTX context;
         int             i;
 
-       MD5Init(&context);
-       MD5Update(&context, vector, AUTH_VECTOR_LEN);
-       MD5Update(&context, secret, strlen(secret));
-       MD5Final(digest, &context);
+       lrad_MD5Init(&context);
+       lrad_MD5Update(&context, vector, AUTH_VECTOR_LEN);
+       lrad_MD5Update(&context, secret, strlen(secret));
+       lrad_MD5Final(digest, &context);
 
         for ( i = 0; i < AUTH_VECTOR_LEN; i++ ) {
                digest[i] ^= value[i];
@@ -177,7 +413,7 @@ static void make_passwd(uint8_t *output, int *outlen,
                        const uint8_t *input, int inlen,
                        const char *secret, const uint8_t *vector)
 {
-       MD5_CTX context, old;
+       lrad_MD5_CTX context, old;
        uint8_t digest[AUTH_VECTOR_LEN];
        uint8_t passwd[MAX_PASS_LEN];
        int     i, n;
@@ -201,24 +437,24 @@ static void make_passwd(uint8_t *output, int *outlen,
        memcpy(passwd, input, len);
        memset(passwd + len, 0, sizeof(passwd) - len);
 
-       MD5Init(&context);
-       MD5Update(&context, secret, strlen(secret));
+       lrad_MD5Init(&context);
+       lrad_MD5Update(&context, secret, strlen(secret));
        old = context;
 
        /*
         *      Do first pass.
         */
-       MD5Update(&context, vector, AUTH_PASS_LEN);
+       lrad_MD5Update(&context, vector, AUTH_PASS_LEN);
 
        for (n = 0; n < len; n += AUTH_PASS_LEN) {
                if (n > 0) {
                        context = old;
-                       MD5Update(&context,
+                       lrad_MD5Update(&context,
                                       passwd + n - AUTH_PASS_LEN,
                                       AUTH_PASS_LEN);
                }
 
-               MD5Final(digest, &context);
+               lrad_MD5Final(digest, &context);
                for (i = 0; i < AUTH_PASS_LEN; i++) {
                        passwd[i + n] ^= digest[i];
                }
@@ -231,13 +467,18 @@ static void make_tunnel_passwd(uint8_t *output, int *outlen,
                               const uint8_t *input, int inlen, int room,
                               const char *secret, const uint8_t *vector)
 {
-       MD5_CTX context, old;
+       lrad_MD5_CTX context, old;
        uint8_t digest[AUTH_VECTOR_LEN];
        uint8_t passwd[MAX_STRING_LEN + AUTH_VECTOR_LEN];
        int     i, n;
        int     len;
 
        /*
+        *      Be paranoid.
+        */
+       if (room > 253) room = 253;
+
+       /*
         *      Account for 2 bytes of the salt, and round the room
         *      available down to the nearest multiple of 16.  Then,
         *      subtract one from that to account for the length byte,
@@ -290,22 +531,22 @@ static void make_tunnel_passwd(uint8_t *output, int *outlen,
        passwd[1] = lrad_rand();
        passwd[2] = inlen;      /* length of the password string */
 
-       MD5Init(&context);
-       MD5Update(&context, secret, strlen(secret));
+       lrad_MD5Init(&context);
+       lrad_MD5Update(&context, secret, strlen(secret));
        old = context;
 
-       MD5Update(&context, vector, AUTH_VECTOR_LEN);
-       MD5Update(&context, &passwd[0], 2);
+       lrad_MD5Update(&context, vector, AUTH_VECTOR_LEN);
+       lrad_MD5Update(&context, &passwd[0], 2);
 
        for (n = 0; n < len; n += AUTH_PASS_LEN) {
                if (n > 0) {
                        context = old;
-                       MD5Update(&context,
+                       lrad_MD5Update(&context,
                                       passwd + 2 + n - AUTH_PASS_LEN,
                                       AUTH_PASS_LEN);
                }
 
-               MD5Final(digest, &context);
+               lrad_MD5Final(digest, &context);
                for (i = 0; i < AUTH_PASS_LEN; i++) {
                        passwd[i + 2 + n] ^= digest[i];
                }
@@ -329,12 +570,33 @@ int rad_vp2attr(const RADIUS_PACKET *packet, const RADIUS_PACKET *original,
 
        vendorcode = total_length = 0;
        length_ptr = vsa_length_ptr = NULL;
-       
+
        /*
         *      For interoperability, always put vendor attributes
         *      into their own VSA.
         */
-       if ((vendorcode = VENDOR(vp->attribute)) != 0) {
+       if ((vendorcode = VENDOR(vp->attribute)) == 0) {
+               *(ptr++) = vp->attribute & 0xFF;
+               length_ptr = ptr;
+               *(ptr++) = 2;
+               total_length += 2;
+
+       } else {
+               int vsa_tlen = 1;
+               int vsa_llen = 1;
+               DICT_VENDOR *dv = dict_vendorbyvalue(vendorcode);
+
+               /*
+                *      This must be an RFC-format attribute.  If it
+                *      wasn't, then the "decode" function would have
+                *      made a Vendor-Specific attribute (i.e. type
+                *      26), and we would have "vendorcode == 0" here.
+                */
+               if (dv) {
+                       vsa_tlen = dv->type;
+                       vsa_llen = dv->length;
+               }
+
                /*
                 *      Build a VSA header.
                 */
@@ -345,64 +607,52 @@ int rad_vp2attr(const RADIUS_PACKET *packet, const RADIUS_PACKET *original,
                memcpy(ptr, &lvalue, 4);
                ptr += 4;
                total_length += 6;
-               
-               if (vendorcode == VENDORPEC_USR) {
-                       lvalue = htonl(vp->attribute & 0xFFFF);
-                       memcpy(ptr, &lvalue, 4);
-                       
+
+               switch (vsa_tlen) {
+               case 1:
+                       ptr[0] = (vp->attribute & 0xFF);
+                       break;
+
+               case 2:
+                       ptr[0] = ((vp->attribute >> 8) & 0xFF);
+                       ptr[1] = (vp->attribute & 0xFF);
+                       break;
+
+               case 4:
+                       ptr[0] = 0;
+                       ptr[1] = 0;
+                       ptr[2] = ((vp->attribute >> 8) & 0xFF);
+                       ptr[3] = (vp->attribute & 0xFF);
+                       break;
+
+               default:
+                       return 0; /* silently discard it */
+               }
+               ptr += vsa_tlen;
+
+               switch (vsa_llen) {
+               case 0:
                        length_ptr = vsa_length_ptr;
-                       
-                       total_length += 4;
-                       *length_ptr  += 4;
-                       ptr          += 4;
-                       
-                       /*
-                        *      We don't have two different lengths.
-                        */
                        vsa_length_ptr = NULL;
-                       
-               } else if (vendorcode == VENDORPEC_LUCENT) {
-                       /*
-                        *      16-bit attribute, 8-bit length
-                        */
-                       *ptr++ = ((vp->attribute >> 8) & 0xFF);
-                       *ptr++ = (vp->attribute & 0xFF);
+                       break;
+               case 1:
+                       ptr[0] = 0;
                        length_ptr = ptr;
-                       *vsa_length_ptr += 3;
-                       *ptr++ = 3;
-                       total_length += 3;
+                       break;
+               case 2:
+                       ptr[0] = 0;
+                       ptr[1] = 0;
+                       length_ptr = ptr + 1;
+                       break;
 
-               } else if (vendorcode == VENDORPEC_STARENT) {
-                       /*
-                        *      16-bit attribute, 16-bit length
-                        *      with the upper 8 bits of the length
-                        *      always zero!
-                        */
-                       *ptr++ = ((vp->attribute >> 8) & 0xFF);
-                       *ptr++ = (vp->attribute & 0xFF);
-                       *ptr++ = 0;
-                       length_ptr = ptr;
-                       *vsa_length_ptr += 4;
-                       *ptr++ = 4;
-                       total_length += 4;
-               } else {
-                       /*
-                        *      All other VSA's are encoded the same
-                        *      as RFC attributes.
-                        */
-                       *vsa_length_ptr += 2;
-                       goto rfc;
+               default:
+                       return 0; /* silently discard it */
                }
-       } else {
-       rfc:
-               /*
-                *      All other attributes are encoded as
-                *      per the RFC.
-                */
-               *ptr++ = (vp->attribute & 0xFF);
-               length_ptr = ptr;
-               *ptr++ = 2;
-               total_length += 2;
+               ptr += vsa_llen;
+
+               total_length += vsa_tlen + vsa_llen;
+               if (vsa_length_ptr) *vsa_length_ptr += vsa_tlen + vsa_llen;
+               *length_ptr += vsa_tlen + vsa_llen;
        }
 
        offset = 0;
@@ -424,21 +674,9 @@ int rad_vp2attr(const RADIUS_PACKET *packet, const RADIUS_PACKET *original,
        /*
         *      Set up the default sources for the data.
         */
-       data = vp->strvalue;
+       data = vp->vp_octets;
        len = vp->length;
 
-       /*
-        *      Encrypted passwords can't be very long.
-        *      This check also ensures that the hashed version
-        *      of the password + attribute header fits into one
-        *      attribute.
-        *
-        *      FIXME: Print a warning message if it's too long?
-        */
-       if (vp->flags.encrypt && (len > MAX_PASS_LEN)) {
-               len = MAX_PASS_LEN;
-       }
-
        switch(vp->type) {
        case PW_TYPE_STRING:
        case PW_TYPE_OCTETS:
@@ -449,6 +687,22 @@ int rad_vp2attr(const RADIUS_PACKET *packet, const RADIUS_PACKET *original,
                /* nothing more to do */
                break;
                        
+       case PW_TYPE_BYTE:
+               len = 1;        /* just in case */
+               array[0] = vp->lvalue & 0xff;
+               data = array;
+               offset = 0;
+               break;
+                       
+
+       case PW_TYPE_SHORT:
+               len = 2;        /* just in case */
+               array[0] = (vp->lvalue >> 8) & 0xff;
+               array[1] = vp->lvalue & 0xff;
+               data = array;
+               offset = 0;
+               break;
+
        case PW_TYPE_INTEGER:
                len = 4;        /* just in case */
                lvalue = htonl(vp->lvalue);
@@ -517,9 +771,6 @@ int rad_vp2attr(const RADIUS_PACKET *packet, const RADIUS_PACKET *original,
                 */
                if ((255 - offset - total_length) < 18) return 0;
 
-               /*
-                *      Can't make the password, suppress it.
-                */
                make_tunnel_passwd(ptr + offset, &len,
                                   data, len, 255 - offset - total_length,
                                   secret, original->vector);
@@ -578,6 +829,8 @@ int rad_encode(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
        uint16_t        total_length;
        int             len;
        VALUE_PAIR      *reply;
+       const char      *what;
+       char            ip_buffer[128];
        
        /*
         *      For simplicity in the following logic, we allow
@@ -588,6 +841,19 @@ int rad_encode(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
         */
        uint32_t        data[(MAX_PACKET_LEN + 256) / 4];
 
+       if ((packet->code > 0) && (packet->code < MAX_PACKET_CODE)) {
+               what = packet_codes[packet->code];
+       } else {
+               what = "Reply";
+       }
+
+       DEBUG("Sending %s of id %d to %s port %d\n",
+             what, packet->id,
+             inet_ntop(packet->dst_ipaddr.af,
+                       &packet->dst_ipaddr.ipaddr,
+                       ip_buffer, sizeof(ip_buffer)),
+             packet->dst_port);
+
        /*
         *      Double-check some things based on packet code.
         */
@@ -663,18 +929,19 @@ int rad_encode(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
                 */
                if (reply->attribute == PW_MESSAGE_AUTHENTICATOR) {
                        reply->length = AUTH_VECTOR_LEN;
-                       memset(reply->strvalue, 0, AUTH_VECTOR_LEN);
+                       memset(reply->vp_strvalue, 0, AUTH_VECTOR_LEN);
                        packet->verified = total_length; /* HACK! */
                }
-               
+
                /*
                 *      Print out ONLY the attributes which
                 *      we're sending over the wire, and print
                 *      them out BEFORE they're encrypted.
                 */
                debug_pair(reply);
-
+               
                len = rad_vp2attr(packet, original, secret, reply, ptr);
+
                if (len < 0) return -1;
 
                /*
@@ -842,8 +1109,6 @@ int rad_send(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
        VALUE_PAIR              *reply;
        const char              *what;
        char                    ip_buffer[128];
-       struct  sockaddr_in     saremote;
-       struct  sockaddr_in     *sa;
 
        /*
         *      Maybe it's a fake packet.  Don't send it.
@@ -852,7 +1117,7 @@ int rad_send(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
                return 0;
        }
 
-       if ((packet->code > 0) && (packet->code < 52)) {
+       if ((packet->code > 0) && (packet->code < MAX_PACKET_CODE)) {
                what = packet_codes[packet->code];
        } else {
                what = "Reply";
@@ -862,11 +1127,6 @@ int rad_send(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
         *  First time through, allocate room for the packet
         */
        if (!packet->data) {
-               DEBUG("Sending %s of id %d to %s port %d\n",
-                     what, packet->id,
-                     ip_ntoa(ip_buffer, packet->dst_ipaddr),
-                     packet->dst_port);
-               
                /*
                 *      Encode the packet.
                 */
@@ -888,7 +1148,9 @@ int rad_send(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
                 */
        } else if (librad_debug) {
                DEBUG("Re-sending %s of id %d to %s port %d\n", what, packet->id,
-                     ip_ntoa(ip_buffer, packet->dst_ipaddr),
+                     inet_ntop(packet->dst_ipaddr.af,
+                               &packet->dst_ipaddr.ipaddr,
+                               ip_buffer, sizeof(ip_buffer)),
                      packet->dst_port);
 
                for (reply = packet->vps; reply; reply = reply->next) {
@@ -900,26 +1162,9 @@ int rad_send(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
        /*
         *      And send it on it's way.
         */
-       sa = (struct sockaddr_in *) &saremote;
-        memset ((char *) sa, '\0', sizeof (saremote));
-       sa->sin_family = AF_INET;
-       sa->sin_addr.s_addr = packet->dst_ipaddr;
-       sa->sin_port = htons(packet->dst_port);
-#ifndef WITH_UDPFROMTO
-       return sendto(packet->sockfd, packet->data, (int)packet->data_len, 0,
-                     (struct sockaddr *)&saremote, sizeof(struct sockaddr_in));
-#else
-       {
-               struct sockaddr_in salocal;
-               memset ((char *) &salocal, '\0', sizeof (salocal));
-               salocal.sin_family = AF_INET;
-               salocal.sin_addr.s_addr = packet->src_ipaddr;
-               
-               return sendfromto(packet->sockfd, packet->data, (int)packet->data_len, 0,
-                                 (struct sockaddr *)&salocal,  sizeof(struct sockaddr_in),
-                                 (struct sockaddr *)&saremote, sizeof(struct sockaddr_in));
-       }
-#endif
+       return rad_sendto(packet->sockfd, packet->data, packet->data_len, 0,
+                         &packet->src_ipaddr, &packet->dst_ipaddr,
+                         packet->dst_port);
 }
 
 
@@ -929,7 +1174,7 @@ int rad_send(RADIUS_PACKET *packet, const RADIUS_PACKET *original,
  */
 static int calc_acctdigest(RADIUS_PACKET *packet, const char *secret)
 {
-       u_char          digest[AUTH_VECTOR_LEN];
+       uint8_t         digest[AUTH_VECTOR_LEN];
        MD5_CTX         context;
 
        /*
@@ -1010,85 +1255,25 @@ static int calc_replydigest(RADIUS_PACKET *packet, RADIUS_PACKET *original,
        return packet->verified;
 }
 
+
 /*
- *     Receive UDP client requests, and fill in
- *     the basics of a RADIUS_PACKET structure.
+ *     See if the data pointed to by PTR is a valid RADIUS packet.
+ *
+ *     packet is not 'const * const' because we may update data_len,
+ *     if there's more data in the UDP packet than in the RADIUS packet.
  */
-RADIUS_PACKET *rad_recv(int fd)
+int rad_packet_ok(RADIUS_PACKET *packet)
 {
-       RADIUS_PACKET           *packet;
-       struct sockaddr_in      saremote;
-       int                     totallen;
-       socklen_t               salen;
        uint8_t                 *attr;
+       int                     totallen;
        int                     count;
        radius_packet_t         *hdr;
-       char                    host_ipaddr[16];
+       char                    host_ipaddr[128];
        int                     require_ma = 0;
        int                     seen_ma = 0;
-       uint8_t                 data[MAX_PACKET_LEN];
        int                     num_attributes;
 
        /*
-        *      Allocate the new request data structure
-        */
-       if ((packet = malloc(sizeof(RADIUS_PACKET))) == NULL) {
-               librad_log("out of memory");
-               return NULL;
-       }
-       memset(packet, 0, sizeof(RADIUS_PACKET));
-
-       /*
-        *      Receive the packet.
-        */
-       salen = sizeof(saremote);
-       memset(&saremote, 0, sizeof(saremote));
-#ifndef WITH_UDPFROMTO
-       packet->data_len = recvfrom(fd, data, sizeof(data),
-                                   0, (struct sockaddr *)&saremote, &salen);
-       packet->dst_ipaddr = htonl(INADDR_ANY); /* i.e. unknown */
-#else
-       {
-               socklen_t               salen_local;
-               struct sockaddr_in      salocal;
-               salen_local = sizeof(salocal);
-               memset(&salocal, 0, sizeof(salocal));
-               packet->data_len = recvfromto(fd, data, sizeof(data), 0,
-                                             (struct sockaddr *)&saremote, &salen,
-                                             (struct sockaddr *)&salocal, &salen_local);
-               packet->dst_ipaddr = salocal.sin_addr.s_addr;
-       }
-#endif
-
-       /*
-        *      Check for socket errors.
-        */
-       if (packet->data_len < 0) {
-               librad_log("Error receiving packet: %s", strerror(errno));
-               free(packet);
-               return NULL;
-       }
-
-       /*
-        *      Fill IP header fields.  We need these for the error
-        *      messages which may come later.
-        */
-       packet->sockfd = fd;
-       packet->src_ipaddr = saremote.sin_addr.s_addr;
-       packet->src_port = ntohs(saremote.sin_port);
-
-       /*
-        *      FIXME: Do even more filtering by only permitting
-        *      certain IP's.  The problem is that we don't know
-        *      how to do this properly for all possible clients...
-        */
-
-       /*
-        *      Explicitely set the VP list to empty.
-        */
-       packet->vps = NULL;
-
-       /*
         *      Check for packets smaller than the packet header.
         *
         *      RFC 2865, Section 3., subsection 'length' says:
@@ -1097,10 +1282,11 @@ RADIUS_PACKET *rad_recv(int fd)
         */
        if (packet->data_len < AUTH_HDR_LEN) {
                librad_log("WARNING: Malformed RADIUS packet from host %s: too short (received %d < minimum %d)",
-                          ip_ntoa(host_ipaddr, packet->src_ipaddr),
+                          inet_ntop(packet->src_ipaddr.af,
+                                    &packet->src_ipaddr.ipaddr,
+                                    host_ipaddr, sizeof(host_ipaddr)),
                           packet->data_len, AUTH_HDR_LEN);
-               free(packet);
-               return NULL;
+               return 0;
        }
 
        /*
@@ -1110,10 +1296,11 @@ RADIUS_PACKET *rad_recv(int fd)
         */
        if (packet->data_len > MAX_PACKET_LEN) {
                librad_log("WARNING: Malformed RADIUS packet from host %s: too long (received %d > maximum %d)",
-                          ip_ntoa(host_ipaddr, packet->src_ipaddr),
+                          inet_ntop(packet->src_ipaddr.af,
+                                    &packet->src_ipaddr.ipaddr,
+                                    host_ipaddr, sizeof(host_ipaddr)),
                           packet->data_len, MAX_PACKET_LEN);
-               free(packet);
-               return NULL;
+               return 0;
        }
 
        /*
@@ -1121,20 +1308,21 @@ RADIUS_PACKET *rad_recv(int fd)
         *      i.e. We've received 128 bytes, and the packet header
         *      says it's 256 bytes long.
         */
-       totallen = (data[2] << 8) | data[3];
-       hdr = (radius_packet_t *)data;
+       totallen = (packet->data[2] << 8) | packet->data[3];
+       hdr = (radius_packet_t *)packet->data;
 
        /*
         *      Code of 0 is not understood.
         *      Code of 16 or greate is not understood.
         */
        if ((hdr->code == 0) ||
-           (hdr->code >= 52)) {
+           (hdr->code >= MAX_PACKET_CODE)) {
                librad_log("WARNING: Bad RADIUS packet from host %s: unknown packet code %d",
-                          ip_ntoa(host_ipaddr, packet->src_ipaddr),
+                          inet_ntop(packet->src_ipaddr.af,
+                                    &packet->src_ipaddr.ipaddr,
+                                    host_ipaddr, sizeof(host_ipaddr)),
                           hdr->code);
-               free(packet);
-               return NULL;
+               return 0;
        }
 
        /*
@@ -1156,10 +1344,11 @@ RADIUS_PACKET *rad_recv(int fd)
         */
        if (totallen < AUTH_HDR_LEN) {
                librad_log("WARNING: Malformed RADIUS packet from host %s: too short (length %d < minimum %d)",
-                          ip_ntoa(host_ipaddr, packet->src_ipaddr),
+                          inet_ntop(packet->src_ipaddr.af,
+                                    &packet->src_ipaddr.ipaddr,
+                                    host_ipaddr, sizeof(host_ipaddr)),
                           totallen, AUTH_HDR_LEN);
-               free(packet);
-               return NULL;
+               return 0;
        }
 
        /*
@@ -1171,10 +1360,11 @@ RADIUS_PACKET *rad_recv(int fd)
         */
        if (totallen > MAX_PACKET_LEN) {
                librad_log("WARNING: Malformed RADIUS packet from host %s: too long (length %d > maximum %d)",
-                          ip_ntoa(host_ipaddr, packet->src_ipaddr),
+                          inet_ntop(packet->src_ipaddr.af,
+                                    &packet->src_ipaddr.ipaddr,
+                                    host_ipaddr, sizeof(host_ipaddr)),
                           totallen, MAX_PACKET_LEN);
-               free(packet);
-               return NULL;
+               return 0;
        }
 
        /*
@@ -1187,10 +1377,11 @@ RADIUS_PACKET *rad_recv(int fd)
         */
        if (packet->data_len < totallen) {
                librad_log("WARNING: Malformed RADIUS packet from host %s: received %d octets, packet length says %d",
-                          ip_ntoa(host_ipaddr, packet->src_ipaddr),
+                          inet_ntop(packet->src_ipaddr.af,
+                                    &packet->src_ipaddr.ipaddr,
+                                    host_ipaddr, sizeof(host_ipaddr)),
                           packet->data_len, totallen);
-               free(packet);
-               return NULL;
+               return 0;
        }
 
        /*
@@ -1204,7 +1395,7 @@ RADIUS_PACKET *rad_recv(int fd)
                 *      We're shortening the packet below, but just
                 *      to be paranoid, zero out the extra data.
                 */
-               memset(data + totallen, 0, packet->data_len - totallen);
+               memset(packet->data + totallen, 0, packet->data_len - totallen);
                packet->data_len = totallen;
        }
 
@@ -1230,9 +1421,10 @@ RADIUS_PACKET *rad_recv(int fd)
                 */
                if (attr[0] == 0) {
                        librad_log("WARNING: Malformed RADIUS packet from host %s: Invalid attribute 0",
-                                  ip_ntoa(host_ipaddr, packet->src_ipaddr));
-                       free(packet);
-                       return NULL;
+                                  inet_ntop(packet->src_ipaddr.af,
+                                            &packet->src_ipaddr.ipaddr,
+                                            host_ipaddr, sizeof(host_ipaddr)));
+                       return 0;
                }
 
                /*
@@ -1241,10 +1433,11 @@ RADIUS_PACKET *rad_recv(int fd)
                 */
                        if (attr[1] < 2) {
                        librad_log("WARNING: Malformed RADIUS packet from host %s: attribute %d too short",
-                                  ip_ntoa(host_ipaddr, packet->src_ipaddr),
+                                  inet_ntop(packet->src_ipaddr.af,
+                                            &packet->src_ipaddr.ipaddr,
+                                            host_ipaddr, sizeof(host_ipaddr)),
                                   attr[0]);
-                       free(packet);
-                       return NULL;
+                       return 0;
                }
 
                /*
@@ -1266,10 +1459,11 @@ RADIUS_PACKET *rad_recv(int fd)
                case PW_MESSAGE_AUTHENTICATOR:
                        if (attr[1] != 2 + AUTH_VECTOR_LEN) {
                                librad_log("WARNING: Malformed RADIUS packet from host %s: Message-Authenticator has invalid length %d",
-                                          ip_ntoa(host_ipaddr, packet->src_ipaddr),
+                                          inet_ntop(packet->src_ipaddr.af,
+                                                    &packet->src_ipaddr.ipaddr,
+                                                    host_ipaddr, sizeof(host_ipaddr)),
                                           attr[1] - 2);
-                               free(packet);
-                               return NULL;
+                               return 0;
                        }
                        seen_ma = 1;
                        break;
@@ -1293,9 +1487,10 @@ RADIUS_PACKET *rad_recv(int fd)
         */
        if (count != 0) {
                librad_log("WARNING: Malformed RADIUS packet from host %s: packet attributes do NOT exactly fill the packet",
-                          ip_ntoa(host_ipaddr, packet->src_ipaddr));
-               free(packet);
-               return NULL;
+                          inet_ntop(packet->src_ipaddr.af,
+                                    &packet->src_ipaddr.ipaddr,
+                                    host_ipaddr, sizeof(host_ipaddr)));
+               return 0;
        }
 
        /*
@@ -1306,10 +1501,11 @@ RADIUS_PACKET *rad_recv(int fd)
        if ((librad_max_attributes > 0) &&
            (num_attributes > librad_max_attributes)) {
                librad_log("WARNING: Possible DoS attack from host %s: Too many attributes in request (received %d, max %d are allowed).",
-                          ip_ntoa(host_ipaddr, packet->src_ipaddr),
+                          inet_ntop(packet->src_ipaddr.af,
+                                    &packet->src_ipaddr.ipaddr,
+                                    host_ipaddr, sizeof(host_ipaddr)),
                           num_attributes, librad_max_attributes);
-               free(packet);
-               return NULL;
+               return 0;
        }
 
        /*
@@ -1325,22 +1521,10 @@ RADIUS_PACKET *rad_recv(int fd)
         */
        if (require_ma && ! seen_ma) {
                librad_log("WARNING: Insecure packet from host %s:  Packet does not contain required Message-Authenticator attribute",
-                          ip_ntoa(host_ipaddr, packet->src_ipaddr));
-               free(packet);
-               return NULL;
-       }
-
-       if (librad_debug) {
-               if ((hdr->code > 0) && (hdr->code < 52)) {
-                       printf("rad_recv: %s packet from host %s:%d",
-                              packet_codes[hdr->code],
-                              ip_ntoa(host_ipaddr, packet->src_ipaddr), packet->src_port);
-               } else {
-                       printf("rad_recv: Packet from host %s:%d code=%d",
-                              ip_ntoa(host_ipaddr, packet->src_ipaddr), packet->src_port,
-                              hdr->code);
-               }
-               printf(", id=%d, length=%d\n", hdr->id, totallen);
+                          inet_ntop(packet->src_ipaddr.af,
+                                    &packet->src_ipaddr.ipaddr,
+                                    host_ipaddr, sizeof(host_ipaddr)));
+               return 0;
        }
 
        /*
@@ -1350,17 +1534,109 @@ RADIUS_PACKET *rad_recv(int fd)
        packet->id = hdr->id;
        memcpy(packet->vector, hdr->vector, AUTH_VECTOR_LEN);
 
+       return 1;
+}
+
+
+/*
+ *     Receive UDP client requests, and fill in
+ *     the basics of a RADIUS_PACKET structure.
+ */
+RADIUS_PACKET *rad_recv(int fd)
+{
+       RADIUS_PACKET           *packet;
+
        /*
-        *  Now that we've sanity checked the packet, we can allocate
-        *  memory for it, and copy the data from the local area to
-        *  the packet buffer.
+        *      Allocate the new request data structure
         */
-       if ((packet->data = malloc(packet->data_len)) == NULL) {
-         free(packet);
-         librad_log("out of memory");
-         return NULL;
+       if ((packet = malloc(sizeof(*packet))) == NULL) {
+               librad_log("out of memory");
+               return NULL;
+       }
+       memset(packet, 0, sizeof(*packet));
+
+       packet->data_len = rad_recvfrom(fd, &packet->data, 0,
+                                       &packet->src_ipaddr, &packet->src_port,
+                                       &packet->dst_ipaddr, &packet->dst_port);
+
+       /*
+        *      Check for socket errors.
+        */
+       if (packet->data_len < 0) {
+               librad_log("Error receiving packet: %s", strerror(errno));
+               /* packet->data is NULL */
+               free(packet);
+               return NULL;
+       }
+
+       /*
+        *      If the packet is too big, then rad_recvfrom did NOT
+        *      allocate memory.  Instead, it just discarded the
+        *      packet.
+        */
+       if (packet->data_len > MAX_PACKET_LEN) {
+               librad_log("Discarding packet: Larger than RFC limitation of 4096 bytes.");
+               /* packet->data is NULL */
+               free(packet);
+               return NULL;
+       }
+
+       /*
+        *      Read no data.  Continue.
+        *      This check is AFTER the MAX_PACKET_LEN check above, because
+        *      if the packet is larger than MAX_PACKET_LEN, we also have
+        *      packet->data == NULL
+        */
+       if ((packet->data_len == 0) || !packet->data) {
+               librad_log("No data.");
+               free(packet);
+               return NULL;
+       }
+
+       /*
+        *      See if it's a well-formed RADIUS packet.
+        */
+       if (!rad_packet_ok(packet)) {
+               rad_free(&packet);
+               return NULL;
+       }
+
+       /*
+        *      Remember which socket we read the packet from.
+        */
+       packet->sockfd = fd;
+
+       /*
+        *      FIXME: Do even more filtering by only permitting
+        *      certain IP's.  The problem is that we don't know
+        *      how to do this properly for all possible clients...
+        */
+
+       /*
+        *      Explicitely set the VP list to empty.
+        */
+       packet->vps = NULL;
+
+       if (librad_debug) {
+               char host_ipaddr[128];
+
+               if ((packet->code > 0) && (packet->code < MAX_PACKET_CODE)) {
+                       printf("rad_recv: %s packet from host %s port %d",
+                              packet_codes[packet->code],
+                              inet_ntop(packet->src_ipaddr.af,
+                                        &packet->src_ipaddr.ipaddr,
+                                        host_ipaddr, sizeof(host_ipaddr)),
+                              packet->src_port);
+               } else {
+                       printf("rad_recv: Packet from host %s port %d code=%d",
+                              inet_ntop(packet->src_ipaddr.af,
+                                        &packet->src_ipaddr.ipaddr,
+                                        host_ipaddr, sizeof(host_ipaddr)),
+                              packet->src_port,
+                              packet->code);
+               }
+               printf(", id=%d, length=%d\n", packet->id, packet->data_len);
        }
-       memcpy(packet->data, data, packet->data_len);
 
        return packet;
 }
@@ -1434,9 +1710,11 @@ int rad_verify(RADIUS_PACKET *packet, RADIUS_PACKET *original,
                                   sizeof(calc_auth_vector)) != 0) {
                                char buffer[32];
                                librad_log("Received packet from %s with invalid Message-Authenticator!  (Shared secret is incorrect.)",
-                                          ip_ntoa(buffer, packet->src_ipaddr));
+                                          inet_ntop(packet->src_ipaddr.af,
+                                                    &packet->src_ipaddr.ipaddr,
+                                                    buffer, sizeof(buffer)));
                                /* Silently drop packet, according to RFC 3579 */
-                               return -2;
+                               return -1;
                        } /* else the message authenticator was good */
 
                        /*
@@ -1452,10 +1730,27 @@ int rad_verify(RADIUS_PACKET *packet, RADIUS_PACKET *original,
        } /* loop over the packet, sanity checking the attributes */
 
        /*
+        *      It looks like a RADIUS packet, but we can't validate
+        *      the signature.
+        */
+       if ((packet->code == 0) || packet->code >= MAX_PACKET_CODE) {
+               char buffer[32];
+               librad_log("Received Unknown packet code %d"
+                          "from client %s port %d: Cannot validate signature",
+                          packet->code,
+                          inet_ntop(packet->src_ipaddr.af,
+                                    &packet->src_ipaddr.ipaddr,
+                                    buffer, sizeof(buffer)),
+                          packet->src_port);
+               return -1;
+       }
+
+       /*
         *      Calculate and/or verify digest.
         */
        switch(packet->code) {
                int rcode;
+               char buffer[32];
 
                case PW_AUTHENTICATION_REQUEST:
                case PW_STATUS_SERVER:
@@ -1468,10 +1763,11 @@ int rad_verify(RADIUS_PACKET *packet, RADIUS_PACKET *original,
 
                case PW_ACCOUNTING_REQUEST:
                        if (calc_acctdigest(packet, secret) > 1) {
-                               char buffer[32];
                                librad_log("Received Accounting-Request packet "
                                           "from %s with invalid signature!  (Shared secret is incorrect.)",
-                                          ip_ntoa(buffer, packet->src_ipaddr));
+                                          inet_ntop(packet->src_ipaddr.af,
+                                                    &packet->src_ipaddr.ipaddr,
+                                                    buffer, sizeof(buffer)));
                                return -1;
                        }
                        break;
@@ -1481,18 +1777,33 @@ int rad_verify(RADIUS_PACKET *packet, RADIUS_PACKET *original,
                case PW_AUTHENTICATION_REJECT:
                case PW_ACCESS_CHALLENGE:
                case PW_ACCOUNTING_RESPONSE:
+               case PW_DISCONNECT_ACK:
+               case PW_DISCONNECT_NAK:
+               case PW_COA_ACK:
+               case PW_COA_NAK:
                        rcode = calc_replydigest(packet, original, secret);
                        if (rcode > 1) {
-                               char buffer[32];
                                librad_log("Received %s packet "
                                           "from client %s port %d with invalid signature (err=%d)!  (Shared secret is incorrect.)",
                                           packet_codes[packet->code],
-                                          ip_ntoa(buffer, packet->src_ipaddr),
+                                          inet_ntop(packet->src_ipaddr.af,
+                                                    &packet->src_ipaddr.ipaddr,
+                                                    buffer, sizeof(buffer)),
                                           packet->src_port,
                                           rcode);
                                return -1;
                        }
-                 break;
+                       break;
+
+               default:
+                       librad_log("Received Unknown packet code %d"
+                                  "from client %s port %d: Cannot validate signature",
+                                  packet->code,
+                                  inet_ntop(packet->src_ipaddr.af,
+                                            &packet->src_ipaddr.ipaddr,
+                                                    buffer, sizeof(buffer)),
+                                  packet->src_port);
+                       return -1;
        }
 
        return 0;
@@ -1502,7 +1813,7 @@ int rad_verify(RADIUS_PACKET *packet, RADIUS_PACKET *original,
 /*
  *     Parse a RADIUS attribute into a data structure.
  */
-static VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET *original,
+VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET *original,
                        const char *secret, int attribute, int length,
                        const uint8_t *data)
 {
@@ -1543,7 +1854,7 @@ static VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET
        /*
         *      Copy the data to be decrypted
         */
-       memcpy(&vp->strvalue[0], data + offset, length - offset);
+       memcpy(&vp->vp_octets[0], data + offset, length - offset);
        vp->length -= offset;
 
        /*
@@ -1555,16 +1866,16 @@ static VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET
                 */
        case FLAG_ENCRYPT_USER_PASSWORD:
                if (original) {
-                       rad_pwdecode((char *)vp->strvalue,
+                       rad_pwdecode((char *)vp->vp_strvalue,
                                     vp->length, secret,
                                     original->vector);
                } else {
-                       rad_pwdecode((char *)vp->strvalue,
+                       rad_pwdecode((char *)vp->vp_strvalue,
                                     vp->length, secret,
                                     packet->vector);
                }
                if (vp->attribute == PW_USER_PASSWORD) {
-                       vp->length = strlen(vp->strvalue);
+                       vp->length = strlen(vp->vp_strvalue);
                }
                break;
                
@@ -1575,7 +1886,7 @@ static VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET
        case FLAG_ENCRYPT_TUNNEL_PASSWORD:
                if (!original) goto raw;
                
-               if (rad_tunnel_pwdecode(vp->strvalue, &vp->length,
+               if (rad_tunnel_pwdecode(vp->vp_octets, &vp->length,
                                        secret, original->vector) < 0) {
                        goto raw;
                }
@@ -1593,10 +1904,10 @@ static VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET
                        make_secret(my_digest,
                                    original->vector,
                                    secret, data);
-                       memcpy(vp->strvalue, my_digest,
+                       memcpy(vp->vp_strvalue, my_digest,
                               AUTH_VECTOR_LEN );
-                       vp->strvalue[AUTH_VECTOR_LEN] = '\0';
-                       vp->length = strlen(vp->strvalue);
+                       vp->vp_strvalue[AUTH_VECTOR_LEN] = '\0';
+                       vp->length = strlen(vp->vp_strvalue);
                }
                break;
 
@@ -1612,10 +1923,23 @@ static VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET
                /* nothing more to do */
                break;
 
+       case PW_TYPE_BYTE:
+               if (vp->length != 1) goto raw;
+
+               vp->lvalue = vp->vp_octets[0];
+               break;
+
+
+       case PW_TYPE_SHORT:
+               if (vp->length != 2) goto raw;
+
+               vp->lvalue = (vp->vp_octets[0] << 8) | vp->vp_octets[1];
+               break;
+
        case PW_TYPE_INTEGER:
                if (vp->length != 4) goto raw;
 
-               memcpy(&vp->lvalue, vp->strvalue, 4);
+               memcpy(&vp->lvalue, vp->vp_octets, 4);
                vp->lvalue = ntohl(vp->lvalue);
 
                if (vp->flags.has_tag) vp->lvalue &= 0x00ffffff;
@@ -1628,9 +1952,9 @@ static VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET
                        dval = dict_valbyattr(vp->attribute,
                                              vp->lvalue);
                        if (dval) {
-                               strNcpy(vp->strvalue,
+                               strlcpy(vp->vp_strvalue,
                                        dval->name,
-                                       sizeof(vp->strvalue));
+                                       sizeof(vp->vp_strvalue));
                        }
                }
                break;
@@ -1638,20 +1962,15 @@ static VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET
        case PW_TYPE_DATE:
                if (vp->length != 4) goto raw;
 
-               memcpy(&vp->lvalue, vp->strvalue, 4);
+               memcpy(&vp->lvalue, vp->vp_octets, 4);
                vp->lvalue = ntohl(vp->lvalue);
                break;
 
-               /*
-                *      IPv4 address. Keep it in network byte order in
-                *      vp->lvalue and put ASCII IP address in standard
-                *      dot notation into vp->strvalue.
-                */
+
        case PW_TYPE_IPADDR:
                if (vp->length != 4) goto raw;
 
-               memcpy(&vp->lvalue, vp->strvalue, 4);
-               ip_ntoa(vp->strvalue, vp->lvalue);
+               memcpy(&vp->lvalue, vp->vp_octets, 4);
                break;
 
                /*
@@ -1659,7 +1978,7 @@ static VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET
                 */
        case PW_TYPE_IFID:
                if (vp->length != 8) goto raw;
-               /* vp->vp_ifid == vp->strvalue */
+               /* vp->vp_ifid == vp->vp_octets */
                break;
                
                /*
@@ -1667,7 +1986,7 @@ static VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET
                 */
        case PW_TYPE_IPV6ADDR:
                if (vp->length != 16) goto raw;
-               /* vp->vp_ipv6addr == vp->strvalue */
+               /* vp->vp_ipv6addr == vp->vp_octets */
                break;
                
                /*
@@ -1681,14 +2000,14 @@ static VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET
                 */
        case PW_TYPE_IPV6PREFIX:
                if (vp->length < 2 || vp->length > 18) goto raw;
-               if (vp->strvalue[1] > 128) goto raw;
+               if (vp->vp_octets[1] > 128) goto raw;
 
                /*
                 *      FIXME: double-check that
-                *      (vp->strvalue[1] >> 3) matches vp->length + 2
+                *      (vp->vp_octets[1] >> 3) matches vp->length + 2
                 */
                if (vp->length < 18) {
-                       memset(vp->strvalue + vp->length, 0,
+                       memset(vp->vp_octets + vp->length, 0,
                               18 - vp->length);
                }
                break;
@@ -1697,7 +2016,7 @@ static VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET
        raw:
                vp->type = PW_TYPE_OCTETS;
                vp->length = length;
-               memcpy(vp->strvalue, data, length);
+               memcpy(vp->vp_octets, data, length);
                
 
                /*
@@ -1713,6 +2032,9 @@ static VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET
 
 /*
  *     Calculate/check digest, and decode radius attributes.
+ *     Returns:
+ *     -1 on decoding error
+ *     0 on success
  */
 int rad_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original,
               const char *secret)
@@ -1959,22 +2281,26 @@ int rad_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original,
 
                /*
                 *      Create the attribute, setting the default type
-                *      to 'octects'.  If the type in the dictionary
+                *      to 'octets'.  If the type in the dictionary
                 *      is different, then the dictionary type will
                 *      over-ride this one.
                 */
        create_pair:
                pair = rad_attr2vp(packet, original, secret,
-                                attribute, attrlen, ptr);
+                                  attribute, attrlen, ptr);
+       check_pair:
                if (!pair) {
                        pairfree(&packet->vps);
                        librad_log("out of memory");
                        return -1;
                }
 
-               debug_pair(pair);
                *tail = pair;
-               tail = &pair->next;
+               while (pair) {
+                       debug_pair(pair);
+                       tail = &pair->next;
+                       pair = pair->next;
+               }
 
                ptr += attrlen;
                packet_length -= attrlen;
@@ -2002,55 +2328,62 @@ int rad_decode(RADIUS_PACKET *packet, RADIUS_PACKET *original,
  *     password - a multiple of 16 bytes.
  */
 int rad_pwencode(char *passwd, int *pwlen, const char *secret,
-                const char *vector)
+                const uint8_t *vector)
 {
-       uint8_t buffer[AUTH_VECTOR_LEN + MAX_STRING_LEN + 1];
-       char    digest[AUTH_VECTOR_LEN];
+       lrad_MD5_CTX context, old;
+       uint8_t digest[AUTH_VECTOR_LEN];
        int     i, n, secretlen;
        int     len;
 
        /*
-        *      Pad password to multiple of AUTH_PASS_LEN bytes.
+        *      RFC maximum is 128 bytes.
+        *
+        *      If length is zero, pad it out with zeros.
+        *
+        *      If the length isn't aligned to 16 bytes,
+        *      zero out the extra data.
         */
        len = *pwlen;
+
        if (len > 128) len = 128;
-       *pwlen = len;
-       if (len % AUTH_PASS_LEN != 0) {
-               n = AUTH_PASS_LEN - (len % AUTH_PASS_LEN);
-               for (i = len; n > 0; n--, i++)
-                       passwd[i] = 0;
-               len = *pwlen = i;
 
-       } else if (len == 0) {
+       if (len == 0) {
                memset(passwd, 0, AUTH_PASS_LEN);
-               *pwlen = len = AUTH_PASS_LEN;
+               len = AUTH_PASS_LEN;
+       } else if ((len % AUTH_PASS_LEN) != 0) {
+               memset(&passwd[len], 0, AUTH_PASS_LEN - (len % AUTH_PASS_LEN));
+               len += AUTH_PASS_LEN - (len % AUTH_PASS_LEN);
        }
+       *pwlen = len;
 
        /*
         *      Use the secret to setup the decryption digest
         */
        secretlen = strlen(secret);
-       memcpy(buffer, secret, secretlen);
-       memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN);
-       librad_md5_calc((u_char *)digest, buffer, secretlen + AUTH_VECTOR_LEN);
-
-       /*
-        *      Now we can encode the password *in place*
-        */
-       for (i = 0; i < AUTH_PASS_LEN; i++)
-               passwd[i] ^= digest[i];
-
-       if (len <= AUTH_PASS_LEN) return 0;
+       
+       lrad_MD5Init(&context);
+       lrad_MD5Update(&context, secret, secretlen);
+       old = context;          /* save intermediate work */
 
        /*
-        *      Length > AUTH_PASS_LEN, so we need to use the extended
-        *      algorithm.
+        *      Encrypt it in place.  Don't bother checking
+        *      len, as we've ensured above that it's OK.
         */
-       for (n = 0; n < 128 && n <= (len - AUTH_PASS_LEN); n += AUTH_PASS_LEN) {
-               memcpy(buffer + secretlen, passwd + n, AUTH_PASS_LEN);
-               librad_md5_calc((u_char *)digest, buffer, secretlen + AUTH_PASS_LEN);
-               for (i = 0; i < AUTH_PASS_LEN; i++)
-                       passwd[i + n + AUTH_PASS_LEN] ^= digest[i];
+       for (n = 0; n < len; n += AUTH_PASS_LEN) {
+               if (n == 0) {
+                       lrad_MD5Update(&context, vector, AUTH_PASS_LEN);
+                       lrad_MD5Final(digest, &context);
+               } else {
+                       context = old;
+                       lrad_MD5Update(&context,
+                                        passwd + n - AUTH_PASS_LEN,
+                                        AUTH_PASS_LEN);
+                       lrad_MD5Final(digest, &context);
+               }
+               
+               for (i = 0; i < AUTH_PASS_LEN; i++) {
+                       passwd[i + n] ^= digest[i];
+               }
        }
 
        return 0;
@@ -2060,51 +2393,58 @@ int rad_pwencode(char *passwd, int *pwlen, const char *secret,
  *     Decode password.
  */
 int rad_pwdecode(char *passwd, int pwlen, const char *secret,
-                const char *vector)
+                const uint8_t *vector)
 {
-       uint8_t buffer[AUTH_VECTOR_LEN + MAX_STRING_LEN + 1];
-       char    digest[AUTH_VECTOR_LEN];
-       char    r[AUTH_VECTOR_LEN];
-       char    *s;
+       lrad_MD5_CTX context, old;
+       uint8_t digest[AUTH_VECTOR_LEN];
        int     i, n, secretlen;
-       int     rlen;
 
        /*
-        *      Use the secret to setup the decryption digest
+        *      The RFC's say that the maximum is 128.
+        *      The buffer we're putting it into above is 254, so
+        *      we don't need to do any length checking.
         */
-       secretlen = strlen(secret);
-       memcpy(buffer, secret, secretlen);
-       memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN);
-       librad_md5_calc((u_char *)digest, buffer, secretlen + AUTH_VECTOR_LEN);
+       if (pwlen > 128) pwlen = 128;
 
        /*
-        *      Now we can decode the password *in place*
+        *      Catch idiots.
         */
-       memcpy(r, passwd, AUTH_PASS_LEN);
-       for (i = 0; i < AUTH_PASS_LEN && i < pwlen; i++)
-               passwd[i] ^= digest[i];
+       if (pwlen == 0) goto done;
 
-       if (pwlen <= AUTH_PASS_LEN) {
-               passwd[pwlen+1] = 0;
-               return pwlen;
-       }
+       /*
+        *      Use the secret to setup the decryption digest
+        */
+       secretlen = strlen(secret);
+       
+       lrad_MD5Init(&context);
+       lrad_MD5Update(&context, secret, secretlen);
+       old = context;          /* save intermediate work */
 
        /*
-        *      Length > AUTH_PASS_LEN, so we need to use the extended
-        *      algorithm.
+        *      The inverse of the code above.
         */
-       rlen = ((pwlen - 1) / AUTH_PASS_LEN) * AUTH_PASS_LEN;
+       for (n = 0; n < pwlen; n += AUTH_PASS_LEN) {
+               if (n == 0) {
+                       lrad_MD5Update(&context, vector, AUTH_VECTOR_LEN);
+                       lrad_MD5Final(digest, &context);
 
-       for (n = rlen; n > 0; n -= AUTH_PASS_LEN ) {
-               s = (n == AUTH_PASS_LEN) ? r : (passwd + n - AUTH_PASS_LEN);
-               memcpy(buffer + secretlen, s, AUTH_PASS_LEN);
-               librad_md5_calc((u_char *)digest, buffer, secretlen + AUTH_PASS_LEN);
-               for (i = 0; i < AUTH_PASS_LEN && (i + n) < pwlen; i++)
+                       context = old;
+                       lrad_MD5Update(&context, passwd, AUTH_PASS_LEN);
+               } else {
+                       lrad_MD5Final(digest, &context);
+
+                       context = old;
+                       lrad_MD5Update(&context, passwd + n, AUTH_PASS_LEN);
+               }
+               
+               for (i = 0; i < AUTH_PASS_LEN; i++) {
                        passwd[i + n] ^= digest[i];
+               }
        }
-       passwd[pwlen] = 0;
 
-       return pwlen;
+ done:
+       passwd[pwlen] = '\0';
+       return strlen(passwd);
 }
 
 
@@ -2118,7 +2458,7 @@ int rad_pwdecode(char *passwd, int pwlen, const char *secret,
  *      value MD5 hash.
  */
 int rad_tunnel_pwencode(char *passwd, int *pwlen, const char *secret,
-                       const char *vector)
+                       const uint8_t *vector)
 {
        uint8_t buffer[AUTH_VECTOR_LEN + MAX_STRING_LEN + 3];
        unsigned char   digest[AUTH_VECTOR_LEN];
@@ -2129,6 +2469,7 @@ int rad_tunnel_pwencode(char *passwd, int *pwlen, const char *secret,
        len = *pwlen;
 
        if (len > 127) len = 127;
+
        /*
         * Shift the password 3 positions right to place a salt and original
         * length, tag will be added automatically on packet send
@@ -2200,13 +2541,12 @@ int rad_tunnel_pwencode(char *passwd, int *pwlen, const char *secret,
  *      above.
  */
 int rad_tunnel_pwdecode(uint8_t *passwd, int *pwlen, const char *secret,
-                       const char *vector)
+                       const uint8_t *vector)
 {
-       uint8_t         buffer[AUTH_VECTOR_LEN + MAX_STRING_LEN + 3];
+       lrad_MD5_CTX  context, old;
        uint8_t         digest[AUTH_VECTOR_LEN];
-       uint8_t         decrypted[MAX_STRING_LEN + 1];
        int             secretlen;
-       unsigned        i, n, len;
+       unsigned        i, n, len, reallen;
 
        len = *pwlen;
 
@@ -2241,64 +2581,62 @@ int rad_tunnel_pwdecode(uint8_t *passwd, int *pwlen, const char *secret,
         */
        secretlen = strlen(secret);
 
+       lrad_MD5Init(&context);
+       lrad_MD5Update(&context, secret, secretlen);
+       old = context;          /* save intermediate work */
+
        /*
         *      Set up the initial key:
         *
         *       b(1) = MD5(secret + vector + salt)
         */
-       memcpy(buffer, secret, secretlen);
-       memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN);
-       memcpy(buffer + secretlen + AUTH_VECTOR_LEN, passwd, 2);
-       librad_md5_calc(digest, buffer, secretlen + AUTH_VECTOR_LEN + 2);
-
-       /*
-        *      A quick check: decrypt the first octet of the password,
-        *      which is the 'data_len' field.  Ensure it's sane.
-        *
-        *      'n' doesn't include the 'data_len' octet
-        *      'len' does.
-        */
-       n = passwd[2] ^ digest[0];
-       if (n >= len) {
-               librad_log("tunnel password is too long for the attribute");
-               return -1;
-       }
+       lrad_MD5Update(&context, vector, AUTH_VECTOR_LEN);
+       lrad_MD5Update(&context, passwd, 2);
 
-       /*
-        *      Loop over the data, decrypting it, and generating
-        *      the key for the next round of decryption.
-        */
+       reallen = 0;
        for (n = 0; n < len; n += AUTH_PASS_LEN) {
-               for (i = 0; i < AUTH_PASS_LEN; i++) {
-                       decrypted[n + i] = passwd[n + i + 2] ^ digest[i];
+               int base = 0;
+
+               if (n == 0) {
+                       lrad_MD5Final(digest, &context);
+
+                       context = old;
 
                        /*
-                        *      Encrypted password may not be aligned
-                        *      on 16 octets, so we catch that here...
+                        *      A quick check: decrypt the first octet
+                        *      of the password, which is the
+                        *      'data_len' field.  Ensure it's sane.
                         */
-                       if ((n + i) == len) break;
+                       reallen = passwd[2] ^ digest[0];
+                       if (reallen >= len) {
+                               librad_log("tunnel password is too long for the attribute");
+                               return -1;
+                       }
+
+                       lrad_MD5Update(&context, passwd + 2, AUTH_PASS_LEN);
+
+                       base = 1;
+               } else {
+                       lrad_MD5Final(digest, &context);
+
+                       context = old;
+                       lrad_MD5Update(&context, passwd + n + 2, AUTH_PASS_LEN);
                }
 
-               /*
-                *      Update the digest, based on
-                *
-                *      b(n) = MD5(secret + cleartext(n-1)
-                *
-                *      but only if there's more data...
-                */
-               memcpy(buffer + secretlen, passwd + n + 2, AUTH_PASS_LEN);
-               librad_md5_calc(digest, buffer, secretlen + AUTH_PASS_LEN);
+               for (i = base; i < AUTH_PASS_LEN; i++) {
+                       passwd[n + i - 1] = passwd[n + i + 2] ^ digest[i];
+               }
        }
 
        /*
-        *      We've already validated the length of the decrypted
-        *      password.  Copy it back to the caller.
+        *      See make_tunnel_password, above.
         */
-       memcpy(passwd, decrypted + 1, decrypted[0]);
-       passwd[decrypted[0]] = 0;
-       *pwlen = decrypted[0];
+       if (reallen > 239) reallen = 239;
 
-       return decrypted[0];
+       *pwlen = reallen;
+       passwd[reallen] = 0;
+
+       return reallen;
 }
 
 /*
@@ -2308,12 +2646,12 @@ int rad_tunnel_pwdecode(uint8_t *passwd, int *pwlen, const char *secret,
  *     we use vp->length, and Ascend gear likes
  *     to send an extra '\0' in the string!
  */
-int rad_chap_encode(RADIUS_PACKET *packet, char *output, int id,
+int rad_chap_encode(RADIUS_PACKET *packet, uint8_t *output, int id,
                    VALUE_PAIR *password)
 {
        int             i;
        char            *ptr;
-       char            string[MAX_STRING_LEN * 2 + 1];
+       uint8_t         string[MAX_STRING_LEN * 2 + 1];
        VALUE_PAIR      *challenge;
 
        /*
@@ -2335,7 +2673,7 @@ int rad_chap_encode(RADIUS_PACKET *packet, char *output, int id,
        *ptr++ = id;
 
        i++;
-       memcpy(ptr, password->strvalue, password->length);
+       memcpy(ptr, password->vp_strvalue, password->length);
        ptr += password->length;
        i += password->length;
 
@@ -2345,7 +2683,7 @@ int rad_chap_encode(RADIUS_PACKET *packet, char *output, int id,
         */
        challenge = pairfind(packet->vps, PW_CHAP_CHALLENGE);
        if (challenge) {
-               memcpy(ptr, challenge->strvalue, challenge->length);
+               memcpy(ptr, challenge->vp_strvalue, challenge->length);
                i += challenge->length;
        } else {
                memcpy(ptr, packet->vector, AUTH_VECTOR_LEN);
@@ -2353,7 +2691,7 @@ int rad_chap_encode(RADIUS_PACKET *packet, char *output, int id,
        }
 
        *output = id;
-       librad_md5_calc((u_char *)output + 1, (u_char *)string, i);
+       librad_md5_calc((uint8_t *)output + 1, (uint8_t *)string, i);
 
        return 0;
 }
@@ -2371,7 +2709,7 @@ void lrad_rand_seed(const void *data, size_t size)
        /*
         *      Ensure that the pool is initialized.
         */
-       if (lrad_rand_index < 0) {
+       if (!lrad_rand_initialized) {
                int fd;
                
                memset(&lrad_rand_pool, 0, sizeof(lrad_rand_pool));
@@ -2396,7 +2734,8 @@ void lrad_rand_seed(const void *data, size_t size)
                }
 
                lrad_randinit(&lrad_rand_pool, 1);
-               lrad_rand_index = 0;
+               lrad_rand_pool.randcnt = 0;
+               lrad_rand_initialized = 1;
        }
 
        if (!data) return;
@@ -2404,18 +2743,11 @@ void lrad_rand_seed(const void *data, size_t size)
        /*
         *      Hash the user data
         */
-       hash = lrad_hash(data, size);
+       hash = lrad_rand();
+       if (!hash) hash = lrad_rand();
+       hash = lrad_hash_update(data, size, hash);
        
-       lrad_rand_pool.randrsl[lrad_rand_index & 0xff] ^= hash;
-       lrad_rand_index++;
-       lrad_rand_index &= 0xff;
-
-       /*
-        *      Churn the pool every so often after seeding it.
-        */
-       if (((int) (hash & 0xff)) == lrad_rand_index) {
-               lrad_isaac(&lrad_rand_pool);
-       }
+       lrad_rand_pool.randmem[lrad_rand_pool.randcnt] ^= hash;
 }
 
 
@@ -2429,28 +2761,20 @@ uint32_t lrad_rand(void)
        /*
         *      Ensure that the pool is initialized.
         */
-       if (lrad_rand_index < 0) {
+       if (!lrad_rand_initialized) {
                lrad_rand_seed(NULL, 0);
        }
 
-       /*
-        *      We don't return data directly from the pool.
-        *      Rather, we return a summary of the data.
-        */
-       num = lrad_rand_pool.randrsl[lrad_rand_index & 0xff];
-       lrad_rand_index++;
-       lrad_rand_index &= 0xff;
-
-       /*
-        *      Every so often, churn the pool.
-        */
-       if (((int) (num & 0xff)) == lrad_rand_index) {
+       num = lrad_rand_pool.randrsl[lrad_rand_pool.randcnt++];
+       if (lrad_rand_pool.randcnt == 256) {
                lrad_isaac(&lrad_rand_pool);
+               lrad_rand_pool.randcnt = 0;
        }
 
        return num;
 }
 
+
 /*
  *     Allocate a new RADIUS_PACKET
  */
@@ -2462,7 +2786,10 @@ RADIUS_PACKET *rad_alloc(int newvector)
                librad_log("out of memory");
                return NULL;
        }
-       memset(rp, 0, sizeof(RADIUS_PACKET));
+       memset(rp, 0, sizeof(*rp));
+       rp->id = -1;
+       rp->verified = -1;
+
        if (newvector) {
                int i;
                uint32_t hash, base;
@@ -2477,7 +2804,7 @@ RADIUS_PACKET *rad_alloc(int newvector)
                        memcpy(rp->vector + i, &hash, sizeof(hash));
                }
        }
-       lrad_rand();
+       lrad_rand();            /* stir the pool again */
 
        return rp;
 }
@@ -2492,8 +2819,8 @@ void rad_free(RADIUS_PACKET **radius_packet_ptr)
        if (!radius_packet_ptr) return;
        radius_packet = *radius_packet_ptr;
 
-       if (radius_packet->data) free(radius_packet->data);
-       if (radius_packet->vps) pairfree(&radius_packet->vps);
+       free(radius_packet->data);
+       pairfree(&radius_packet->vps);
 
        free(radius_packet);
 
index 26dcc43..4ece7ac 100644 (file)
  *   License along with this library; if not, write to the Free Software
  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- *  Copyright 2004  The FreeRADIUS server project
+ *  Copyright 2004,2006  The FreeRADIUS server project
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdlib.h>
 #include <string.h>
 
-#include "missing.h"
-#include "libradius.h"
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
 
 /* red-black tree description */
 typedef enum { Black, Red } NodeColor;
@@ -42,7 +43,7 @@ struct rbnode_t {
 };
 
 #define NIL &Sentinel           /* all leafs are sentinels */
-static const rbnode_t Sentinel = { NIL, NIL, NULL, Black, NULL};
+static rbnode_t Sentinel = { NIL, NIL, NULL, Black, NULL};
 
 struct rbtree_t {
 #ifndef NDEBUG
index 534c24a..75cb9f7 100644 (file)
@@ -6,7 +6,10 @@
  *  Version:   $Id$
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <string.h>
 
 #include <stdint.h>
 #endif
 
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
 #include "../include/sha1.h"
 
 #define blk0(i) (block->l[i] = htonl(block->l[i]))
@@ -143,9 +150,9 @@ uint8_t finalcount[8];
         finalcount[i] = (uint8_t)((context->count[(i >= 4 ? 0 : 1)]
          >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
     }
-    SHA1Update(context, "\200", 1);
+    SHA1Update(context, (const unsigned char *) "\200", 1);
     while ((context->count[0] & 504) != 448) {
-        SHA1Update(context, "\0", 1);
+        SHA1Update(context, (const unsigned char *) "\0", 1);
     }
     SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
     for (i = 0; i < 20; i++) {
index 85cb649..409c920 100644 (file)
@@ -24,8 +24,7 @@
          *  Fetched from: http://savannah.gnu.org/cgi-bin/viewcvs/mailutils/mailutils/lib/snprintf.c?rev=1.4
          *  Fetched from: http://savannah.gnu.org/cgi-bin/viewcvs/mailutils/mailutils/lib/snprintf.h?rev=1.4
          *  Replace config.h with autoconf.h
-         *  Protect with HAVE_LOCAL_SNPRINTF
-  
+         *  Protect with HAVE_SNPRINTF and HAVE_VSNPRINTF
    1.3:
       *  add #include <config.h> ifdef HAVE_CONFIG_H
       *  cosmetic change, when exponent is 0 print xxxE+00
 
 */
 
-#include "autoconf.h"
-
-#ifdef HAVE_LOCAL_SNPRINTF
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
+#include <freeradius-devel/autoconf.h>
 #include "snprintf.h"
 
+#ifndef HAVE_VSNPRINTF
+
 /*
  * Find the nth power of 10
  */
@@ -676,6 +677,8 @@ va_list args;
   return data.counter;
 }
 
+#endif /* HAVE_VSNPRINTF */
+
 #ifndef HAVE_SNPRINTF
 
 PUBLIC int
@@ -876,6 +879,4 @@ int main()
 
   return 0;
 }
-#endif
-
-#endif /* !HAVE_LOCAL_SNPRINTF */
+#endif /* !DRIVER */
index c951ac7..094a085 100644 (file)
@@ -35,6 +35,11 @@ Return values:
 Alain Magloire: alainm@rcsm.ee.mcgill.ca
 */
 
+#ifndef HAVE_VSNPRINTF
+
+#include <freeradius-devel/ident.h>
+RCSIDH(snprintf_h, "$Id$")
+
 #if __STDC__
 #include <stdarg.h>
 #else
@@ -44,6 +49,8 @@ Alain Magloire: alainm@rcsm.ee.mcgill.ca
 #include <stdlib.h>    /* for atoi() */
 #include <ctype.h>
 
+#define PRIVATE static
+#define PUBLIC
 
 /*
  * For the FLOATING POINT FORMAT :
@@ -117,8 +124,6 @@ struct DATA {
   int square, space, star_w, star_p, a_long, a_longlong;
 };
 
-#define PRIVATE static
-#define PUBLIC
 /* signature of the functions */
 #ifdef __STDC__
 /* the floating point stuff */
@@ -212,3 +217,5 @@ struct DATA {
               (p)->width = va_arg(args, int); \
             if ((p)->star_p == FOUND) \
               (p)->precision = va_arg(args, int)
+
+#endif /* HAVE_VSNPRINTF */
diff --git a/src/lib/strlcat.c b/src/lib/strlcat.c
new file mode 100644 (file)
index 0000000..56bfae4
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  strlcat.c  Concatenate strings.
+ *
+ *  Version:   $Id$
+ *
+ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Copyright 2006  The FreeRADIUS server project
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#ifndef HAVE_STRLCAT
+
+#include <sys/types.h>
+#include <string.h>
+#include <freeradius-devel/missing.h>
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left).  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t siz)
+{
+       char *d = dst;
+       const char *s = src;
+       size_t n = siz;
+       size_t dlen;
+
+       /* Find the end of dst and adjust bytes left but don't go past end */
+       while (n-- != 0 && *d != '\0')
+               d++;
+       dlen = d - dst;
+       n = siz - dlen;
+
+       if (n == 0)
+               return(dlen + strlen(s));
+       while (*s != '\0') {
+               if (n != 1) {
+                       *d++ = *s;
+                       n--;
+               }
+               s++;
+       }
+       *d = '\0';
+
+       return(dlen + (s - src));       /* count does not include NUL */
+}
+
+#endif
diff --git a/src/lib/strlcpy.c b/src/lib/strlcpy.c
new file mode 100644 (file)
index 0000000..c507e47
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *  strlcpy.c  Copy strings.
+ *
+ *  Version:   $Id$
+ *
+ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Copyright 2006  The FreeRADIUS server project
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#ifndef HAVE_STRLCPY
+
+#include <sys/types.h>
+#include <freeradius-devel/missing.h>
+
+/*
+ * Copy src to string dst of size siz.  At most siz-1 characters
+ * will be copied.  Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+       char *d = dst;
+       const char *s = src;
+       size_t n = siz;
+
+       /* Copy as many bytes as will fit */
+       if (n != 0 && --n != 0) {
+               do {
+                       if ((*d++ = *s++) == 0)
+                               break;
+               } while (--n != 0);
+       }
+
+       /* Not enough room in dst, add NUL and traverse rest of src */
+       if (n == 0) {
+               if (siz != 0)
+                       *d = '\0';              /* NUL-terminate dst */
+               while (*s++)
+                       ;
+       }
+
+       return(s - src - 1);    /* count does not include NUL */
+}
+
+#endif
index cdad21c..6191471 100644 (file)
  *   License along with this library; if not, write to the Free Software
  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include "token.h"
-
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/token.h>
 
 static const LRAD_NAME_NUMBER tokens[] = {
        { "=~", T_OP_REG_EQ,    }, /* order is important! */
index 3798ffa..bad2c34 100644 (file)
  * Version: $Id$
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #ifdef WITH_UDPFROMTO
-static const char rcsid[] = "$Id$";
 
 #include <sys/types.h>
 
@@ -51,7 +53,7 @@ static const char rcsid[] = "$Id$";
 #include <fcntl.h>
 #include <string.h>
 
-#include "udpfromto.h"
+#include <freeradius-devel/udpfromto.h>
 
 int udpfromto_init(int s)
 {
@@ -180,11 +182,22 @@ int sendfromto(int s, void *buf, size_t len, int flags,
        struct in_pktinfo pktinfo, *pktinfo_ptr;
        memset(&pktinfo, 0, sizeof(struct in_pktinfo));
 # endif
+       struct sockaddr_in      *s4;
 
 # ifdef HAVE_IP_SENDSRCADDR
        char cmsgbuf[CMSG_SPACE(sizeof(struct in_addr))];
 # endif
 
+       s4 = (struct sockaddr_in *) from;
+
+       /*
+        *      Source is unset, empty, or unspecified,
+        *      fall back to sendto().
+        */
+       if (!s4 || (fromlen == 0) || (s4->sin_family == AF_UNSPEC)) {
+               return sendto(s, buf, len, flags, to, tolen);
+       }
+
        /* Set up iov and msgh structures. */
        memset(&msgh, 0, sizeof(struct msghdr));
        iov.iov_base = buf;
index 535c79f..7b3a3e8 100644 (file)
  *   License along with this library; if not, write to the Free Software
  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include       "autoconf.h"
+#include       <freeradius-devel/autoconf.h>
 
 #include       <sys/types.h>
 
@@ -31,8 +32,6 @@ static const char rcsid[] = "$Id$";
 #include       <string.h>
 #include       <ctype.h>
 
-#include       "libradius.h"
-
 #ifdef HAVE_MALLOC_H
 #  include     <malloc.h>
 #endif
@@ -41,7 +40,8 @@ static const char rcsid[] = "$Id$";
 #  include     <regex.h>
 #endif
 
-#include       "missing.h"
+#include       <freeradius-devel/missing.h>
+#include       <freeradius-devel/libradius.h>
 
 static const char *months[] = {
         "jan", "feb", "mar", "apr", "may", "jun",
@@ -87,11 +87,32 @@ VALUE_PAIR *paircreate(int attr, int type)
                }
        }
        switch (vp->type) {
+               case PW_TYPE_BYTE:
+                       vp->length = 1;
+                       break;
+
+               case PW_TYPE_SHORT:
+                       vp->length = 2;
+                       break;
+
                case PW_TYPE_INTEGER:
                case PW_TYPE_IPADDR:
                case PW_TYPE_DATE:
                        vp->length = 4;
                        break;
+
+               case PW_TYPE_IFID:
+                       vp->length = sizeof(vp->vp_ifid);
+                       break;
+
+               case PW_TYPE_IPV6ADDR:
+                       vp->length = sizeof(vp->vp_ipv6addr);
+                       break;
+
+               case PW_TYPE_IPV6PREFIX:
+                       vp->length = sizeof(vp->vp_ipv6prefix);
+                       break;
+
                default:
                        vp->length = 0;
                        break;
@@ -169,6 +190,8 @@ void pairadd(VALUE_PAIR **first, VALUE_PAIR *add)
 {
        VALUE_PAIR *i;
 
+       if (!add) return;
+
        if (*first == NULL) {
                *first = add;
                return;
@@ -276,19 +299,13 @@ void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
        VALUE_PAIR *found;
        int has_password = 0;
 
-       if (*to == NULL) {
-               *to = *from;
-               *from = NULL;
-               return;
-       }
-
        /*
         *      First, see if there are any passwords here, and
         *      point "tailto" to the end of the "to" list.
         */
        tailto = to;
        for(i = *to; i; i = i->next) {
-               if (i->attribute == PW_PASSWORD ||
+               if (i->attribute == PW_USER_PASSWORD ||
                    i->attribute == PW_CRYPT_PASSWORD)
                        has_password = 1;
                tailto = &i->next;
@@ -299,17 +316,40 @@ void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
         */
        for(i = *from; i; i = next) {
                next = i->next;
+
                /*
                 *      If there was a password in the "to" list,
                 *      do not move any other password from the
                 *      "from" to the "to" list.
                 */
                if (has_password &&
-                   (i->attribute == PW_PASSWORD ||
+                   (i->attribute == PW_USER_PASSWORD ||
                     i->attribute == PW_CRYPT_PASSWORD)) {
                        tailfrom = i;
                        continue;
                }
+
+               switch (i->operator) {
+                       /*
+                        *      These are COMPARISON attributes
+                        *      from a check list, and are not
+                        *      supposed to be copied!
+                        */
+                       case T_OP_NE:
+                       case T_OP_GE:
+                       case T_OP_GT:
+                       case T_OP_LE:
+                       case T_OP_LT:
+                       case T_OP_CMP_TRUE:
+                       case T_OP_CMP_FALSE:
+                       case T_OP_CMP_EQ:
+                               tailfrom = i;
+                               continue;
+
+                       default:
+                               break;
+               }
+
                /*
                 *      If the attribute is already present in "to",
                 *      do not move it from "from" to "to". We make
@@ -323,14 +363,14 @@ void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
                        switch (i->operator) {
 
                          /*
-                          *  If a similar attribute is found,
-                          *  delete it.
+                          *    If matching attributes are found,
+                          *    delete them.
                           */
                        case T_OP_SUB:          /* -= */
                                if (found) {
-                                       if (!i->strvalue[0] ||
-                                           (strcmp((char *)found->strvalue,
-                                                   (char *)i->strvalue) == 0)){
+                                       if (!i->vp_strvalue[0] ||
+                                           (strcmp((char *)found->vp_strvalue,
+                                                   (char *)i->vp_strvalue) == 0)){
                                                pairdelete(to, found->attribute);
 
                                                /*
@@ -358,29 +398,29 @@ void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
 
                        case T_OP_REG_EQ:
                          if (found &&
-                             (i->strvalue[0] == 's')) {
+                             (i->vp_strvalue[0] == 's')) {
                            regex_t             reg;
                            regmatch_t          match[1];
 
                            char *str;
                            char *p, *q;
 
-                           p = i->strvalue + 1;
+                           p = i->vp_strvalue + 1;
                            q = strchr(p + 1, *p);
                            if (!q || (q[strlen(q) - 1] != *p)) {
                              tailfrom = i;
                              continue;
                            }
-                           str = strdup(i->strvalue + 2);
+                           str = strdup(i->vp_strvalue + 2);
                            q = strchr(str, *p);
                            *(q++) = '\0';
                            q[strlen(q) - 1] = '\0';
 
                            regcomp(&reg, str, 0);
-                           if (regexec(&reg, found->strvalue,
+                           if (regexec(&reg, found->vp_strvalue,
                                        1, match, 0) == 0) {
                              fprintf(stderr, "\"%s\" will have %d to %d replaced with %s\n",
-                                     found->strvalue, match[0].rm_so,
+                                     found->vp_strvalue, match[0].rm_so,
                                      match[0].rm_eo, q);
 
                            }
@@ -410,15 +450,32 @@ void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
                           */
                        case T_OP_SET:          /* := */
                                if (found) {
-                                       pairdelete(to, found->attribute);
+                                       VALUE_PAIR *mynext = found->next;
+
+                                       /*
+                                        *      Do NOT call pairdelete()
+                                        *      here, due to issues with
+                                        *      re-writing "request->username".
+                                        *
+                                        *      Everybody calls pairmove,
+                                        *      and expects it to work.
+                                        *      We can't update request->username
+                                        *      here, so instead we over-write
+                                        *      the vp that it's pointing to.
+                                        */
+                                       memcpy(found, i, sizeof(*found));
+                                       found->next = mynext;
+
+                                       pairdelete(&found->next, found->attribute);
+
                                        /*
                                         *      'tailto' may have been
                                         *      deleted...
                                         */
-                                       tailto = to;
-                                       for(j = *to; j; j = j->next) {
+                                       for(j = found; j; j = j->next) {
                                                tailto = &j->next;
                                        }
+                                       continue;
                                }
                                break;
 
@@ -540,7 +597,7 @@ static char *mystrtok(char **ptr, const char *sep)
  *     Turn printable string into time_t
  *     Returns -1 on error, 0 on OK.
  */
-static int gettime(const char *valstr, time_t *lvalue)
+static int gettime(const char *valstr, uint32_t *lvalue)
 {
        int             i;
        time_t          t;
@@ -562,7 +619,7 @@ static int gettime(const char *valstr, time_t *lvalue)
        memset(tm, 0, sizeof(*tm));
        tm->tm_isdst = -1;      /* don't know, and don't care about DST */
 
-       strNcpy(buf, valstr, sizeof(buf));
+       strlcpy(buf, valstr, sizeof(buf));
 
        p = buf;
        f[0] = mystrtok(&p, " \t");
@@ -572,6 +629,21 @@ static int gettime(const char *valstr, time_t *lvalue)
        if (!f[0] || !f[1] || !f[2]) return -1;
 
        /*
+        *      The time has a colon, where nothing else does.
+        *      So if we find it, bubble it to the back of the list.
+        */
+       if (f[3]) {
+               for (i = 0; i < 3; i++) {
+                       if (strchr(f[i], ':')) {
+                               p = f[3];
+                               f[3] = f[i];
+                               f[i] = p;
+                               break;
+                       }
+               }
+       }
+
+       /*
         *  The month is text, which allows us to find it easily.
         */
        tm->tm_mon = 12;
@@ -638,8 +710,11 @@ static int gettime(const char *valstr, time_t *lvalue)
                *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
 
                f[2] = strchr(f[1], ':'); /* find : separator */
-               if (!f[2]) return -1;
-               *(f[2]++) = '\0';       /* nuke it, and point to SS */
+               if (f[2]) {
+                 *(f[2]++) = '\0';     /* nuke it, and point to SS */
+               } else {
+                 strcpy(f[2], "0");    /* assignment would discard const */
+               }
 
                tm->tm_hour = atoi(f[0]);
                tm->tm_min = atoi(f[1]);
@@ -657,8 +732,14 @@ static int gettime(const char *valstr, time_t *lvalue)
        return 0;
 }
 
+
 /*
  *  Parse a string value into a given VALUE_PAIR
+ *
+ *  FIXME: we probably want to fix this function to accept
+ *  octets as values for any type of attribute.  We should then
+ *  double-check the parsed value, to be sure it's legal for that
+ *  type (length, etc.)
  */
 VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
 {
@@ -668,10 +749,10 @@ VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
 
        /*
         *      Even for integers, dates and ip addresses we
-        *      keep the original string in vp->strvalue.
+        *      keep the original string in vp->vp_strvalue.
         */
-       strNcpy((char *)vp->strvalue, value, sizeof(vp->strvalue));
-       vp->length = strlen(vp->strvalue);
+       strlcpy((char *)vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
+       vp->length = strlen(vp->vp_strvalue);
 
        switch(vp->type) {
                case PW_TYPE_STRING:
@@ -682,6 +763,14 @@ VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
 
                case PW_TYPE_IPADDR:
                        /*
+                        *      It's a comparison, not a real IP.
+                        */
+                       if ((vp->operator == T_OP_REG_EQ) ||
+                           (vp->operator == T_OP_REG_NE)) {
+                               break;
+                       }
+
+                       /*
                         *      FIXME: complain if hostname
                         *      cannot be resolved, or resolve later!
                         */
@@ -694,38 +783,100 @@ VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
                                p = NULL;
                                cs = value;
                        }
-                       vp->lvalue = librad_dodns ? ip_getaddr(cs) :
-                                                   ip_addr(cs);
+                       
+                       {
+                               lrad_ipaddr_t ipaddr;
+
+                               if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
+                                       librad_log("Failed to find IP address for %s", cs);
+                                       return NULL;
+                               }
+
+                               vp->lvalue = ipaddr.ipaddr.ip4addr.s_addr;
+                       }
                        if (s) free(s);
                        vp->length = 4;
                        break;
+
+               case PW_TYPE_BYTE:
+                       /*
+                        *      Note that ALL integers are unsigned!
+                        */
+                       vp->lvalue = (uint32_t) strtoul(value, &p, 10);
+                       if (!*p) {
+                               if (vp->lvalue > 255) {
+                                       librad_log("Byte value \"%s\" is larger than 255", value);
+                                       return NULL;
+                               }
+                               vp->length = 1;
+                               break;
+                       }
+
+                       /*
+                        *      Look for the named value for the given
+                        *      attribute.
+                        */
+                       if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
+                               librad_log("Unknown value %s for attribute %s",
+                                          value, vp->name);
+                               return NULL;
+                       }
+                       vp->lvalue = dval->value;
+                       vp->length = 1;
+                       break;
+
+               case PW_TYPE_SHORT:
+                       /*
+                        *      Note that ALL integers are unsigned!
+                        */
+                       vp->lvalue = (uint32_t) strtoul(value, &p, 10);
+                       if (!*p) {
+                               if (vp->lvalue > 65535) {
+                                       librad_log("Byte value \"%s\" is larger than 65535", value);
+                                       return NULL;
+                               }
+                               vp->length = 2;
+                               break;
+                       }
+
+                       /*
+                        *      Look for the named value for the given
+                        *      attribute.
+                        */
+                       if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
+                               librad_log("Unknown value %s for attribute %s",
+                                          value, vp->name);
+                               return NULL;
+                       }
+                       vp->lvalue = dval->value;
+                       vp->length = 2;
+                       break;
+
                case PW_TYPE_INTEGER:
                        /*
-                        *      If it starts with a digit, it must
-                        *      be a number (or a range).
-                        *
                         *      Note that ALL integers are unsigned!
                         */
-                       if (strspn(value, "0123456789") == strlen(value)) {
-                               vp->lvalue = (uint32_t) strtoul(value, NULL, 10);
+                       vp->lvalue = (uint32_t) strtoul(value, &p, 10);
+                       if (!*p) {
                                vp->length = 4;
+                               break;
                        }
+
                        /*
                         *      Look for the named value for the given
                         *      attribute.
                         */
-                       else if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
+                       if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
                                librad_log("Unknown value %s for attribute %s",
                                           value, vp->name);
                                return NULL;
-                       } else {
-                               vp->lvalue = dval->value;
-                               vp->length = 4;
                        }
+                       vp->lvalue = dval->value;
+                       vp->length = 4;
                        break;
 
                case PW_TYPE_DATE:
-                       if (gettime(value, (time_t *)&vp->lvalue) < 0) {
+                       if (gettime(value, &vp->lvalue) < 0) {
                                librad_log("failed to parse time string "
                                           "\"%s\"", value);
                                return NULL;
@@ -737,14 +888,9 @@ VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
                        if (strncasecmp(value, "0x", 2) == 0) {
                                vp->type = PW_TYPE_OCTETS;
                                goto do_octets;
-                       }                       
+                       }
 
-                       /*
-                        *      Special case to convert filter to binary
-                        */
-                       strNcpy(vp->strvalue, value, sizeof(vp->strvalue));
                        if (ascend_parse_filter(vp) < 0 ) {
-                         fprintf(stderr, "FUCK %s\n", value);
                                librad_log("failed to parse Ascend binary attribute: %s",
                                           librad_errstr);
                                return NULL;
@@ -763,7 +909,7 @@ VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
                        if (strncasecmp(value, "0x", 2) == 0) {
                                uint8_t *us;
                                cp = value + 2;
-                               us = vp->strvalue;
+                               us = vp->vp_octets;
                                vp->length = 0;
 
 
@@ -777,7 +923,8 @@ VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
                                }
                                
                                
-                               while (*cp && vp->length < MAX_STRING_LEN) {
+                               while (*cp &&
+                                      (vp->length < MAX_STRING_LEN)) {
                                        unsigned int tmp;
 
                                        if (sscanf(cp, "%02x", &tmp) != 1) {
@@ -789,32 +936,62 @@ VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
                                        *(us++) = tmp;
                                        vp->length++;
                                }
-                               *us = '\0';
                        }
                        break;
 
                case PW_TYPE_IFID:
-                       if (ifid_aton(value, vp->strvalue) == NULL) {
+                       if (ifid_aton(value, (unsigned char *) vp->vp_strvalue) == NULL) {
                                librad_log("failed to parse interface-id "
                                           "string \"%s\"", value);
                                return NULL;
                        }
                        vp->length = 8;
-                       vp->strvalue[vp->length] = '\0';
+                       vp->vp_strvalue[vp->length] = '\0';
                        break;
 
                case PW_TYPE_IPV6ADDR:
-                       if (ipv6_addr(value, vp->strvalue) < 0) {
+                       if (inet_pton(AF_INET6, value, vp->vp_strvalue) <= 0) {
                                librad_log("failed to parse IPv6 address "
                                           "string \"%s\"", value);
                                return NULL;
                        }
                        vp->length = 16; /* length of IPv6 address */
-                       vp->strvalue[vp->length] = '\0';
+                       vp->vp_strvalue[vp->length] = '\0';
                        break;
                        /*
                         *  Anything else.
                         */
+               case PW_TYPE_IPV6PREFIX:
+                       p = strchr(value, '/');
+                       if (!p || ((p - value) >= 256)) {
+                               librad_log("invalid IPv6 prefix "
+                                          "string \"%s\"", value);
+                               return NULL;
+                       } else {
+                               unsigned int prefix;
+                               char buffer[256], *eptr;
+                               
+                               memcpy(buffer, value, p - value);
+                               buffer[p - value] = '\0';
+                               
+                               if (inet_pton(AF_INET6, buffer, vp->vp_strvalue + 2) <= 0) {
+                                       librad_log("failed to parse IPv6 address "
+                                                  "string \"%s\"", value);
+                                       return NULL;
+                               }
+                               
+                               prefix = strtoul(p + 1, &eptr, 10);
+                               if ((prefix > 128) || *eptr) {
+                                       librad_log("failed to parse IPv6 address "
+                                                  "string \"%s\"", value);
+                                       return NULL;
+                               }
+                               vp->vp_strvalue[1] = prefix;
+                       }
+                       vp->vp_strvalue[0] = '\0';
+                       vp->length = 16 + 2;
+                       break;
+
                default:
                        librad_log("unknown attribute type %d", vp->type);
                        return NULL;
@@ -836,7 +1013,6 @@ static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
        int             attr;
        const char      *p;
        VALUE_PAIR      *vp;
-       DICT_ATTR       *da;
 
        /*
         *      Unknown attributes MUST be of type 'octets'
@@ -854,7 +1030,6 @@ static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
                p += strspn(p, "0123456789");
                if (*p != 0) goto error;
 
-
                /*
                 *      Vendor-%d-Attr-%d
                 */
@@ -890,7 +1065,7 @@ static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
                int vendor;
                char buffer[256];
 
-               if ((p - attribute) >= sizeof(buffer)) goto error;
+               if (((size_t) (p - attribute)) >= sizeof(buffer)) goto error;
 
                memcpy(buffer, attribute, p - attribute);
                buffer[p - attribute] = '\0';
@@ -933,56 +1108,7 @@ static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
                return NULL;
        }
 
-       /*
-        *      Dictionary type over-rides what the caller says.
-        *      This "converts" the parsed value into the appropriate
-        *      type.
-        *
-        *      Also, normalize the name of the attribute...
-        *
-        *      Much of this code is copied from paircreate()
-        */
-       if ((da = dict_attrbyvalue(attr)) != NULL) {
-               strcpy(vp->name, da->name);
-               vp->type = da->type;
-               vp->flags = da->flags;
-
-               /*
-                *      Sanity check the type for length.  We don't
-                *      want to look at attributes which are of the
-                *      wrong length.
-                */
-               switch (vp->type) {
-               case PW_TYPE_DATE:
-               case PW_TYPE_INTEGER:
-               case PW_TYPE_IPADDR: /* always kept in network byte order */
-                       if (vp->length != 4) {
-                       length_error:
-                               pairfree(&vp);
-                               librad_log("Attribute has invalid length");
-                               return NULL;
-                       }
-                       memcpy(&vp->lvalue, vp->strvalue, sizeof(vp->lvalue));
-                       break;
-
-               case PW_TYPE_IFID:
-                       if (vp->length != 8) goto length_error;
-                       break;
-
-               case PW_TYPE_IPV6ADDR:
-                       if (vp->length != 16) goto length_error;
-                       break;
-
-#ifdef ASCEND_BINARY
-               case PW_TYPE_ABINARY:
-                       if (vp->length != 32) goto length_error;
-                       break;
-#endif
-               default:        /* string, octets, etc. */
-                       break;
-               }
-
-       } else if (VENDOR(attr) == 0) {
+       if (VENDOR(attr) == 0) {
                sprintf(vp->name, "Attr-%u", attr);
        } else {
                sprintf(vp->name, "Vendor-%u-Attr-%u",
@@ -1018,7 +1144,12 @@ VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator)
        found_tag = 0;
        tag = 0;
 
-       ts = strrchr( attribute, ':' );
+       ts = strrchr(attribute, ':');
+       if (ts && !ts[1]) {
+               librad_log("Invalid tag for attribute %s", attribute);
+               return NULL;
+       }
+
        if (ts && ts[1]) {
                 /* Colon found with something behind it */
                 if (ts[1] == '*' && ts[2] == 0) {
@@ -1104,7 +1235,7 @@ VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator)
                 */
        case T_OP_CMP_TRUE:
        case T_OP_CMP_FALSE:
-               vp->strvalue[0] = '\0';
+               vp->vp_strvalue[0] = '\0';
                vp->length = 0;
                return vp;
                break;
@@ -1148,6 +1279,14 @@ VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator)
 #endif
        }
 
+       /*
+        *      FIXME: if (strcasecmp(attribute, vp->name) != 0)
+        *      then the user MAY have typed in the attribute name
+        *      as Vendor-%d-Attr-%d, and the value MAY be octets.
+        *
+        *      We probably want to fix pairparsevalue to accept
+        *      octets as values for any attribute.
+        */
        if (value && (pairparsevalue(vp, value) == NULL)) {
                pairbasicfree(vp);
                return NULL;
@@ -1156,6 +1295,29 @@ VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator)
        return vp;
 }
 
+
+/*
+ *     [a-zA-Z0-9_-:]+
+ */
+static const int valid_attr_name[256] = {
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+       0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
+       0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
 /*
  *     Read a valuepair from a buffer, and advance pointer.
  *     Sets *eol to T_EOL if end of line was encountered.
@@ -1164,34 +1326,59 @@ VALUE_PAIR *pairread(char **ptr, LRAD_TOKEN *eol)
 {
        char            buf[64];
        char            attr[64];
-       char            value[520];
-       char            *p;
+       char            value[512];
+       char            *p, *q;
        LRAD_TOKEN      token, t, xlat;
        VALUE_PAIR      *vp;
+       size_t          len;
 
-       *eol = T_INVALID;
+       *eol = T_OP_INVALID;
 
-       /* Get attribute. */
-       token = gettoken(ptr, attr, sizeof(attr));
+       p = *ptr;
+       while ((*p == ' ') || (*p == '\t')) p++;
 
-       /*  If it's a comment, then exit, as we haven't read a pair */
-       if (token == T_HASH) {
-               *eol = token;
+       if (!*p) {
+               *eol = T_OP_INVALID;
+               librad_log("No token read where we expected an attribute name");
+               return NULL;
+       }
+
+       if (*p == '#') {
+               *eol = T_HASH;
                librad_log("Read a comment instead of a token");
                return NULL;
        }
 
-       /*  It's not a comment, so it MUST be an attribute */
-       if ((token == T_EOL) ||
-           (attr[0] == 0)) {
-               librad_log("No token read where we expected an attribute name");
+       q = attr;
+       for (len = 0; len < sizeof(attr); len++) {
+               if (valid_attr_name[(int)*p]) {
+                       *q++ = *p++;
+                       continue;
+               }
+               break;
+       }
+
+       if (len == sizeof(attr)) {
+               *eol = T_OP_INVALID;
+               librad_log("Attribute name is too long");
                return NULL;
        }
 
-       /* Now we should have an '=' here. */
+       /*
+        *      We may have Foo-Bar:= stuff, so back up.
+        */
+       if (attr[len - 1] == ':') {
+               p--;
+               len--;
+       }
+
+       attr[len] = '\0';
+       *ptr = p;
+
+       /* Now we should have an operator here. */
        token = gettoken(ptr, buf, sizeof(buf));
        if (token < T_EQSTART || token > T_EQEND) {
-               librad_log("expecting '='");
+               librad_log("expecting operator");
                return NULL;
        }
 
@@ -1217,6 +1404,7 @@ VALUE_PAIR *pairread(char **ptr, LRAD_TOKEN *eol)
                *ptr = p;
        }
 
+       vp = NULL;
        switch (xlat) {
                /*
                 *      Make the full pair now.
@@ -1231,13 +1419,17 @@ VALUE_PAIR *pairread(char **ptr, LRAD_TOKEN *eol)
        case T_DOUBLE_QUOTED_STRING:
                p = strchr(value, '%');
                if (p && (p[1] == '{')) {
+                       if (strlen(value) >= sizeof(vp->vp_strvalue)) {
+                               librad_log("Value too long");
+                               return NULL;
+                       }
                        vp = pairmake(attr, NULL, token);
                        if (!vp) {
-                               *eol = T_INVALID;
+                               *eol = T_OP_INVALID;
                                return NULL;
                        }
 
-                       strNcpy(vp->strvalue, value, sizeof(vp->strvalue));
+                       strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
                        vp->flags.do_xlat = 1;
                        vp->length = 0;
                } else {
@@ -1250,23 +1442,28 @@ VALUE_PAIR *pairread(char **ptr, LRAD_TOKEN *eol)
                 *      Mark the pair to be allocated later.
                 */
        case T_BACK_QUOTED_STRING:
+               if (strlen(value) >= sizeof(vp->vp_strvalue)) {
+                       librad_log("Value too long");
+                       return NULL;
+               }
+
                vp = pairmake(attr, NULL, token);
                if (!vp) {
-                       *eol = T_INVALID;
+                       *eol = T_OP_INVALID;
                        return NULL;
                }
 
                vp->flags.do_xlat = 1;
-               strNcpy(vp->strvalue, value, sizeof(vp->strvalue));
+               strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
                vp->length = 0;
                break;
        }
 
        /*
-        *      If we didn't make a pair, return an error.
+        *      If we didn't make a pair, return an error.
         */
        if (!vp) {
-               *eol = T_INVALID;
+               *eol = T_OP_INVALID;
                return NULL;
        }
 
@@ -1281,7 +1478,7 @@ LRAD_TOKEN userparse(char *buffer, VALUE_PAIR **first_pair)
 {
        VALUE_PAIR      *vp;
        char            *p;
-       LRAD_TOKEN      last_token = T_INVALID;
+       LRAD_TOKEN      last_token = T_OP_INVALID;
        LRAD_TOKEN      previous_token;
 
        /*
@@ -1351,7 +1548,7 @@ VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix)
                last_token = userparse(buf, &vp);
                if (!vp) {
                        if (last_token != T_EOL) {
-                               librad_perror(errprefix);
+                               librad_perror("%s", errprefix);
                                error = 1;
                                break;
                        }
@@ -1369,3 +1566,170 @@ VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix)
        return error ? NULL: list;
 }
 
+
+
+/*
+ *     Compare two pairs, using the operator from "one".
+ *
+ *     i.e. given two attributes, it does:
+ *
+ *     (two->data) (one->operator) (one->data)
+ *
+ *     e.g. "foo" != "bar"
+ *
+ *     Returns true (comparison is true), or false (comparison is not true);
+ */
+int paircmp(VALUE_PAIR *one, VALUE_PAIR *two)
+{
+       int compare;
+
+       switch (one->operator) {
+       case T_OP_CMP_TRUE:
+               return (two != NULL);
+
+       case T_OP_CMP_FALSE:
+               return (two == NULL);
+
+               /*
+                *      One is a regex, compile it, print two to a string,
+                *      and then do string comparisons.
+                */
+       case T_OP_REG_EQ:
+       case T_OP_REG_NE:
+#ifndef HAVE_REGEX_H
+               return -1;
+#else
+               {
+                       regex_t reg;
+                       char buffer[MAX_STRING_LEN * 4 + 1];
+                       
+                       compare = regcomp(&reg, one->vp_strvalue,
+                                         REG_EXTENDED);
+                       if (compare != 0) {
+                               regerror(compare, &reg, buffer, sizeof(buffer));
+                               librad_log("Illegal regular expression in attribute: %s: %s",
+                                          one->name, buffer);
+                               return -1;
+                       }
+
+                       vp_prints_value(buffer, sizeof(buffer), two, 0);
+
+                       /*
+                        *      Don't care about substring matches,
+                        *      oh well...
+                        */
+                       compare = regexec(&reg, buffer, 0, NULL, 0);
+
+                       regfree(&reg);
+                       if (one->operator == T_OP_REG_EQ) return (compare == 0);
+                       return (compare != 0);
+               }
+#endif
+
+       default:                /* we're OK */
+               break;
+       }
+               
+       /*
+        *      After doing the previous check for special comparisons,
+        *      do the per-type comparison here.
+        */
+       switch (one->type) {
+       case PW_TYPE_ABINARY:
+       case PW_TYPE_OCTETS:
+       {
+               size_t length;
+               const uint8_t *p, *q;
+
+               if (one->length < two->length) {
+                       length = one->length;
+               } else {
+                       length = two->length;
+               }
+               
+               p = two->vp_octets;
+               q = one->vp_octets;
+               while (length) {
+                       compare = ((int) *p) - ((int) *q);
+                       if (compare != 0) goto type_switch;
+               }
+
+               /*
+                *      Contents are the same.  The return code
+                *      is therefore the difference in lengths.
+                *
+                *      i.e. "0x00" is smaller than "0x0000"
+                */
+               compare = two->length - one->length;
+       }
+               break;
+
+       case PW_TYPE_STRING:
+               if (one->flags.caseless) {
+                       compare = strcasecmp(two->vp_strvalue,
+                                            one->vp_strvalue);
+               } else {
+                       compare = strcmp(two->vp_strvalue,
+                                        one->vp_strvalue);
+               }
+               break;
+               
+       case PW_TYPE_BYTE:
+       case PW_TYPE_SHORT:
+       case PW_TYPE_INTEGER:
+       case PW_TYPE_DATE:
+               compare = two->lvalue - one->lvalue;
+               break;
+
+       case PW_TYPE_IPADDR:
+               compare = ntohl(two->vp_ipaddr) - ntohl(one->vp_ipaddr);
+               break;
+
+       case PW_TYPE_IPV6ADDR:
+               compare = memcmp(&two->vp_ipv6addr, &one->vp_ipv6addr,
+                                sizeof(two->vp_ipv6addr));
+               break;
+               
+       case PW_TYPE_IPV6PREFIX:
+               compare = memcmp(&two->vp_ipv6prefix, &one->vp_ipv6prefix,
+                                sizeof(two->vp_ipv6prefix));
+               break;
+
+       case PW_TYPE_IFID:
+               compare = memcmp(&two->vp_ifid, &one->vp_ifid,
+                                sizeof(two->vp_ifid));
+               break;
+
+       default:
+               return 0;       /* unknown type */
+       }
+
+       /*
+        *      Now do the operator comparison.
+        */
+ type_switch:
+       switch (one->operator) {
+       case T_OP_CMP_EQ:
+               return (compare == 0);
+               
+       case T_OP_NE:
+               return (compare != 0);
+               
+       case T_OP_LT:
+               return (compare < 0);
+               
+       case T_OP_GT:
+               return (compare > 0);
+
+       case T_OP_LE:
+               return (compare <= 0);
+
+       case T_OP_GE:
+               return (compare >= 0);
+
+       default:
+               return 0;
+       }
+
+       return 0;
+}
diff --git a/src/main/00-OLD/Make.inc b/src/main/00-OLD/Make.inc
deleted file mode 100644 (file)
index 44defb7..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-#
-# Makefile     RADIUS - 
-#              Remote Authentication Dial In User Service
-#
-#
-
-SERVER_OBJS    = radiusd.o dict.o files.o util.o md5.o attrprint.o \
-                       acct.o radius.o pam.o log.o version.o proxy.o \
-                       exec.o auth.o timestr.o cache.o
-SERVERDBM_OBJS = radiusddbm.o dict.o filesdbm.o util.o md5.o attrprint.o \
-                       acct.o radius.o pam.o log.o versiondbm.o proxy.o \
-                       exec.o auth.o timestr.o cache.o
-SERVER_SRCS    = radiusd.c dict.c files.c util.c md5.c attrprint.c acct.c \
-                       radius.c pam.c log.c version.c proxy.c \
-                       exec.c auth.c timestr.c cache.c
-INCLUDES       = radius.h conf.h
-
-all:   radiusd radwho radzap raduse radtest
-
-dbm:   radiusd.dbm builddbm
-
-radiusd: $(SERVER_OBJS)
-       $(CC) $(LDFLAGS) -o radiusd $(SERVER_OBJS) $(LIBS) $(LCRYPT) $(PAMLIB)
-
-radiusd.dbm: $(SERVERDBM_OBJS)
-       $(CC) $(LDFLAGS) -o radiusd.dbm $(SERVERDBM_OBJS) $(LIBS) $(LCRYPT) \
-                        $(DBMLIB) $(PAMLIB)
-
-radiusd.o: radiusd.c $(INCLUDES)
-       $(CC) $(CFLAGS) -c radiusd.c
-
-radiusddbm.o: radiusd.c $(INCLUDES)
-       $(CC) $(CFLAGS) $(DBM) -c radiusd.c -o radiusddbm.o
-
-acct.o: acct.c $(INCLUDES)
-       $(CC) $(CFLAGS) -c acct.c
-
-attrprint.o: attrprint.c $(INCLUDES)
-       $(CC) $(CFLAGS) -c attrprint.c
-
-dict.o: dict.c $(INCLUDES)
-       $(CC) $(CFLAGS) -c dict.c
-
-files.o: files.c $(INCLUDES)
-       $(CC) $(CFLAGS) $(PAM) -c files.c
-
-filesdbm.o: files.c $(INCLUDES)
-       $(CC) $(CFLAGS) $(DBM) $(PAM) -o filesdbm.o -c files.c
-
-radius.o: radius.c $(INCLUDES)
-       $(CC) $(CFLAGS) -c radius.c
-
-util.o: util.c $(INCLUDES)
-       $(CC) $(CFLAGS) -c util.c
-
-pam.o:  pam.c $(INCLUDES)
-       $(CC) $(CFLAGS) $(PAM) -c pam.c
-
-cache.o:  cache.c $(INCLUDES)
-       $(CC) $(CFLAGS) -c cache.c 
-
-proxy.o:  proxy.c $(INCLUDES)
-       $(CC) $(CFLAGS) -c proxy.c
-
-exec.o:  exec.c $(INCLUDES)
-       $(CC) $(CFLAGS) -c exec.c
-
-auth.o:  auth.c $(INCLUDES)
-       $(CC) $(CFLAGS) $(PAM) -c auth.c
-
-version.o: version.c $(INCLUDES)
-       $(CC) $(CFLAGS) -o version.o -c version.c
-
-versiondbm.o: version.c $(INCLUDES)
-       $(CC) $(CFLAGS) $(DBM) -o versiondbm.o -c version.c
-
-radtest: radtest.o md5.o util.o dict.o attrprint.o log.o
-       $(CC) $(LDFLAGS) -o radtest radtest.o md5.o util.o \
-               dict.o attrprint.o log.o $(LIBS)
-
-radtest.o: radtest.c $(INCLUDES)
-       $(CC) $(CFLAGS) -c radtest.c
-
-md5.o: md5.c md5.h
-       $(CC) $(CFLAGS) -c md5.c
-
-builddbm: builddbm.o
-       $(CC) $(LDFLAGS) -o builddbm builddbm.o $(DBMLIB) $(LIBS)
-
-builddbm.o: builddbm.c
-       $(CC) $(CFLAGS) -c $(DBM) builddbm.c
-
-radwho: radwho.o util.o
-       $(CC) $(LDFLAGS) -o radwho radwho.o util.o $(LIBS)
-
-raduse: raduse.o
-       $(CC) $(LDFLAGS) -o raduse raduse.o $(LIBS)
-
-radzap: radzap.o util.o
-       $(CC) $(LDFLAGS) -o radzap radzap.o util.o $(LIBS)
-
-lint:
-       -lint -hbacvx -DLINT $(SERVER_SRCS)
-       -lint -hbacvx -DLINT ../radpass.c ../md5.c ../util.c
-
-clean:
-       rm -f *.o radiusd radwho raduse radtest radzap builddbm radiusd.dbm
-       rm -f ../build ../debian/substvars ../debian/files
-
-install:
-       install -m 755 -s radiusd $(SBINDIR)/radiusd
-       install -m 755 -s radwho  $(BINDIR)
-       install -m 755 -s raduse  $(BINDIR)
-       install -m 755 -s radzap  $(BINDIR)
-       install -m 755    checkrad.pl $(SBINDIR)/checkrad
-       install -m 755    radlast $(BINDIR)
-
diff --git a/src/main/00-OLD/Makefile b/src/main/00-OLD/Makefile
deleted file mode 100644 (file)
index 47ff6d2..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Makefile     Radius Makefile for Linux (2.0.x, lib5 or libc6)
-#
-#
-
-#
-#      Autoselect -lshadow and -lcrypt
-#
-ifneq ($(wildcard /usr/lib/libshadow.a),)
-LSHADOW        = -lshadow
-endif
-ifneq ($(wildcard /usr/lib/libcrypt.a),)
-LCRYPT = -lcrypt
-endif
-
-CC     = gcc
-CFLAGS = -Wall -g # -DNOSHADOW
-LDFLAGS        = # -s # tatic
-LIBS   = $(LSHADOW)
-
-DBM    = -DNDBM
-DBMLIB = -ldb
-
-# Uncomment these if you want PAM support
-#PAM   = -DPAM
-#PAMLIB        = -lpam -ldl
-
-BINDIR  = /usr/local/bin
-SBINDIR = /usr/local/sbin
-
-include Make.inc
diff --git a/src/main/00-OLD/Makefile.BSD b/src/main/00-OLD/Makefile.BSD
deleted file mode 100644 (file)
index 900c5e4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Makefile     Radius Makefile for BSD (FreeBSD, NetBSD, etc)
-#
-#
-
-CC     = gcc
-CFLAGS = -Wall -g -DNOSHADOW
-LDFLAGS        = # -s #tatic
-LIBS   =
-LCRYPT = -lcrypt
-
-DBM     = -DNDBM
-DBMLIB  = #-ldb
-
-#PAM   = -DPAM
-#PAMLIB        = -lpam
-
-BINDIR  = /usr/local/bin
-SBINDIR = /usr/local/sbin
-
-.include "Make.inc"
diff --git a/src/main/00-OLD/Makefile.lnx b/src/main/00-OLD/Makefile.lnx
deleted file mode 100644 (file)
index 47ff6d2..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Makefile     Radius Makefile for Linux (2.0.x, lib5 or libc6)
-#
-#
-
-#
-#      Autoselect -lshadow and -lcrypt
-#
-ifneq ($(wildcard /usr/lib/libshadow.a),)
-LSHADOW        = -lshadow
-endif
-ifneq ($(wildcard /usr/lib/libcrypt.a),)
-LCRYPT = -lcrypt
-endif
-
-CC     = gcc
-CFLAGS = -Wall -g # -DNOSHADOW
-LDFLAGS        = # -s # tatic
-LIBS   = $(LSHADOW)
-
-DBM    = -DNDBM
-DBMLIB = -ldb
-
-# Uncomment these if you want PAM support
-#PAM   = -DPAM
-#PAMLIB        = -lpam -ldl
-
-BINDIR  = /usr/local/bin
-SBINDIR = /usr/local/sbin
-
-include Make.inc
diff --git a/src/main/00-OLD/Makefile.osf b/src/main/00-OLD/Makefile.osf
deleted file mode 100644 (file)
index 5414fd3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#
-# Makefile     Radius Makefile for OSF/Unix (Digital)
-#
-#              Add "-DOSFC2" to CFLAGS and "-lsecurity" to LIBS
-#              if you want to compile for OSF with C2 security
-#
-
-CC     = gcc
-CFLAGS = -g -Wall -Wno-unused -DNOSHADOW
-LDFLAGS        = # -s #tatic
-LIBS   = 
-LCRYPT =
-
-DBM     = #-DNDBM
-DBMLIB  = #-ldb
-
-#PAM   = -DPAM
-#PAMLIB        = -lpam
-
-BINDIR  = /usr/local/bin
-SBINDIR = /usr/local/sbin
-
-include Make.inc
diff --git a/src/main/00-OLD/Makefile.sunos5 b/src/main/00-OLD/Makefile.sunos5
deleted file mode 100644 (file)
index 6cecbaf..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-# Makefile     Radius Makefile for Solaris 2.5.x
-#
-
-CC     = gcc
-CFLAGS = -g # -DNOSHADOW
-LDFLAGS        = # -s #tatic
-LIBS   = -lsocket -lnsl
-LCRYPT =
-
-DBM     = #-DNDBM
-DBMLIB  = #-ldb
-
-#PAM   = -DPAM
-#PAMLIB        = -lpam
-
-BINDIR  = /usr/local/bin
-SBINDIR = /usr/local/sbin
-
-include Make.inc
index ef86887..b28ad98 100644 (file)
@@ -4,18 +4,19 @@
 
 include ../../Make.inc
 
-SERVER_SRCS    = acct.c auth.c client.c conffile.c exec.c files.c log.c   \
-                 mainconfig.c modules.c modcall.c nas.c proxy.c radiusd.c \
-                 radius_snmp.c request_list.c session.c smux.c threads.c  \
-                 util.c valuepair.c version.c timestr.c xlat.c
+SERVER_SRCS    = acct.c auth.c client.c conffile.c crypt.c exec.c files.c \
+                 listen.c log.c mainconfig.c modules.c modcall.c proxy.c  \
+                 radiusd.c radius_snmp.c request_list.c request_process.c \
+                 session.c smux.c threads.c util.c valuepair.c version.c  \
+                 xlat.c
 
 SERVER_OBJS    += $(SERVER_SRCS:.c=.lo)
 
 INCLUDES       = ../include/autoconf.h ../include/conf.h    \
                  ../include/libradius.h ../include/radius.h \
-                 ../include/radiusd.h
+                 ../include/radiusd.h ../include/ident.h
 
-CFLAGS         += -I../include
+CFLAGS         += -I$(top_builddir)/src
 CFLAGS         += -DHOSTINFO=\"${HOSTINFO}\"
 CFLAGS         += -DRADIUSD_VERSION=\"${RADIUSD_VERSION}\"
 CFLAGS         += $(SNMP_INCLUDE)
@@ -23,7 +24,15 @@ CFLAGS               += $(OPENSSL_INCLUDE)
 VFLAGS         = -DRADIUSD_MAJOR_VERSION=$(RADIUSD_MAJOR_VERSION)
 VFLAGS         += -DRADIUSD_MINOR_VERSION=$(RADIUSD_MINOR_VERSION)
 MODULE_LIBS    = $(STATIC_MODULES)
-BINARIES       = radiusd radclient radrelay radwho
+BINARIES       = radiusd radwho radclient
+
+#
+#  The RADIUS sniffer
+#
+PCAP_LIBS      = @PCAP_LIBS@
+ifneq ($(PCAP_LIBS),)
+BINARIES       += radsniff
+endif
 
 #
 #  Not using shared libraries, add in ALL known static modules
@@ -40,15 +49,12 @@ SUB_MODULES += rlm_eap_peap rlm_eap_mschapv2 rlm_eap_gtc
 SUB_MODULES += rlm_sql_db2 rlm_sql_freetds rlm_sql_iodbc rlm_sql_mysql
 SUB_MODULES += rlm_sql_oracle rlm_sql_postgresql rlm_sql_sybase rlm_sql_unixodbc
 LIBS        += $(shell test -f ../modules/rlm_eap/libeap/libeap.la && echo ../modules/rlm_eap/libeap/libeap.la)
-ifneq ($(OPENSSL_LIBS),)
-LIBS += $(OPENSSL_LIBS)
-endif
 
 MODULE_LIBS    += $(shell for x in $(MODULES);do test -f ../modules/$$x/$$x.la && echo -dlpreopen ../modules/$$x/$$x.la;done)
 MODULE_LIBS    += $(shell for x in $(SUB_MODULES);do test -f ../modules/*/types/$$x/$$x.la && echo -dlpreopen ../modules/*/types/$$x/$$x.la;done)
 MODULE_LIBS    += $(shell for x in $(SUB_MODULES);do test -f ../modules/*/drivers/$$x/$$x.la && echo -dlpreopen ../modules/*/drivers/$$x/$$x.la;done)
-MODULE_OBJS     += $(shell for x in $(MODULES);do test -f ../modules/$$x/$$x.la && echo ../modules/$$x/$$x.la;done)     
-MODULE_OBJS     += $(shell for x in $(SUB_MODULES);do test -f ../modules/*/types/$$x/$$x.la && echo ../modules/*/types/$$x/$$x.la;done)         
+MODULE_OBJS     += $(shell for x in $(MODULES);do test -f ../modules/$$x/$$x.la && echo ../modules/$$x/$$x.la;done)
+MODULE_OBJS     += $(shell for x in $(SUB_MODULES);do test -f ../modules/*/types/$$x/$$x.la && echo ../modules/*/types/$$x/$$x.la;done)
 MODULE_OBJS     += $(shell for x in $(SUB_MODULES);do test -f ../modules/*/drivers/$$x/$$x.la && echo ../modules/*/drivers/$$x/$$x.la;done)
 endif
 
@@ -62,8 +68,8 @@ $(SERVER_OBJS): $(INCLUDES)
 radiusd: $(SERVER_OBJS) $(MODULE_OBJS) ../lib/libradius.la
        $(LIBTOOL) --mode=link $(CC) -export-dynamic -dlopen self \
                $(LDFLAGS) -pie $(LINK_MODE) -o $@ $(SERVER_OBJS)      \
-               $(MODULE_LIBS) $(LIBS) $(SNMP_LIBS) $(PTHREADLIB) \
-               $(LIBLTDL) $(OPENSSL_LIBS)
+               $(MODULE_LIBS) $(LIBS) $(SNMP_LIBS) $(LCRYPT)     \
+               $(PTHREADLIB) $(LIBLTDL) $(OPENSSL_LIBS)
 
 radiusd.lo: radiusd.c ../include/request_list.h ../include/modules.h ../include/modcall.h ../include/modpriv.h
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c radiusd.c
@@ -80,12 +86,18 @@ client.lo: client.c ../include/conffile.h
 conffile.lo: conffile.c ../include/conffile.h ../include/modules.h
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c conffile.c
 
+crypt.lo: crypt.c
+       $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c crypt.c
+
 exec.lo: exec.c
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c exec.c
 
 files.lo: files.c
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c files.c
 
+listen.lo: listen.c
+       $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c listen.c
+
 log.lo: log.c
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c log.c
 
@@ -98,9 +110,6 @@ modcall.lo: modcall.c
 modules.lo: modules.c
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(VFLAGS) $(INCLTDL) -c modules.c
 
-nas.lo: nas.c
-       $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c nas.c
-
 proxy.lo: proxy.c
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c proxy.c
 
@@ -110,6 +119,9 @@ radius_snmp.lo: radius_snmp.c
 request_list.lo: request_list.c
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c request_list.c
 
+request_process.lo: request_process.c
+       $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c request_process.c
+
 session.lo: session.c ../include/modules.h
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c session.c
 
@@ -119,9 +131,6 @@ smux.lo: smux.c
 threads.lo: threads.c
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c threads.c
 
-timestr.lo: timestr.c
-       $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c timestr.c
-
 util.lo: util.c
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c util.c
 
@@ -144,11 +153,11 @@ radclient.lo: radclient.c $(INCLUDES)
 radclient: radclient.lo ../lib/libradius.la
        $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o radclient radclient.lo $(LIBS)
 
-radrelay.lo: radrelay.c $(INCLUDES)
-       $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c radrelay.c
+radsniff.lo: radsniff.c $(INCLUDES) ../include/radsniff.h
+       $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c radsniff.c
 
-radrelay: radrelay.lo util.lo nas.lo client.lo log.lo conffile.lo files.lo xlat.lo ../lib/libradius.la
-       $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o radrelay radrelay.lo util.lo nas.lo client.lo log.lo conffile.lo files.lo xlat.lo $(LIBS)
+radsniff: radsniff.lo ../lib/libradius.la
+       $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LINK_MODE) -o radsniff radsniff.lo $(LIBS) $(PCAP_LIBS)
 
 radwho.lo: radwho.c $(INCLUDES)
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c radwho.c
@@ -163,8 +172,10 @@ clean:
 install:
        $(LIBTOOL) --mode=install $(INSTALL) -m 755 $(INSTALLSTRIP) radiusd$(EXEEXT)    $(R)$(sbindir)
        $(LIBTOOL) --mode=install $(INSTALL) -m 755 $(INSTALLSTRIP) radclient$(EXEEXT)  $(R)$(bindir)
-       $(LIBTOOL) --mode=install $(INSTALL) -m 755 $(INSTALLSTRIP) radrelay$(EXEEXT)   $(R)$(bindir)
        $(LIBTOOL) --mode=install $(INSTALL) -m 755 $(INSTALLSTRIP) radwho$(EXEEXT)     $(R)$(bindir)
+ifneq ($(PCAP_LIBS),)
+       $(LIBTOOL) --mode=install $(INSTALL) -m 755 $(INSTALLSTRIP) radsniff$(EXEEXT)   $(R)$(bindir)
+endif
        $(INSTALL) -m 755    checkrad.pl                $(R)$(sbindir)/checkrad
        $(INSTALL) -m 755    radlast                    $(R)$(bindir)
        $(INSTALL) -m 755    radtest                    $(R)$(bindir)
index 09f0412..6dc9305 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  * Copyright 2000  Alan Curry <pacman@world.std.com>
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
-
-#include <stdlib.h>
-
-#include "radiusd.h"
-#include "modules.h"
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 /*
  *     rad_accounting: call modules.
@@ -46,10 +44,7 @@ int rad_accounting(REQUEST *request)
         *      Run the modules only once, before proxying.
         */
        if (!request->proxy) {
-               char            *exec_program;
-               int             exec_wait;
                VALUE_PAIR      *vp;
-               int             rcode;
                int             acct_type = 0;
 
                result = module_preacct(request);
@@ -85,7 +80,7 @@ int rad_accounting(REQUEST *request)
                 */
                vp = pairfind(request->config_items, PW_ACCT_TYPE);
                if (vp) {
-                       DEBUG2("  Found Acct-Type %s", vp->strvalue);
+                       DEBUG2("  Found Acct-Type %s", vp->vp_strvalue);
                        acct_type = vp->lvalue;
                }
                result = module_accounting(acct_type, request);
@@ -117,62 +112,6 @@ int rad_accounting(REQUEST *request)
                }
 
                /*
-                *      See if we need to execute a program.
-                *      FIXME: somehow cache this info, and only execute the
-                *      program when we receive an Accounting-START packet.
-                *      Only at that time we know dynamic IP etc.
-                */
-               exec_program = NULL;
-               exec_wait = 0;
-               if ((vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM)) != NULL) {
-                       exec_wait = 0;
-                       exec_program = strdup((char *)vp->strvalue);
-                       pairdelete(&request->reply->vps, PW_EXEC_PROGRAM);
-               }
-
-               if ((vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM_WAIT)) != NULL) {
-                       free(exec_program);
-                       exec_wait = 1;
-                       exec_program = strdup((char *)vp->strvalue);
-                       pairdelete(&request->reply->vps, PW_EXEC_PROGRAM_WAIT);
-               }
-
-               /*
-                *      If we want to exec a program, but wait for it,
-                *      do it first before sending the reply, or
-                *      proxying the packet.
-                *
-                *      If we're NOT waiting, then also do this now, but
-                *      don't check the return code.
-                */
-               if (exec_program) {
-                       /*
-                        *      Wait for the answer.
-                        *      Don't look for a user message.
-                        *      Do look for returned VP's.
-                        */
-                       rcode = radius_exec_program(exec_program, request,
-                                                   exec_wait, NULL, 0,
-                                                   request->packet->vps, &vp);
-                       free(exec_program);
-
-                       /*
-                        *      Always add the value-pairs to the reply.
-                        *
-                        *      If we're not waiting, then the pairs
-                        *      will be empty, so this won't matter.
-                        */
-                       pairmove(&request->reply->vps, &vp);
-                       pairfree(&vp);
-
-                       if (exec_wait) {
-                               if (rcode != 0) {
-                                       return result;
-                               }
-                       }
-               }
-
-               /*
                 *      Maybe one of the preacct modules has decided
                 *      that a proxy should be used.
                 */
@@ -183,9 +122,10 @@ int rad_accounting(REQUEST *request)
                         *      Check whether Proxy-To-Realm is
                         *      a LOCAL realm.
                         */
-                       realm = realm_find(vp->strvalue, TRUE);
+                       realm = realm_find(vp->vp_strvalue, TRUE);
                        if (realm != NULL &&
-                           realm->acct_ipaddr == htonl(INADDR_NONE)) {
+                           realm->acct_ipaddr.af == AF_INET &&
+                           realm->acct_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)) {
                                DEBUG("rad_accounting: Cancelling proxy to realm %s, as it is a LOCAL realm.", realm->realm);
                                pairdelete(&request->config_items, PW_PROXY_TO_REALM);
                        } else {
index 2b57e71..ffa3a6b 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
  * Copyright 2000  Jeff Carneal <jeff@apex.net>
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdlib.h>
 #include <string.h>
@@ -35,8 +35,9 @@ static const char rcsid[] = "$Id$";
 #      include <netinet/in.h>
 #endif
 
-#include "radiusd.h"
-#include "modules.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/rad_assert.h>
 
 /*
  *     Return a short string showing the terminal server, port
@@ -53,59 +54,13 @@ char *auth_name(char *buf, size_t buflen, REQUEST *request, int do_cli) {
                port = pair->lvalue;
 
        snprintf(buf, buflen, "from client %.128s port %u%s%.128s",
-                       client_name(request->packet->src_ipaddr), port,
-                       (do_cli ? " cli " : ""), (do_cli ? (char *)cli->strvalue : ""));
+                       client_name_old(&request->packet->src_ipaddr), port,
+                       (do_cli ? " cli " : ""), (do_cli ? (char *)cli->vp_strvalue : ""));
 
        return buf;
 }
 
 
-/*
- *     Check if account has expired, and if user may login now.
- */
-static int check_expiration(REQUEST *request)
-{
-       VALUE_PAIR *check_item;
-       VALUE_PAIR *vp;
-
-       check_item = pairfind(request->config_items, PW_EXPIRATION);
-
-       if (!check_item)  return 0;
-
-       /*
-        *      Has this user's password expired?
-        *
-        *      If so, remove ALL reply attributes,
-        *      and add our own Reply-Message, saying
-        *      why they're being rejected.
-        */
-       if (((time_t) check_item->lvalue) <= request->timestamp) {
-               vp = pairmake("Reply-Message",
-                             "Password Has Expired\r\n",
-                             T_OP_ADD);
-               pairfree(&request->reply->vps);
-               request->reply->vps = vp;
-               return -1;
-       }
-
-#define EXP_TIMEOUT ((uint32_t) (((time_t) check_item->lvalue) - request->timestamp))
-       /*
-        *      Otherwise, set the Session-Timeout based on expiration.
-        */
-       vp = pairfind(request->reply->vps, PW_SESSION_TIMEOUT);
-       if (!vp) {
-               vp = pairmake("Session-Timeout", "0", T_OP_SET);
-               if (!vp) return -1; /* out of memory */
-               
-               vp->lvalue = EXP_TIMEOUT;
-               pairadd(&request->reply->vps, vp);
-       } else if (vp->lvalue > EXP_TIMEOUT) {
-               vp->lvalue = EXP_TIMEOUT;
-       } /* else Session-Timeout is smaller than Expiration, leave it alone */
-
-       return 0;
-}
-
 
 /*
  * Make sure user/pass are clean
@@ -137,7 +92,7 @@ static int rad_authlog(const char *msg, REQUEST *request, int goodpass) {
        if (username == NULL) {
                strcpy(clean_username, "<no User-Name attribute>");
        } else {
-               librad_safeprint((char *)username->strvalue,
+               librad_safeprint((char *)username->vp_strvalue,
                                username->length,
                                clean_username, sizeof(clean_username));
        }
@@ -147,11 +102,21 @@ static int rad_authlog(const char *msg, REQUEST *request, int goodpass) {
         */
        if (mainconfig.log_auth_badpass || mainconfig.log_auth_goodpass) {
                if (!request->password) {
-                       strcpy(clean_password, "<no User-Password attribute>");
-               } else if (request->password->attribute == PW_CHAP_PASSWORD) {
+                       VALUE_PAIR *auth_type;
+
+                       auth_type = pairfind(request->config_items,
+                                            PW_AUTH_TYPE);
+                       if (auth_type && (auth_type->vp_strvalue[0] != '\0')) {
+                               snprintf(clean_password, sizeof(clean_password),
+                                        "<via Auth-Type = %s>",
+                                        auth_type->vp_strvalue);
+                       } else {
+                               strcpy(clean_password, "<no User-Password attribute>");
+                       }
+               } else if (pairfind(request->packet->vps, PW_CHAP_PASSWORD)) {
                        strcpy(clean_password, "<CHAP-Password>");
                } else {
-                       librad_safeprint((char *)request->password->strvalue,
+                       librad_safeprint((char *)request->password->vp_strvalue,
                                         request->password->length,
                                         clean_password, sizeof(clean_password));
                }
@@ -186,7 +151,7 @@ static int rad_authlog(const char *msg, REQUEST *request, int goodpass) {
  *
  *     NOTE: NOT the same as the RLM_ values !
  */
-int rad_check_password(REQUEST *request)
+static int rad_check_password(REQUEST *request)
 {
        VALUE_PAIR *auth_type_pair;
        VALUE_PAIR *cur_config_item;
@@ -209,7 +174,7 @@ int rad_check_password(REQUEST *request)
                auth_type_count++;
 
                DEBUG2("  rad_check_password:  Found Auth-Type %s",
-                               auth_type_pair->strvalue);
+                               auth_type_pair->vp_strvalue);
                cur_config_item = auth_type_pair->next;
 
                if (auth_type == PW_AUTHTYPE_REJECT) {
@@ -220,7 +185,7 @@ int rad_check_password(REQUEST *request)
 
        if (( auth_type_count > 1) && (debug_flag)) {
                radlog(L_ERR, "Warning:  Found %d auth-types on request for user '%s'",
-                       auth_type_count, request->username->strvalue);
+                       auth_type_count, request->username->vp_strvalue);
        }
 
        /*
@@ -234,8 +199,30 @@ int rad_check_password(REQUEST *request)
                return 0;
        }
 
+       password_pair =  pairfind(request->config_items, PW_USER_PASSWORD);
+       if (password_pair &&
+           pairfind(request->config_items, PW_CLEARTEXT_PASSWORD)) {
+               pairdelete(&request->config_items, PW_USER_PASSWORD);
+               password_pair = NULL;
+       }
+
+       if (password_pair) {
+               DEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+               DEBUG("!!!    Replacing User-Password in config items with Cleartext-Password.     !!!");
+               DEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+               DEBUG("!!! Please update your configuration so that the \"known good\"               !!!");
+               DEBUG("!!! clear text password is in Cleartext-Password, and not in User-Password. !!!");
+               DEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+               password_pair->attribute = PW_CLEARTEXT_PASSWORD;
+               strlcpy(password_pair->name, "Cleatext-Password",
+                       sizeof(password_pair->name));
+       }
+
        /*
-        *      Find the password from the users file.
+        *      Find the "known good" password.
+        *
+        *      FIXME: We should get rid of these hacks, and replace
+        *      them with a module.
         */
        if ((password_pair = pairfind(request->config_items, PW_CRYPT_PASSWORD)) != NULL) {
                /*
@@ -244,20 +231,7 @@ int rad_check_password(REQUEST *request)
                 */
                if (auth_type == -1) auth_type = PW_AUTHTYPE_CRYPT;
        } else {
-               password_pair = pairfind(request->config_items, PW_PASSWORD);
-               if (!password_pair) {
-                       password_pair = pairfind(request->config_items,
-                                                PW_CLEARTEXT_PASSWORD);
-                       if (password_pair) {
-                               VALUE_PAIR *old;
-
-                               old = pairmake("User-Password",
-                                              password_pair->strvalue,
-                                              T_OP_SET);
-                               if (old) pairadd(&request->config_items, old);
-                       }
-               }
-               
+               password_pair = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);
        }
 
        if (auth_type < 0) {
@@ -298,8 +272,8 @@ int rad_check_password(REQUEST *request)
                                return -1;
                        }
 
-                       switch (lrad_crypt_check((char *)auth_item->strvalue,
-                                                                        (char *)password_pair->strvalue)) {
+                       switch (lrad_crypt_check((char *)auth_item->vp_strvalue,
+                                                                        (char *)password_pair->vp_strvalue)) {
                        case -1:
                          rad_authlog("Login incorrect "
                                                  "(system failed to supply an encrypted password for comparison)", request, 0);
@@ -316,7 +290,10 @@ int rad_check_password(REQUEST *request)
                         *      authentication fails.
                         */
                        auth_item = request->password;
-                       if (auth_item == NULL) {
+                       if (!auth_item) 
+                               auth_item = pairfind(request->packet->vps,
+                                                    PW_CHAP_PASSWORD);
+                       if (!auth_item) {
                                DEBUG2("auth: No User-Password or CHAP-Password attribute in the request");
                                return -1;
                        }
@@ -334,9 +311,9 @@ int rad_check_password(REQUEST *request)
                        /*
                         *      Local password is just plain text.
                         */
-                       if (auth_item->attribute == PW_PASSWORD) {
-                               if (strcmp((char *)password_pair->strvalue,
-                                          (char *)auth_item->strvalue) != 0) {
+                       if (auth_item->attribute == PW_USER_PASSWORD) {
+                               if (strcmp((char *)password_pair->vp_strvalue,
+                                          (char *)auth_item->vp_strvalue) != 0) {
                                        DEBUG2("auth: user supplied User-Password does NOT match local User-Password");
                                        return -1;
                                }
@@ -351,12 +328,12 @@ int rad_check_password(REQUEST *request)
                        }
 
                        rad_chap_encode(request->packet, string,
-                                       auth_item->strvalue[0], password_pair);
+                                       auth_item->vp_strvalue[0], password_pair);
 
                        /*
                         *      Compare them
                         */
-                       if (memcmp(string + 1, auth_item->strvalue + 1,
+                       if (memcmp(string + 1, auth_item->vp_strvalue + 1,
                                   CHAP_VALUE_LENGTH) != 0) {
                                DEBUG2("auth: user supplied CHAP-Password does NOT match local User-Password");
                                return -1;
@@ -424,7 +401,7 @@ int rad_postauth(REQUEST *request)
         */
        vp = pairfind(request->config_items, PW_POST_AUTH_TYPE);
        if (vp) {
-               DEBUG2("  Found Post-Auth-Type %s", vp->strvalue);
+               DEBUG2("  Found Post-Auth-Type %s", vp->vp_strvalue);
                postauth_type = vp->lvalue;
        }
        result = module_post_auth(postauth_type, request);
@@ -445,7 +422,6 @@ int rad_postauth(REQUEST *request)
                 */
                case RLM_MODULE_HANDLED:
                        /* FIXME */
-                       result = RLM_MODULE_OK;
                        break;
                /*
                 *      The module had a number of OK return codes.
@@ -495,18 +471,14 @@ int rad_authenticate(REQUEST *request)
 {
        VALUE_PAIR      *namepair;
        VALUE_PAIR      *check_item;
-       VALUE_PAIR      *reply_item;
        VALUE_PAIR      *auth_item;
        VALUE_PAIR      *module_msg;
        VALUE_PAIR      *tmp = NULL;
-       int             result, r;
+       int             result;
        char            umsg[MAX_STRING_LEN + 1];
        const char      *user_msg = NULL;
        const char      *password;
-       char            *exec_program;
-       int             exec_wait;
-       int             seen_callback_id;
-       char            buf[1024], logstr[1024];
+       char            logstr[1024];
        char            autz_retry = 0;
        int             autz_type = 0;
 
@@ -568,7 +540,7 @@ int rad_authenticate(REQUEST *request)
         */
        if (!request->password) {
                request->password = pairfind(request->packet->vps,
-                                            PW_PASSWORD);
+                                            PW_USER_PASSWORD);
        }
 
        /*
@@ -576,14 +548,14 @@ int rad_authenticate(REQUEST *request)
         */
        auth_item = request->password;
        if (auth_item) {
-               password = (const char *)auth_item->strvalue;
+               password = (const char *)auth_item->vp_strvalue;
 
        } else {
                /*
                 *      Maybe there's a CHAP-Password?
                 */
                if ((auth_item = pairfind(request->packet->vps,
-                               PW_CHAP_PASSWORD)) != NULL) {
+                                         PW_CHAP_PASSWORD)) != NULL) {
                        password = "<CHAP-PASSWORD>";
 
                } else {
@@ -617,7 +589,7 @@ autz_redo:
                                        PW_MODULE_FAILURE_MESSAGE)) != NULL) {
                                char msg[MAX_STRING_LEN + 16];
                                snprintf(msg, sizeof(msg), "Invalid user (%s)",
-                                        module_msg->strvalue);
+                                        module_msg->vp_strvalue);
                                rad_authlog(msg,request,0);
                        } else {
                                rad_authlog("Invalid user", request, 0);
@@ -628,7 +600,7 @@ autz_redo:
        if (!autz_retry) {
                tmp = pairfind(request->config_items, PW_AUTZ_TYPE);
                if (tmp) {
-                       DEBUG2("  Found Autz-Type %s", tmp->strvalue);
+                       DEBUG2("  Found Autz-Type %s", tmp->vp_strvalue);
                        autz_type = tmp->lvalue;
                        autz_retry = 1;
                        goto autz_redo;
@@ -649,8 +621,9 @@ autz_redo:
                 *      Catch users who set Proxy-To-Realm to a LOCAL
                 *      realm (sigh).
                 */
-               realm = realm_find(tmp->strvalue, 0);
-               if (realm && (realm->ipaddr == htonl(INADDR_NONE))) {
+               realm = realm_find(tmp->vp_strvalue, 0);
+               rad_assert((realm == NULL) || (realm->ipaddr.af == AF_INET));
+               if (realm && (realm->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE))) {
                        DEBUG2("  WARNING: You set Proxy-To-Realm = %s, but it is a LOCAL realm!  Cancelling invalid proxy request.", realm->realm);
                } else {
                        /*
@@ -670,8 +643,6 @@ autz_redo:
         *      Validate the user
         */
        do {
-               if ((result = check_expiration(request)) < 0)
-                               break;
                result = rad_check_password(request);
                if (result > 0) {
                        /* don't reply! */
@@ -694,7 +665,7 @@ autz_redo:
                        char msg[MAX_STRING_LEN+19];
 
                        snprintf(msg, sizeof(msg), "Login incorrect (%s)",
-                                module_msg->strvalue);
+                                module_msg->vp_strvalue);
                        rad_authlog(msg, request, 0);
                } else {
                        rad_authlog("Login incorrect", request, 0);
@@ -702,10 +673,10 @@ autz_redo:
 
                /* double check: maybe the secret is wrong? */
                if ((debug_flag > 1) && (auth_item != NULL) &&
-                               (auth_item->attribute == PW_PASSWORD)) {
+                               (auth_item->attribute == PW_USER_PASSWORD)) {
                        u_char *p;
 
-                       p = auth_item->strvalue;
+                       p = auth_item->vp_strvalue;
                        while (*p != '\0') {
                                if (!isprint((int) *p)) {
                                        log_debug("  WARNING: Unprintable characters in the password.\n\t  Double-check the shared secret on the server and the NAS!");
@@ -718,11 +689,11 @@ autz_redo:
 
        if (result >= 0 &&
            (check_item = pairfind(request->config_items, PW_SIMULTANEOUS_USE)) != NULL) {
-               int session_type = 0;
+               int r, session_type = 0;
 
                tmp = pairfind(request->config_items, PW_SESSION_TYPE);
                if (tmp) {
-                       DEBUG2("  Found Session-Type %s", tmp->strvalue);
+                       DEBUG2("  Found Session-Type %s", tmp->vp_strvalue);
                        session_type = tmp->lvalue;
                }
 
@@ -774,65 +745,6 @@ autz_redo:
                }
        }
 
-       if (result >= 0 &&
-           (check_item = pairfind(request->config_items, PW_LOGIN_TIME)) != NULL) {
-
-               /*
-                *      Authentication is OK. Now see if this
-                *      user may login at this time of the day.
-                */
-               r = timestr_match((char *)check_item->strvalue,
-                                 request->timestamp);
-
-               if (r == 0) {   /* unlimited */
-                       /*
-                        *      Do nothing: login-time is OK.
-                        */
-
-                       /*
-                        *      Session-Timeout needs to be at least
-                        *      60 seconds, some terminal servers
-                        *      ignore smaller values.
-                        */
-               } else if (r < 60) {
-                       /*
-                        *      User called outside allowed time interval.
-                        */
-                       result = -1;
-                       user_msg = "You are calling outside your allowed timespan\r\n";
-
-                       request->reply->code = PW_AUTHENTICATION_REJECT;
-                       pairfree(&request->reply->vps);
-
-                       tmp = pairmake("Reply-Message", user_msg, T_OP_SET);
-                       request->reply->vps = tmp;
-
-                       snprintf(logstr, sizeof(logstr), "Outside allowed timespan (time allowed %s)",
-                                check_item->strvalue);
-                       rad_authlog(logstr, request, 1);
-
-               } else if (r > 0) {
-
-                       /*
-                        *      User is allowed, but set Session-Timeout.
-                        */
-                       if ((reply_item = pairfind(request->reply->vps,
-                                       PW_SESSION_TIMEOUT)) != NULL) {
-                               if (reply_item->lvalue > (unsigned) r)
-                                       reply_item->lvalue = r;
-                       } else {
-                               if ((reply_item = paircreate(
-                                               PW_SESSION_TIMEOUT,
-                                               PW_TYPE_INTEGER)) == NULL) {
-                                       radlog(L_ERR|L_CONS, "no memory");
-                                       exit(1);
-                               }
-                               reply_item->lvalue = r;
-                               pairadd(&request->reply->vps, reply_item);
-                       }
-               }
-       }
-
        /*
         *      Result should be >= 0 here - if not, it means the user
         *      is rejected, so we just process post-auth and return.
@@ -868,7 +780,7 @@ autz_redo:
                  unsigned long tvalue = ntohl(tmp->lvalue);
                  tmp->lvalue = htonl(tvalue + vpPortId->lvalue);
                  tmp->flags.addport = 0;
-                 ip_ntoa(tmp->strvalue, tmp->lvalue);
+                 ip_ntoa(tmp->vp_strvalue, tmp->lvalue);
                } else {
                        DEBUG2("WARNING: No NAS-Port attribute in request.  CANNOT return a Framed-IP-Address + NAS-Port.\n");
                        pairdelete(&request->reply->vps, PW_FRAMED_IP_ADDRESS);
@@ -876,129 +788,6 @@ autz_redo:
        }
 
        /*
-        *      See if we need to execute a program.
-        *      FIXME: somehow cache this info, and only execute the
-        *      program when we receive an Accounting-START packet.
-        *      Only at that time we know dynamic IP etc.
-        */
-       exec_program = NULL;
-       exec_wait = 0;
-       if ((auth_item = pairfind(request->reply->vps, PW_EXEC_PROGRAM)) != NULL) {
-               exec_wait = 0;
-               exec_program = strdup((char *)auth_item->strvalue);
-               pairdelete(&request->reply->vps, PW_EXEC_PROGRAM);
-       }
-       if ((auth_item = pairfind(request->reply->vps, PW_EXEC_PROGRAM_WAIT)) != NULL) {
-               free(exec_program);
-               exec_wait = 1;
-               exec_program = strdup((char *)auth_item->strvalue);
-               pairdelete(&request->reply->vps, PW_EXEC_PROGRAM_WAIT);
-       }
-
-       /*
-        *      Hack - allow % expansion in certain value strings.
-        *      This is nice for certain Exec-Program programs.
-        */
-       seen_callback_id = 0;
-       if ((auth_item = pairfind(request->reply->vps, PW_CALLBACK_ID)) != NULL) {
-               seen_callback_id = 1;
-               radius_xlat(buf, sizeof(auth_item->strvalue),
-                           (char *)auth_item->strvalue, request, NULL);
-               strNcpy((char *)auth_item->strvalue, buf,
-                       sizeof(auth_item->strvalue));
-               auth_item->length = strlen((char *)auth_item->strvalue);
-       }
-
-
-       /*
-        *      If we want to exec a program, but wait for it,
-        *      do it first before sending the reply.
-        */
-       if (exec_program && exec_wait) {
-               r = radius_exec_program(exec_program, request,
-                                       exec_wait,
-                                       NULL, 0,
-                                       request->packet->vps, &tmp);
-               free(exec_program);
-               exec_program = NULL;
-
-               /*
-                *      Always add the value-pairs to the reply.
-                */
-               pairmove(&request->reply->vps, &tmp);
-               pairfree(&tmp);
-
-               if (r < 0) {
-                       /*
-                        *      Error. radius_exec_program() returns -1 on
-                        *      fork/exec errors.
-                        */
-                       user_msg = "Access denied (external check failed)";
-                       tmp = pairmake("Reply-Message", user_msg, T_OP_SET);
-                       pairadd(&request->reply->vps, tmp);
-
-                       request->reply->code = PW_AUTHENTICATION_REJECT;
-                       rad_authlog("Login incorrect (external check failed)",
-                                   request, 0);
-                       rad_postauth_reject(request);
-
-                       return RLM_MODULE_REJECT;
-               }
-               if (r > 0) {
-                       /*
-                        *      Reject. radius_exec_program() returns >0
-                        *      if the exec'ed program had a non-zero
-                        *      exit status.
-                        */
-                       request->reply->code = PW_AUTHENTICATION_REJECT;
-                       rad_authlog("Login incorrect (external check said so)",
-                                   request, 0);
-                       rad_postauth_reject(request);
-
-                       return RLM_MODULE_REJECT;
-               }
-       }
-
-       /*
-        *      Delete "normal" A/V pairs when using callback.
-        *
-        *      FIXME: This is stupid. The portmaster should accept
-        *      these settings instead of insisting on using a
-        *      dialout location.
-        *
-        *      FIXME2: Move this into the above exec thingy?
-        *      (if you knew how I use the exec_wait, you'd understand).
-        */
-       if (seen_callback_id) {
-               pairdelete(&request->reply->vps, PW_FRAMED_PROTOCOL);
-               pairdelete(&request->reply->vps, PW_FRAMED_IP_ADDRESS);
-               pairdelete(&request->reply->vps, PW_FRAMED_IP_NETMASK);
-               pairdelete(&request->reply->vps, PW_FRAMED_ROUTE);
-               pairdelete(&request->reply->vps, PW_FRAMED_MTU);
-               pairdelete(&request->reply->vps, PW_FRAMED_COMPRESSION);
-               pairdelete(&request->reply->vps, PW_FILTER_ID);
-               pairdelete(&request->reply->vps, PW_PORT_LIMIT);
-               pairdelete(&request->reply->vps, PW_CALLBACK_NUMBER);
-       }
-
-       /*
-        *      Filter (possibly multiple) Reply-Message attributes
-        *      through radius_xlat, modifying them in place.
-        */
-       if (user_msg == NULL) {
-               reply_item = pairfind(request->reply->vps, PW_REPLY_MESSAGE);
-               while (reply_item) {
-                       radius_xlat(buf, sizeof(reply_item->strvalue),
-                                   (char *)reply_item->strvalue, request, NULL);
-                       strNcpy((char *)reply_item->strvalue, buf,
-                               sizeof(reply_item->strvalue));
-                       reply_item->length = strlen((char *)reply_item->strvalue);
-                       user_msg = NULL;
-                       reply_item = pairfind(reply_item->next, PW_REPLY_MESSAGE);
-               }
-       }
-
-       /*
         *      Set the reply to Access-Accept, if it hasn't already
         *      been set to something.  (i.e. Access-Challenge)
         */
@@ -1009,23 +798,15 @@ autz_redo:
                char msg[MAX_STRING_LEN+12];
 
                snprintf(msg, sizeof(msg), "Login OK (%s)",
-                        module_msg->strvalue);
+                        module_msg->vp_strvalue);
                rad_authlog(msg, request, 1);
        } else {
                rad_authlog("Login OK", request, 1);
        }
 
-       if (exec_program && !exec_wait) {
-               /*
-                *      No need to check the exit status here.
-                */
-               radius_exec_program(exec_program, request, exec_wait,
-                                   NULL, 0, request->packet->vps, NULL);
-       }
-
-       if (exec_program)
-               free(exec_program);
-
+       /*
+        *      Run the modules in the 'post-auth' section.
+        */
        result = rad_postauth(request);
 
        return result;
index 1a80a3d..124a1ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * files.c     Read config files into memory.
+ * client.c    Read clients into memory.
  *
  * Version:     $Id$
  *
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <sys/stat.h>
 
@@ -39,242 +39,300 @@ static const char rcsid[] = "$Id$";
 #include <ctype.h>
 #include <fcntl.h>
 
-#include "radiusd.h"
-#include "conffile.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
+
+struct radclient_list {
+       /*
+        *      FIXME: One set of trees for IPv4, and another for IPv6?
+        */
+       rbtree_t        *trees[129]; /* for 0..128, inclusive. */
+       int             min_prefix;
+#ifdef WITH_SNMP
+       rbtree_t        *num;   /* client numbers 0..N */
+       int             max;
+#endif
+};
 
 /*
- *     Free a RADCLIENT list.
+ *     Callback for freeing a client.
+ */
+void client_free(RADCLIENT *client)
+{
+       free(client->longname);
+       free(client->secret);
+       free(client->shortname);
+       free(client->nastype);
+       free(client->login);
+       free(client->password);
+       
+       free(client);
+}
+
+
+/*
+ *     Callback for comparing two clients.
  */
-void clients_free(RADCLIENT *cl)
+static int client_ipaddr_cmp(const void *one, const void *two)
 {
-       RADCLIENT *next;
+       const RADCLIENT *a = one;
+       const RADCLIENT *b = two;
+
+       if (a->ipaddr.af < b->ipaddr.af) return -1;
+       if (a->ipaddr.af > b->ipaddr.af) return +1;
+
+       rad_assert(a->prefix == b->prefix);
+
+       switch (a->ipaddr.af) {
+       case AF_INET:
+               return memcmp(&a->ipaddr.ipaddr.ip4addr,
+                             &b->ipaddr.ipaddr.ip4addr,
+                             sizeof(a->ipaddr.ipaddr.ip4addr));
+               break;
+
+       case AF_INET6:
+               return memcmp(&a->ipaddr.ipaddr.ip6addr,
+                             &b->ipaddr.ipaddr.ip6addr,
+                             sizeof(a->ipaddr.ipaddr.ip6addr));
+               break;
 
-       while(cl) {
-               next = cl->next;
-               free(cl);
-               cl = next;
+       default:
+               break;
        }
+
+       /*
+        *      Something bad happened...
+        */
+       rad_assert("Internal sanity check failed");
+       return -1;
 }
 
+#ifdef WITH_SNMP
+static int client_num_cmp(const void *one, const void *two)
+{
+       const RADCLIENT *a = one;
+       const RADCLIENT *b = two;
+
+       return (a->number - b->number);
+}
+#endif
 
 /*
- *     Read the clients file.
+ *     Free a RADCLIENT list.
  */
-int read_clients_file(const char *file)
+void clients_free(RADCLIENT_LIST *clients)
 {
-       FILE *fp;
-       RADCLIENT *c;
-       char buffer[256];
-       char hostnm[256];
-       char secret[256];
-       char shortnm[256];
-       uint32_t mask;
-       int lineno = 0;
-       char *p;
-       int got_clients = FALSE;
-
-       clients_free(mainconfig.clients);
-       mainconfig.clients = NULL;
-
-       if ((fp = fopen(file, "r")) == NULL) {
-               /* The clients file is no longer required.  All configuration
-                  information is read from radiusd.conf and friends.  If
-                  clients exists it will be used, but if it doesn't no harm
-                  done. */
-               return 0;
+       int i;
+
+       if (!clients) return;
+
+       for (i = 0; i <= 128; i++) {
+               if (clients->trees[i]) rbtree_free(clients->trees[i]);
+               clients->trees[i] = NULL;
        }
+#ifdef WITH_SNMP
+       if (clients->num) rbtree_free(clients->num);
+#endif
+       free(clients);
+}
 
-       while(fgets(buffer, 256, fp) != NULL) {
-               lineno++;
-               if (!feof(fp) && (strchr(buffer, '\n') == NULL)) {
-                       radlog(L_ERR, "%s[%d]: line too long", file, lineno);
-                       return -1;
-               }
+/*
+ *     Return a new, initialized, set of clients.
+ */
+RADCLIENT_LIST *clients_init(void)
+{
+       RADCLIENT_LIST *clients = calloc(1, sizeof(RADCLIENT_LIST));
 
-               /*
-                *      Skip whitespace.
-                */
-               p = buffer;
-               while (*p &&
-                               ((*p == ' ') || (*p == '\t')))
-                       p++;
+       if (!clients) return NULL;
 
-               /*
-                *      Skip comments and blank lines.
-                */
-               if ((*p == '#') || (*p == '\n') || (*p == '\r'))
-                       continue;
-
-               if (!getword(&p, hostnm, sizeof(hostnm)) ||
-                               !getword(&p, secret, sizeof(secret))) {
-                       radlog(L_ERR, "%s[%d]: unexpected end of line",
-                                       file, lineno);
-                       return -1;
-               }
+       clients->min_prefix = 128;
+
+       return clients;
+}
 
-               (void)getword(&p, shortnm, sizeof(shortnm));
+
+/*
+ *     Sanity check a client.
+ */
+static int client_sane(RADCLIENT *client)
+{
+       switch (client->ipaddr.af) {
+       case AF_INET:
+               if (client->prefix > 32) {
+                       return 0;
+               }
 
                /*
-                *      Look for a mask in the hostname
+                *      Zero out the subnet bits.
                 */
-               p = strchr(hostnm, '/');
-               mask = ~0;
+               if (client->prefix < 32) {
+                       uint32_t mask = ~0;
 
-               if (p) {
-                       int mask_length;
+                       mask <<= (32 - client->prefix);
+                       client->ipaddr.ipaddr.ip4addr.s_addr &= htonl(mask);
+               }
+               break;
 
-                       *p = '\0';
-                       p++;
+       case AF_INET6:
+               if (client->prefix > 128) return 0;
 
-                       mask_length = atoi(p);
-                       if ((mask_length < 0) || (mask_length > 32)) {
-                               radlog(L_ERR, "%s[%d]: Invalid value '%s' for IP network mask.",
-                                      file, lineno, p);
-                               return -1;
-                       }
+               if (client->prefix < 128) {
+                       int i;
+                       uint32_t mask, *addr;
+
+                       addr = (uint32_t *) &client->ipaddr.ipaddr.ip6addr;
 
-                       if (mask_length == 0) {
-                               mask = 0;
-                       } else {
-                               mask = ~0 << (32 - mask_length);
+                       for (i = client->prefix; i < 128; i += 32) {
+                               mask = ~0;
+                               mask <<= ((128 - i) & 0x1f);
+                               addr[i / 32] &= mask;
                        }
                }
+               break;
 
-               /*
-                *      Double-check lengths to be sure they're sane
-                */
-               if (strlen(hostnm) >= sizeof(c->longname)) {
-                       radlog(L_ERR, "%s[%d]: host name of length %d is greater than the allowed maximum of %d.",
-                              file, lineno,
-                              (int) strlen(hostnm),
-                              (int) sizeof(c->longname) - 1);
-                       return -1;
-               }
-               if (strlen(secret) >= sizeof(c->secret)) {
-                       radlog(L_ERR, "%s[%d]: secret of length %d is greater than the allowed maximum of %d.",
-                              file, lineno,
-                              (int) strlen(secret),
-                              (int) sizeof(c->secret) - 1);
-                       return -1;
-               }
-               if (strlen(shortnm) > sizeof(c->shortname)) {
-                       radlog(L_ERR, "%s[%d]: short name of length %d is greater than the allowed maximum of %d.",
-                              file, lineno,
-                              (int) strlen(shortnm),
-                              (int) sizeof(c->shortname) - 1);
-                       return -1;
-               }
+       default:
+               return 0;
+       }
 
-               /*
-                *      It should be OK now, let's create the buffer.
-                */
-               got_clients = TRUE;
-               c = rad_malloc(sizeof(RADCLIENT));
-               memset(c, 0, sizeof(*c));
-
-               c->ipaddr = ip_getaddr(hostnm);
-               if (c->ipaddr == INADDR_NONE) {
-                       clients_free(c);
-                       radlog(L_CONS|L_ERR, "%s[%d]: Failed to look up hostname %s",
-                                       file, lineno, hostnm);
-                       return -1;
-               }
-               c->netmask = htonl(mask);
-               c->ipaddr &= c->netmask; /* addr & mask are in network order */
+       return 1;
+}
 
-               strcpy((char *)c->secret, secret);
-               strcpy(c->shortname, shortnm);
 
-               /*
-                *      Only do DNS lookups for machines.  Just print
-                *      the network as the long name.
-                */
-               if ((~mask) == 0) {
-                       NAS *nas;
-                       ip_hostname(c->longname, sizeof(c->longname), c->ipaddr);
-
-                       /*
-                        *      Pull information over from the NAS.
-                        */
-                       nas = nas_find(c->ipaddr);
-                       if (nas) {
-                               /*
-                                *      No short name in the 'clients' file,
-                                *      try copying one over from the
-                                *      'naslist' file.
-                                */
-                               if (c->shortname[0] == '\0') {
-                                       strcpy(c->shortname, nas->shortname);
-                               }
-
-                               /*
-                                *  Copy the nastype over, too.
-                                */
-                               strcpy(c->nastype, nas->nastype);
-                       }
-               } else {
-                       hostnm[strlen(hostnm)] = '/';
-                       strNcpy(c->longname, hostnm, sizeof(c->longname));
+/*
+ *     Add a client to the tree.
+ */
+int client_add(RADCLIENT_LIST *clients, RADCLIENT *client)
+{
+       if (!clients || !client) {
+               return 0;
+       }
+
+       if (client->prefix < 0) {
+               return 0;
+       }
+
+       if (!client_sane(client)) return 0;
+
+       /*
+        *      Create a tree for it.
+        */
+       if (!clients->trees[client->prefix]) {
+               clients->trees[client->prefix] = rbtree_create(client_ipaddr_cmp,
+                                                              client_free, 0);
+               if (!clients->trees[client->prefix]) {
+                       return 0;
                }
+       }
 
-               c->next = mainconfig.clients;
-               mainconfig.clients = c;
+       /*
+        *      Duplicate?
+        */
+       if (!rbtree_insert(clients->trees[client->prefix], client)) {
+               return 0;
        }
-       fclose(fp);
 
-       if (got_clients) {
-               radlog(L_INFO, "Using deprecated clients file.  Support for this will go away soon.");
+#ifdef WITH_SNMP
+       if (!clients->num) rbtree_create(client_num_cmp, NULL, 0);
+
+       client->number = clients->max;
+       clients->max++;
+       if (clients->num) rbtree_insert(clients->num, client);
+#endif
+
+       if (client->prefix < clients->min_prefix) {
+               clients->min_prefix = client->prefix;
        }
 
-       return 0;
+       return 1;
+}
+
+
+/*
+ *     Find a client in the RADCLIENTS list by number.
+ *     This is a support function for the SNMP code.
+ */
+RADCLIENT *client_findbynumber(const RADCLIENT_LIST *clients,
+                              int number)
+{
+#ifdef WITH_SNMP
+       if (!clients) return NULL;
+
+       if (clients->num) {
+               RADCLIENT myclient;
+               
+               myclient.number = number;
+               
+               return rbtree_finddata(clients->num, &myclient);
+       }
+#endif
+       return NULL;
 }
 
 
 /*
  *     Find a client in the RADCLIENTS list.
  */
-RADCLIENT *client_find(uint32_t ipaddr)
+RADCLIENT *client_find(const RADCLIENT_LIST *clients,
+                      const lrad_ipaddr_t *ipaddr)
 {
-       RADCLIENT *cl;
-       RADCLIENT *match = NULL;
+       int i, max_prefix;
+       RADCLIENT myclient;
 
-       for (cl = mainconfig.clients; cl; cl = cl->next) {
-               if ((ipaddr & cl->netmask) == cl->ipaddr) {
-                       if ((!match) ||
-                           (ntohl(cl->netmask) > ntohl(match->netmask))) {
-                               match = cl;
-                       }
+       if (!clients || !ipaddr) return NULL;
+
+       switch (ipaddr->af) {
+       case AF_INET:
+               max_prefix = 32;
+               break;
+
+       case AF_INET6:
+               max_prefix = 128;
+               break;
+
+       default :
+               return NULL;
+       }
+
+       for (i = max_prefix; i >= clients->min_prefix; i--) {
+               void *data;
+
+               myclient.prefix = i;
+               myclient.ipaddr = *ipaddr;
+               client_sane(&myclient); /* clean up the ipaddress */
+
+               if (!clients->trees[i]) continue;
+               
+               data = rbtree_finddata(clients->trees[i], &myclient);
+               if (data) {
+                       return data;
                }
        }
 
-       return match;
+       return NULL;
 }
 
+
 /*
- *     Walk the RADCLIENT list displaying the clients.  This function
- *     is for debugging purposes.
+ *     Old wrapper for client_find
  */
-void client_walk(void)
+RADCLIENT *client_find_old(const lrad_ipaddr_t *ipaddr)
 {
-       RADCLIENT *cl;
-       char host_ipaddr[16];
-
-       for (cl = mainconfig.clients; cl != NULL; cl = cl->next)
-               radlog(L_ERR, "client: client_walk: %s\n",
-                               ip_ntoa(host_ipaddr, cl->ipaddr));
+       return client_find(mainconfig.clients, ipaddr);
 }
 
+
 /*
  *     Find the name of a client (prefer short name).
  */
-const char *client_name(uint32_t ipaddr)
+const char *client_name(const RADCLIENT_LIST *clients,
+                       const lrad_ipaddr_t *ipaddr)
 {
        /* We don't call this unless we should know about the client. */
        RADCLIENT *cl;
-       char host_ipaddr[16];
+       char host_ipaddr[128];
 
-       if ((cl = client_find(ipaddr)) != NULL) {
-               if (cl->shortname[0])
+       if ((cl = client_find(clients, ipaddr)) != NULL) {
+               if (cl->shortname && cl->shortname[0])
                        return cl->shortname;
                else
                        return cl->longname;
@@ -288,7 +346,152 @@ const char *client_name(uint32_t ipaddr)
         * If you see lots of these, then there's something wrong.
         */
        radlog(L_ERR, "Trying to look up name of unknown client %s.\n",
-              ip_ntoa(host_ipaddr, ipaddr));
+              ip_ntoh(ipaddr, host_ipaddr, sizeof(host_ipaddr)));
 
        return "UNKNOWN-CLIENT";
 }
+
+const char *client_name_old(const lrad_ipaddr_t *ipaddr)
+{
+       return client_name(mainconfig.clients, ipaddr);
+}
+
+static const CONF_PARSER client_config[] = {
+       { "secret",  PW_TYPE_STRING_PTR, 
+         offsetof(RADCLIENT, secret), 0, NULL },
+       { "shortname",  PW_TYPE_STRING_PTR, 
+         offsetof(RADCLIENT, shortname), 0, NULL },
+       { "nastype",  PW_TYPE_STRING_PTR, 
+         offsetof(RADCLIENT, nastype), 0, NULL },
+       { "login",  PW_TYPE_STRING_PTR, 
+         offsetof(RADCLIENT, login), 0, NULL },
+       { "password",  PW_TYPE_STRING_PTR, 
+         offsetof(RADCLIENT, password), 0, NULL },
+
+       { NULL, -1, 0, NULL, NULL }
+};
+
+
+/*
+ *     Create the linked list of clients from the new configuration
+ *     type.  This way we don't have to change too much in the other
+ *     source-files.
+ */
+RADCLIENT_LIST *clients_parse_section(const char *filename,
+                                     CONF_SECTION *section)
+{
+       CONF_SECTION    *cs;
+       RADCLIENT       *c;
+       char            *hostnm, *prefix_ptr = NULL;
+       const char      *name2;
+       RADCLIENT_LIST  *clients;
+
+       /*
+        *      Be forgiving.  If there's already a clients, return
+        *      it.  Otherwise create a new one.
+        */
+       clients = cf_data_find(section, "clients");
+       if (clients) return clients;
+
+       clients = clients_init();
+       if (!clients) return NULL;
+
+       /*
+        *      Associate the clients structure with the section, where
+        *      it will be freed once the section is freed.
+        */
+       if (cf_data_add(section, "clients", clients, clients_free) < 0) {
+               radlog(L_ERR, "%s[%d]: Failed to associate clients with section %s",
+                      filename, cf_section_lineno(section),
+                      cf_section_name1(section));
+               clients_free(clients);
+               return NULL;
+       }
+
+       for (cs = cf_subsection_find_next(section, NULL, "client");
+            cs != NULL;
+            cs = cf_subsection_find_next(section, cs, "client")) {
+               name2 = cf_section_name2(cs);
+               if (!name2) {
+                       radlog(L_CONS|L_ERR, "%s[%d]: Missing client name",
+                              filename, cf_section_lineno(cs));
+                       return NULL;
+               }
+               /*
+                * Check the lengths, we don't want any core dumps
+                */
+               hostnm = name2;
+               prefix_ptr = strchr(hostnm, '/');
+
+               /*
+                * The size is fine.. Let's create the buffer
+                */
+               c = rad_malloc(sizeof(RADCLIENT));
+               memset(c, 0, sizeof(RADCLIENT));
+
+               if (cf_section_parse(cs, c, client_config) < 0) {
+                       radlog(L_CONS|L_ERR, "%s[%d]: Error parsing client section.",
+                              filename, cf_section_lineno(cs));
+                       return NULL;
+               }
+
+               /*
+                * Look for prefixes.
+                */
+               c->prefix = -1;
+               if (prefix_ptr) {
+                       c->prefix = atoi(prefix_ptr + 1);
+                       if ((c->prefix < 0) || (c->prefix > 128)) {
+                               radlog(L_ERR, "%s[%d]: Invalid Prefix value '%s' for IP.",
+                                               filename, cf_section_lineno(cs), prefix_ptr + 1);
+                               return NULL;
+                       }
+                       /* Replace '/' with '\0' */
+                       *prefix_ptr = '\0';
+               }
+
+               /*
+                * Always get the numeric representation of IP
+                */
+               if (ip_hton(hostnm, AF_UNSPEC, &c->ipaddr) < 0) {
+                       radlog(L_CONS|L_ERR, "%s[%d]: Failed to look up hostname %s: %s",
+                              filename, cf_section_lineno(cs),
+                              hostnm, librad_errstr);
+                       return NULL;
+               } else {
+                       char buffer[256];
+                       ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
+                       c->longname = strdup(buffer);
+               }
+
+               /*
+                *      This makes later life easier.
+                */
+               if (!c->shortname) c->shortname = strdup(c->longname);
+
+               if (c->prefix < 0) switch (c->ipaddr.af) {
+               case AF_INET:
+                       c->prefix = 32;
+                       break;
+               case AF_INET6:
+                       c->prefix = 128;
+                       break;
+               default:
+                       break;
+               }
+
+               /*
+                *      FIXME: Add the client as data via cf_data_add,
+                *      for migration issues.
+                */
+
+               if (!client_add(clients, c)) {
+                       radlog(L_CONS|L_ERR, "%s[%d]: Failed to add client %s",
+                              filename, cf_section_lineno(cs), hostnm);
+                       client_free(c);
+                       return NULL;
+               }
+       }
+
+       return clients;
+}
index ed1953d..4d60e66 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdlib.h>
 #include <string.h>
 #      include <netinet/in.h>
 #endif
 
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+
 #ifdef HAVE_SYS_STAT_H
-#include       <sys/stat.h>
+#include <sys/stat.h>
+#endif
 #endif
 
-#include "radiusd.h"
-#include "rad_assert.h"
-#include "conffile.h"
-#include "token.h"
-#include "modules.h"
-
-static const char rcsid[] =
-"$Id$";
+#include <ctype.h>
 
-#define xstrdup strdup
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/modules.h>
 
 typedef enum conf_type {
+       CONF_ITEM_INVALID = 0,
        CONF_ITEM_PAIR,
-       CONF_ITEM_SECTION
+       CONF_ITEM_SECTION,
+       CONF_ITEM_DATA
 } CONF_ITEM_TYPE;
 
 struct conf_item {
@@ -70,13 +73,38 @@ struct conf_pair {
 };
 struct conf_part {
        CONF_ITEM item;
-       char *name1;
-       char *name2;
+       const char *name1;
+       const char *name2;
+       struct conf_item *children;
+       struct conf_item *tail; /* for speed */
+       rbtree_t        *pair_tree; /* and a partridge.. */
+       rbtree_t        *section_tree; /* no jokes here */
+       rbtree_t        *name2_tree; /* for sections of the same name2 */
+       rbtree_t        *data_tree;
        void *base;
        const CONF_PARSER *variables;
-       struct conf_item *children;
 };
 
+
+/*
+ *     Internal data that is associated with a configuration section,
+ *     so that we don't have to track it separately.
+ */
+struct conf_data {
+       CONF_ITEM  item;
+       const char *name;
+       int        flag;
+       void       *data;       /* user data */
+       void       (*free)(void *); /* free user data function */
+};
+
+
+static int cf_data_add_internal(CONF_SECTION *cs, const char *name,
+                               void *data, void (*data_free)(void *),
+                               int flag);
+static void *cf_data_find_internal(CONF_SECTION *cs, const char *name,
+                                  int flag);
+
 /*
  *     Isolate the scary casts in these tiny provably-safe functions
  */
@@ -107,20 +135,34 @@ CONF_ITEM *cf_sectiontoitem(CONF_SECTION *cs)
        return (CONF_ITEM *)cs;
 }
 
+static CONF_DATA *cf_itemtodata(CONF_ITEM *ci)
+{
+       if (ci == NULL)
+               return NULL;
+       rad_assert(ci->type == CONF_ITEM_DATA);
+       return (CONF_DATA *)ci;
+}
+static CONF_ITEM *cf_datatoitem(CONF_DATA *cd)
+{
+       if (cd == NULL)
+               return NULL;
+       return (CONF_ITEM *)cd;
+}
+
 /*
  *     Create a new CONF_PAIR
  */
 static CONF_PAIR *cf_pair_alloc(const char *attr, const char *value,
-               LRAD_TOKEN operator, CONF_SECTION *parent)
+                               LRAD_TOKEN operator, CONF_SECTION *parent)
 {
        CONF_PAIR *cp;
 
-       cp = (CONF_PAIR *)rad_malloc(sizeof(CONF_PAIR));
-       memset(cp, 0, sizeof(CONF_PAIR));
+       cp = rad_malloc(sizeof(*cp));
+       memset(cp, 0, sizeof(*cp));
        cp->item.type = CONF_ITEM_PAIR;
        cp->item.parent = parent;
-       cp->attr = xstrdup(attr);
-       cp->value = xstrdup(value);
+       cp->attr = strdup(attr);
+       cp->value = strdup(value);
        cp->operator = operator;
 
        return cp;
@@ -146,6 +188,83 @@ void cf_pair_free(CONF_PAIR **cp)
        *cp = NULL;
 }
 
+
+static void cf_data_free(CONF_DATA **cd)
+{
+       if (!cd || !*cd) return;
+
+       free((*cd)->name);
+       if (!(*cd)->free) {
+               free((*cd)->data);
+       } else {
+               ((*cd)->free)((*cd)->data);
+       }
+#ifndef NDEBUG
+       memset(*cd, 0, sizeof(*cd));
+#endif
+       free(*cd);
+       *cd = NULL;
+}
+
+/*
+ *     rbtree callback function
+ */
+static int pair_cmp(const void *a, const void *b)
+{
+       const CONF_PAIR *one = a;
+       const CONF_PAIR *two = b;
+
+       return strcmp(one->attr, two->attr);
+}
+
+
+/*
+ *     rbtree callback function
+ */
+static int section_cmp(const void *a, const void *b)
+{
+       const CONF_SECTION *one = a;
+       const CONF_SECTION *two = b;
+
+       return strcmp(one->name1, two->name1);
+}
+
+
+/*
+ *     rbtree callback function
+ */
+static int name2_cmp(const void *a, const void *b)
+{
+       const CONF_SECTION *one = a;
+       const CONF_SECTION *two = b;
+
+       rad_assert(strcmp(one->name1, two->name1) == 0);
+
+       if (!one->name2 && !two->name2) return 0;
+       if (!one->name2) return -1;
+       if (!two->name2) return +1;
+
+       return strcmp(one->name2, two->name2);
+}
+
+
+/*
+ *     rbtree callback function
+ */
+static int data_cmp(const void *a, const void *b)
+{
+       int rcode;
+
+       const CONF_DATA *one = a;
+       const CONF_DATA *two = b;
+
+       rcode = one->flag - two->flag;
+       if (rcode != 0) return rcode;
+
+       return strcmp(one->name, two->name);
+}
+
+
 /*
  *     Free strings we've parsed into data structures.
  */
@@ -155,33 +274,42 @@ static void cf_section_parse_free(void *base, const CONF_PARSER *variables)
 
        /*
         *      Don't automatically free the strings if we're being
-        *      called from a module.
+        *      called from a module.  This is also for clients.c,
+        *      where client_free() expects to be able to free the
+        *      client structure.  If we moved everything to key off
+        *      of the config files, we might solve some problems...
         */
-       if (base || !variables) return;
-       
+       if (!variables) return;
+
        /*
         *      Free up dynamically allocated string pointers.
         */
        for (i = 0; variables[i].name != NULL; i++) {
                char **p;
 
-               if (variables[i].type != PW_TYPE_STRING_PTR) {
+               if ((variables[i].type != PW_TYPE_STRING_PTR) &&
+                   (variables[i].type != PW_TYPE_FILENAME)) {
                        continue;
                }
 
                /*
-                *      Prefer the data, if it's there.
-                *      Else use the base + offset.
+                *      No base struct offset, data must be the pointer.
+                *      If data doesn't exist, ignore the entry, there
+                *      must be something wrong.
                 */
-               if (!variables[i].data) {
-                       continue;
-               }
+               if (!base) {
+                       if (!variables[i].data) {
+                               continue;
+                       }
 
-               /*
-                *      FIXME: Add base
-                */
-               p = (char **) (variables[i].data);
+                       p = (char **) variables[i].data;;
 
+               } else if (variables[i].data) {
+                       p = (char **) variables[i].data;;
+
+               } else {
+                       p = (char **) (((char *)base) + variables[i].offset);
+               }
 
                free(*p);
                *p = NULL;
@@ -190,27 +318,6 @@ static void cf_section_parse_free(void *base, const CONF_PARSER *variables)
 
 
 /*
- *     Allocate a CONF_SECTION
- */
-static CONF_SECTION *cf_section_alloc(const char *name1, const char *name2,
-                                     CONF_SECTION *parent, const char *cf)
-{
-       CONF_SECTION    *cs;
-
-       if (name1 == NULL || !name1[0])
-               name1 = "main";
-
-       cs = (CONF_SECTION *)rad_malloc(sizeof(CONF_SECTION));
-       memset(cs, 0, sizeof(CONF_SECTION));
-       cs->item.type = CONF_ITEM_SECTION;
-       cs->item.parent = parent;
-       cs->name1 = strdup(name1);
-       cs->name2 = (name2 && *name2) ? xstrdup(name2) : NULL;
-
-       return cs;
-}
-
-/*
  *     Free a CONF_SECTION
  */
 void cf_section_free(CONF_SECTION **cs)
@@ -225,12 +332,29 @@ void cf_section_free(CONF_SECTION **cs)
 
        for (ci = (*cs)->children; ci; ci = next) {
                next = ci->next;
-               if (ci->type==CONF_ITEM_PAIR) {
-                       CONF_PAIR *pair = cf_itemtopair(ci);
-                       cf_pair_free(&pair);
-               } else {
-                       CONF_SECTION *section = cf_itemtosection(ci);
-                       cf_section_free(&section);
+
+               switch (ci->type) {
+               case CONF_ITEM_PAIR: {
+                               CONF_PAIR *pair = cf_itemtopair(ci);
+                               cf_pair_free(&pair);
+                       }
+                       break;
+
+               case CONF_ITEM_SECTION: {
+                               
+                               CONF_SECTION *section = cf_itemtosection(ci);
+                               cf_section_free(&section);
+                       }
+                       break;
+
+               case CONF_ITEM_DATA: {
+                               CONF_DATA *data = cf_itemtodata(ci);
+                               cf_data_free(&data);
+                       }
+                       break;
+
+               default:        /* should really be an error. */
+                       break;
                }
        }
 
@@ -238,6 +362,14 @@ void cf_section_free(CONF_SECTION **cs)
                free((*cs)->name1);
        if ((*cs)->name2)
                free((*cs)->name2);
+       if ((*cs)->pair_tree)
+               rbtree_free((*cs)->pair_tree);
+       if ((*cs)->section_tree)
+               rbtree_free((*cs)->section_tree);
+       if ((*cs)->name2_tree)
+               rbtree_free((*cs)->name2_tree);
+       if ((*cs)->data_tree)
+               rbtree_free((*cs)->data_tree);
 
        /*
         * And free the section
@@ -250,33 +382,145 @@ void cf_section_free(CONF_SECTION **cs)
        *cs = NULL;
 }
 
+
+/*
+ *     Allocate a CONF_SECTION
+ */
+static CONF_SECTION *cf_section_alloc(const char *name1, const char *name2,
+                                     CONF_SECTION *parent)
+{
+       CONF_SECTION    *cs;
+
+       if (!name1) return NULL;
+
+       cs = rad_malloc(sizeof(*cs));
+       memset(cs, 0, sizeof(*cs));
+       cs->item.type = CONF_ITEM_SECTION;
+       cs->item.parent = parent;
+       cs->name1 = strdup(name1);
+       if (!cs->name1) {
+               cf_section_free(&cs);
+               return NULL;
+       }
+       
+       if (name2 && *name2) {
+               cs->name2 = strdup(name2);
+               if (!cs->name2) {
+                       cf_section_free(&cs);
+                       return NULL;
+               }
+       }
+       cs->pair_tree = rbtree_create(pair_cmp, NULL, 0);
+       if (!cs->pair_tree) {
+               cf_section_free(&cs);
+               return NULL;
+       }
+
+       /*
+        *      Don't create a data tree, it may not be needed.
+        */
+
+       /*
+        *      Don't create the section tree here, it may not
+        *      be needed.
+        */
+       return cs;
+}
+
+
 /*
  *     Add an item to a configuration section.
  */
-static void cf_item_add(CONF_SECTION *cs, CONF_ITEM *ci_new)
+static void cf_item_add(CONF_SECTION *cs, CONF_ITEM *ci)
 {
-       CONF_ITEM *ci;
+       if (!cs->children) {
+               rad_assert(cs->tail == NULL);
+               cs->children = ci;
+       } else {
+               rad_assert(cs->tail != NULL);
+               cs->tail->next = ci;
+       }
 
-       for (ci = cs->children; ci && ci->next; ci = ci->next)
-               ;
+       /*
+        *      Update the trees (and tail) for each item added.
+        */
+       for (/* nothing */; ci != NULL; ci = ci->next) {
+               cs->tail = ci;
 
-       if (ci == NULL)
-               cs->children = ci_new;
-       else
-               ci->next = ci_new;
+               /*
+                *      For fast lookups, pair's and sections get
+                *      added to rbtree's.
+                */
+               switch (ci->type) {
+                       case CONF_ITEM_PAIR:
+                               rbtree_insert(cs->pair_tree, ci);
+                               break;
+                               
+                       case CONF_ITEM_SECTION: {
+                               const CONF_SECTION *cs_new = cf_itemtosection(ci);
+                               
+                               if (!cs->section_tree) {
+                                       cs->section_tree = rbtree_create(section_cmp, NULL, 0);
+                                       /* ignore any errors */
+                               }
+                               
+                               if (cs->section_tree) {
+                                       rbtree_insert(cs->section_tree, cs_new);                                }
+                               
+                               /*
+                                *      Two names: find the named instance.
+                                */
+                               if (cs_new->name2) {
+                                       CONF_SECTION *old_cs;
+                                       
+                                       /*
+                                        *      Find the FIRST
+                                        *      CONF_SECTION having
+                                        *      the given name1, and
+                                        *      create a new tree
+                                        *      under it.
+                                        */
+                                       old_cs = rbtree_finddata(cs->section_tree, cs_new);
+                                       if (!old_cs) return; /* this is a bad error! */
+                                       
+                                       if (!old_cs->name2_tree) {
+                                               old_cs->name2_tree = rbtree_create(name2_cmp,
+                                                                                  NULL, 0);
+                                       }
+                                       if (old_cs->name2_tree) {
+                                               rbtree_insert(old_cs->name2_tree, cs_new);
+                                       }
+                               } /* had a name2 */
+                               break;
+                       } /* was a section */
+
+                       case CONF_ITEM_DATA:
+                               if (!cs->data_tree) {
+                                       cs->data_tree = rbtree_create(data_cmp, NULL, 0);
+                               }
+                               if (cs->data_tree) {
+                                       rbtree_insert(cs->data_tree, ci);
+                               }
+                               break;
+
+                       default: /* FIXME: assert & error! */
+                               break;
+
+               } /* switch over conf types */
+       } /* loop over ci */
 }
 
 /*
  *     Expand the variables in an input string.
  */
 static const char *cf_expand_variables(const char *cf, int *lineno,
-                                      CONF_SECTION *outercs,
+                                      const CONF_SECTION *outercs,
                                       char *output, const char *input)
 {
        char *p;
        const char *end, *ptr;
        char name[8192];
-       CONF_SECTION *parentcs;
+       const CONF_SECTION *parentcs;
 
        /*
         *      Find the master parent conf section.
@@ -298,7 +542,12 @@ static const char *cf_expand_variables(const char *cf, int *lineno,
                if ((*ptr == '$') && (ptr[1] == '{')) {
                        int up;
                        CONF_PAIR *cp;
-                       CONF_SECTION *cs;
+                       const CONF_SECTION *cs;
+
+                       /*
+                        *      FIXME: Add support for ${foo:-bar},
+                        *      like in xlat.c
+                        */
 
                        /*
                         *      Look for trailing '}', and log a
@@ -405,7 +654,9 @@ static const char *cf_expand_variables(const char *cf, int *lineno,
                                                if (!up) cp = cf_pair_find(parentcs, name);
                                        }
                                        if (cp == NULL) {
-                                               radlog(L_ERR, "config: No such entry %s for string %s", name, input);
+                                               radlog(L_ERR, "config: No such configuration item %s in section %s when expanding string \"%s\"", name,
+                                                      cf_section_name1(cs),
+                                                      input);
                                                return NULL;
                                        }
                                }
@@ -468,44 +719,239 @@ static const char *cf_expand_variables(const char *cf, int *lineno,
 
 
 /*
- *     Parse a configuration section into user-supplied variables.
+ *     Parses an item (not a CONF_ITEM) into the specified format,
+ *     with a default value.
+ *
+ *     Returns -1 on error, 0 for correctly parsed, and 1 if the
+ *     default value was used.  Note that the default value will be
+ *     used ONLY if the CONF_PAIR is NULL.
  */
-int cf_section_parse(CONF_SECTION *cs, void *base,
-                    const CONF_PARSER *variables)
+int cf_item_parse(CONF_SECTION *cs, const char *name,
+                 int type, void *data, const char *dflt)
 {
-       int i;
-       int rcode;
+       int rcode = 0;
        char **q;
-       CONF_PAIR *cp;
-       CONF_SECTION *subsection;
-       uint32_t ipaddr;
-       char buffer[8192];
        const char *value;
-       void *data;
+       lrad_ipaddr_t ipaddr;
+       const CONF_PAIR *cp;
+       char ipbuf[128];
 
-       /*
-        *      Handle the user-supplied variables.
-        */
-       for (i = 0; variables[i].name != NULL; i++) {
-               value = variables[i].dflt;
-               if (variables[i].data) {
-                       data = variables[i].data; /* prefer this. */
-               } else if (base) {
-                       data = ((char *)base) + variables[i].offset;
+       cp = cf_pair_find(cs, name);
+       if (cp) {
+               value = cp->value;
+
+       } else if (!dflt) {
+               return 1;       /* nothing to parse, return default value */
+
+       } else {
+               rcode = 1;
+               value = dflt;
+       }
+
+       switch (type) {
+       case PW_TYPE_BOOLEAN:
+               /*
+                *      Allow yes/no and on/off
+                */
+               if ((strcasecmp(value, "yes") == 0) ||
+                   (strcasecmp(value, "on") == 0)) {
+                       *(int *)data = 1;
+               } else if ((strcasecmp(value, "no") == 0) ||
+                          (strcasecmp(value, "off") == 0)) {
+                       *(int *)data = 0;
+               } else {
+                       *(int *)data = 0;
+                       radlog(L_ERR, "Bad value \"%s\" for boolean variable %s", value, name);
+                       return -1;
+               }
+               if (cs->name2) {
+                       DEBUG2(" %s %s: %s = %s", cs->name1, cs->name2, name, value);
+               } else {
+                       DEBUG2(" %s: %s = %s", cs->name1, name, value);
+               }
+               break;
+               
+       case PW_TYPE_INTEGER:
+               *(int *)data = strtol(value, 0, 0);
+               if (cs->name2) {
+                       DEBUG2(" %s %s: %s = %d",
+                              cs->name1, cs->name2, name,
+                              *(int *)data);
+               } else {
+                       DEBUG2(" %s: %s = %d",
+                              cs->name1, name,
+                              *(int *)data);
+               }
+               break;
+               
+       case PW_TYPE_STRING_PTR:
+               q = (char **) data;
+               if (*q != NULL) {
+                       free(*q);
+               }
+               
+               /*
+                *      Expand variables which haven't already been
+                *      expanded automagically when the configuration
+                *      file was read.
+                */
+               if (value == dflt) {
+                       char buffer[8192];
+
+                       int lineno = cs->item.lineno;
+
+                       /*
+                        *      FIXME: sizeof(buffer)?
+                        */
+                       value = cf_expand_variables("?",
+                                                   &lineno,
+                                                   cs, buffer, value);
+                       if (!value) return -1;
+               }
+               
+               if (cs->name2) {
+                       DEBUG2(" %s %s: %s = \"%s\"",
+                              cs->name1, cs->name2, name,
+                              value ? value : "(null)");
+               } else {
+                       DEBUG2(" %s: %s = \"%s\"",
+                              cs->name1, name,
+                              value ? value : "(null)");
+               }
+               *q = value ? strdup(value) : NULL;
+               break;
+               
+               /*
+                *      This is the same as PW_TYPE_STRING_PTR,
+                *      except that we also "stat" the file, and
+                *      cache the result.
+                */
+       case PW_TYPE_FILENAME:
+               q = (char **) data;
+               if (*q != NULL) {
+                       free(*q);
+               }
+               
+               /*
+                *      Expand variables which haven't already been
+                *      expanded automagically when the configuration
+                *      file was read.
+                */
+               if (value == dflt) {
+                       char buffer[8192];
+
+                       int lineno = cs->item.lineno;
+
+                       /*
+                        *      FIXME: sizeof(buffer)?
+                        */
+                       value = cf_expand_variables("?",
+                                                   &lineno,
+                                                   cs, buffer, value);
+                       if (!value) return -1;
+               }
+               
+               if (cs->name2) {
+                       DEBUG2(" %s %s: %s = \"%s\"",
+                              cs->name1, cs->name2, name,
+                              value ? value : "(null)");
                } else {
-                       data = variables[i].data;
+                       DEBUG2(" %s: %s = \"%s\"",
+                              cs->name1, name,
+                              value ? value : "(null)");
+               }
+               *q = value ? strdup(value) : NULL;
+
+               /*
+                *      And now we "stat" the file.
+                */
+               if (*q) {
+                       struct stat buf;
+
+                       if (stat(*q, &buf) == 0) {
+                               time_t *mtime;
+
+                               mtime = rad_malloc(sizeof(*mtime));
+                               *mtime = buf.st_mtime;
+                               /* FIXME: error? */
+                               cf_data_add_internal(cs, *q, mtime, free,
+                                                    PW_TYPE_FILENAME);
+                       }
                }
+               break;
 
-               cp = cf_pair_find(cs, variables[i].name);
-               if (cp) {
-                       value = cp->value;
+       case PW_TYPE_IPADDR:
+               /*
+                *      Allow '*' as any address
+                */
+               if (strcmp(value, "*") == 0) {
+                       *(uint32_t *) data = htonl(INADDR_ANY);
+                       DEBUG2(" %s: %s = *", cs->name1, name);
+                       break;
+               }
+               if (ip_hton(value, AF_INET, &ipaddr) < 0) {
+                       radlog(L_ERR, "Can't find IP address for host %s", value);
+                       return -1;
+               }
+               if (cs->name2) {
+                       DEBUG2(" %s %s: %s = %s IP address [%s]",
+                              cs->name1, cs->name2, name, value,
+                              ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
+               } else {
+                       DEBUG2(" %s: %s = %s IP address [%s]",
+                              cs->name1, name, value,
+                              ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
+               }
+               *(uint32_t *) data = ipaddr.ipaddr.ip4addr.s_addr;
+               break;
+               
+       case PW_TYPE_IPV6ADDR:
+               if (ip_hton(value, AF_INET6, &ipaddr) < 0) {
+                       radlog(L_ERR, "Can't find IPv6 address for host %s", value);
+                       return -1;
+               }
+               if (cs->name2) {
+                       DEBUG2(" %s %s: %s = %s IPv6 address [%s]",
+                              cs->name1, cs->name2, name, value,
+                              ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
+               } else {
+                       DEBUG2(" %s: %s = %s IPv6 address [%s]",
+                              cs->name1, name, value,
+                              ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
                }
+               memcpy(data, &ipaddr.ipaddr.ip6addr,
+                      sizeof(ipaddr.ipaddr.ip6addr));
+               break;
+               
+       default:
+               radlog(L_ERR, "type %d not supported yet", type);
+               return -1;
+               break;
+       } /* switch over variable type */
+       
+       return rcode;
+}
 
-               switch (variables[i].type)
-               {
-               case PW_TYPE_SUBSECTION:
-                       subsection = cf_section_sub_find(cs,variables[i].name);
+/*
+ *     Parse a configuration section into user-supplied variables.
+ */
+int cf_section_parse(CONF_SECTION *cs, void *base,
+                    const CONF_PARSER *variables)
+{
+       int i;
+       void *data;
 
+       /*
+        *      Handle the known configuration parameters.
+        */
+       for (i = 0; variables[i].name != NULL; i++) {
+               /*
+                *      Handle subsections specially
+                */
+               if (variables[i].type == PW_TYPE_SUBSECTION) {
+                       const CONF_SECTION *subcs;
+                       subcs = cf_section_sub_find(cs, variables[i].name);
+                       
                        /*
                         *      If the configuration section is NOT there,
                         *      then ignore it.
@@ -513,103 +959,40 @@ int cf_section_parse(CONF_SECTION *cs, void *base,
                         *      FIXME! This is probably wrong... we should
                         *      probably set the items to their default values.
                         */
-                       if (subsection == NULL) {
-                               break;
-                       }
+                       if (!subcs) continue;
 
-                       rcode = cf_section_parse(subsection, base,
-                                                (CONF_PARSER *) data);
-                       if (rcode < 0) {
+                       if (!variables[i].dflt) {
+                               DEBUG2("Internal sanity check 1 failed in cf_section_parse");
                                cf_section_parse_free(base, variables);
                                return -1;
                        }
-                       break;
-
-               case PW_TYPE_BOOLEAN:
-                       /*
-                        *      Allow yes/no and on/off
-                        */
-                       if ((strcasecmp(value, "yes") == 0) ||
-                                       (strcasecmp(value, "on") == 0)) {
-                               *(int *)data = 1;
-                       } else if ((strcasecmp(value, "no") == 0) ||
-                                               (strcasecmp(value, "off") == 0)) {
-                               *(int *)data = 0;
-                       } else {
-                               *(int *)data = 0;
-                               radlog(L_ERR, "Bad value \"%s\" for boolean variable %s", value, variables[i].name);
+                       
+                       if (cf_section_parse(subcs, base,
+                                            (const CONF_PARSER *) variables[i].dflt) < 0) {
                                cf_section_parse_free(base, variables);
                                return -1;
                        }
-                       DEBUG2(" %s: %s = %s",
-                                       cs->name1,
-                                       variables[i].name,
-                                       value);
-                       break;
-
-               case PW_TYPE_INTEGER:
-                       *(int *)data = strtol(value, 0, 0);
-                       DEBUG2(" %s: %s = %d",
-                                       cs->name1,
-                                       variables[i].name,
-                                       *(int *)data);
-                       break;
-
-               case PW_TYPE_STRING_PTR:
-                       q = (char **) data;
-                       if (*q != NULL) {
-                               free(*q);
-                       }
-
-                       /*
-                        *      Expand variables while parsing,
-                        *      but ONLY expand ones which haven't already
-                        *      been expanded.
-                        */
-                       if (value && (value == variables[i].dflt)) {
-                               value = cf_expand_variables("?",
-                                                           &cs->item.lineno,
-                                                           cs, buffer, value);
-                               if (!value) {
-                                       cf_section_parse_free(base, variables);
-                                       return -1;
-                               }
-                       }
-
-                       DEBUG2(" %s: %s = \"%s\"",
-                                       cs->name1,
-                                       variables[i].name,
-                                       value ? value : "(null)");
-                       *q = value ? strdup(value) : NULL;
-                       break;
-
-               case PW_TYPE_IPADDR:
-                       /*
-                        *      Allow '*' as any address
-                        */
-                       if (strcmp(value, "*") == 0) {
-                               *(uint32_t *) data = 0;
-                               break;
-                       }
-                       ipaddr = ip_getaddr(value);
-                       if (ipaddr == 0) {
-                               radlog(L_ERR, "Can't find IP address for host %s", value);
-                               cf_section_parse_free(base, variables);
-                               return -1;
-                       }
-                       DEBUG2(" %s: %s = %s IP address [%s]",
-                                       cs->name1,
-                                       variables[i].name,
-                                       value, ip_ntoa(buffer, ipaddr));
-                       *(uint32_t *) data = ipaddr;
-                       break;
+                       continue;
+               } /* else it's a CONF_PAIR */
+               
+               if (variables[i].data) {
+                       data = variables[i].data; /* prefer this. */
+               } else if (base) {
+                       data = ((char *)base) + variables[i].offset;
+               } else {
+                       DEBUG2("Internal sanity check 2 failed in cf_section_parse");
+                       cf_section_parse_free(base, variables);
+                       return -1;
+               }
 
-               default:
-                       radlog(L_ERR, "type %d not supported yet", variables[i].type);
+               /*
+                *      Parse the pair we found, or a default value.
+                */
+               if (cf_item_parse(cs, variables[i].name, variables[i].type,
+                                 data, variables[i].dflt) < 0) {
                        cf_section_parse_free(base, variables);
                        return -1;
-                       break;
-               } /* switch over variable type */
+               }
        } /* for all variables in the configuration section */
 
        cs->base = base;
@@ -622,11 +1005,11 @@ int cf_section_parse(CONF_SECTION *cs, void *base,
 /*
  *     Read a part of the config file.
  */
-static CONF_SECTION *cf_section_read(const char *cf, int *lineno, FILE *fp,
-                                    const char *name1, const char *name2,
-                                    CONF_SECTION *parent)
+static int cf_section_read(const char *file, int *lineno, FILE *fp,
+                          CONF_SECTION *current)
+
 {
-       CONF_SECTION *cs, *css;
+       CONF_SECTION *this, *css;
        CONF_PAIR *cpn;
        char *ptr;
        const char *value;
@@ -638,21 +1021,7 @@ static CONF_SECTION *cf_section_read(const char *cf, int *lineno, FILE *fp,
        char *cbuf = buf;
        int len;
 
-       /*
-        *      Ensure that the user can't add CONF_SECTIONs
-        *      with 'internal' names;
-        */
-       if ((name1 != NULL) && (name1[0] == '_')) {
-               radlog(L_ERR, "%s[%d]: Illegal configuration section name",
-                       cf, *lineno);
-               return NULL;
-       }
-
-       /*
-        *      Allocate new section.
-        */
-       cs = cf_section_alloc(name1, name2, parent, cf);
-       cs->item.lineno = *lineno;
+       this = current;         /* add items here */
 
        /*
         *      Read, checking for line continuations ('\\' at EOL)
@@ -672,13 +1041,11 @@ static CONF_SECTION *cf_section_read(const char *cf, int *lineno, FILE *fp,
                 *      We've filled the buffer, and there isn't
                 *      a CR in it.  Die!
                 */
-               if ((len >= (sizeof(buf) - 1)) &&
-                   (((cbuf[len - 1] != '\n')) ||
-                    (cbuf[len - 1] == '\\'))) {
+               if ((len == (sizeof(buf) - 1)) &&
+                   (cbuf[len - 1] != '\n')) {
                        radlog(L_ERR, "%s[%d]: Line too long",
-                              cf, *lineno);
-                       cf_section_free(&cs);
-                       return NULL;
+                              file, *lineno);
+                       return -1;
                }
 
                /*
@@ -706,11 +1073,25 @@ static CONF_SECTION *cf_section_read(const char *cf, int *lineno, FILE *fp,
                ptr = cbuf = buf;
                t1 = gettoken(&ptr, buf1, sizeof(buf1));
 
+               if ((*buf1 == '#') || (*buf1 == '\0')) {
+                       continue;
+              }
+
                /*
-                *      Skip comments and blank lines immediately.
+                *      The caller eats "name1 name2 {", and calls us
+                *      for the data inside of the section.  So if we
+                *      receive a closing brace, then it must mean the
+                *      end of the section.
                 */
-               if ((*buf1 == '#') || (*buf1 == '\0')) {
-                       continue;
+              if (t1 == T_RCBRACE) {
+                      if (this == current) {
+                              radlog(L_ERR, "%s[%d]: Too many closing braces",
+                                     file, *lineno);
+                              return -1;
+                              
+                      }
+                      this = this->item.parent;
+                      continue;
                }
 
                /*
@@ -720,58 +1101,75 @@ static CONF_SECTION *cf_section_read(const char *cf, int *lineno, FILE *fp,
                 *      I really really really hate this file.  -cparker
                 */
                if (strcasecmp(buf1, "$INCLUDE") == 0) {
-
-                       CONF_SECTION      *is;
-
                        t2 = getword(&ptr, buf2, sizeof(buf2));
 
-                       value = cf_expand_variables(cf, lineno, cs, buf, buf2);
-                       if (value == NULL) {
-                               cf_section_free(&cs);
-                               return NULL;
-                       }
-
-                       DEBUG2( "Config:   including file: %s", value );
-
-                       if ((is = conf_read(cf, *lineno, value, cs)) == NULL) {
-                               cf_section_free(&cs);
-                               return NULL;
-                       }
+                       value = cf_expand_variables(file, lineno, this, buf, buf2);
+                       if (!value) return -1;
 
+#ifdef HAVE_DIRENT_H
                        /*
-                        *      Add the included conf to our CONF_SECTION
+                        *      $INCLUDE foo/
+                        *
+                        *      Include ALL non-"dot" files in the directory.
+                        *      careful!
                         */
-                       if (is != NULL) {
-                               if (is->children != NULL) {
-                                       CONF_ITEM *ci;
+                       if (value[strlen(value) - 1] == '/') {
+                               DIR             *dir;
+                               struct dirent   *dp;
+                               struct stat stat_buf;
+
+                               DEBUG2( "Config:   including files in directory: %s", value );
+                               dir = opendir(value);
+                               if (!dir) {
+                                       radlog(L_ERR, "%s[%d]: Error reading directory %s: %s",
+                                              file, *lineno, value,
+                                              strerror(errno));
+                                       return -1;
+                               }
+
+                               /*
+                                *      Read the directory, ignoring "." files.
+                                */
+                               while ((dp = readdir(dir)) != NULL) {
+                                       const char *p;
+
+                                       if (dp->d_name[0] == '.') continue;
 
                                        /*
-                                        *      Re-write the parent of the
-                                        *      moved children to be the
-                                        *      upper-layer section.
+                                        *      Check for valid characters
                                         */
-                                       for (ci = is->children; ci; ci = ci->next) {
-                                               ci->parent = cs;
+                                       for (p = dp->d_name; *p != '\0'; p++) {
+                                               if (isalpha((int)*p) ||
+                                                   isdigit((int)*p) ||
+                                                   (*p == '_') ||
+                                                   (*p == '.')) continue;
+                                               break;
                                        }
+                                       if (*p != '\0') continue;
 
+                                       snprintf(buf2, sizeof(buf2), "%s%s",
+                                                value, dp->d_name);
+                                       if ((stat(buf2, &stat_buf) != 0) ||
+                                           S_ISDIR(stat_buf.st_mode)) continue;
                                        /*
-                                        *      If there are children, then
-                                        *      move them up a layer.
+                                        *      Read the file into the current
+                                        *      configuration sectoin.
                                         */
-                                       if (is->children) {
-                                               cf_item_add(cs, is->children);
+                                       if (cf_file_include(buf2, this) < 0) {
+                                               closedir(dir);
+                                               return -1;
                                        }
-                                       is->children = NULL;
                                }
-                               /*
-                                *      Always free the section for the
-                                *      $INCLUDEd file.
-                                */
-                               cf_section_free(&is);
+                               closedir(dir);
+                       }  else
+#endif
+                       { /* it was a normal file */
+                               if (cf_file_include(value, this) < 0) {
+                                       return -1;
+                               }
                        }
-
                        continue;
-               }
+               } /* we were in an include */
 
                /*
                 *      No '=': must be a section or sub-section.
@@ -785,30 +1183,23 @@ static CONF_SECTION *cf_section_read(const char *cf, int *lineno, FILE *fp,
                }
 
                /*
-                *      See if it's the end of a section.
-                */
-               if (t1 == T_RCBRACE) {
-                       if (name1 == NULL || buf2[0]) {
-                               radlog(L_ERR, "%s[%d]: Unexpected end of section",
-                                               cf, *lineno);
-                               cf_section_free(&cs);
-                               return NULL;
-                       }
-                       return cs;
-               }
-
-               /*
                 * Perhaps a subsection.
                 */
                if (t2 == T_LCBRACE || t3 == T_LCBRACE) {
-                       css = cf_section_read(cf, lineno, fp, buf1,
-                                             t2==T_LCBRACE ? NULL : buf2, cs);
-                       if (css == NULL) {
-                               cf_section_free(&cs);
-                               return NULL;
+                       css = cf_section_alloc(buf1,
+                                              t2 == T_LCBRACE ? NULL : buf2,
+                                              this);
+                       if (!css) {
+                               radlog(L_ERR, "%s[%d]: Failed allocating memory for section",
+                                               file, *lineno);
                        }
-                       cf_item_add(cs, cf_sectiontoitem(css));
+                       cf_item_add(this, cf_sectiontoitem(css));
+                       css->item.lineno = *lineno;
 
+                       /*
+                        *      The current section is now the child section.
+                        */
+                       this = css;
                        continue;
                }
 
@@ -826,9 +1217,8 @@ static CONF_SECTION *cf_section_read(const char *cf, int *lineno, FILE *fp,
                } else if (buf1[0] == 0 || buf2[0] == 0 ||
                           (t2 < T_EQSTART || t2 > T_EQEND)) {
                        radlog(L_ERR, "%s[%d]: Line is not in 'attribute = value' format",
-                                       cf, *lineno);
-                       cf_section_free(&cs);
-                       return NULL;
+                                       file, *lineno);
+                       return -1;
                }
 
                /*
@@ -837,105 +1227,139 @@ static CONF_SECTION *cf_section_read(const char *cf, int *lineno, FILE *fp,
                 */
                if (buf1[0] == '_') {
                        radlog(L_ERR, "%s[%d]: Illegal configuration pair name \"%s\"",
-                                       cf, *lineno, buf1);
-                       cf_section_free(&cs);
-                       return NULL;
+                                       file, *lineno, buf1);
+                       return -1;
                }
 
                /*
                 *      Handle variable substitution via ${foo}
                 */
-               value = cf_expand_variables(cf, lineno, cs, buf, buf3);
-               if (!value) {
-                       cf_section_free(&cs);
-                       return NULL;
-               }
+               value = cf_expand_variables(file, lineno, this, buf, buf3);
+               if (!value) return -1;
 
 
                /*
                 *      Add this CONF_PAIR to our CONF_SECTION
                 */
-               cpn = cf_pair_alloc(buf1, value, t2, parent);
+               cpn = cf_pair_alloc(buf1, value, t2, this);
                cpn->item.lineno = *lineno;
-               cf_item_add(cs, cf_pairtoitem(cpn));
+               cf_item_add(this, cf_pairtoitem(cpn));
        }
 
        /*
         *      See if EOF was unexpected ..
         */
-       if (name1 != NULL) {
-               radlog(L_ERR, "%s[%d]: Unexpected end of file", cf, *lineno);
-               cf_section_free(&cs);
-               return NULL;
+       if (feof(fp) && (this != current)) {
+               radlog(L_ERR, "%s[%d]: EOF reached without closing brace for section %s starting at line %d",
+                      file, *lineno,
+                      cf_section_name1(this), cf_section_lineno(this));
+               return -1;
        }
 
-       return cs;
+       return 0;
 }
 
 /*
- *     Read the config file.
+ *     Include one config file in another.
  */
-CONF_SECTION *conf_read(const char *fromfile, int fromline,
-                       const char *conffile, CONF_SECTION *parent)
+int cf_file_include(const char *file, CONF_SECTION *cs)
 {
        FILE            *fp;
        int             lineno = 0;
-       CONF_SECTION    *cs;
        struct stat     statbuf;
-       char            buf[8192];
+       time_t          *mtime;
 
-       buf[0] = '\0';
-       if (fromfile) {
-               snprintf(buf, sizeof(buf), "%s[%d]: ", fromfile, fromline);
-       }
+       DEBUG2( "Config:   including file: %s", file);
 
-       if (stat(conffile, &statbuf) == 0) {
+       if (stat(file, &statbuf) == 0) {
                if ((statbuf.st_mode & S_IWOTH) != 0) {
-                       radlog(L_ERR|L_CONS, "%sConfiguration file %s is globally writable.  Refusing to start due to insecure configuration.",
-                              buf[0] ? buf : "", conffile);
-                       return NULL;
+                       radlog(L_ERR|L_CONS, "Configuration file %s is globally writable.  Refusing to start due to insecure configuration.",
+                              file);
+                       return -1;
                }
 
                if (0 && (statbuf.st_mode & S_IROTH) != 0) {
-                       radlog(L_ERR|L_CONS, "%sConfiguration file %s is globally readable.  Refusing to start due to insecure configuration.",
-                              buf[0] ? buf : "", conffile);
-                       return NULL;
+                       radlog(L_ERR|L_CONS, "Configuration file %s is globally readable.  Refusing to start due to insecure configuration.",
+                              file);
+                       return -1;
                }
        }
 
-       if ((fp = fopen(conffile, "r")) == NULL) {
-               radlog(L_ERR|L_CONS, "%sUnable to open file \"%s\": %s",
-                      buf[0] ? buf : "", conffile, strerror(errno));
-               return NULL;
+       fp = fopen(file, "r");
+       if (!fp) {
+               radlog(L_ERR|L_CONS, "Unable to open file \"%s\": %s",
+                      file, strerror(errno));
+               return -1;
+       }
+
+       /*
+        *      Read the section.  It's OK to have EOF without a
+        *      matching close brace.
+        */
+       if (cf_section_read(file, &lineno, fp, cs) < 0) {
+               fclose(fp);
+               return -1;
        }
 
-       cs = cf_section_read(conffile, &lineno, fp, NULL, NULL, parent);
+       /*
+        *      Add the filename to the section
+        */
+       mtime = rad_malloc(sizeof(*mtime));
+       *mtime = statbuf.st_mtime;
+       /* FIXME: error? */
+       cf_data_add_internal(cs, file, mtime, free,
+                            PW_TYPE_FILENAME);
 
        fclose(fp);
+       return 0;
+}
+
+/*
+ *     Bootstrap a config file.
+ */
+CONF_SECTION *cf_file_read(const char *file)
+{
+       CONF_SECTION *cs;
+
+       cs = cf_section_alloc("main", NULL, NULL);
+       if (!cs) return NULL;
+
+       if (cf_file_include(file, cs) < 0) {
+               cf_section_free(&cs);
+               return NULL;
+       }
 
        return cs;
 }
 
-
 /*
  * Return a CONF_PAIR within a CONF_SECTION.
  */
-CONF_PAIR *cf_pair_find(CONF_SECTION *section, const char *name)
+CONF_PAIR *cf_pair_find(const CONF_SECTION *cs, const char *name)
 {
        CONF_ITEM       *ci;
 
-       if (section == NULL) {
-               section = mainconfig.config;
-       }
+       if (!cs) cs = mainconfig.config;
 
-       for (ci = section->children; ci; ci = ci->next) {
-               if (ci->type != CONF_ITEM_PAIR)
-                       continue;
-               if (name == NULL || strcmp(cf_itemtopair(ci)->attr, name) == 0)
-                       break;
+       /*
+        *      Find the name in the tree, for speed.
+        */
+       if (name) {
+               CONF_PAIR mycp;
+
+               mycp.attr = name;
+               return rbtree_finddata(cs->pair_tree, &mycp);
        }
 
-       return cf_itemtopair(ci);
+       /*
+        *      Else find the first one
+        */
+       for (ci = cs->children; ci; ci = ci->next) {
+               if (ci->type == CONF_ITEM_PAIR)
+                       return cf_itemtopair(ci);
+       }
+       
+       return NULL;
 }
 
 /*
@@ -960,28 +1384,28 @@ char *cf_pair_value(CONF_PAIR *pair)
  * Return the first label of a CONF_SECTION
  */
 
-char *cf_section_name1(CONF_SECTION *section)
+const char *cf_section_name1(const CONF_SECTION *cs)
 {
-       return (section ? section->name1 : NULL);
+       return (cs ? cs->name1 : NULL);
 }
 
 /*
  * Return the second label of a CONF_SECTION
  */
 
-char *cf_section_name2(CONF_SECTION *section)
+const char *cf_section_name2(const CONF_SECTION *cs)
 {
-       return (section ? section->name2 : NULL);
+       return (cs ? cs->name2 : NULL);
 }
 
 /*
  * Find a value in a CONF_SECTION
  */
-char *cf_section_value_find(CONF_SECTION *section, const char *attr)
+char *cf_section_value_find(const CONF_SECTION *cs, const char *attr)
 {
        CONF_PAIR       *cp;
 
-       cp = cf_pair_find(section, attr);
+       cp = cf_pair_find(cs, attr);
 
        return (cp ? cp->value : NULL);
 }
@@ -992,7 +1416,8 @@ char *cf_section_value_find(CONF_SECTION *section, const char *attr)
  * attr is NULL, any attr matches.
  */
 
-CONF_PAIR *cf_pair_find_next(CONF_SECTION *section, CONF_PAIR *pair, const char *attr)
+CONF_PAIR *cf_pair_find_next(const CONF_SECTION *cs,
+                            const CONF_PAIR *pair, const char *attr)
 {
        CONF_ITEM       *ci;
 
@@ -1002,7 +1427,7 @@ CONF_PAIR *cf_pair_find_next(CONF_SECTION *section, CONF_PAIR *pair, const char
         */
 
        if (pair == NULL){
-               return cf_pair_find(section, attr);
+               return cf_pair_find(cs, attr);
        }
 
        ci = cf_pairtoitem(pair)->next;
@@ -1033,11 +1458,22 @@ CONF_SECTION *cf_section_find(const char *name)
  * Find a sub-section in a section
  */
 
-CONF_SECTION *cf_section_sub_find(CONF_SECTION *section, const char *name)
+CONF_SECTION *cf_section_sub_find(const CONF_SECTION *cs, const char *name)
 {
        CONF_ITEM *ci;
 
-       for (ci = section->children; ci; ci = ci->next) {
+       /*
+        *      Do the fast lookup if possible.
+        */
+       if (name && cs->section_tree) {
+               CONF_SECTION mycs;
+
+               mycs.name1 = name;
+               mycs.name2 = NULL;
+               return rbtree_finddata(cs->section_tree, &mycs);
+       }
+
+       for (ci = cs->children; ci; ci = ci->next) {
                if (ci->type != CONF_ITEM_SECTION)
                        continue;
                if (strcmp(cf_itemtosection(ci)->name1, name) == 0)
@@ -1048,6 +1484,59 @@ CONF_SECTION *cf_section_sub_find(CONF_SECTION *section, const char *name)
 
 }
 
+
+/*
+ *     Find a CONF_SECTION with both names.
+ */
+CONF_SECTION *cf_section_sub_find_name2(const CONF_SECTION *cs,
+                                       const char *name1, const char *name2)
+{
+       CONF_ITEM    *ci;
+
+       if (!name2) return cf_section_sub_find(cs, name1);
+
+       if (!cs) cs = mainconfig.config;
+
+       if (name1 && (cs->section_tree)) {
+               CONF_SECTION mycs, *master_cs;
+               
+               mycs.name1 = name1;
+               mycs.name2 = name2;
+               
+               master_cs = rbtree_finddata(cs->section_tree, &mycs);
+               if (master_cs) {
+                       return rbtree_finddata(master_cs->name2_tree, &mycs);
+               }
+       }
+
+       /*
+        *      Else do it the old-fashioned way.
+        */
+       for (ci = cs->children; ci; ci = ci->next) {
+               CONF_SECTION *subcs;
+
+               if (ci->type != CONF_ITEM_SECTION)
+                       continue;
+
+               subcs = cf_itemtosection(ci);
+               if (!name1) {
+                       if (!subcs->name2) {
+                               if (strcmp(subcs->name1, name2) == 0) break;
+                       } else {
+                               if (strcmp(subcs->name2, name2) == 0) break;
+                       }
+                       continue; /* don't do the string comparisons below */
+               }
+
+               if ((strcmp(subcs->name1, name1) == 0) &&
+                   (subcs->name2 != NULL) &&
+                   (strcmp(subcs->name2, name2) == 0))
+                       break;
+       }
+
+       return cf_itemtosection(ci);
+}
+
 /*
  * Return the next subsection after a CONF_SECTION
  * with a certain name1 (char *name1). If the requested
@@ -1055,8 +1544,8 @@ CONF_SECTION *cf_section_sub_find(CONF_SECTION *section, const char *name)
  */
 
 CONF_SECTION *cf_subsection_find_next(CONF_SECTION *section,
-               CONF_SECTION *subsection,
-               const char *name1)
+                                     CONF_SECTION *subsection,
+                                     const char *name1)
 {
        CONF_ITEM       *ci;
 
@@ -1075,7 +1564,7 @@ CONF_SECTION *cf_subsection_find_next(CONF_SECTION *section,
                if (ci->type != CONF_ITEM_SECTION)
                        continue;
                if ((name1 == NULL) ||
-                               (strcmp(cf_itemtosection(ci)->name1, name1) == 0))
+                   (strcmp(cf_itemtosection(ci)->name1, name1) == 0))
                        break;
        }
 
@@ -1120,6 +1609,291 @@ int cf_item_is_pair(CONF_ITEM *item)
 }
 
 
+static CONF_DATA *cf_data_alloc(CONF_SECTION *parent, const char *name,
+                               void *data, void (*data_free)(void *))
+{
+       CONF_DATA *cd;
+
+       cd = rad_malloc(sizeof(*cd));
+       memset(cd, 0, sizeof(*cd));
+
+       cd->item.type = CONF_ITEM_DATA;
+       cd->item.parent = parent;
+       cd->name = strdup(name);
+       cd->data = data;
+       cd->free = data_free;
+
+       return cd;
+}
+
+
+static void *cf_data_find_internal(CONF_SECTION *cs, const char *name,
+                                  int flag)
+{
+       if (!cs || !name) return NULL;
+       
+       /*
+        *      Find the name in the tree, for speed.
+        */
+       if (cs->data_tree) {
+               CONF_DATA mycd, *cd;
+
+               mycd.name = name;
+               mycd.flag = flag;
+               cd = rbtree_finddata(cs->data_tree, &mycd);
+               if (cd) return cd->data;
+       }
+
+       return NULL;
+}
+
+/*
+ *     Find data from a particular section.
+ */
+void *cf_data_find(CONF_SECTION *cs, const char *name)
+{
+       return cf_data_find_internal(cs, name, 0);
+}
+
+
+/*
+ *     Add named data to a configuration section.
+ */
+static int cf_data_add_internal(CONF_SECTION *cs, const char *name,
+                               void *data, void (*data_free)(void *),
+                               int flag)
+{
+       CONF_DATA *cd;
+
+       if (!cs || !name) return -1;
+
+       /*
+        *      Already exists.  Can't add it.
+        */
+       if (cf_data_find_internal(cs, name, flag) != NULL) return -1;
+
+       cd = cf_data_alloc(cs, name, data, data_free);
+       if (!cd) return -1;
+       cd->flag = flag;
+
+       cf_item_add(cs, cf_datatoitem(cd));
+
+       return 0;
+}
+
+/*
+ *     Add named data to a configuration section.
+ */
+int cf_data_add(CONF_SECTION *cs, const char *name,
+               void *data, void (*data_free)(void *))
+{
+       return cf_data_add_internal(cs, name, data, data_free, 0);
+}
+
+
+/*
+ *     Copy CONF_DATA from src to dst
+ */
+static void cf_section_copy_data(CONF_SECTION *s, CONF_SECTION *d)
+{
+       
+       CONF_ITEM *cd, *next, **last;
+
+       /*
+        *      Don't check if s->data_tree is NULL.  It's child
+        *      sections may have data, even if this section doesn't.
+        */
+
+       rad_assert(d->data_tree == NULL);
+       d->data_tree = s->data_tree;
+       s->data_tree = NULL;
+       
+       /*
+        *      Walk through src, moving CONF_ITEM_DATA
+        *      to dst, by hand.
+        */
+       last = &(s->children);
+       for (cd = s->children; cd != NULL; cd = next) {
+               next = cd->next;
+               
+               /*
+                *      Recursively copy data from child sections.
+                */
+               if (cd->type == CONF_ITEM_SECTION) {
+                       CONF_SECTION *s1, *d1;
+                       
+                       s1 = cf_itemtosection(cd);
+                       d1 = cf_section_sub_find_name2(d, s1->name1, s1->name2);
+                       if (d1) {
+                               cf_section_copy_data(s1, d1);
+                       }
+                       last = &(cd->next);
+                       continue;
+               }
+
+               /*
+                *      Not conf data, remember last ptr.
+                */
+               if (cd->type != CONF_ITEM_DATA) {
+                       last = &(cd->next);
+                       continue;
+               }
+               
+               /*
+                *      Remove it from the src list
+                */
+               *last = cd->next;
+               cd->next = NULL;
+               
+               /*
+                *      Add it to the dst list
+                */
+               if (!d->children) {
+                       rad_assert(d->tail == NULL);
+                       d->children = cd;
+               } else {
+                       rad_assert(d->tail != NULL);
+                       d->tail->next = cd;
+               }
+               d->tail = cd;
+       }
+}
+
+/*
+ *     For a CONF_DATA element, stat the filename, if necessary.
+ */
+static int filename_stat(void *context, void *data)
+{
+       struct stat buf;
+       CONF_DATA *cd = data;
+
+       context = context;      /* -Wunused */
+
+       if (cd->flag != PW_TYPE_FILENAME) return 0;
+
+       if (stat(cd->name, &buf) < 0) return -1;
+
+       if (buf.st_mtime != *(time_t *) cd->data) return -1;
+
+       return 0;
+}
+
+
+/*
+ *     Compare two CONF_SECTIONS.  The items MUST be in the same
+ *     order.
+ */
+static int cf_section_cmp(CONF_SECTION *a, CONF_SECTION *b)
+{
+       CONF_ITEM *ca = a->children;
+       CONF_ITEM *cb = b->children;
+
+       while (1) {
+               CONF_PAIR *pa, *pb;
+
+               /*
+                *      Done.  Stop.
+                */
+               if (!ca && !cb) break;
+
+               /*
+                *      Skip CONF_DATA.
+                */
+               if (ca && ca->type == CONF_ITEM_DATA) {
+                       ca = ca->next;
+                       continue;
+               }
+               if (cb && cb->type == CONF_ITEM_DATA) {
+                       cb = cb->next;
+                       continue;
+               }
+
+               /*
+                *      One is smaller than the other.  Exit.
+                */
+               if (!ca || !cb) return 0;
+
+               if (ca->type != cb->type) return 0;
+
+               /*
+                *      Deal with subsections.
+                */
+               if (ca->type == CONF_ITEM_SECTION) {
+                       CONF_SECTION *sa = cf_itemtosection(ca);
+                       CONF_SECTION *sb = cf_itemtosection(cb);
+
+                       if (!cf_section_cmp(sa, sb)) return 0;
+                       goto next;
+               }
+
+               rad_assert(ca->type == CONF_ITEM_PAIR);
+
+               pa = cf_itemtopair(ca);
+               pb = cf_itemtopair(cb);
+
+               /*
+                *      Different attr and/or value, Exit.
+                */
+               if ((strcmp(pa->attr, pb->attr) != 0) ||
+                   (strcmp(pa->value, pb->value) != 0)) return 0;
+               
+
+               /*
+                *      And go to the next element.
+                */
+       next:
+               ca = ca->next;
+               cb = cb->next;
+       }
+
+       /*
+        *      Walk over the CONF_DATA, stat'ing PW_TYPE_FILENAME.
+        */
+       if (a->data_tree &&
+           (rbtree_walk(a->data_tree, InOrder, filename_stat, NULL) != 0)) {
+               return 0;
+       }
+
+       /*
+        *      They must be the same, say so.
+        */
+       return 1;
+}
+
+
+
+
+/*
+ *     Migrate CONF_DATA from one section to another.
+ */
+int cf_section_migrate(CONF_SECTION *dst, CONF_SECTION *src)
+{
+       CONF_ITEM *ci;
+       CONF_SECTION *s, *d;
+
+       for (ci = src->children; ci != NULL; ci = ci->next) {
+               if (ci->type != CONF_ITEM_SECTION)
+                       continue;
+
+               s = cf_itemtosection(ci);
+               d = cf_section_sub_find_name2(dst, s->name1, s->name2);
+
+               if (!d) continue; /* not in new one, don't migrate it */
+
+               /*
+                *      A section of the same name is in BOTH src & dst,
+                *      compare the CONF_PAIR's.  If they're all the same,
+                *      then copy the CONF_DATA from one to the other.
+                */
+               if (cf_section_cmp(s, d)) {
+                       cf_section_copy_data(s, d);
+               }
+       }
+
+       return 1;               /* rcode means anything? */
+}
+
+
 #if 0
 /*
  * JMG dump_config tries to dump the config structure in a readable format
@@ -1137,12 +1911,15 @@ static int dump_config_section(CONF_SECTION *cs, int indent)
         * so I had to get creative. --Pac. */
 
        for (ci = cs->children; ci; ci = ci->next) {
-               if (ci->type == CONF_ITEM_PAIR) {
+               switch (ci->type) {
+               case CONF_ITEM_PAIR:
                        cp=cf_itemtopair(ci);
                        DEBUG("%.*s%s = %s",
                                indent, "\t\t\t\t\t\t\t\t\t\t\t",
                                cp->attr, cp->value);
-               } else {
+                       break;
+
+               case CONF_ITEM_SECTION:
                        scs=cf_itemtosection(ci);
                        DEBUG("%.*s%s %s%s{",
                                indent, "\t\t\t\t\t\t\t\t\t\t\t",
@@ -1152,6 +1929,10 @@ static int dump_config_section(CONF_SECTION *cs, int indent)
                        dump_config_section(scs, indent+1);
                        DEBUG("%.*s}",
                                indent, "\t\t\t\t\t\t\t\t\t\t\t");
+                       break;
+
+               default:        /* FIXME: Do more! */
+                       break;
                }
        }
 
similarity index 64%
rename from src/lib/crypt.c
rename to src/main/crypt.c
index 5334841..001daff 100644 (file)
@@ -1,24 +1,27 @@
 /*
  * crypt.c     A thread-safe crypt wrapper
  *
- *   This library is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU Lesser General Public
- *   License as published by the Free Software Foundation; either
- *   version 2.1 of the License, or (at your option) any later version.
+ *   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 library is distributed in the hope that it will be useful,
+ *   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
- *   Lesser General Public License for more details.
+ *   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 Lesser General Public
- *   License along with this library; if not, write to the Free Software
+ *   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 2000  The FreeRADIUS server project
+ * Copyright 2000-2006  The FreeRADIUS server project
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 #include <string.h>
 
 #ifdef HAVE_CRYPT_H
@@ -37,7 +40,8 @@ static int lrad_crypt_init = 0;
 static pthread_mutex_t lrad_crypt_mutex;
 #endif
 
-#include "libradius.h"
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
 
 /*
  * performs a crypt password check in an thread-safe way.
index 64ab343..f200255 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
- * Copyright 2000  Michael J. Hartwick <hartwick@hartwick.com>
+ * Copyright 2000-2004,2006  The FreeRADIUS server project
  */
-static const char rcsid[] = "$Id$";
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <sys/file.h>
 
@@ -30,9 +31,12 @@ static const char rcsid[] = "$Id$";
 #include <string.h>
 #include <fcntl.h>
 #include <ctype.h>
-#include <unistd.h>
 #include <signal.h>
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 #ifdef HAVE_SYS_WAIT_H
 #      include <sys/wait.h>
 #endif
@@ -43,97 +47,8 @@ static const char rcsid[] = "$Id$";
 #      define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
 #endif
 
-#include "radiusd.h"
-#include "rad_assert.h"
-
-/*
- *     Copy a quoted string.
- */
-static int rad_copy_string(char *to, const char *from)
-{
-       int length = 0;
-       char quote = *from;
-
-       do {
-               if (*from == '\\') {
-                       *(to++) = *(from++);
-                       length++;
-               }
-               *(to++) = *(from++);
-               length++;
-       } while (*from && (*from != quote));
-
-       if (*from != quote) return -1; /* not properly quoted */
-
-       *(to++) = quote;
-       length++;
-       *to = '\0';
-
-       return length;
-}
-
-
-/*
- *     Copy a %{} string.
- */
-static int rad_copy_variable(char *to, const char *from)
-{
-       int length = 0;
-       int sublen;
-
-       *(to++) = *(from++);
-       length++;
-
-       while (*from) {
-               switch (*from) {
-               case '"':
-               case '\'':
-                       sublen = rad_copy_string(to, from);
-                       if (sublen < 0) return sublen;
-                       from += sublen;
-                       to += sublen;
-                       break;
-
-               case '}':       /* end of variable expansion */
-                       *(to++) = *(from++);
-                       *to = '\0';
-                       length++;
-                       return length; /* proper end of variable */
-
-               case '\\':
-                       *(to++) = *(from++);
-                       *(to++) = *(from++);
-                       length += 2;
-                       break;
-
-               case '%':       /* start of variable expansion */
-                       if (from[1] == '{') {
-                               *(to++) = *(from++);
-                               length++;
-                               
-                               sublen = rad_copy_variable(to, from);
-                               if (sublen < 0) return sublen;
-                               from += sublen;
-                               to += sublen;
-                               length += sublen;
-                       } /* else FIXME: catch %%{ ?*/
-
-                       /* FALL-THROUGH */
-                       break;
-
-               default:
-                       *(to++) = *(from++);
-                       length++;
-                       break;
-               }
-       } /* loop over the input string */
-
-       /*
-        *      We ended the string before a trailing '}'
-        */
-
-       return -1;
-}
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
 
 #define MAX_ARGV (256)
 /*
@@ -146,7 +61,8 @@ int radius_exec_program(const char *cmd, REQUEST *request,
                        int exec_wait,
                        char *user_msg, int msg_len,
                        VALUE_PAIR *input_pairs,
-                       VALUE_PAIR **output_pairs)
+                       VALUE_PAIR **output_pairs,
+                       int shell_escape)
 {
        VALUE_PAIR *vp;
        char mycmd[1024];
@@ -179,7 +95,7 @@ int radius_exec_program(const char *cmd, REQUEST *request,
                return -1;
        }
 
-       strNcpy(mycmd, cmd, sizeof(mycmd));
+       strlcpy(mycmd, cmd, sizeof(mycmd));
 
        /*
         *      Split the string into argv's BEFORE doing radius_xlat...
@@ -293,8 +209,7 @@ int radius_exec_program(const char *cmd, REQUEST *request,
        argv[argc] = NULL;
 
        /*
-        *      Open a pipe for child/parent communication, if
-        *      necessary.
+        *      Open a pipe for child/parent communication, if necessary.
         */
        if (exec_wait) {
                if (pipe(pd) != 0) {
@@ -327,7 +242,7 @@ int radius_exec_program(const char *cmd, REQUEST *request,
                /*
                 *      Child process.
                 *
-                *      We try to be fail-safe here.  So if ANYTHING
+                *      We try to be fail-safe here. So if ANYTHING
                 *      goes wrong, we exit with status 1.
                 */
 
@@ -405,16 +320,18 @@ int radius_exec_program(const char *cmd, REQUEST *request,
                         *      variable...
                         */
                        snprintf(buffer, sizeof(buffer), "%s=", vp->name);
-                       for (p = buffer; *p != '='; p++) {
-                               if (*p == '-') {
-                                       *p = '_';
-                               } else if (isalpha((int) *p)) {
-                                       *p = toupper(*p);
+                       if (shell_escape) {
+                               for (p = buffer; *p != '='; p++) {
+                                       if (*p == '-') {
+                                               *p = '_';
+                                       } else if (isalpha((int) *p)) {
+                                               *p = toupper(*p);
+                                       }
                                }
                        }
 
                        n = strlen(buffer);
-                       vp_prints_value(buffer+n, sizeof(buffer) - n, vp, 1);
+                       vp_prints_value(buffer+n, sizeof(buffer) - n, vp, shell_escape);
 
                        envp[envlen++] = strdup(buffer);
 
@@ -424,6 +341,7 @@ int radius_exec_program(const char *cmd, REQUEST *request,
                        if (envlen == (MAX_ENVP - 1)) break;
                }
                envp[envlen] = NULL;
+
                execve(argv[0], argv, envp);
                radlog(L_ERR, "Exec-Program: FAILED to execute %s: %s",
                       argv[0], strerror(errno));
@@ -440,8 +358,7 @@ int radius_exec_program(const char *cmd, REQUEST *request,
        }
 
        /*
-        *      We're not waiting, exit, and ignore any child's
-        *      status.
+        *      We're not waiting, exit, and ignore any child's status.
         */
        if (!exec_wait) {
                return 0;
@@ -511,7 +428,7 @@ int radius_exec_program(const char *cmd, REQUEST *request,
         *      Parse the output, if any.
         */
        if (done) {
-               n = T_INVALID;
+               n = T_OP_INVALID;
                if (output_pairs) {
                        /*
                         *      For backwards compatibility, first check
@@ -524,10 +441,10 @@ int radius_exec_program(const char *cmd, REQUEST *request,
                        }
                }
 
-               if (n == T_INVALID) {
-                       radlog(L_DBG, "Exec-Program-Wait: plaintext: %s", answer);
+               if (n == T_OP_INVALID) {
+                       DEBUG("Exec-Program-Wait: plaintext: %s", answer);
                        if (user_msg) {
-                               strNcpy(user_msg, answer, msg_len);
+                               strlcpy(user_msg, answer, msg_len);
                        }
                } else {
                        /*
@@ -546,14 +463,14 @@ int radius_exec_program(const char *cmd, REQUEST *request,
                        }
 
                        /*
-                        *  Replace any trailing comma by a NUL.
+                        *      Replace any trailing comma by a NUL.
                         */
                        if (answer[strlen(answer) - 1] == ',') {
                                answer[strlen(answer) - 1] = '\0';
                        }
 
                        radlog(L_DBG,"Exec-Program-Wait: value-pairs: %s", answer);
-                       if (userparse(answer, &vp) == T_INVALID) {
+                       if (userparse(answer, &vp) == T_OP_INVALID) {
                                radlog(L_ERR, "Exec-Program-Wait: %s: unparsable reply", cmd);
 
                        } else {
@@ -564,7 +481,7 @@ int radius_exec_program(const char *cmd, REQUEST *request,
                                *output_pairs = vp;
                        }
                } /* else the answer was a set of VP's, not a text message */
-       } /* else we didn't read anything from the child. */
+       } /* else we didn't read anything from the child */
 
        /*
         *      Call rad_waitpid (should map to waitpid on non-threaded
index 3dc128c..cf4d24e 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <sys/stat.h>
 
@@ -39,9 +39,8 @@ static const char rcsid[] = "$Id$";
 #include <ctype.h>
 #include <fcntl.h>
 
-#include "radiusd.h"
-
-int maximum_proxies;
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
 
 /*
  *     Free a PAIR_LIST
@@ -162,7 +161,7 @@ parse_again:
                                 *      file.
                                 */
                                if (*s != '/') {
-                                       strNcpy(newfile, file,
+                                       strlcpy(newfile, file,
                                                sizeof(newfile));
                                        ptr = strrchr(newfile, '/');
                                        strcpy(ptr + 1, s);
@@ -198,7 +197,7 @@ parse_again:
                        reply_tmp = NULL;
                        old_lineno = lineno;
                        parsecode = userparse(ptr, &check_tmp);
-                       if (parsecode == T_INVALID) {
+                       if (parsecode == T_OP_INVALID) {
                                pairlist_free(&pl);
                                radlog(L_ERR|L_CONS,
                                "%s[%d]: Parse error (check) for entry %s: %s",
@@ -379,27 +378,27 @@ int read_realms_file(const char *file)
                         *      Local realms don't have an IP address,
                         *      secret, or port.
                         */
-                       c->acct_ipaddr = c->ipaddr = htonl(INADDR_NONE);
+                       c->ipaddr.af = c->acct_ipaddr.af = AF_INET;
+                       c->ipaddr.ipaddr.ip4addr.s_addr = c->acct_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
                        c->secret[0] = '\0';
                        c->auth_port = 0;
                        c->acct_port = 0;
 
                } else {
                        RADCLIENT *client;
-                       c->ipaddr = ip_getaddr(hostnm);
-                       c->acct_ipaddr = c->ipaddr;
 
-                       if (c->ipaddr == htonl(INADDR_NONE)) {
+                       if (ip_hton(hostnm, AF_INET, &c->ipaddr) < 0) {
                                radlog(L_CONS|L_ERR, "%s[%d]: Failed to look up hostname %s",
                                       file, lineno, hostnm);
                                return -1;
                        }
+                       c->acct_ipaddr = c->ipaddr;
 
                        /*
                         *      Find the remote server in the "clients" list.
                         *      If we can't find it, there's a big problem...
                         */
-                       client = client_find(c->ipaddr);
+                       client = client_find_old(&c->ipaddr);
                        if (client == NULL) {
                          radlog(L_CONS|L_ERR, "%s[%d]: Cannot find 'clients' file entry of remote server %s for realm \"%s\"",
                                 file, lineno, hostnm, realm);
@@ -412,17 +411,17 @@ int read_realms_file(const char *file)
                 *      Double-check lengths to be sure they're sane
                 */
                if (strlen(hostnm) >= sizeof(c->server)) {
-                       radlog(L_ERR, "%s[%d]: server name of length %d is greater than the allowed maximum of %d.",
+                       radlog(L_ERR, "%s[%d]: server name of length %u is greater than the allowed maximum of %u.",
                               file, lineno,
-                              (int) strlen(hostnm),
-                              (int) sizeof(c->server) - 1);
+                              strlen(hostnm),
+                              sizeof(c->server) - 1);
                        return -1;
                }
                if (strlen(realm) > sizeof(c->realm)) {
-                       radlog(L_ERR, "%s[%d]: realm of length %d is greater than the allowed maximum of %d.",
+                       radlog(L_ERR, "%s[%d]: realm of length %u is greater than the allowed maximum of %u.",
                               file, lineno,
-                              (int) strlen(realm),
-                              (int) sizeof(c->realm) - 1);
+                              strlen(realm),
+                              sizeof(c->realm) - 1);
                        return -1;
                }
 
@@ -468,14 +467,29 @@ int read_realms_file(const char *file)
 /*
  * Mark a host inactive
  */
-void realm_disable(uint32_t ipaddr, int port)
+void realm_disable(REQUEST *request)
 {
        REALM *cl;
        time_t now;
+       lrad_ipaddr_t *ipaddr;
+       int port;
 
        now = time(NULL);
-       for(cl = mainconfig.realms; cl; cl = cl->next) {
-               if ((ipaddr == cl->ipaddr) && (port == cl->auth_port)) {
+
+       if (!request || !request->proxy ||
+           (request->proxy->dst_ipaddr.af != AF_INET)) return;
+       
+       ipaddr = &request->proxy->dst_ipaddr;
+       port = request->proxy->dst_port;
+
+       for (cl = mainconfig.realms; cl; cl = cl->next) {
+               if (ipaddr->af != cl->ipaddr.af) continue;
+
+               /*
+                *      FIXME: Switch over AF
+                */
+               if ((ipaddr->ipaddr.ip4addr.s_addr == cl->ipaddr.ipaddr.ip4addr.s_addr) &&
+                   (port == cl->auth_port)) {
                        /*
                         *      If we've received a reply (any reply)
                         *      from the home server in the time spent
@@ -490,7 +504,8 @@ void realm_disable(uint32_t ipaddr, int port)
                        cl->wakeup = now + mainconfig.proxy_dead_time;
                        radlog(L_PROXY, "marking authentication server %s:%d for realm %s dead",
                                cl->server, port, cl->realm);
-               } else if ((ipaddr == cl->acct_ipaddr) && (port == cl->acct_port)) {
+               } else if ((ipaddr->ipaddr.ip4addr.s_addr == cl->acct_ipaddr.ipaddr.ip4addr.s_addr) &&
+                          (port == cl->acct_port)) {
                        if (cl->last_reply > (( now - mainconfig.proxy_retry_delay * mainconfig.proxy_retry_count ))) {
                                continue;
                        }
@@ -639,10 +654,14 @@ REALM *realm_findbyaddr(uint32_t ipaddr, int port)
         *      doesn't matter if we think the realm is inactive.
         */
        for (cl = mainconfig.realms; cl != NULL; cl = cl->next) {
-               if ((ipaddr == cl->ipaddr) && (port == cl->auth_port)) {
+               if (cl->ipaddr.af != AF_INET) rad_assert(0 == 1);
+
+               if ((ipaddr == cl->ipaddr.ipaddr.ip4addr.s_addr) &&
+                   (port == cl->auth_port)) {
                        return cl;
 
-               } else if ((ipaddr == cl->acct_ipaddr) && (port == cl->acct_port)) {
+               } else if ((ipaddr == cl->acct_ipaddr.ipaddr.ip4addr.s_addr) &&
+                          (port == cl->acct_port)) {
                        return cl;
                }
        }
diff --git a/src/main/listen.c b/src/main/listen.c
new file mode 100644 (file)
index 0000000..393e3fa
--- /dev/null
@@ -0,0 +1,2138 @@
+/*
+ * listen.c    Handle socket stuff
+ *
+ * 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 2005,2006  The FreeRADIUS server project
+ * Copyright 2005  Alan DeKok <aland@ox.org>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include <sys/resource.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef WITH_UDPFROMTO
+#include <freeradius-devel/udpfromto.h>
+#endif
+
+#include <fcntl.h>
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
+
+#include <freeradius-devel/radius_snmp.h>
+#include <freeradius-devel/request_list.h>
+
+static time_t start_time = 0;
+
+/*
+ *     FIXME: Delete this crap!
+ */
+extern time_t time_now;
+
+/*
+ *     We'll use this below.
+ */
+typedef int (*rad_listen_parse_t)(const char *, int, const CONF_SECTION *, rad_listen_t *);
+typedef void (*rad_listen_free_t)(rad_listen_t *);
+
+typedef struct rad_listen_master_t {
+       rad_listen_parse_t      parse;
+       rad_listen_free_t       free;
+       rad_listen_recv_t       recv;
+       rad_listen_send_t       send;
+       rad_listen_update_t     update;
+       rad_listen_print_t      print;
+} rad_listen_master_t;
+
+typedef struct listen_socket_t {
+       /*
+        *      For normal sockets.
+        */
+       lrad_ipaddr_t   ipaddr;
+       int             port;
+       RADCLIENT_LIST  *clients;
+} listen_socket_t;
+
+typedef struct listen_detail_t {
+       const char      *detail;
+       VALUE_PAIR      *vps;
+       FILE            *fp;
+       int             state;
+       time_t          timestamp;
+       lrad_ipaddr_t   client_ip;
+       int             max_outstanding;
+       int             *outstanding;
+} listen_detail_t;
+                              
+
+/*
+ *     Find a per-socket client.
+ */
+static RADCLIENT *client_listener_find(const rad_listen_t *listener,
+                                      const lrad_ipaddr_t *ipaddr)
+{
+       const RADCLIENT_LIST *clients;
+
+       rad_assert(listener != NULL);
+       rad_assert(ipaddr != NULL);
+
+       rad_assert((listener->type == RAD_LISTEN_AUTH) ||
+                  (listener->type == RAD_LISTEN_ACCT));
+
+       clients = ((listen_socket_t *)listener->data)->clients;
+       if (!clients) clients = mainconfig.clients;
+
+       rad_assert(clients != NULL);
+       
+       return client_find(clients, ipaddr);
+}
+
+static int listen_bind(rad_listen_t *this);
+
+/*
+ *     FIXME: have the detail reader use another config "exit when done",
+ *     so that it can be used as a one-off tool to update stuff.
+ */
+
+/*
+ *     Process and reply to a server-status request.
+ *     Like rad_authenticate and rad_accounting this should
+ *     live in it's own file but it's so small we don't bother.
+ */
+static int rad_status_server(REQUEST *request)
+{
+       switch (request->listener->type) {
+       case RAD_LISTEN_AUTH:
+               request->reply->code = PW_AUTHENTICATION_ACK;
+
+               /*
+                *      Commented out for now.
+                */
+#if 0
+ { 
+               char            reply_msg[64];
+               time_t          t;
+               VALUE_PAIR      *vp;
+               
+               /*
+                *      Reply with an ACK. We might want to add some more
+                *      interesting reply attributes, such as server uptime.
+                */
+               t = request->timestamp - start_time;
+               sprintf(reply_msg, "FreeRADIUS STUFF %d day%s, %02d:%02d",
+                       (int)(t / 86400), (t / 86400) == 1 ? "" : "s",
+                       (int)((t / 3600) % 24), (int)(t / 60) % 60);
+               
+               vp = pairmake("Reply-Message", reply_msg, T_OP_SET);
+               pairadd(&request->reply->vps, vp); /* don't need to check if !vp */
+ }
+#endif
+               break;
+
+       case RAD_LISTEN_ACCT:
+               request->reply->code = PW_ACCOUNTING_RESPONSE;
+               break;
+
+       default:
+               return 0;
+       }
+       
+
+       return 0;
+}
+
+static int request_num_counter = 0;
+
+/*
+ *     Check for dups, etc.  Common to Access-Request &&
+ *     Accounting-Request packets.
+ */
+static int common_checks(rad_listen_t *listener,
+                        RADIUS_PACKET *packet, REQUEST **prequest,
+                        const RADCLIENT *client)
+{
+       REQUEST *curreq;
+       char buffer[128];
+
+       rad_assert(listener->rl != NULL);
+
+       /*
+        *      If there is no existing request of id, code, etc.,
+        *      then we can return, and let it be processed.
+        */
+       if ((curreq = rl_find(listener->rl, packet)) == NULL) {
+               /*
+                *      Count the total number of requests, to see if
+                *      there are too many.  If so, return with an
+                *      error.
+                */
+               if (mainconfig.max_requests) {
+                       /*
+                        *      FIXME: This is now per-socket,
+                        *      when it should really be global
+                        *      to the server!
+                        */
+                       int request_count = rl_num_requests(listener->rl);
+
+                       /*
+                        *      This is a new request.  Let's see if
+                        *      it makes us go over our configured
+                        *      bounds.
+                        */
+                       if (request_count > mainconfig.max_requests) {
+                               radlog(L_ERR, "Dropping request (%d is too many): "
+                                      "from client %s port %d - ID: %d", request_count,
+                                      client->shortname,
+                                      packet->src_port, packet->id);
+                               radlog(L_INFO, "WARNING: Please check the %s file.\n"
+                                      "\tThe value for 'max_requests' is probably set too low.\n", mainconfig.radiusd_conf);
+                               return 0;
+                       } /* else there were a small number of requests */
+               } /* else there was no configured limit for requests */
+
+               /*
+                *      FIXME: Add checks for system load.  If the
+                *      system is busy, start dropping requests...
+                *
+                *      We can probably keep some statistics
+                *      ourselves...  if there are more requests
+                *      coming in than we can handle, start dropping
+                *      some.
+                */
+
+       /*
+        *      The current request isn't finished, which
+        *      means that the NAS sent us a new packet, while
+        *      we are still processing the old request.
+        */
+       } else if (!curreq->finished) {
+               /*
+                *      If the authentication vectors are identical,
+                *      then the NAS is re-transmitting it, trying to
+                *      kick us into responding to the request.
+                */
+               if (memcmp(curreq->packet->vector, packet->vector,
+                          sizeof(packet->vector)) == 0) {
+                       RAD_SNMP_INC(rad_snmp.auth.total_dup_requests);
+
+                       /*
+                        *      It's not finished because the request
+                        *      was proxied, but there was no reply
+                        *      from the home server.
+                        *
+                        *      This code will never get hit for
+                        *      accounting packets, as they're always
+                        *      updated, and never re-transmitted.
+                        */
+                       if (curreq->proxy && !curreq->proxy_reply) {
+                               DEBUG2("Sending duplicate proxied request to home server %s port %d - ID: %d",
+                                      inet_ntop(curreq->proxy->dst_ipaddr.af,
+                                                &curreq->proxy->dst_ipaddr.ipaddr,
+                                                buffer, sizeof(buffer)),                                              curreq->proxy->dst_port,
+                                      
+                                      curreq->proxy->id);
+                               curreq->proxy_listener->send(curreq->proxy_listener, curreq);
+                               return 0;
+                       } /* else the packet was not proxied */
+
+                       /*
+                        *      Someone's still working on it, so we
+                        *      ignore the duplicate request.
+                        */
+                       radlog(L_ERR, "Discarding duplicate request from "
+                              "client %s port %d - ID: %d due to unfinished request %d",
+                              client->shortname,
+                              packet->src_port, packet->id,
+                              curreq->number);
+                       return 0;
+               } /* else the authentication vectors were different */
+
+               /*
+                *      We're waiting for a proxy reply, but no one is
+                *      currently processing the request.  We can
+                *      discard the old request, and ignore any reply
+                *      from the home server, because the NAS will
+                *      never care...
+                */
+               if (curreq->proxy && !curreq->proxy_reply &&
+                   (curreq->child_pid == NO_SUCH_CHILD_PID)) {
+                       radlog(L_ERR, "Discarding old proxied request %d from "
+                              "client %s port %d - ID: %d due to new request from the client",
+                              curreq->number, client->shortname,
+                              packet->src_port, packet->id);
+               } else {
+                       /*
+                        *      The authentication vectors are different, so
+                        *      the NAS has given up on us, as we've taken too
+                        *      long to process the request.  This is a
+                        *      SERIOUS problem!
+                        */
+                       RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
+                       
+                       radlog(L_ERR, "Dropping conflicting packet from "
+                              "client %s port %d - ID: %d due to unfinished request %d",
+                              client->shortname,
+                              packet->src_port, packet->id,
+                              curreq->number);
+                       return 0;
+               }
+               
+               /*
+                *      The old request is finished.  We now check the
+                *      authentication vectors.  If the client has sent us a
+                *      request with identical code && ID, but different
+                *      vector, then they MUST have gotten our response, so we
+                *      can delete the original request, and process the new
+                *      one.
+                *
+                *      If the vectors are the same, then it's a duplicate
+                *      request, and we can send a duplicate reply.
+                */
+       } else if (memcmp(curreq->packet->vector, packet->vector,
+                         sizeof(packet->vector)) == 0) {
+               RAD_SNMP_INC(rad_snmp.auth.total_dup_requests);
+
+               /*
+                *      If the packet has been delayed, then silently
+                *      send a response, and clear the delayed flag.
+                *
+                *      Note that this means if the NAS kicks us while
+                *      we're delaying a reject, then the reject may
+                *      be sent sooner than otherwise.
+                *
+                *      This COULD be construed as a bug.  Maybe what
+                *      we want to do is to ignore the duplicate
+                *      packet, and send the reject later.
+                */
+               if (curreq->options & RAD_REQUEST_OPTION_DELAYED_REJECT) {
+                       curreq->options &= ~RAD_REQUEST_OPTION_DELAYED_REJECT;
+                       rad_assert(curreq->listener == listener);
+                       listener->send(listener, curreq);
+                       return 0;
+               }
+
+               /*
+                *      Maybe we've saved a reply packet.  If so,
+                *      re-send it.  Otherwise, just complain.
+                */
+               if (curreq->reply->code != 0) {
+                       DEBUG2("Sending duplicate reply "
+                              "to client %s port %d - ID: %d",
+                              client->shortname,
+                              packet->src_port, packet->id);
+                       rad_assert(curreq->listener == listener);
+                       listener->send(listener, curreq);
+                       return 0;
+               }
+
+               /*
+                *      Else we never sent a reply to the NAS,
+                *      as we decided somehow we didn't like the request.
+                *
+                *      This shouldn't happen, in general...
+                */
+               DEBUG2("Discarding duplicate request from client %s port %d - ID: %d",
+                      client->shortname, packet->src_port, packet->id);
+               return 0;
+       } /* else the vectors were different, so we discard the old request. */
+
+       /*
+        *      'packet' has the same source IP, source port, code,
+        *      and Id as 'curreq', but a different authentication
+        *      vector.  We can therefore delete 'curreq', as we were
+        *      only keeping it around to send out duplicate replies,
+        *      if the first reply got lost in the network.
+        */
+       if (curreq) {
+               rl_yank(listener->rl, curreq);
+               request_free(&curreq);
+       }
+
+       /*
+        *      A unique per-request counter.
+        */
+       curreq = request_alloc(); /* never fails */
+       
+       if ((curreq->reply = rad_alloc(0)) == NULL) {
+               radlog(L_ERR, "No memory");
+               exit(1);
+       }
+       curreq->listener = listener;
+       curreq->packet = packet;
+       curreq->packet->timestamp = curreq->timestamp;
+       curreq->number = request_num_counter++;
+       strlcpy(curreq->secret, client->secret, sizeof(curreq->secret));
+       
+       /*
+        *      Remember the request in the list.
+        */
+       if (!rl_add(listener->rl, curreq)) {
+               radlog(L_ERR, "Failed to insert request %d in the list of live requests: discarding", curreq->number);
+               request_free(&curreq);
+               return 0;
+       }
+       
+       /*
+        *      The request passes many of our sanity checks.
+        *      From here on in, if anything goes wrong, we
+        *      send a reject message, instead of dropping the
+        *      packet.
+        */
+
+       /*
+        *      Build the reply template from the request.
+        */
+
+       curreq->reply->sockfd = curreq->packet->sockfd;
+       curreq->reply->dst_ipaddr = curreq->packet->src_ipaddr;
+       curreq->reply->src_ipaddr = curreq->packet->dst_ipaddr;
+       curreq->reply->dst_port = curreq->packet->src_port;
+       curreq->reply->src_port = curreq->packet->dst_port;
+       curreq->reply->id = curreq->packet->id;
+       curreq->reply->code = 0; /* UNKNOWN code */
+       memcpy(curreq->reply->vector, curreq->packet->vector,
+              sizeof(curreq->reply->vector));
+       curreq->reply->vps = NULL;
+       curreq->reply->data = NULL;
+       curreq->reply->data_len = 0;
+
+       *prequest = curreq;
+       return 1;
+}
+
+
+static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
+{
+       size_t len;
+       listen_socket_t *sock = this->data;
+
+       if ((sock->ipaddr.af == AF_INET) &&
+           (sock->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY))) {
+               strcpy(buffer, "*");
+       } else {
+               ip_ntoh(&sock->ipaddr, buffer, bufsize);
+       }
+
+       len = strlen(buffer);
+
+       return len + snprintf(buffer + len, bufsize - len, " port %d",
+                             sock->port);
+}
+
+
+/*
+ *     Parse an authentication or accounting socket.
+ */
+static int common_socket_parse(const char *filename, int lineno,
+                            const CONF_SECTION *cs, rad_listen_t *this)
+{
+       int             rcode;
+       int             listen_port;
+       lrad_ipaddr_t   ipaddr;
+       listen_socket_t *sock = this->data;
+       const char      *section_name = NULL;
+       CONF_SECTION    *client_cs;
+
+       /*
+        *      Try IPv4 first
+        */
+       ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
+       rcode = cf_item_parse(cs, "ipaddr", PW_TYPE_IPADDR,
+                             &ipaddr.ipaddr.ip4addr, NULL);
+       if (rcode < 0) return -1;
+       
+       if (rcode == 0) { /* successfully parsed IPv4 */
+               ipaddr.af = AF_INET;
+               
+       } else {        /* maybe IPv6? */
+               rcode = cf_item_parse(cs, "ipv6addr", PW_TYPE_IPV6ADDR,
+                                     &ipaddr.ipaddr.ip6addr, NULL);
+               if (rcode < 0) return -1;
+               
+               if (rcode == 1) {
+                       radlog(L_ERR, "%s[%d]: No address specified in listen section",
+                              filename, lineno);
+                       return -1;
+               }
+               ipaddr.af = AF_INET6;
+       }
+       
+       rcode = cf_item_parse(cs, "port", PW_TYPE_INTEGER,
+                             &listen_port, "0");
+       if (rcode < 0) return -1;
+       
+       sock->ipaddr = ipaddr;
+       sock->port = listen_port;
+
+       /*
+        *      And bind it to the port.
+        */
+       if (listen_bind(this) < 0) {
+               char buffer[128];
+               radlog(L_CONS|L_ERR, "%s[%d]: Error binding to port for %s port %d",
+                      filename, cf_section_lineno(cs),
+                      ip_ntoh(&sock->ipaddr, buffer, sizeof(buffer)),
+                      sock->port);
+               return -1;
+       }
+
+       /*
+        *      If we can bind to interfaces, do so,
+        *      else don't.
+        */
+       if (cf_pair_find(cs, "interface")) {
+#ifndef SO_BINDTODEVICE
+               radlog(L_CONS|L_ERR, "%s[%d]: System does not support binding to interfaces, delete this line from the configuration file.",
+                      filename, cf_section_lineno(cs));
+               return -1;
+#else
+               const char *value;
+               const CONF_PAIR *cp = cf_pair_find(cs, "interface");
+               struct ifreq ifreq;
+
+               rad_assert(cp != NULL);
+               value = cf_pair_value(cp);
+               rad_assert(value != NULL);
+               
+               strcpy(ifreq.ifr_name, value);
+       
+               if (setsockopt(this->fd, SOL_SOCKET, SO_BINDTODEVICE,
+                              (char *)&ifreq, sizeof(ifreq)) < 0) {
+                       radlog(L_CONS|L_ERR, "%s[%d]: Failed binding to interface %s: %s",
+                              filename, cf_section_lineno(cs),
+                              value, strerror(errno));
+                       return -1;
+               } /* else it worked. */
+#endif
+       }
+
+       /*
+        *      Look for the name of a section that holds a list
+        *      of clients.
+        */
+       rcode = cf_item_parse(cs, "clients", PW_TYPE_STRING_PTR,
+                             &section_name, NULL);
+       if (rcode < 0) return -1; /* bad string */
+       if (rcode > 0) return 0; /* non-existent is OK. */
+
+       client_cs = cf_section_find(section_name);
+       free(section_name);
+       if (!client_cs) {
+               radlog(L_CONS|L_ERR, "%s[%d]: Failed to find client section %s",
+                      filename, cf_section_lineno(cs), section_name);
+               return -1;
+       }
+
+       sock->clients = clients_parse_section(filename, client_cs);
+       if (!sock->clients) {
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ *     Send an authentication response packet
+ */
+static int auth_socket_send(rad_listen_t *listener, REQUEST *request)
+{
+       rad_assert(request->listener == listener);
+       rad_assert(listener->send == auth_socket_send);
+
+       /*
+        *      Ensure that the reply is sane
+        */
+       if (request->reply->code == 0) {
+               DEBUG2("There was no response configured: rejecting request %d", request->number);
+               request->reply->code = PW_AUTHENTICATION_REJECT;
+       }
+
+       /*
+        *      If we're delaying authentication rejects, then
+        *      mark the request as delayed, and do NOT send a
+        *      response right now.
+        *
+        *      However, if it's already marked as delayed, then
+        *      send it now.
+        */
+       if ((request->reply->code == PW_AUTHENTICATION_REJECT) &&
+           ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) == 0) &&
+           (mainconfig.reject_delay > 0) &&
+           ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) == 0)) {
+               DEBUG2("Delaying request %d for %d seconds",
+                      request->number, mainconfig.reject_delay);
+               request->options |= RAD_REQUEST_OPTION_DELAYED_REJECT;
+               return 0;
+       }
+
+       return rad_send(request->reply, request->packet, request->secret);
+}
+
+
+/*
+ *     Send an accounting response packet (or not)
+ */
+static int acct_socket_send(rad_listen_t *listener, REQUEST *request)
+{
+       rad_assert(request->listener == listener);
+       rad_assert(listener->send == acct_socket_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;
+
+       return rad_send(request->reply, request->packet, request->secret);
+}
+
+
+/*
+ *     Send a packet to a home server.
+ *
+ *     FIXME: have different code for proxy auth & acct!
+ */
+static int proxy_socket_send(rad_listen_t *listener, REQUEST *request)
+{
+       listen_socket_t *sock = listener->data;
+
+       rad_assert(request->proxy_listener == listener);
+       rad_assert(listener->send == proxy_socket_send);
+
+       request->proxy->src_ipaddr = sock->ipaddr;
+       request->proxy->src_port = sock->port;
+
+       return rad_send(request->proxy, request->packet, request->proxysecret);
+}
+
+
+/*
+ *     Check if an incoming request is "ok"
+ *
+ *     It takes packets, not requests.  It sees if the packet looks
+ *     OK.  If so, it does a number of sanity checks on it.
+  */
+static int auth_socket_recv(rad_listen_t *listener,
+                           RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+{
+       RADIUS_PACKET   *packet;
+       RAD_REQUEST_FUNP fun = NULL;
+       char            buffer[128];
+       RADCLIENT       *client;
+
+       packet = rad_recv(listener->fd);
+       if (!packet) {
+               radlog(L_ERR, "%s", librad_errstr);
+               return 0;
+       }
+
+       RAD_SNMP_TYPE_INC(listener, total_requests); /* FIXME: auth specific */
+
+       if ((client = client_listener_find(listener,
+                                          &packet->src_ipaddr)) == NULL) {
+               RAD_SNMP_TYPE_INC(listener, total_invalid_requests);
+               
+               radlog(L_ERR, "Ignoring request from unknown client %s port %d",
+                      inet_ntop(packet->src_ipaddr.af,
+                                &packet->src_ipaddr.ipaddr,
+                                buffer, sizeof(buffer)),
+                      packet->src_port);
+               rad_free(&packet);
+               return 0;
+       }
+
+       /*
+        *      Some sanity checks, based on the packet code.
+        */
+       switch(packet->code) {
+       case PW_AUTHENTICATION_REQUEST:
+               fun = rad_authenticate;
+               break;
+               
+       case PW_STATUS_SERVER:
+               if (!mainconfig.status_server) {
+                       RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
+                       DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
+                       rad_free(&packet);
+                       return 0;
+               }
+               fun = rad_status_server;
+               break;
+
+       default:
+               RAD_SNMP_INC(rad_snmp.auth.total_unknown_types);
+               
+               radlog(L_ERR, "Invalid packet code %d sent to authentication port from client %s port %d "
+                      "- ID %d : IGNORED",
+                      packet->code, client->shortname,
+                      packet->src_port, packet->id);
+               rad_free(&packet);
+               return 0;
+               break;
+       } /* switch over packet types */
+       
+       if (!common_checks(listener, packet, prequest, client)) {
+               rad_free(&packet);
+               return 0;
+       }
+
+       *pfun = fun;
+       return 1;
+}
+
+
+/*
+ *     Receive packets from an accounting socket
+ */
+static int acct_socket_recv(rad_listen_t *listener,
+       RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+{
+       RADIUS_PACKET   *packet;
+       RAD_REQUEST_FUNP fun = NULL;
+       char            buffer[128];
+       RADCLIENT       *client;
+       
+       packet = rad_recv(listener->fd);
+       if (!packet) {
+               radlog(L_ERR, "%s", librad_errstr);
+               return 0;
+       }
+       
+       RAD_SNMP_TYPE_INC(listener, total_requests); /* FIXME: acct-specific */
+
+       if ((client = client_listener_find(listener,
+                                          &packet->src_ipaddr)) == NULL) {
+               RAD_SNMP_TYPE_INC(listener, total_invalid_requests);
+               
+               radlog(L_ERR, "Ignoring request from unknown client %s port %d",
+                      inet_ntop(packet->src_ipaddr.af,
+                                &packet->src_ipaddr.ipaddr,
+                                buffer, sizeof(buffer)),
+                      packet->src_port);
+               rad_free(&packet);
+               return 0;
+       }
+
+       switch(packet->code) {
+       case PW_ACCOUNTING_REQUEST:
+               fun = rad_accounting;
+               break;
+               
+       case PW_STATUS_SERVER:
+               if (!mainconfig.status_server) {
+                       RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
+                       DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
+                       rad_free(&packet);
+                       return 0;
+               }
+               fun = rad_status_server;
+               break;
+
+       default:
+               /*
+                *      FIXME: Update MIB for packet types?
+                */
+               radlog(L_ERR, "Invalid packet code %d sent to a accounting port "
+                      "from client %s port %d - ID %d : IGNORED",
+                      packet->code, client->shortname,
+                      packet->src_port, packet->id);
+               rad_free(&packet);
+               return 0;
+       }
+
+       /*
+        *      FIXME: Accounting duplicates should be handled
+        *      differently than authentication duplicates.
+        */
+       if (!common_checks(listener, packet, prequest, client)) {
+               rad_free(&packet);
+               return 0;
+       }
+
+       *pfun = fun;
+       return 1;
+}
+
+
+/*
+ *     Recieve packets from a proxy socket.
+ */
+static int proxy_socket_recv(rad_listen_t *listener,
+                             RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+{
+       REALM           *cl;
+       REQUEST         *oldreq;
+       RADIUS_PACKET   *packet;
+       RAD_REQUEST_FUNP fun = NULL;
+       char            buffer[128];
+       
+       packet = rad_recv(listener->fd);
+       if (!packet) {
+               radlog(L_ERR, "%s", librad_errstr);
+               return 0;
+       }
+
+       /*
+        *      Unsupported stuff
+        */
+       if (packet->src_ipaddr.af != AF_INET) {
+               rad_assert("PROXY IPV6 NOT SUPPORTED" == NULL);
+       }
+       
+       /*
+        *      FIXME: Add support for home servers!
+        */
+       if ((cl = realm_findbyaddr(packet->src_ipaddr.ipaddr.ip4addr.s_addr,
+                                  packet->src_port)) == NULL) {
+               radlog(L_ERR, "Ignoring request from unknown home server %s port %d",
+                      inet_ntop(packet->src_ipaddr.af,
+                                &packet->src_ipaddr.ipaddr,
+                                buffer, sizeof(buffer)),
+                              packet->src_port);
+               rad_free(&packet);
+               return 0;
+       }
+
+       /*
+        *      FIXME: Client MIB updates?
+        */
+       switch(packet->code) {
+       case PW_AUTHENTICATION_ACK:
+       case PW_ACCESS_CHALLENGE:
+       case PW_AUTHENTICATION_REJECT:
+               fun = rad_authenticate;
+               break;
+               
+       case PW_ACCOUNTING_RESPONSE:
+               fun = rad_accounting;
+               break;
+               
+       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;
+       }
+
+       /*
+        *      Find the original request in the request list
+        */
+       oldreq = rl_find_proxy(packet);
+
+       /*
+        *      If we haven't found the original request which was
+        *      sent, to get this reply.  Complain, and discard this
+        *      request, as there's no way for us to send it to a NAS.
+        */
+       if (!oldreq) {
+               radlog(L_PROXY, "No outstanding request was found for proxy reply from home server %s port %d - ID %d",
+                      inet_ntop(packet->src_ipaddr.af,
+                                &packet->src_ipaddr.ipaddr,
+                                buffer, sizeof(buffer)),
+                      packet->src_port, packet->id);
+               rad_free(&packet);
+               return 0;
+       }
+
+       /*
+        *      The proxy reply has arrived too late, as the original
+        *      (old) request has timed out, been rejected, and marked
+        *      as finished.  The client has already received a
+        *      response, so there is nothing that can be done. Delete
+        *      the tardy reply from the home server, and return nothing.
+        */
+       if ((oldreq->reply->code != 0) ||
+           (oldreq->finished)) {
+               radlog(L_ERR, "Reply from home server %s port %d  - ID: %d arrived too late for request %d. Try increasing 'retry_delay' or 'max_request_time'",
+                      inet_ntop(packet->src_ipaddr.af,
+                                &packet->src_ipaddr.ipaddr,
+                                buffer, sizeof(buffer)),
+                      packet->src_port, packet->id,
+                      oldreq->number);
+               rad_free(&packet);
+               return 0;
+       }
+
+       /*
+        *      If there is already a reply, maybe this one is a
+        *      duplicate?
+        */
+       if (oldreq->proxy_reply) {
+               if (memcmp(oldreq->proxy_reply->vector,
+                          packet->vector,
+                          sizeof(oldreq->proxy_reply->vector)) == 0) {
+                       radlog(L_ERR, "Discarding duplicate reply from home server %s port %d  - ID: %d for request %d",
+                              inet_ntop(packet->src_ipaddr.af,
+                                        &packet->src_ipaddr.ipaddr,
+                                        buffer, sizeof(buffer)),
+                              packet->src_port, packet->id,
+                              oldreq->number);
+               } else {
+                       /*
+                        *      ? The home server gave us a new proxy
+                        *      reply, which doesn't match the old
+                        *      one.  Delete it.
+                        */
+                       DEBUG2("Ignoring conflicting proxy reply");
+               }
+
+               /*
+                *      We've already received a reply, so
+                *      we discard this one, as we don't want
+                *      to do duplicate work.
+                */
+               rad_free(&packet);
+               return 0;
+       } /* else there wasn't a proxy reply yet, so we can process it */
+
+       /*
+        *       Refresh the old request, and update it with the proxy
+        *       reply.
+        *
+        *      ? Can we delete the proxy request here?  * Is there
+        *      any more need for it?
+        *
+        *      FIXME: we probably shouldn't be updating the time
+        *      stamp here.
+        */
+       oldreq->timestamp = time_now;
+       oldreq->proxy_reply = packet;
+
+       /*
+        *      FIXME: we should really verify the digest here,
+        *      before marking this packet as a valid response.
+        *
+        *      This is a security problem, I think...
+        */
+
+       /*
+        *      Now that we've verified the packet IS actually from
+        *      that home server, and not forged, we can go mark the
+        *      entries for this home server as active.
+        *
+        *      If we had done this check in the 'find realm by IP address'
+        *      function, then an attacker could force us to use a home
+        *      server which was inactive, by forging reply packets
+        *      which didn't match any request.  We would think that
+        *      the reply meant the home server was active, would
+        *      re-activate the realms, and THEN bounce the packet
+        *      as garbage.
+        */
+       for (cl = mainconfig.realms; cl != NULL; cl = cl->next) {
+               if (oldreq->proxy_reply->src_ipaddr.af != cl->ipaddr.af) continue;
+               if (cl->ipaddr.af != AF_INET) continue; /* FIXME */
+
+               if (oldreq->proxy_reply->src_ipaddr.ipaddr.ip4addr.s_addr == cl->ipaddr.ipaddr.ip4addr.s_addr) {
+                       if (oldreq->proxy_reply->src_port == cl->auth_port) {
+                               cl->active = TRUE;
+                               cl->last_reply = oldreq->timestamp;
+                       } else if (oldreq->proxy_reply->src_port == cl->acct_port) {
+                               cl->acct_active = TRUE;
+                               cl->last_reply = oldreq->timestamp;
+                       }
+               }
+       }
+
+       rad_assert(fun != NULL);
+       *pfun = fun;
+       *prequest = oldreq;
+
+       return 1;
+}
+
+#define STATE_UNOPENED (0)
+#define STATE_UNLOCKED (1)
+#define STATE_HEADER   (2)
+#define STATE_READING  (3)
+#define STATE_DONE     (4)
+#define STATE_WAITING  (5)
+
+/*
+ *     If we're limiting outstanding packets, then mark the response
+ *     as being sent.
+ */
+static int detail_send(rad_listen_t *listener, REQUEST *request)
+{
+       listen_detail_t *data = listener->data;
+
+       rad_assert(request->listener == listener);
+       rad_assert(listener->send == detail_send);
+
+       if (request->simul_max >= 0) {
+               rad_assert(data->outstanding != NULL);
+               rad_assert(request->simul_max < data->max_outstanding);
+
+               data->outstanding[request->simul_max] = 0;
+       }
+
+       return 0;
+}
+
+
+/*
+ *     Open the detail file..
+ *
+ *     FIXME: create it, if it's not already there, so that the main
+ *     server select() will wake us up if there's anything to read.
+ */
+static int detail_open(rad_listen_t *this)
+{
+       struct stat st;
+       char buffer[2048];
+       listen_detail_t *data = this->data;
+
+       rad_assert(data->state == STATE_UNOPENED);
+       snprintf(buffer, sizeof(buffer), "%s.work", data->detail);
+       
+       /*
+        *      FIXME: Have "one-shot" configuration, where it
+        *      will read the detail file, and exit once it's
+        *      done.
+        *
+        *      FIXME: Try harder to open the detail file.
+        *      Maybe sleep for X usecs if it doesn't exist?
+        */
+
+       /*
+        *      Open detail.work first, so we don't lose
+        *      accounting packets.  It's probably better to
+        *      duplicate them than to lose them.
+        *
+        *      Note that we're not writing to the file, but
+        *      we've got to open it for writing in order to
+        *      establish the lock, to prevent rlm_detail from
+        *      writing to it.
+        */
+       this->fd = open(buffer, O_RDWR);
+       if (this->fd < 0) {
+               /*
+                *      Try reading the detail file.  If it
+                *      doesn't exist, we can't do anything.
+                *
+                *      Doing the stat will tell us if the file
+                *      exists, even if we don't have permissions
+                *      to read it.
+                */
+               if (stat(data->detail, &st) < 0) {
+                       return 0;
+               }
+               
+               /*
+                *      Open it BEFORE we rename it, just to
+                *      be safe...
+                */
+               this->fd = open(data->detail, O_RDWR);
+               if (this->fd < 0) {
+                       radlog(L_ERR, "Failed to open %s: %s",
+                              data->detail, strerror(errno));
+                       return 0;
+               }
+               
+               /*
+                *      Rename detail to detail.work
+                */
+               if (rename(data->detail, buffer) < 0) {
+                       close(this->fd);
+                       this->fd = -1;
+                       return 0;
+               }
+       } /* else detail.work existed, and we opened it */
+       
+       rad_assert(data->vps == NULL);
+       
+       rad_assert(data->fp == NULL);
+       data->fp = fdopen(this->fd, "r");
+       if (!data->fp) {
+               radlog(L_ERR, "Failed to re-open %s: %s",
+                      data->detail, strerror(errno));
+               return 0;
+       }
+
+       data->state = STATE_UNLOCKED;
+
+       data->client_ip.af = AF_UNSPEC;
+       data->timestamp = 0;
+       
+       return 1;
+}
+
+/*
+ *     This is a bad hack, just so complaints have meaningful text.
+ */
+static const RADCLIENT detail_client = {
+       {               /* ipaddr */
+               AF_INET,
+               {{ INADDR_NONE }}
+       },
+       32,
+       "<detail-file>",
+       "secret",
+       "UNKNOWN-CLIENT",
+       "other",
+       "",
+       "",
+       -1
+};
+
+static int detail_recv(rad_listen_t *listener,
+                      RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+{
+       int             free_slot = -1;
+       char            key[256], value[1024];
+       VALUE_PAIR      *vp, **tail;
+       RADIUS_PACKET   *packet;
+       char            buffer[2048];
+       listen_detail_t *data = listener->data;
+
+       if (data->state == STATE_UNOPENED) {
+               rad_assert(listener->fd < 0);
+               if (!detail_open(listener)) return 0;
+       }
+       rad_assert(listener->fd >= 0);
+
+       /*
+        *      Try to lock fd.  If we can't, return.  If we can,
+        *      continue.  This means that the server doesn't block
+        *      while waiting for the lock to open...
+        */
+       if (data->state == STATE_UNLOCKED) {
+               /*
+                *      Note that we do NOT block waiting for the
+                *      lock.  We've re-named the file above, so we've
+                *      already guaranteed that any *new* detail
+                *      writer will not be opening this file.  The
+                *      only purpose of the lock is to catch a race
+                *      condition where the execution "ping-pongs"
+                *      between radiusd & radrelay.
+                */
+               if (rad_lockfd_nonblock(listener->fd, 0) < 0) {
+                       return 0;
+               }
+               /*
+                *      Look for the header
+                */
+               data->state = STATE_HEADER;
+       }
+
+       /*
+        *      If we keep track of the outstanding requests, do so
+        *      here.  Note that to minimize potential work, we do
+        *      so only once the file is opened & locked.
+        */
+       if (data->max_outstanding) {
+               int i;
+
+               for (i = 0; i < data->max_outstanding; i++) {
+                       if (!data->outstanding[i]) {
+                               free_slot = i;
+                               break;
+                       }
+               }
+
+               /*
+                *      All of the slots are full, don't read data.
+                */
+               if (free_slot < 0) return 0;
+       }
+
+       /*
+        *      Catch an out of memory condition which will most likely
+        *      never be met.
+        */
+       if (data->state == STATE_DONE) goto alloc_packet;
+
+       /*
+        *      If we're in another state, then it means that we read
+        *      a partial packet, which is bad.
+        */
+       rad_assert(data->state == STATE_HEADER);
+       rad_assert(data->vps == NULL);
+
+       /*
+        *      We read the last packet, and returned it for
+        *      processing.  We later come back here to shut
+        *      everything down, and unlink the file.
+        */
+       if (feof(data->fp)) {
+               rad_assert(data->state == STATE_HEADER);
+
+               /*
+                *      Don't unlink the file until we've received
+                *      all of the responses.
+                */
+               if (data->max_outstanding > 0) {
+                       int i;
+
+                       for (i = 0; i < data->max_outstanding; i++) {
+                               /*
+                                *      FIXME: close the file?
+                                */
+                               if (data->outstanding[i]) {
+                                       data->state = STATE_WAITING;
+                                       return 0;
+                               }
+                       }
+               }
+
+       cleanup:
+               rad_assert(data->vps == NULL);
+
+               snprintf(buffer, sizeof(buffer), "%s.work", data->detail);
+               unlink(buffer);
+               fclose(data->fp); /* closes listener->fd */
+               data->fp = NULL;
+               listener->fd = -1;
+               data->state = STATE_UNOPENED;
+
+               /*
+                *      Try to open "detail" again.  If we're on a
+                *      busy RADIUS server, odds are that it will
+                *      now exist.
+                */
+               detail_open(listener);
+               return 0;
+       }
+
+       tail = &data->vps;
+
+       /*
+        *      Fill the buffer...
+        */
+       while (fgets(buffer, sizeof(buffer), data->fp)) {
+               /*
+                *      No CR, die.
+                */
+               if (!strchr(buffer, '\n')) {
+                       pairfree(&data->vps);
+                       goto cleanup;
+               }
+
+               /*
+                *      We've read a header, possibly packet contents,
+                *      and are now at the end of the packet.
+                */
+               if ((data->state == STATE_READING) &&
+                   (buffer[0] == '\n')) {
+                       data->state = STATE_DONE;
+                       break;
+               }
+
+               /*
+                *      Look for date/time header, and read VP's if
+                *      found.  If not, keep reading lines until we
+                *      find one.
+                */
+               if (data->state == STATE_HEADER) {
+                       int y;
+                       
+                       if (sscanf(buffer, "%*s %*s %*d %*d:%*d:%*d %d", &y)) {
+                               data->state = STATE_READING;
+                       }
+                       continue;
+               }
+
+               /*
+                *      We have a full "attribute = value" line.
+                *      If it doesn't look reasonable, skip it.
+                */
+               if (sscanf(buffer, "%255s = %1023s", key, value) != 2) {
+                       continue;
+               }
+
+               /*
+                *      Skip non-protocol attributes.
+                */
+               if (!strcasecmp(key, "Request-Authenticator")) continue;
+
+               /*
+                *      Set the original client IP address, based on
+                *      what's in the detail file.
+                *
+                *      Hmm... we don't set the server IP address.
+                *      or port.  Oh well.
+                */
+               if (!strcasecmp(key, "Client-IP-Address")) {
+                       data->client_ip.af = AF_INET;
+                       ip_hton(value, AF_INET, &data->client_ip);
+                       continue;
+               }
+
+               /*
+                *      The original time at which we received the
+                *      packet.  We need this to properly calculate
+                *      Acct-Delay-Time.
+                */
+               if (!strcasecmp(key, "Timestamp")) {
+                       data->timestamp = atoi(value);
+                       continue;
+               }
+
+               /*
+                *      Read one VP.
+                *
+                *      FIXME: do we want to check for non-protocol
+                *      attributes like radsqlrelay does?
+                */
+               vp = NULL;
+               if ((userparse(buffer, &vp) > 0) &&
+                   (vp != NULL)) {
+                       *tail = vp;
+                       tail = &(vp->next);
+               }               
+       }
+
+       /*
+        *      We got to EOF,  If we're in STATE_HEADER, it's OK.
+        *      Otherwise it's a problem.  In any case, nuke the file
+        *      and start over from scratch,
+        */
+       if (feof(data->fp)) {
+               goto cleanup;
+       }
+
+       /*
+        *      FIXME: Do load management.
+        */
+
+       /*
+        *      If we're not done, then there's a problem.  The checks
+        *      above for EOF
+        */
+       rad_assert(data->state == STATE_DONE);
+
+       /*
+        *      The packet we read was empty, re-set the state to look
+        *      for a header, and don't return anything.
+        */
+       if (!data->vps) {
+               data->state = STATE_HEADER;
+               return 0;
+       }
+
+       /*
+        *      Allocate the packet.  If we fail, it's a serious
+        *      problem.
+        */
+ alloc_packet:
+       packet = rad_alloc(1);
+       if (!packet) {
+               return 0;       /* maybe memory will magically free up... */
+       }
+
+       memset(packet, 0, sizeof(*packet));
+       packet->sockfd = -1;
+       packet->src_ipaddr.af = AF_INET;
+       packet->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
+       packet->code = PW_ACCOUNTING_REQUEST;
+       packet->timestamp = time(NULL);
+
+       /*
+        *      Look for Acct-Delay-Time, and update
+        *      based on Acct-Delay-Time += (time(NULL) - timestamp)
+        */
+       vp = pairfind(packet->vps, PW_ACCT_DELAY_TIME);
+       if (!vp) {
+               vp = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
+               rad_assert(vp != NULL);
+       }
+       if (data->timestamp != 0) {
+               vp->lvalue += time(NULL) - data->timestamp;
+       }
+
+       /*
+        *      Remember where it came from, so that we don't
+        *      proxy it to the place it came from...
+        */
+       if (data->client_ip.af != AF_UNSPEC) {
+               packet->src_ipaddr = data->client_ip;
+       }
+
+       vp = pairfind(packet->vps, PW_PACKET_SRC_IP_ADDRESS);
+       if (vp) {
+               packet->src_ipaddr.af = AF_INET;
+               packet->src_ipaddr.ipaddr.ip4addr.s_addr = vp->lvalue;
+       } else {
+               vp = pairfind(packet->vps, PW_PACKET_SRC_IPV6_ADDRESS);
+               if (vp) {
+                       packet->src_ipaddr.af = AF_INET6;
+                       memcpy(&packet->src_ipaddr.ipaddr.ip6addr,
+                              &vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
+               }
+       }
+
+       vp = pairfind(packet->vps, PW_PACKET_DST_IP_ADDRESS);
+       if (vp) {
+               packet->dst_ipaddr.af = AF_INET;
+               packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->lvalue;
+       } else {
+               vp = pairfind(packet->vps, PW_PACKET_DST_IPV6_ADDRESS);
+               if (vp) {
+                       packet->dst_ipaddr.af = AF_INET6;
+                       memcpy(&packet->dst_ipaddr.ipaddr.ip6addr,
+                              &vp->vp_ipv6addr, sizeof(vp->vp_ipv6addr));
+               }
+       }
+
+       /*
+        *      We've got to give SOME value for Id & ports, so that
+        *      the packets can be added to the request queue.
+        *      However, we don't want to keep track of used/unused
+        *      id's and ports, as that's a lot of work.  This hack
+        *      ensures that (if we have real random numbers), that
+        *      there will be a collision on every (2^(16+16+2+24))/2
+        *      packets, on average.  That means we can read 2^32 (4G)
+        *      packets before having a collision, which means it's
+        *      effectively impossible.  Having 4G packets currently
+        *      being process is ridiculous.
+        */
+       packet->id = lrad_rand() & 0xff;
+       packet->src_port = lrad_rand() & 0xffff;
+       packet->dst_port = lrad_rand() & 0xffff;
+
+       packet->dst_ipaddr.af = AF_INET;
+       packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl((INADDR_LOOPBACK & ~0xffffff) | (lrad_rand() & 0xffffff));
+
+       packet->vps = data->vps;
+
+       /*
+        *      Re-set the state.
+        */
+       data->vps = NULL;
+       data->state = STATE_HEADER;
+
+       /*
+        *      FIXME: many of these checks may not be necessary...
+        */
+       if (!common_checks(listener, packet, prequest, &detail_client)) {
+               rad_free(&packet);
+               return 0;
+       }
+
+       /*
+        *      Keep track of free slots, as a hack, in an otherwise
+        *      unused 'int'
+        */
+       (*prequest)->simul_max = free_slot;
+       if (free_slot) data->outstanding[free_slot] = 1;
+
+       *pfun = rad_accounting;
+
+       if (debug_flag) {
+               printf("detail_recv: Read packet from %s\n", data->detail);
+               for (vp = packet->vps; vp; vp = vp->next) {
+                       putchar('\t');
+                       vp_print(stdout, vp);
+                       putchar('\n');
+               }
+       }
+
+       return 1;
+}
+
+
+/*
+ *     Free detail-specific stuff.
+ */
+static void detail_free(rad_listen_t *this)
+{
+       listen_detail_t *data = this->data;
+
+       free(data->detail);
+       pairfree(&data->vps);
+       free(data->outstanding);
+
+       if (data->fp != NULL) fclose(data->fp);
+}
+
+
+static int detail_print(rad_listen_t *this, char *buffer, size_t bufsize)
+{
+       return snprintf(buffer, bufsize, "%s",
+                       ((listen_detail_t *)(this->data))->detail);
+}
+
+
+static const CONF_PARSER detail_config[] = {
+       { "detail",   PW_TYPE_STRING_PTR,
+         offsetof(listen_detail_t, detail), NULL,  NULL },
+       { "max_outstanding",  PW_TYPE_INTEGER,
+          offsetof(listen_detail_t, max_outstanding), NULL, "100" },
+
+       { NULL, -1, 0, NULL, NULL }             /* end the list */
+};
+
+
+/*
+ *     Parse a detail section.
+ */
+static int detail_parse(const char *filename, int lineno,
+                       const CONF_SECTION *cs, rad_listen_t *this)
+{
+       int             rcode;
+       listen_detail_t *data;
+
+       data = this->data;
+
+       rcode = cf_section_parse(cs, data, detail_config);
+       if (rcode < 0) {
+               radlog(L_ERR, "%s[%d]: Failed parsing listen section",
+                      filename, lineno);
+               return -1;
+       }
+
+       if (!data->detail) {
+               radlog(L_ERR, "%s[%d]: No detail file specified in listen section",
+                      filename, lineno);
+               return -1;
+       }
+       
+       data->vps = NULL;
+       data->fp = NULL;
+       data->state = STATE_UNOPENED;
+
+       if (data->max_outstanding > 32768) data->max_outstanding = 32768;
+
+       if (data->max_outstanding > 0) {
+               data->outstanding = rad_malloc(sizeof(int) * data->max_outstanding);
+       }
+       
+       detail_open(this);
+
+       return 0;
+}
+
+
+/*
+ *     See radiusd.c & request_list.c
+ */
+#define SLEEP_FOREVER (65536)
+/*
+ *     A generic "update the request list once a second" function.
+ */
+static int generic_update(rad_listen_t *this, time_t now)
+{
+       if (!this->rl) return SLEEP_FOREVER;
+
+       return rl_clean_list(this->rl, now);
+}
+
+
+
+static const rad_listen_master_t master_listen[RAD_LISTEN_MAX] = {
+       { NULL, NULL, NULL, NULL, NULL, NULL},  /* RAD_LISTEN_NONE */
+
+       /* authentication */
+       { common_socket_parse, NULL,
+         auth_socket_recv, auth_socket_send,
+         generic_update, socket_print },
+
+       /* accounting */
+       { common_socket_parse, NULL,
+         acct_socket_recv, acct_socket_send,
+         generic_update, socket_print},
+
+       /* proxying */
+       { NULL, NULL,
+         proxy_socket_recv, proxy_socket_send,
+         generic_update, socket_print }, /* FIXME: update func is wrong! */
+
+       /* detail */
+       { detail_parse, detail_free,
+         detail_recv, detail_send,
+         generic_update, detail_print }
+};
+
+
+/*
+ *     Binds a listener to a socket.
+ */
+static int listen_bind(rad_listen_t *this)
+{
+       rad_listen_t    **last;
+       listen_socket_t *sock = this->data;
+
+       /*
+        *      If the port is zero, then it means the appropriate
+        *      thing from /etc/services.
+        */
+       if (sock->port == 0) {
+               struct servent  *svp;
+
+               switch (this->type) {
+               case RAD_LISTEN_AUTH:
+                       svp = getservbyname ("radius", "udp");
+                       if (svp != NULL) {
+                               sock->port = ntohs(svp->s_port);
+                       } else {
+                               sock->port = PW_AUTH_UDP_PORT;
+                       }
+                       break;
+
+               case RAD_LISTEN_ACCT:
+                       svp = getservbyname ("radacct", "udp");
+                       if (svp != NULL) {
+                               sock->port = ntohs(svp->s_port);
+                       } else {
+                               sock->port = PW_ACCT_UDP_PORT;
+                       }
+                       break;
+
+               default:
+                       radlog(L_ERR|L_CONS, "ERROR: Non-fatal internal sanity check failed in bind.");
+                       return -1;
+               }
+       }
+
+       /*
+        *      Find it in the old list, AFTER updating the port.  If
+        *      it's there, use that, rather than creating a new
+        *      socket.  This allows HUP's to re-use the old sockets,
+        *      which means that packets waiting in the socket queue
+        *      don't get lost.
+        */
+       for (last = &mainconfig.listen;
+            *last != NULL;
+            last = &((*last)->next)) {
+               if ((this->type == (*last)->type) &&
+                   (sock->port == ((listen_socket_t *)((*last)->data))->port) &&
+                   (sock->ipaddr.af == ((listen_socket_t *)((*last)->data))->ipaddr.af)) {
+                       int equal;
+
+                       if (sock->ipaddr.af == AF_INET) {
+                               equal = (sock->ipaddr.ipaddr.ip4addr.s_addr == ((listen_socket_t *)((*last)->data))->ipaddr.ipaddr.ip4addr.s_addr);
+                       } else if (sock->ipaddr.af == AF_INET6) {
+                               equal = IN6_ARE_ADDR_EQUAL(&(sock->ipaddr.ipaddr.ip6addr), &(((listen_socket_t *)((*last)->data))->ipaddr.ipaddr.ip6addr));
+                       } else {
+                               equal = 0;
+                       }
+                       
+                       if (equal) {
+                               this->rl = (*last)->rl;
+                               this->fd = (*last)->fd;
+                               (*last)->fd = -1;
+                               (*last)->rl = NULL;
+                               return 0;
+                       }
+               }
+       }
+
+       this->fd = lrad_socket(&sock->ipaddr, sock->port);
+       if (this->fd < 0) {
+               radlog(L_ERR|L_CONS, "ERROR: Failed to open socket: %s",
+                      librad_errstr);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/*
+ *     Allocate & initialize a new listener.
+ */
+static rad_listen_t *listen_alloc(RAD_LISTEN_TYPE type)
+{
+       rad_listen_t *this;
+
+       this = rad_malloc(sizeof(*this));
+       memset(this, 0, sizeof(*this));
+
+       this->type = type;
+       this->recv = master_listen[this->type].recv;
+       this->send = master_listen[this->type].send;
+       this->update = master_listen[this->type].update;
+       this->print = master_listen[this->type].print;
+
+       switch (type) {
+       case RAD_LISTEN_AUTH:
+       case RAD_LISTEN_ACCT:
+       case RAD_LISTEN_PROXY:
+               this->data = rad_malloc(sizeof(listen_socket_t));
+               memset(this->data, 0, sizeof(listen_socket_t));
+               break;
+
+       case RAD_LISTEN_DETAIL:
+               this->data = rad_malloc(sizeof(listen_detail_t));
+               memset(this->data, 0, sizeof(listen_detail_t));
+               
+       default:
+               break;
+       }
+
+       return this;
+}
+
+
+/*
+ *     Externally visible function for creating a new proxy LISTENER.
+ *
+ *     For now, don't take ipaddr or port.
+ *
+ *     Not thread-safe, but all calls to it are protected by the
+ *     proxy mutex in request_list.c
+ */
+rad_listen_t *proxy_new_listener()
+{
+       int last_proxy_port, port;
+       rad_listen_t *this, *tmp, **last;
+       listen_socket_t *sock, *old;
+
+       this = listen_alloc(RAD_LISTEN_PROXY);
+
+       /*
+        *      Find an existing proxy socket to copy.
+        *
+        *      FIXME: Make it per-realm, or per-home server!
+        */
+       last_proxy_port = 0;
+       old = NULL;
+       last = &mainconfig.listen;
+       for (tmp = mainconfig.listen; tmp != NULL; tmp = tmp->next) {
+               if (tmp->type == RAD_LISTEN_PROXY) {
+                       sock = tmp->data;
+                       if (sock->port > last_proxy_port) {
+                               last_proxy_port = sock->port + 1;
+                       }
+                       if (!old) old = sock;
+               }
+
+               last = &(tmp->next);
+       }
+
+       if (!old) return NULL;  /* This is a serious error. */
+
+       /*
+        *      FIXME: find a new IP address to listen on?
+        */
+       sock = this->data;
+       memcpy(&sock->ipaddr, &old->ipaddr, sizeof(sock->ipaddr));
+
+       /*
+        *      Keep going until we find an unused port.
+        */
+       for (port = last_proxy_port; port < 64000; port++) {
+               sock->port = port;
+               if (listen_bind(this) == 0) {
+                       /*
+                        *      Add the new listener to the list of
+                        *      listeners.
+                        */
+                       *last = this;
+                       return this;
+               }
+       }
+
+       return NULL;
+}
+
+
+static const LRAD_NAME_NUMBER listen_compare[] = {
+       { "auth",       RAD_LISTEN_AUTH },
+       { "acct",       RAD_LISTEN_ACCT },
+       { "detail",     RAD_LISTEN_DETAIL },
+       { NULL, 0 },
+};
+
+
+/*
+ *     Generate a list of listeners.  Takes an input list of
+ *     listeners, too, so we don't close sockets with waiting packets.
+ */
+int listen_init(const char *filename, rad_listen_t **head)
+{
+       int             rcode;
+       CONF_SECTION    *cs;
+       rad_listen_t    **last;
+       rad_listen_t    *this;
+       lrad_ipaddr_t   server_ipaddr;
+       int             auth_port = 0;
+
+       /*
+        *      We shouldn't be called with a pre-existing list.
+        */
+       rad_assert(head && (*head == NULL));
+       
+       if (start_time != 0) start_time = time(NULL);
+
+       last = head;
+       server_ipaddr.af = AF_UNSPEC;
+
+       /*
+        *      If the port is specified on the command-line,
+        *      it over-rides the configuration file.
+        */
+       if (mainconfig.port >= 0) {
+               auth_port = mainconfig.port;
+       } else {
+               rcode = cf_item_parse(mainconfig.config, "port",
+                                     PW_TYPE_INTEGER, &auth_port,
+                                     Stringify(PW_AUTH_UDP_PORT));
+               if (rcode < 0) return -1; /* error parsing it */
+
+               if (rcode == 0)
+                       radlog(L_INFO, "WARNING: The directive 'port' is deprecated, and will be removed in future versions of FreeRADIUS. Please edit the configuration files to use the directive 'listen'.");
+       }
+
+       /*
+        *      If the IP address was configured on the command-line,
+        *      use that as the "bind_address"
+        */
+       if (mainconfig.myip.af != AF_UNSPEC) {
+               memcpy(&server_ipaddr, &mainconfig.myip,
+                      sizeof(server_ipaddr));
+               goto bind_it;
+       }
+
+       /*
+        *      Else look for bind_address and/or listen sections.
+        */
+       server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
+       rcode = cf_item_parse(mainconfig.config, "bind_address",
+                             PW_TYPE_IPADDR,
+                             &server_ipaddr.ipaddr.ip4addr, NULL);
+       if (rcode < 0) return -1; /* error parsing it */
+       
+       if (rcode == 0) { /* successfully parsed IPv4 */
+               listen_socket_t *sock;
+               server_ipaddr.af = AF_INET;
+
+               radlog(L_INFO, "WARNING: The directive 'bind_adress' is deprecated, and will be removed in future versions of FreeRADIUS. Please edit the configuration files to use the directive 'listen'.");
+
+       bind_it:
+               this = listen_alloc(RAD_LISTEN_AUTH);
+               sock = this->data;
+
+               sock->ipaddr = server_ipaddr;
+               sock->port = auth_port;
+               
+               if (listen_bind(this) < 0) {
+                       listen_free(&this);
+                       listen_free(head);
+                       radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the authentication port %d", sock->port);
+                       return -1;
+               }
+               auth_port = sock->port; /* may have been updated in listen_bind */
+               *last = this;
+               last = &(this->next);
+               
+               /*
+                *      Open Accounting Socket.
+                *
+                *      If we haven't already gotten acct_port from
+                *      /etc/services, then make it auth_port + 1.
+                */
+               this = listen_alloc(RAD_LISTEN_ACCT);
+               sock = this->data;
+               
+               /*
+                *      Create the accounting socket.
+                *
+                *      The accounting port is always the
+                *      authentication port + 1
+                */
+               sock->ipaddr = server_ipaddr;
+               sock->port = auth_port + 1;
+               
+               if (listen_bind(this) < 0) {
+                       listen_free(&this);
+                       listen_free(head);
+                       radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the accounting port %d", sock->port);
+                       return -1;
+               }
+
+               *last = this;
+               last = &(this->next);
+
+       } else if (mainconfig.port > 0) { /* no bind address, but a port */
+               radlog(L_CONS|L_ERR, "The command-line says \"-p %d\", but there is no associated IP address to use",
+                      mainconfig.port);
+               return -1;
+       }
+
+       /*
+        *      They specified an IP on the command-line, ignore
+        *      all listen sections.
+        */
+       if (mainconfig.myip.af != AF_UNSPEC) goto do_proxy;
+
+       /*
+        *      Walk through the "listen" sections, if they exist.
+        */
+       for (cs = cf_subsection_find_next(mainconfig.config, NULL, "listen");
+            cs != NULL;
+            cs = cf_subsection_find_next(mainconfig.config, cs, "listen")) {
+               int             type;
+               char            *listen_type, *identity;
+               int             lineno = cf_section_lineno(cs);
+
+               listen_type = identity = NULL;
+               
+               rcode = cf_item_parse(cs, "type", PW_TYPE_STRING_PTR,
+                                     &listen_type, "");
+               if (rcode < 0) return -1;
+               if (rcode == 1) {
+                       listen_free(head);
+                       free(listen_type);
+                       radlog(L_ERR, "%s[%d]: No type specified in listen section",
+                              filename, lineno);
+                       return -1;
+               }
+
+               /*
+                *      See if there's an identity.
+                */
+               rcode = cf_item_parse(cs, "identity", PW_TYPE_STRING_PTR,
+                                     &identity, NULL);
+               if (rcode < 0) {
+                       listen_free(head);
+                       free(identity);
+                       return -1;
+               }
+
+               type = lrad_str2int(listen_compare, listen_type,
+                                   RAD_LISTEN_NONE);
+               free(listen_type);
+               if (type == RAD_LISTEN_NONE) {
+                       listen_free(head);
+                       radlog(L_CONS|L_ERR, "%s[%d]: Invalid type in listen section.",
+                              filename, lineno);
+                       return -1;
+               }
+
+               /*
+                *      Set up cross-type data.
+                */
+               this = listen_alloc(type);
+               this->identity = identity;
+               this->fd = -1;
+               
+               /*
+                *      Call per-type parser.
+                */
+               if (master_listen[type].parse(filename, lineno,
+                                             cs, this) < 0) {
+                       listen_free(&this);
+                       listen_free(head);
+                       return -1;
+               }
+
+               *last = this;
+               last = &(this->next);   
+       }
+
+       /*
+        *      If we're proxying requests, open the proxy FD.
+        *      Otherwise, don't do anything.
+        */
+ do_proxy:
+       if (mainconfig.proxy_requests == TRUE) {
+               int             port = -1;
+               listen_socket_t *sock = NULL;
+
+               /*
+                *      No sockets to receive packets, therefore
+                *      proxying is pointless.
+                */
+               if (!*head) return -1;
+
+               /*
+                *      If we previously had proxy sockets, copy them
+                *      to the new config.
+                */
+               if (mainconfig.listen != NULL) {
+                       rad_listen_t *old, *next, **tail;
+
+                       tail = &mainconfig.listen;
+                       for (old = mainconfig.listen;
+                            old != NULL;
+                            old = next) {
+                               next = old->next;
+
+                               if (old->type != RAD_LISTEN_PROXY) {
+                                       tail = &((*tail)->next);
+                                       continue;
+                               }
+
+                               *last = old;
+                               *tail = next;
+                               old->next = NULL;
+                               last = &(old->next);
+                       }
+
+                       goto done;
+               }
+
+               /*
+                *      Find the first authentication port,
+                *      and use it
+                */
+               for (this = *head; this != NULL; this = this->next) {
+                       if (this->type == RAD_LISTEN_AUTH) {
+                               sock = this->data;
+                               if (server_ipaddr.af == AF_UNSPEC) {
+                                       server_ipaddr = sock->ipaddr;
+                               }
+                               port = sock->port + 2; /* skip acct port */
+                               break;
+                       }
+               }
+
+               if (port < 0) port = 1024 + (lrad_rand() & 0x1ff);
+
+               /*
+                *      Address is still unspecified, use IPv4.
+                */
+               if (server_ipaddr.af == AF_UNSPEC) {
+                       server_ipaddr.af = AF_INET;
+                       server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
+               }
+
+               this = listen_alloc(RAD_LISTEN_PROXY);
+               sock = this->data;
+
+               /*
+                *      Create the first proxy socket.
+                */
+               sock->ipaddr = server_ipaddr;
+
+               /*
+                *      Try to find a proxy port (value doesn't matter)
+                */
+               for (sock->port = port;
+                    sock->port < 64000;
+                    sock->port++) {
+                       if (listen_bind(this) == 0) {
+                               *last = this;
+                               last = &(this->next); /* just in case */
+                               break;
+                       }
+               }
+
+               if (sock->port >= 64000) {
+                       listen_free(head);
+                       listen_free(&this);
+                       radlog(L_ERR|L_CONS, "Failed to open socket for proxying");
+                       return -1;
+               }
+       }
+
+       /*
+        *      Sanity check the configuration.
+        */
+       rcode = 0;
+       for (this = *head; this != NULL; this = this->next) {
+               if ((this->type != RAD_LISTEN_PROXY) &&
+                   !this->rl) {
+                       /*
+                        *      FIXME: Pass type to rl_init, so that
+                        *      it knows how to deal with accounting
+                        *      packets.  i.e. it caches them, but
+                        *      doesn't bother trying to re-transmit.
+                        */
+                       this->rl = rl_init();
+                       if (!this->rl) {
+                               rad_assert(0 == 1); /* FIXME: */
+                       }
+               }
+
+               if (((this->type == RAD_LISTEN_ACCT) &&
+                    (rcode == RAD_LISTEN_DETAIL)) ||
+                   ((this->type == RAD_LISTEN_DETAIL) &&
+                    (rcode == RAD_LISTEN_ACCT))) {
+                       rad_assert(0 == 1); /* FIXME: configuration error */
+               }
+
+               if (rcode != 0) continue;
+
+               if ((this->type == RAD_LISTEN_ACCT) ||
+                   (this->type == RAD_LISTEN_DETAIL)) {
+                       rcode = this->type;
+               }
+       }
+
+ done:
+       return 0;
+}
+
+/*
+ *     Free a linked list of listeners;
+ */
+void listen_free(rad_listen_t **head)
+{
+       rad_listen_t *this;
+
+       if (!head || !*head) return;
+
+       this = *head;
+       while (this) {
+               rad_listen_t *next = this->next;
+               
+               free(this->identity);
+
+               rl_deinit(this->rl);
+
+               /*
+                *      Other code may have eaten the FD.
+                */
+               if (this->fd >= 0) close(this->fd);
+
+               if (master_listen[this->type].free) {
+                       master_listen[this->type].free(this);
+               }
+               free(this->data);
+               free(this);
+               
+               this = next;
+       }
+
+       *head = NULL;
+}
index eb50a2e..78fd893 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2001  The FreeRADIUS server project
+ * Copyright 2001,2006  The FreeRADIUS server project
  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  * Copyright 2001  Chad Miller <cmiller@surfsouth.com>
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdlib.h>
 #include <string.h>
-#include <stdarg.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <errno.h>
 
-#include "radiusd.h"
+#include <freeradius-devel/radiusd.h>
 
 #ifdef HAVE_SYSLOG_H
 #      include <syslog.h>
+/* keep track of whether we've run openlog() */
+static int openlog_run = 0;
 #endif
 
  /*
  * Logging facility names
  */
-static LRAD_NAME_NUMBER levels[] = {
+static const LRAD_NAME_NUMBER levels[] = {
        { ": Debug: ",          L_DBG   },
        { ": Auth: ",           L_AUTH  },
        { ": Proxy: ",          L_PROXY },
        { ": Info: ",           L_INFO  },
+       { ": Acct: ",           L_ACCT  },
        { ": Error: ",          L_ERR   },
        { NULL, 0 }
 };
@@ -59,10 +61,11 @@ static LRAD_NAME_NUMBER levels[] = {
  */
 int vradlog(int lvl, const char *fmt, va_list ap)
 {
-       FILE *msgfd = NULL;
+       int fd = mainconfig.radlog_fd;
+       FILE *fp = NULL;
        unsigned char *p;
        char buffer[8192];
-       int len;
+       int len, print_timestamp = 0;
 
        /*
         *      NOT debugging, and trying to log debug messages.
@@ -77,51 +80,73 @@ int vradlog(int lvl, const char *fmt, va_list ap)
         *      If we don't want any messages, then
         *      throw them away.
         */
-       if (radlog_dest == RADLOG_NULL) {
+       if (mainconfig.radlog_dest == RADLOG_NULL) {
                return 0;
        }
+       
+       /*
+        *      Don't print timestamps to syslog, it does that for us.
+        *      Don't print timestamps for low levels of debugging.
+        *
+        *      Print timestamps for non-debugging, and for high levels
+        *      of debugging.
+        */
+       if ((mainconfig.radlog_dest != RADLOG_SYSLOG) &&
+           (debug_flag != 1) && (debug_flag != 2)) {
+               print_timestamp = 1;
+       }
 
-       if (debug_flag
-           || (radlog_dest == RADLOG_STDOUT)
-           || (radlog_dir == NULL)) {
-               msgfd = stdout;
-
-       } else if (radlog_dest == RADLOG_STDERR) {
-               msgfd = stderr;
+       *buffer = '\0';
+       len = 0;
+       if (fd != -1) {
+               /*
+                *      Use it, rather than anything else.
+                */
 
-       } else if (radlog_dest != RADLOG_SYSLOG) {
+#ifdef HAVE_SYSLOG_H
+       } else if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
                /*
-                *      No log file set.  It must go to stdout.
+                *      Open run openlog() on the first log message
                 */
-               if (!mainconfig.log_file) {
-                       msgfd = stdout;
+               if(!openlog_run) {
+                       openlog(progname, LOG_PID, mainconfig.syslog_facility);
+                       openlog_run = 1;
+               }
+#endif
 
+       } else if (!mainconfig.log_file) {
+               /*
+                *      Errors go to stderr, in the hope that they will
+                *      be printed somewhere.
+                */
+               if (lvl & L_ERR) {
+                       fd = STDERR_FILENO;
+                       print_timestamp = 0;
+                       snprintf(buffer, sizeof(buffer), "%s: ", progname);
+                       len = strlen(buffer);
+               } else {
                        /*
-                        *      Else try to open the file.
+                        *      No log file set.  Discard it.
                         */
-               } else if ((msgfd = fopen(mainconfig.log_file, "a")) == NULL) {
-                        fprintf(stderr, "%s: Couldn't open %s for logging: %s\n",
-                                progname, mainconfig.log_file, strerror(errno));
-
-                        fprintf(stderr, "  (");
-                        vfprintf(stderr, fmt, ap);  /* the message that caused the log */
-                        fprintf(stderr, ")\n");
-                        return -1;
+                       return 0;
                }
+
+       } else if ((fp = fopen(mainconfig.log_file, "a")) == NULL) {
+               fprintf(stderr, "%s: Couldn't open %s for logging: %s\n",
+                       progname, mainconfig.log_file, strerror(errno));
+               
+               fprintf(stderr, "  (");
+               vfprintf(stderr, fmt, ap);  /* the message that caused the log */
+               fprintf(stderr, ")\n");
+               return -1;
        }
 
-#ifdef HAVE_SYSLOG_H
-       if (radlog_dest == RADLOG_SYSLOG) {
-               *buffer = '\0';
-               len = 0;
-       } else
-#endif
-       {
+       if (print_timestamp) {
                const char *s;
                time_t timeval;
 
                timeval = time(NULL);
-               CTIME_R(&timeval, buffer, 8192);
+               CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
 
                s = lrad_int2str(levels, (lvl & ~L_CONS), ": ");
 
@@ -129,14 +154,7 @@ int vradlog(int lvl, const char *fmt, va_list ap)
                len = strlen(buffer);
        }
 
-#ifdef HAVE_VSNPRINTF
-       vsnprintf(buffer + len, sizeof(buffer) - len -1, fmt, ap);
-#else
-       vsprintf(buffer + len, fmt, ap);
-       if (strlen(buffer) >= sizeof(buffer) - 1)
-               /* What can we do? */
-               _exit(42);
-#endif
+       vsnprintf(buffer + len, sizeof(buffer) - len - 1, fmt, ap);
 
        /*
         *      Filter out characters not in Latin-1.
@@ -144,41 +162,14 @@ int vradlog(int lvl, const char *fmt, va_list ap)
        for (p = (unsigned char *)buffer; *p != '\0'; p++) {
                if (*p == '\r' || *p == '\n')
                        *p = ' ';
+               else if (*p == '\t') continue;
                else if (*p < 32 || (*p >= 128 && *p <= 160))
                        *p = '?';
        }
        strcat(buffer, "\n");
 
-       /*
-        *   If we're debugging, for small values of debug, then
-        *   we don't do timestamps.
-        */
-       if ((debug_flag == 1) || (debug_flag == 2)) {
-               p = buffer + len;
-
-       } else {
-               /*
-                *  No debugging, or lots of debugging.  Print
-                *  the time stamps.
-                */
-               p = buffer;
-       }
-
 #ifdef HAVE_SYSLOG_H
-       if (radlog_dest != RADLOG_SYSLOG)
-#endif
-       {
-               fputs(p, msgfd);
-               if (msgfd == stdout) {
-                       fflush(stdout);
-               } else if (msgfd == stderr) {
-                       fflush(stderr);
-               } else {
-                       fclose(msgfd);
-               }
-       }
-#ifdef HAVE_SYSLOG_H
-       else {                  /* it was syslog */
+       if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
                switch(lvl & ~L_CONS) {
                        case L_DBG:
                                lvl = LOG_DEBUG;
@@ -189,6 +180,9 @@ int vradlog(int lvl, const char *fmt, va_list ap)
                        case L_PROXY:
                                lvl = LOG_NOTICE;
                                break;
+                       case L_ACCT:
+                               lvl = LOG_NOTICE;
+                               break;
                        case L_INFO:
                                lvl = LOG_INFO;
                                break;
@@ -196,9 +190,16 @@ int vradlog(int lvl, const char *fmt, va_list ap)
                                lvl = LOG_ERR;
                                break;
                }
-               syslog(lvl, "%s", buffer + len); /* don't print timestamp */
-       }
+               syslog(lvl, "%s", buffer);
+       } else
 #endif
+       if (fp != NULL) {
+               fputs(buffer, fp);
+               fflush(fp);
+               fclose(fp);
+       } else if (fd >= 0) {
+               write(fd, buffer, strlen(buffer));
+       }
 
        return 0;
 }
index da70058..34d9628 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2002  The FreeRADIUS server project
+ * Copyright 2002,2006-2007  The FreeRADIUS server project
  * Copyright 2002  Alan DeKok <aland@ox.org>
  */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdlib.h>
 #include <string.h>
 #include <arpa/inet.h>
 #endif
 
-#include "radiusd.h"
-#include "rad_assert.h"
-#include "conffile.h"
-#include "token.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/request_list.h>
 
 #include <sys/resource.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
 #include <netdb.h>
 #include <sys/stat.h>
 #include <grp.h>
 #include <pwd.h>
 
-#ifdef HAVE_SYS_PRCTL_H
+#ifdef HAVE_SYS_PRTCL_H
 #include <sys/prctl.h>
 #endif
 
-#ifdef WITH_UDPFROMTO
-#include "udpfromto.h"
+#ifdef HAVE_SYSLOG_H
+#      include <syslog.h>
 #endif
 
-
 struct main_config_t mainconfig;
 
 /*
- *  Local variables for stuff.
+ *     Temporary local variables for parsing the configuration
+ *     file.
  */
 static uid_t server_uid;
 static gid_t server_gid;
@@ -71,36 +70,106 @@ static gid_t server_gid;
  */
 static const char *localstatedir = NULL;
 static const char *prefix = NULL;
-static int auth_port = 0;
+static char *syslog_facility = NULL;
+static const LRAD_NAME_NUMBER str2fac[] = {
+#ifdef LOG_KERN
+       { "kern", LOG_KERN },
+#endif 
+#ifdef LOG_USER
+       { "user", LOG_USER },
+#endif
+#ifdef LOG_MAIL
+       { "mail", LOG_MAIL },
+#endif
+#ifdef LOG_DAEMON
+       { "daemon", LOG_DAEMON },
+#endif
+#ifdef LOG_AUTH
+       { "auth", LOG_AUTH },
+#endif
+#ifdef LOG_LPR
+       { "lpr", LOG_LPR },
+#endif
+#ifdef LOG_NEWS
+       { "news", LOG_NEWS },
+#endif
+#ifdef LOG_UUCP
+       { "uucp", LOG_UUCP },
+#endif
+#ifdef LOG_CRON
+       { "cron", LOG_CRON },
+#endif
+#ifdef LOG_AUTHPRIV
+       { "authpriv", LOG_AUTHPRIV },
+#endif
+#ifdef LOG_FTP
+       { "ftp", LOG_FTP },
+#endif
+#ifdef LOG_LOCAL0
+       { "local0", LOG_LOCAL0 },
+#endif
+#ifdef LOG_LOCAL1
+       { "local1", LOG_LOCAL1 },
+#endif
+#ifdef LOG_LOCAL2
+       { "local2", LOG_LOCAL2 },
+#endif
+#ifdef LOG_LOCAL3
+       { "local3", LOG_LOCAL3 },
+#endif
+#ifdef LOG_LOCAL4
+       { "local4", LOG_LOCAL4 },
+#endif
+#ifdef LOG_LOCAL5
+       { "local5", LOG_LOCAL5 },
+#endif
+#ifdef LOG_LOCAL6
+       { "local6", LOG_LOCAL6 },
+#endif
+#ifdef LOG_LOCAL7
+       { "local7", LOG_LOCAL7 },
+#endif
+       { NULL, -1 }
+};
 
 /*
  *  Map the proxy server configuration parameters to variables.
  */
-static CONF_PARSER proxy_config[] = {
+static const CONF_PARSER proxy_config[] = {
        { "retry_delay",  PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_delay, Stringify(RETRY_DELAY) },
        { "retry_count",  PW_TYPE_INTEGER, 0, &mainconfig.proxy_retry_count, Stringify(RETRY_COUNT) },
-       { "synchronous",  PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_synchronous, "no" },
        { "default_fallback", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_fallback, "no" },
        { "dead_time",    PW_TYPE_INTEGER, 0, &mainconfig.proxy_dead_time, Stringify(DEAD_TIME) },
-        { "post_proxy_authorize", PW_TYPE_BOOLEAN, 0, &mainconfig.post_proxy_authorize, "yes" },
        { "wake_all_if_all_dead", PW_TYPE_BOOLEAN, 0, &mainconfig.wake_all_if_all_dead, "no" },
+       { "proxy_fail_type", PW_TYPE_STRING_PTR, 0, &mainconfig.proxy_fail_type, NULL},
        { NULL, -1, 0, NULL, NULL }
 };
 
+
 /*
  *  Security configuration for the server.
  */
-static CONF_PARSER security_config[] = {
+static const CONF_PARSER security_config[] = {
        { "max_attributes",  PW_TYPE_INTEGER, 0, &librad_max_attributes, Stringify(0) },
        { "reject_delay",  PW_TYPE_INTEGER, 0, &mainconfig.reject_delay, Stringify(0) },
        { "status_server", PW_TYPE_BOOLEAN, 0, &mainconfig.status_server, "no"},
        { NULL, -1, 0, NULL, NULL }
 };
 
+
+/*
+ *  syslog configuration for the server.
+ */
+static const CONF_PARSER log_config[] = {
+       { "syslog_facility",  PW_TYPE_STRING_PTR, 0, &syslog_facility, Stringify(0) },
+       { NULL, -1, 0, NULL, NULL }
+};
+
+
 /*
  *  A mapping of configuration file names to internal variables
  */
-static CONF_PARSER server_config[] = {
+static const CONF_PARSER server_config[] = {
        /*
         *      FIXME: 'prefix' is the ONLY one which should be
         *      configured at compile time.  Hard-coding it here is
@@ -120,31 +189,32 @@ static CONF_PARSER server_config[] = {
        { "max_request_time", PW_TYPE_INTEGER, 0, &mainconfig.max_request_time, Stringify(MAX_REQUEST_TIME) },
        { "cleanup_delay", PW_TYPE_INTEGER, 0, &mainconfig.cleanup_delay, Stringify(CLEANUP_DELAY) },
        { "max_requests", PW_TYPE_INTEGER, 0, &mainconfig.max_requests, Stringify(MAX_REQUESTS) },
+#ifdef DELETE_BLOCKED_REQUESTS
        { "delete_blocked_requests", PW_TYPE_INTEGER, 0, &mainconfig.kill_unresponsive_children, Stringify(FALSE) },
-       { "port", PW_TYPE_INTEGER, 0, &auth_port, Stringify(PW_AUTH_UDP_PORT) },
+#endif
        { "allow_core_dumps", PW_TYPE_BOOLEAN, 0, &mainconfig.allow_core_dumps, "no" },
        { "log_stripped_names", PW_TYPE_BOOLEAN, 0, &log_stripped_names,"no" },
+
        { "log_file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, "${logdir}/radius.log" },
        { "log_auth", PW_TYPE_BOOLEAN, -1, &mainconfig.log_auth, "no" },
        { "log_auth_badpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_badpass, "no" },
        { "log_auth_goodpass", PW_TYPE_BOOLEAN, 0, &mainconfig.log_auth_goodpass, "no" },
        { "pidfile", PW_TYPE_STRING_PTR, 0, &mainconfig.pid_file, "${run_dir}/radiusd.pid"},
-       { "bind_address", PW_TYPE_IPADDR, 0, &mainconfig.myip, "*" },
        { "user", PW_TYPE_STRING_PTR, 0, &mainconfig.uid_name, NULL},
        { "group", PW_TYPE_STRING_PTR, 0, &mainconfig.gid_name, NULL},
-       { "usercollide", PW_TYPE_BOOLEAN, 0, &mainconfig.do_usercollide,  "no" },
-       { "lower_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_user, "no" },
-       { "lower_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_lower_pass, "no" },
-       { "nospace_user", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_user, "no" },
-       { "nospace_pass", PW_TYPE_STRING_PTR, 0, &mainconfig.do_nospace_pass, "no" },
        { "checkrad", PW_TYPE_STRING_PTR, 0, &mainconfig.checkrad, "${sbindir}/checkrad" },
-       { "proxy_requests", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_requests, "yes" },
-       { "proxy", PW_TYPE_SUBSECTION, 0, proxy_config, NULL },
-       { "security", PW_TYPE_SUBSECTION, 0, security_config, NULL },
+
        { "debug_level", PW_TYPE_INTEGER, 0, &mainconfig.debug_level, "0"},
+
+       { "proxy_requests", PW_TYPE_BOOLEAN, 0, &mainconfig.proxy_requests, "yes" },
+       { "log", PW_TYPE_SUBSECTION, 0, NULL,  (const void *) log_config},
+       { "proxy", PW_TYPE_SUBSECTION, 0, NULL, (const void *) proxy_config },
+       { "security", PW_TYPE_SUBSECTION, 0, NULL, (const void *) security_config },
        { NULL, -1, 0, NULL, NULL }
 };
 
+
+#define MAX_ARGV (256)
 /*
  *     Xlat for %{config:section.subsection.attribute}
  */
@@ -155,9 +225,12 @@ static int xlat_config(void *instance, REQUEST *request,
 {
        CONF_SECTION *cs;
        CONF_PAIR *cp;
-       char buffer[1024];
-       char *p, *value;
-       const char *start = fmt;
+       int i, argc, left;
+       const char *from, *value;
+       char *to;
+       char myfmt[1024];
+       char argv_buf[1024];
+       char *argv[MAX_ARGV];
 
        request = request;      /* -Wunused */
        instance = instance;    /* -Wunused */
@@ -165,44 +238,176 @@ static int xlat_config(void *instance, REQUEST *request,
        cp = NULL;
        cs = NULL;
 
-       while (cp == NULL) {
+       /*
+        *      Split the string into argv's BEFORE doing radius_xlat...
+        *      Copied from exec.c
+        */
+       from = fmt;
+       to = myfmt; 
+       argc = 0;
+       while (*from) {
+               int flag, length;
+               
+               flag = 0;
+               argv[argc] = to;
+               argc++;
+               
+               if (argc >= (MAX_ARGV - 1)) break;
+               
                /*
-                *      Find the next section.
+                *      Copy the argv over to our buffer.
                 */
-               for (p = buffer; (*fmt != 0) && (*fmt != '.'); p++, fmt++) {
-                       *p = *fmt;
+               while (*from) {
+                       if (to >= myfmt + sizeof(myfmt) - 1) {
+                               return 0; /* no error msg */
+                       }
+
+                       switch (*from) {
+                       case '%':
+                               if (from[1] == '{') {
+                                       *(to++) = *(from++);
+                                       
+                                       length = rad_copy_variable(to, from);
+                                       if (length < 0) {
+                                               return -1;
+                                       }
+                                       from += length;
+                                       to += length;
+                               } else { /* FIXME: catch %%{ ? */
+                                       *(to++) = *(from++);
+                               }
+                               break;
+
+                       case '[':
+                               if (flag != 0) {
+                                       radlog(L_ERR, "config: Unexpected nested '[' in \"%s\"", fmt);
+                                       return 0;
+                               }
+                               flag++;
+                               *(to++) = *(from++);
+                               break;
+
+                       case ']':
+                               if (flag == 0) {
+                                       radlog(L_ERR, "config: Unbalanced ']' in \"%s\"", fmt);
+                                       return 0;
+                               }
+                               if (from[1] != '.') {
+                                       radlog(L_ERR, "config: Unexpected text after ']' in \"%s\"", fmt);
+                                       return 0;
+                               }
+
+                               flag--;
+                               *(to++) = *(from++);
+                               break;
+
+                       case '.':
+                               if (flag == 0) break;
+                               /* FALL-THROUGH */
+
+                       default:
+                               *(to++) = *(from++);
+                               break;
+                       }
+
+                       if ((*from == '.') && (flag == 0)) {
+                               from++;
+                               break;
+                       }
+               } /* end of string, or found a period */
+
+               if (flag != 0) {
+                       radlog(L_ERR, "config: Unbalanced '[' in \"%s\"", fmt);
+                       return 0;
                }
-               *p = '\0';
+
+               *(to++) = '\0'; /* terminate the string. */
+       }
+
+       /*
+        *      Expand each string, as appropriate
+        */
+       to = argv_buf;
+       left = sizeof(argv_buf);
+       for (i = 0; i < argc; i++) {
+               int sublen;
 
                /*
-                *  The character is a '.', find a section (as the user
-                *  has given us a subsection to find)
+                *      Don't touch argv's which won't be translated.
                 */
-               if (*fmt == '.') {
-                       CONF_SECTION *next;
+               if (strchr(argv[i], '%') == NULL) continue;
+
+               sublen = radius_xlat(to, left - 1, argv[i], request, NULL);
+               if (sublen <= 0) {
+                       /*
+                        *      Fail to be backwards compatible.
+                        *
+                        *      It's yucky, but it won't break anything,
+                        *      and it won't cause security problems.
+                        */
+                       sublen = 0;
+               }
+               
+               argv[i] = to;
+               to += sublen;
+               *(to++) = '\0';
+               left -= sublen;
+               left--;
+
+               if (left <= 0) {
+                       return 0;
+               }
+       }
+       argv[argc] = NULL;
 
-                       fmt++;  /* skip the period */
+       cs = cf_section_find(NULL); /* get top-level section */
 
-                       if (cs == NULL) {
-                         next = cf_section_find(buffer);
-                       } else {
-                         next = cf_subsection_find_next(cs, NULL, buffer);
-                       }
-                       if (next == NULL) {
-                               radlog(L_ERR, "config: No such section %s in format string %s", buffer, start);
-                               return 0;
-                       }
-                       cs = next;
+       /*
+        *      Root through section & subsection references.
+        *      The last entry of argv MUST be the CONF_PAIR.
+        */
+       for (i = 0; i < argc - 1; i++) {
+               char *name2 = NULL;
+               CONF_SECTION *subcs;
 
-               } else {        /* no period, must be a conf-part */
-                       cp = cf_pair_find(cs, buffer);
+               /*
+                *      FIXME: What about RADIUS attributes containing '['?
+                */
+               name2 = strchr(argv[i], '[');
+               if (name2) {
+                       char *p = strchr(name2, ']');
+                       rad_assert(p != NULL);
+                       rad_assert(p[1] =='\0');
+                       *p = '\0';
+                       *name2 = '\0';
+                       name2++;
+               }
 
-                       if (cp == NULL) {
-                               radlog(L_ERR, "config: No such section %s in format string %s", buffer, start);
-                               return 0;
+               if (name2) {
+                       subcs = cf_section_sub_find_name2(cs, argv[i],
+                                                         name2);
+                       if (!subcs) {
+                         radlog(L_ERR, "config: section \"%s %s {}\" not found while dereferencing \"%s\"", argv[i], name2, fmt);
+                         return 0;
+                       }
+               } else {
+                       subcs = cf_section_sub_find(cs, argv[i]);
+                       if (!subcs) {
+                         radlog(L_ERR, "config: section \"%s {}\" not found while dereferencing \"%s\"", argv[i], fmt);
+                         return 0;
                        }
                }
-       } /* until cp is non-NULL */
+               cs = subcs;
+       } /* until argc - 1 */
+
+       /*
+        *      This can now have embedded periods in it.
+        */
+       cp = cf_pair_find(cs, argv[argc - 1]);
+       if (!cp) {
+               radlog(L_ERR, "config: item \"%s\" not found while dereferencing \"%s\"", argv[argc], fmt);
+               return 0;
+       }
 
        /*
         *  Ensure that we only copy what's necessary.
@@ -242,7 +447,7 @@ static int r_mkdir(const char *part)
                return(1);
 
        if (mkdir(part, 0770) != 0) {
-               fprintf(stderr, "mkdir(%s) error: %s\n", part, strerror(errno));
+               radlog(L_ERR, "mkdir(%s) error: %s\n", part, strerror(errno));
                return(1);
        }
 
@@ -256,7 +461,7 @@ static int radlogdir_iswritable(const char *effectiveuser)
 {
        struct passwd *pwent;
 
-       if (radlog_dir[0] != '/')
+       if (!radlog_dir || radlog_dir[0] != '/')
                return(0);
 
        if (r_mkdir(radlog_dir) != 0)
@@ -292,6 +497,8 @@ static int radlogdir_iswritable(const char *effectiveuser)
  */
 static int switch_users(void)
 {
+       struct rlimit core_limits;
+
        /*  Set GID.  */
        if (mainconfig.gid_name != NULL) {
                struct group *gr;
@@ -342,6 +549,64 @@ static int switch_users(void)
                        exit(1);
                }
        }
+
+       /*  Get the current maximum for core files.  */
+       if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
+               radlog(L_ERR|L_CONS, "Failed to get current core limit:  %s", strerror(errno));
+               exit(1);
+       }
+
+       if (mainconfig.allow_core_dumps) {
+#ifdef HAVE_SYS_PRTCL_H
+#ifdef PR_SET_DUMPABLE
+               if (prctl(PR_SET_DUMPABLE, 1) < 0) {
+                       radlog(L_ERR|L_CONS,"Cannot enable core dumps: prctl(PR_SET_DUMPABLE) failed: '%s'",
+                              strerror(errno));
+               }
+#endif
+#endif
+
+               if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
+                       radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
+                                       strerror(errno));
+                       exit(1);
+
+                       /*
+                        *  If we're running as a daemon, and core
+                        *  dumps are enabled, log that information.
+                        */
+               } else if ((core_limits.rlim_cur != 0) && !debug_flag)
+                       radlog(L_INFO|L_CONS, "Core dumps are enabled.");
+
+       } else if (!debug_flag) {
+               /*
+                *  Not debugging.  Set the core size to zero, to
+                *  prevent security breaches.  i.e. People
+                *  reading passwords from the 'core' file.
+                */
+               struct rlimit limits;
+
+               limits.rlim_cur = 0;
+               limits.rlim_max = core_limits.rlim_max;
+
+               if (setrlimit(RLIMIT_CORE, &limits) < 0) {
+                       radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
+                                       strerror(errno));
+                       exit(1);
+               }
+       }
+
+       /*
+        *      We've probably written to the log file already as
+        *      root.root, so if we have switched users, we've got to
+        *      update the ownership of the file.
+        */
+       if ((debug_flag == 0) &&
+           (mainconfig.radlog_dest == RADLOG_FILES) &&
+           (mainconfig.log_file != NULL)) {
+               chown(mainconfig.log_file, server_uid, server_gid);
+       }
+
        return(0);
 }
 
@@ -356,7 +621,7 @@ static int generate_realms(const char *filename)
        REALM *my_realms = NULL;
        REALM *c, **tail;
        char *s, *t, *authhost, *accthost;
-       char *name2;
+       const char *name2;
 
        tail = &my_realms;
        for (cs = cf_subsection_find_next(mainconfig.config, NULL, "realm");
@@ -380,7 +645,8 @@ static int generate_realms(const char *filename)
                 *      No authhost means LOCAL.
                 */
                if ((authhost = cf_section_value_find(cs, "authhost")) == NULL) {
-                       c->ipaddr = htonl(INADDR_NONE);
+                       c->ipaddr.af = AF_INET;
+                       c->ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
                        c->auth_port = 0;
                } else {
                        if ((s = strchr(authhost, ':')) != NULL) {
@@ -394,11 +660,12 @@ static int generate_realms(const char *filename)
                                 *      Local realms don't have an IP address,
                                 *      secret, or port.
                                 */
-                               c->ipaddr = htonl(INADDR_NONE);
+                               c->ipaddr.af = AF_INET;
+                               c->ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
                                c->auth_port = 0;
                        } else {
-                               c->ipaddr = ip_getaddr(authhost);
-                               if (c->ipaddr == htonl(INADDR_NONE)) {
+                               if (ip_hton(authhost, AF_INET,
+                                           &c->ipaddr) < 0) {
                                        radlog(L_ERR, "%s[%d]: Host %s not found",
                                               filename, cf_section_lineno(cs),
                                               authhost);
@@ -410,10 +677,10 @@ static int generate_realms(const char *filename)
                         * Double check length, just to be sure!
                         */
                        if (strlen(authhost) >= sizeof(c->server)) {
-                               radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
+                               radlog(L_ERR, "%s[%d]: Server name of length %u is greater than allowed: %u",
                                       filename, cf_section_lineno(cs),
-                                      (int) strlen(authhost),
-                                      (int) sizeof(c->server) - 1);
+                                      strlen(authhost),
+                                      sizeof(c->server) - 1);
                                return -1;
                        }
                }
@@ -422,7 +689,8 @@ static int generate_realms(const char *filename)
                 *      No accthost means LOCAL
                 */
                if ((accthost = cf_section_value_find(cs, "accthost")) == NULL) {
-                       c->acct_ipaddr = htonl(INADDR_NONE);
+                       c->acct_ipaddr.af = AF_INET;
+                       c->acct_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
                        c->acct_port = 0;
                } else {
                        if ((s = strchr(accthost, ':')) != NULL) {
@@ -436,11 +704,12 @@ static int generate_realms(const char *filename)
                                 *      Local realms don't have an IP address,
                                 *      secret, or port.
                                 */
-                               c->acct_ipaddr = htonl(INADDR_NONE);
+                               c->acct_ipaddr.af = AF_INET;
+                               c->acct_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_NONE);
                                c->acct_port = 0;
                        } else {
-                               c->acct_ipaddr = ip_getaddr(accthost);
-                               if (c->acct_ipaddr == htonl(INADDR_NONE)) {
+                               if (ip_hton(accthost, AF_INET,
+                                           &c->acct_ipaddr) < 0) {
                                        radlog(L_ERR, "%s[%d]: Host %s not found",
                                               filename, cf_section_lineno(cs),
                                               accthost);
@@ -449,19 +718,19 @@ static int generate_realms(const char *filename)
                        }
 
                        if (strlen(accthost) >= sizeof(c->acct_server)) {
-                               radlog(L_ERR, "%s[%d]: Server name of length %d is greater than allowed: %d",
+                               radlog(L_ERR, "%s[%d]: Server name of length %u is greater than allowed: %u",
                                       filename, cf_section_lineno(cs),
-                                      (int) strlen(accthost),
-                                      (int) sizeof(c->acct_server) - 1);
+                                      strlen(accthost),
+                                      sizeof(c->acct_server) - 1);
                                return -1;
                        }
                }
 
                if (strlen(name2) >= sizeof(c->realm)) {
-                       radlog(L_ERR, "%s[%d]: Realm name of length %d is greater than allowed %d",
+                       radlog(L_ERR, "%s[%d]: Realm name of length %u is greater than allowed %u",
                               filename, cf_section_lineno(cs),
-                              (int) strlen(name2),
-                              (int) sizeof(c->server) - 1);
+                              strlen(name2),
+                              sizeof(c->server) - 1);
                        return -1;
                }
 
@@ -474,8 +743,10 @@ static int generate_realms(const char *filename)
                 *      servers is set to LOCALHOST, then don't require
                 *      a shared secret.
                 */
-               if ((c->ipaddr != htonl(INADDR_NONE)) ||
-                   (c->acct_ipaddr != htonl(INADDR_NONE))) {
+               rad_assert(c->ipaddr.af == AF_INET);
+               rad_assert(c->acct_ipaddr.af == AF_INET);
+               if ((c->ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_NONE)) ||
+                   (c->acct_ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_NONE))) {
                        if ((s = cf_section_value_find(cs, "secret")) == NULL ) {
                                radlog(L_ERR, "%s[%d]: No shared secret supplied for realm: %s",
                                       filename, cf_section_lineno(cs), name2);
@@ -488,7 +759,7 @@ static int generate_realms(const char *filename)
                                       strlen(s), sizeof(c->secret) - 1);
                                return -1;
                        }
-                       strNcpy((char *)c->secret, s, sizeof(c->secret));
+                       strlcpy((char *)c->secret, s, sizeof(c->secret));
                }
 
                c->striprealm = 1;
@@ -549,9 +820,11 @@ static int generate_realms(const char *filename)
                 *      Check that we cannot load balance to LOCAL
                 *      realms, as that doesn't make any sense.
                 */
+               rad_assert(c->ipaddr.af == AF_INET);
+               rad_assert(c->acct_ipaddr.af == AF_INET);
                if ((c->ldflag == 1) &&
-                   ((c->ipaddr == htonl(INADDR_NONE)) ||
-                    (c->acct_ipaddr == htonl(INADDR_NONE)))) {
+                   ((c->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)) ||
+                    (c->acct_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)))) {
                        radlog(L_ERR | L_CONS, "ERROR: Realm %s cannot be load balanced to LOCAL",
                               c->realm);
                        exit(1);
@@ -582,726 +855,163 @@ static int generate_realms(const char *filename)
 }
 
 
+static const LRAD_NAME_NUMBER str2dest[] = {
+       { "null", RADLOG_NULL },
+       { "files", RADLOG_FILES },
+       { "syslog", RADLOG_SYSLOG },
+       { "stdout", RADLOG_STDOUT },
+       { "stderr", RADLOG_STDERR },
+       { NULL, RADLOG_NUM_DEST }
+};
+
+
 /*
- *     Create the linked list of realms from the new configuration
- *     type.  This way we don't have to change too much in the other
- *     source-files.
+ *     Read config files.
+ *
+ *     This function can ONLY be called from the main server process.
  */
-static RADCLIENT *generate_clients(const char *filename, CONF_SECTION *section)
+int read_mainconfig(int reload)
 {
-       CONF_SECTION    *cs;
-       RADCLIENT       *list, *c;
-       char            *hostnm, *secret, *shortnm, *netmask;
-       char            *nastype, *login, *password;
-       char            *name2;
-
-       list = NULL;
-       for (cs = cf_subsection_find_next(section, NULL, "client");
-            cs != NULL;
-            cs = cf_subsection_find_next(section, cs, "client")) {
-
-               name2 = cf_section_name2(cs);
-               if (!name2) {
-                       radlog(L_CONS|L_ERR, "%s[%d]: Missing client name",
-                              filename, cf_section_lineno(cs));
-                       clients_free(list);
-                       return NULL;
-               }
-               /*
-                * Check the lengths, we don't want any core dumps
-                */
-               hostnm = name2;
-
-               if((secret = cf_section_value_find(cs, "secret")) == NULL) {
-                       radlog(L_ERR, "%s[%d]: Missing secret for client: %s",
-                               filename, cf_section_lineno(cs), name2);
-                       clients_free(list);
-                       return NULL;
-               }
-
-               if((shortnm = cf_section_value_find(cs, "shortname")) == NULL) {
-                       radlog(L_ERR, "%s[%d]: Missing shortname for client: %s",
-                               filename, cf_section_lineno(cs), name2);
-                       clients_free(list);
-                       return NULL;
-               }
+       static int old_debug_level = -1;
+       char buffer[1024];
+       CONF_SECTION *cs, *oldcs;
+       rad_listen_t *listener;
+       struct stat statbuf;
 
-               netmask = strchr(hostnm, '/');
+       if (stat(radius_dir, &statbuf) < 0) {
+               radlog(L_ERR|L_CONS, "Errors reading %s: %s",
+                      radius_dir, strerror(errno));
+               return -1;
+       }
 
-               if (strlen(secret) >= sizeof(c->secret)) {
-                       radlog(L_ERR, "%s[%d]: Secret of length %u is greater than the allowed maximum of %u.",
-                               filename, cf_section_lineno(cs),
-                               strlen(secret), sizeof(c->secret) - 1);
-                       clients_free(list);
-                       return NULL;
-               }
+       if ((statbuf.st_mode & S_IWOTH) != 0) {
+               radlog(L_ERR|L_CONS, "Configuration directory %s is globally writable.  Refusing to start due to insecure configuration.",
+                      radius_dir);
+         return -1;
+       }
 
-               if (strlen(shortnm) > sizeof(c->shortname)) {
-                       radlog(L_ERR, "%s[%d]: Client short name of length %u is greater than the allowed maximum of %u.",
-                                       filename, cf_section_lineno(cs),
-                              strlen(shortnm), sizeof(c->shortname) - 1);
-                       clients_free(list);
-                       return NULL;
-               }
 
-               if((nastype = cf_section_value_find(cs, "nastype")) != NULL) {
-                       if(strlen(nastype) >= sizeof(c->nastype)) {
-                              radlog(L_ERR, "%s[%d]: nastype of length %u longer than the allowed maximum of %u",
-                                     filename, cf_section_lineno(cs),
-                                     strlen(nastype), sizeof(c->nastype) - 1);
-                              clients_free(list);
-                              return NULL;
-                       }
-               }
+       if (0 && (statbuf.st_mode & S_IROTH) != 0) {
+               radlog(L_ERR|L_CONS, "Configuration directory %s is globally readable.  Refusing to start due to insecure configuration.",
+                      radius_dir);
+               return -1;
+       }
 
-               if((login = cf_section_value_find(cs, "login")) != NULL) {
-                       if(strlen(login) >= sizeof(c->login)) {
-                              radlog(L_ERR, "%s[%d]: login of length %u longer than the allowed maximum of %u",
-                                     filename, cf_section_lineno(cs),
-                                     strlen(login), sizeof(c->login) - 1);
-                              clients_free(list);
-                              return NULL;
-                       }
-               }
+       /* Read the configuration file */
+       snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
+                radius_dir, mainconfig.radiusd_conf);
+       if ((cs = cf_file_read(buffer)) == NULL) {
+               radlog(L_ERR|L_CONS, "Errors reading %s", buffer);
+               return -1;
+       }
 
-               if((password = cf_section_value_find(cs, "password")) != NULL) {
-                       if(strlen(password) >= sizeof(c->password)) {
-                              radlog(L_ERR, "%s[%d]: password of length %u longer than the allowed maximum of %u",
-                                     filename, cf_section_lineno(cs),
-                                     strlen(password), sizeof(c->password) - 1);
-                              clients_free(list);
-                              return NULL;
-                       }
+       /*
+        *      Debug flag 1 MAY go to files.
+        *      Debug flag 2 ALWAYS goes to stdout
+        *
+        *      Parse the log_destination before printing anything else.
+        *      All messages before this MUST be errors, which log.c
+        *      will print to stderr, since log_file is NULL, too.
+        */
+       if (debug_flag < 2) {
+               int rcode;
+               char *radlog_dest = NULL;
+
+               rcode = cf_item_parse(cs, "log_destination",
+                                     PW_TYPE_STRING_PTR, &radlog_dest,
+                                     "files");
+               if (rcode < 0) return -1;
+       
+               mainconfig.radlog_dest = lrad_str2int(str2dest, radlog_dest, RADLOG_NUM_DEST);
+               if (mainconfig.radlog_dest == RADLOG_NUM_DEST) {
+                       fprintf(stderr, "radiusd: Error: Unknown log_destination %s\n",
+                               radlog_dest);
+                       free(radlog_dest);
+                       cf_section_free(&cs);
+                       return -1;
                }
+               
+               if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
+                       static const CONF_PARSER syslog_config[] = {
+                               { "log", PW_TYPE_SUBSECTION, 0, NULL,  (const void *) log_config},
+                               { NULL, -1, 0, NULL, NULL }
+                       };
+                       cf_section_parse(cs, NULL, syslog_config);
 
-               /*
-                * The size is fine.. Let's create the buffer
-                */
-               c = rad_malloc(sizeof(RADCLIENT));
-               memset(c, 0, sizeof(RADCLIENT));
-
-               /*
-                *      Look for netmasks.
-                */
-               c->netmask = ~0;
-               if (netmask) {
-                       int mask_length;
-
-                       mask_length = atoi(netmask + 1);
-                       if ((mask_length < 0) || (mask_length > 32)) {
-                               radlog(L_ERR, "%s[%d]: Invalid value '%s' for IP network mask.",
-                                               filename, cf_section_lineno(cs), netmask + 1);
-                               clients_free(list);
-                               return NULL;
+                       /*
+                        *      Make sure syslog_facility isn't NULL before using it
+                        */
+                       if (!syslog_facility) {
+                               fprintf(stderr, "radiusd: Error: Unknown syslog chosen but no facility spedified\n");
+                               free(radlog_dest);
+                               cf_section_free(&cs);
+                               return -1;
                        }
-
-                       if (mask_length == 0) {
-                               c->netmask = 0;
-                       } else {
-                               c->netmask = ~0 << (32 - mask_length);
+                       mainconfig.syslog_facility = lrad_str2int(str2fac, syslog_facility, -1);
+                       if (mainconfig.syslog_facility < 0) {
+                               fprintf(stderr, "radiusd: Error: Unknown syslog_facility %s\n",
+                                       syslog_facility);
+                               free(radlog_dest);
+                               free(syslog_facility);
+                               cf_section_free(&cs);
+                               return -1;
                        }
-
-                       *netmask = '\0';
-                       c->netmask = htonl(c->netmask);
                }
 
-               c->ipaddr = ip_getaddr(hostnm);
-               if (c->ipaddr == INADDR_NONE) {
-                       radlog(L_CONS|L_ERR, "%s[%d]: Failed to look up hostname %s",
-                                       filename, cf_section_lineno(cs), hostnm);
-                       clients_free(list);
-                       return NULL;
-               }
+               if (mainconfig.radlog_dest == RADLOG_FILES) {
+                       static const CONF_PARSER file_config[] = {
+                               { "log_file", PW_TYPE_STRING_PTR, -1, &mainconfig.log_file, "${logdir}/radius.log" },
+                               { NULL, -1, 0, NULL, NULL }
+                       };
 
-               /*
-                *      Update the client name again...
-                */
-               if (netmask) {
-                       *netmask = '/';
-                       c->ipaddr &= c->netmask;
-                       strcpy(c->longname, hostnm);
-               } else {
-                       ip_hostname(c->longname, sizeof(c->longname),
-                                       c->ipaddr);
+                       cf_section_parse(cs, NULL, file_config);
                }
 
-               strcpy((char *)c->secret, secret);
-               strcpy(c->shortname, shortnm);
-               if(nastype != NULL)
-                       strcpy(c->nastype, nastype);
-               if(login != NULL)
-                       strcpy(c->login, login);
-               if(password != NULL)
-                       strcpy(c->password, password);
-
-               c->next = list;
-               list = c;
+               free(radlog_dest);
+       } else {
+               mainconfig.radlog_dest = RADLOG_STDOUT;
+               mainconfig.radlog_fd = STDOUT_FILENO;
        }
 
-       return list;
-}
-
-
-/*
- *     Code for handling listening on multiple ports.
- */
-static rad_listen_t listen_inst;
-static const char *listen_type = NULL;
-
-static const CONF_PARSER listen_config[] = {
-       { "ipaddr", PW_TYPE_IPADDR,
-         offsetof(rad_listen_t,ipaddr), NULL, "0.0.0.0" },
-
-       { "port", PW_TYPE_INTEGER,
-         offsetof(rad_listen_t,port), NULL, "0" },
-
-       { "type", PW_TYPE_STRING_PTR,
-         0, &listen_type, "" },
-
-       { NULL, -1, 0, NULL, NULL }             /* end the list */
-};
-
-static const LRAD_NAME_NUMBER listen_compare[] = {
-       { "auth",       RAD_LISTEN_AUTH },
-       { "acct",       RAD_LISTEN_ACCT },
-       { NULL, 0 },
-};
-
-
-/*
- *     Free a linked list of listeners;
- */
-static void listen_free(rad_listen_t *list)
-{
-       while (list) {
-               rad_listen_t *next = list->next;
-               
-               /*
-                *      The code below may have eaten the FD.
-                */
-               if (list->fd >= 0) close(list->fd);
-               free(list);
-               
-               list = next;
+       radlog(L_INFO, "%s", radiusd_version);
+       if (!reload) {
+               radlog(L_INFO, "Starting - reading configuration files ...");
+       } else {
+               radlog(L_INFO, "Reloading - reading configuration files...");
        }
-}
 
-/*
- *     Binds a listener to a socket.
- */
-static int listen_bind(rad_listen_t *this)
-{
-       struct sockaddr salocal;
-       struct sockaddr_in *sa;
+       /* Initialize the dictionary */
+       DEBUG2("read_config_files:  reading dictionary");
+       if (dict_init(radius_dir, RADIUS_DICTIONARY) != 0) {
+               radlog(L_ERR|L_CONS, "Errors reading dictionary: %s",
+                               librad_errstr);
+               return -1;
+       }
 
-       rad_listen_t    **last;
+       /*
+        *      This allows us to figure out where, relative to
+        *      radiusd.conf, the other configuration files exist.
+        */
+       cf_section_parse(cs, NULL, server_config);
 
+#if 0
        /*
-        *      If the port is zero, then it means the appropriate
-        *      thing from /etc/services.
+        *      Merge the old with the new.
         */
-       if (this->port == 0) {
-               struct servent  *svp;
-
-               switch (this->type) {
-               case RAD_LISTEN_AUTH:
-                       svp = getservbyname ("radius", "udp");
-                       if (svp != NULL) {
-                               this->port = ntohs(svp->s_port);
-                       } else {
-                               this->port = PW_AUTH_UDP_PORT;
+       if (reload) {
+               CONF_SECTION *newcs;
+
+               newcs = cf_section_sub_find(cs, "modules");
+               oldcs = cf_section_sub_find(mainconfig.config, "modules");
+               if (newcs && oldcs) {
+                       if (!cf_section_migrate(newcs, oldcs)) {
+                               radlog(L_ERR|L_CONS, "Fatal error migrating configuration data");
+                               return -1;
                        }
-                       break;
-
-               case RAD_LISTEN_ACCT:
-                       svp = getservbyname ("radacct", "udp");
-                       if (svp != NULL) {
-                               this->port = ntohs(svp->s_port);
-                       } else {
-                               this->port = PW_ACCT_UDP_PORT;
-                       }
-                       break;
-
-               default:
-                       radlog(L_ERR|L_CONS, "ERROR: Non-fatal internal sanity check failed in bind.");
-                       return -1;
-               }
-       }
-
-       /*
-        *      Find it in the old list, AFTER updating the port.  If
-        *      it's there, use that, rather than creating a new
-        *      socket.  This allows HUP's to re-use the old sockets,
-        *      which means that packets waiting in the socket queue
-        *      don't get lost.  */
-       for (last = &mainconfig.listen;
-            *last != NULL;
-            last = &((*last)->next)) {
-               if ((this->ipaddr == (*last)->ipaddr) &&
-                   (this->type == (*last)->type) &&
-                   (this->port == (*last)->port)) {
-                       this->fd = (*last)->fd;
-                       (*last)->fd = -1;
-                       return 0;
-               }
-       }
-
-       /*
-        *      Create the socket.
-        */
-       this->fd = socket(AF_INET, SOCK_DGRAM, 0);
-       if (this->fd < 0) {
-               return -1;
-       }
-       
-
-#ifdef WITH_UDPFROMTO
-       /*
-        *      Initialize udpfromto for all sockets.
-        */
-       if (udpfromto_init(this->fd) != 0) {
-               radlog(L_ERR|L_CONS, "ERROR: udpfromto init failed.");
-       }
-#endif
-
-       sa = (struct sockaddr_in *) &salocal;
-       memset ((char *) sa, '\0', sizeof(salocal));
-       sa->sin_family = AF_INET;
-       sa->sin_addr.s_addr = this->ipaddr;
-       sa->sin_port = htons(this->port);
-       
-       if (bind(this->fd, &salocal, sizeof(*sa)) < 0) {
-               close(this->fd);
-               this->fd = -1;
-               return -1;
-       }
-
-       return 0;
-}
-
-
-static int last_proxy_port = 0;
-
-/*
- *     Externally visible function for creating a new proxy LISTENER.
- *
- *     For now, don't take ipaddr or port.
- */
-int proxy_new_listener(void)
-{
-       int port;
-       rad_listen_t *this;
-
-       this = rad_malloc(sizeof(*this));
-
-       memset(this, 0, sizeof(*this));
-
-       this->ipaddr = mainconfig.myip;
-       this->type = RAD_LISTEN_PROXY;
-
-       /*
-        *      Proxying was not previously defined: die.
-        */
-       if (last_proxy_port == 0) return -1;
-
-       /*
-        *      Keep going until we find an unused port.
-        */
-       for (port = last_proxy_port + 1; port < 64000; port++) {
-               this->port = port;
-               if (listen_bind(this) == 0) {
-                       rad_listen_t **last;
-
-                       last_proxy_port = port;
-
-                       /*
-                        *      Add the new listener to the list of
-                        *      listeners.
-                        */
-                       for (last = &mainconfig.listen;
-                            *last != NULL;
-                            last = &((*last)->next)) {
-                               /* do nothing */
-                       }
-
-                       *last = this;
-                       return this->fd;
-               }
-       }
-
-       return -1;
-}
-
-
-/*
- *     Generate a list of listeners.  Takes an input list of
- *     listeners, too, so we don't close sockets with waiting packets.
- */
-static int listen_init(const char *filename, rad_listen_t **head)
-{
-       CONF_SECTION    *cs;
-       rad_listen_t    **last;
-       char            buffer[32];
-       rad_listen_t    *this;
-
-       /*
-        *      Add to the end of the list.
-        */
-       for (last = head; *last != NULL; last = &((*last)->next)) {
-               /* do nothing */
-       }
-
-       /*
-        *      Find the first one (if any).
-        */
-       for (cs = cf_subsection_find_next(mainconfig.config,
-                                         NULL, "listen");
-            cs != NULL;
-            cs = cf_subsection_find_next(mainconfig.config,
-                                         cs, "listen")) {
-               memset(&listen_inst, 0, sizeof(listen_inst));
-               
-               /*
-                *      Fix errors for later.
-                */
-               if (cf_section_parse(cs, &listen_inst, listen_config) < 0) {
-                       radlog(L_CONS|L_ERR, "%s[%d]: Error parsing listen section.",
-                              filename, cf_section_lineno(cs));
-                       return -1;
-               }
-
-               if (listen_type) {
-                       listen_inst.type = lrad_str2int(listen_compare,
-                                                       listen_type, 0);
-               }
-               if (listen_inst.type == RAD_LISTEN_NONE) {
-                       radlog(L_CONS|L_ERR, "%s[%d]: Invalid type in listen section.",
-                              filename, cf_section_lineno(cs));
-                       return -1;
-               }
-
-               this = rad_malloc(sizeof(*this));
-               memcpy(this, &listen_inst, sizeof(*this));
-               
-               /*
-                *      And bind it to the port.
-                */
-               if (listen_bind(this) < 0) {
-                       radlog(L_CONS|L_ERR, "%s[%d]: Error binding to port for %s:%d",
-                              filename, cf_section_lineno(cs),
-                              ip_ntoa(buffer, this->ipaddr), this->port);
-                       free(this);
-                       return -1;
-               }
-
-               *last = this;
-               last = &(this->next);           
-       }
-
-       /*
-        *      If we're proxying requests, open the proxy FD.
-        *      Otherwise, don't do anything.
-        */
-       if (mainconfig.proxy_requests == TRUE) {
-               int             port = -1;
-               rad_listen_t    *auth;
-               int             num_realms = 0;
-               int             localhost = 0;
-               int             otherhost = 0;
-               REALM           *realm;
-               uint32_t        proxy_ip;
-               uint32_t        ipaddr;
-
-               /*
-                *      If there are no realms configured, don't
-                *      open the proxy port.
-                */
-               for (realm = mainconfig.realms;
-                    realm != NULL;
-                    realm = realm->next) {
-                       /*
-                        *      Ignore LOCAL realms.
-                        */
-                       if ((realm->ipaddr == htonl(INADDR_NONE)) &&
-                           (realm->acct_ipaddr == htonl(INADDR_NONE))) {
-                               continue;
-                       }
-                       num_realms++;
-
-                       /*
-                        *      Loopback addresses
-                        */
-                       if (realm->ipaddr == htonl(INADDR_LOOPBACK)) {
-                               localhost = 1;
-                       } else {
-                               otherhost = 1;
-                       }
-                       if (realm->acct_ipaddr == htonl(INADDR_LOOPBACK)) {
-                               localhost = 1;
-                       } else {
-                               otherhost = 1;
-                       }
-               }
-
-               /*
-                *      No external realms.  Don't open another port.
-                */
-               if (num_realms == 0) {
-                       return 0;
-               }
-
-               /*
-                *      All of the realms are localhost, don't open
-                *      an external port.
-                */
-               if (localhost && !otherhost) {
-                       proxy_ip = htonl(INADDR_LOOPBACK);
-               } else {
-                       /*
-                        *      Multiple external realms, listen
-                        *      on any address that will send packets.
-                        */
-                       proxy_ip = htonl(INADDR_NONE);
-               }
-
-               /*
-                *      Find the first authentication port,
-                *      and use it
-                */
-               ipaddr = htonl(INADDR_NONE);
-               for (auth = *head; auth != NULL; auth = auth->next) {
-                       /*
-                        *      Listening on ANY, use that.
-                        */
-                       if (ipaddr != htonl(INADDR_ANY)) {
-                               /*
-                                *      Not set.  Pick the first one.
-                                *      Or, ANY, pick that.
-                                */
-                               if ((ipaddr == htonl(INADDR_NONE)) ||
-                                   (auth->ipaddr == htonl(INADDR_ANY))) {
-                                       ipaddr = auth->ipaddr;
-
-                                       /*
-                                        *      Else listening on multiple
-                                        *      IP's, use ANY for proxying.
-                                        */
-                               } else if (ipaddr != auth->ipaddr) {
-                                       ipaddr = htonl(INADDR_ANY);
-                               }
-                       }
-                       if (auth->type == RAD_LISTEN_AUTH) {
-                               port = auth->port + 2;
-                               break;
-                       }
-               }
-
-               /*
-                *      Not found, pick an accounting port.
-                */
-               if (port < 0) for (auth = *head; auth != NULL; auth = auth->next) {
-                       if (auth->type == RAD_LISTEN_ACCT) {
-                               port = auth->port + 1;
-                               break;
-                       }
-               }
-
-               /*
-                *      Still no port.  Don't do anything.
-                */
-               if (port < 0) {
-                       return 0;
-               }
-
-               this = rad_malloc(sizeof(*this));
-               memset(this, 0, sizeof(*this));
-
-               /*
-                *      More checks to do the right thing.
-                */
-               if (proxy_ip == htonl(INADDR_NONE)) {
-                       proxy_ip = ipaddr;
                }
-               
-               /*
-                *      Create the proxy socket.
-                */
-               this->ipaddr = proxy_ip;
-               this->type = RAD_LISTEN_PROXY;
-
-               /*
-                *      Try to find a proxy port (value doesn't matter)
-                */
-               for (this->port = port;
-                    this->port < 64000;
-                    this->port++) {
-                       if (listen_bind(this) == 0) {
-                               last_proxy_port = this->port;
-                               *last = this;
-                               return 0;
-                       }
-               }
-
-               radlog(L_ERR|L_CONS, "Failed to open socket for proxying");
-               free(this);
-               return -1;
-       }
-
-       return 0;
-}
-
-
-/*
- *     Hack the OLD way of listening on a socket.
- */
-static int old_listen_init(rad_listen_t **head)
-{
-       CONF_PAIR       *cp;
-       rad_listen_t    *this, **last;
-
-       /*
-        *      No "bind_address": all listen directives
-        *      are in the "listen" clauses.
-        */
-       cp = cf_pair_find(mainconfig.config, "bind_address");
-       if (!cp) return 0;
-       
-       last = head;
-
-       this = rad_malloc(sizeof(*this));
-       memset(this, 0, sizeof(*this));
-
-       /*
-        *      Create the authentication socket.
-        */
-               this->ipaddr = mainconfig.myip;
-       this->type = RAD_LISTEN_AUTH;
-       this->port = auth_port;
-
-       if (listen_bind(this) < 0) {
-               radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the authentication port %d", this->port);
-               free(this);
-               return -1;
        }
-       auth_port = this->port; /* may have been updated in listen_bind */
-       *last = this;
-       last = &(this->next);
-
-       /*
-        *  Open Accounting Socket.
-        *
-        *  If we haven't already gotten acct_port from /etc/services,
-        *  then make it auth_port + 1.
-        */
-       this = rad_malloc(sizeof(*this));
-       memset(this, 0, sizeof(*this));
-
-       /*
-        *      Create the accounting socket.
-        *
-        *      The accounting port is always the authentication port + 1
-        */
-               this->ipaddr = mainconfig.myip;
-       this->type = RAD_LISTEN_ACCT;
-       this->port = auth_port + 1;
-
-       if (listen_bind(this) < 0) {
-               radlog(L_CONS|L_ERR, "There appears to be another RADIUS server running on the accounting port %d", this->port);
-               free(this);
-               return -1;
-       }
-       *last = this;
-
-       return 0;
-}
-
-
-#ifndef RADIUS_CONFIG
-#define RADIUS_CONFIG "radiusd.conf"
 #endif
 
-CONF_SECTION *read_radius_conf_file(void)
-{
-       char buffer[256];
-       CONF_SECTION *cs;
-       struct stat statbuf;
-
-       if (stat(radius_dir, &statbuf) < 0) {
-               radlog(L_ERR|L_CONS, "Errors reading %s: %s",
-                      radius_dir, strerror(errno));
-               return NULL;
-       }
-
-       if ((statbuf.st_mode & S_IWOTH) != 0) {
-               radlog(L_ERR|L_CONS, "Configuration directory %s is globally writable.  Refusing to start due to insecure configuration.",
-                      radius_dir);
-         return NULL;
-       }
-
-
-       if (0 && (statbuf.st_mode & S_IROTH) != 0) {
-               radlog(L_ERR|L_CONS, "Configuration directory %s is globally readable.  Refusing to start due to insecure configuration.",
-                      radius_dir);
-               return NULL;
-       }
-
-       /* Lets go look for the new configuration files */
-       snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
-       if ((cs = conf_read(NULL, 0, buffer, NULL)) == NULL) {
-               return NULL;
-       }
-
-       /*
-        *      This allows us to figure out where, relative to
-        *      radiusd.conf, the other configuration files exist.
-        */
-       cf_section_parse(cs, NULL, server_config);
-
-       /* Initialize the dictionary */
-       DEBUG2("read_config_files:  reading dictionary");
-       if (dict_init(radius_dir, RADIUS_DICTIONARY) != 0) {
-               radlog(L_ERR|L_CONS, "Errors reading dictionary: %s",
-                               librad_errstr);
-               cf_section_free(&cs);
-               return NULL;
-       }
-
-       return cs;
-}
-
-
-/*
- *     Read config files.
- *
- *     This function can ONLY be called from the main server process.
- */
-int read_mainconfig(int reload)
-{
-       struct rlimit core_limits;
-       static int old_debug_level = -1;
-       char buffer[1024];
-       CONF_SECTION *cs, *oldcs;
-       rad_listen_t *listener;
-       RADCLIENT *c, *tail;
-
-       if (!reload) {
-               radlog(L_INFO, "Starting - reading configuration files ...");
-       } else {
-               radlog(L_INFO, "Reloading configuration files.");
-       }
-
-       /* First read radiusd.conf */
-       DEBUG2("reread_config:  reading radiusd.conf");
-       if ((cs = read_radius_conf_file()) == NULL) {
-               if (debug_flag ||
-                   (radlog_dir == NULL)) {
-                       radlog(L_ERR|L_CONS, "Errors reading radiusd.conf");
-               } else {
-                       radlog(L_ERR|L_CONS, "Errors reading %s/radiusd.conf: For more information, please read the tail end of %s", radius_dir, mainconfig.log_file);
-               }
-               return -1;
-       }
-
        /*
         *      Free the old configuration items, and replace them
         *      with the new ones.
@@ -1313,40 +1023,9 @@ int read_mainconfig(int reload)
        mainconfig.config = cs;
        cf_section_free(&oldcs);
 
-       /* old-style naslist file */
-       snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_NASLIST);
-       DEBUG2("read_config_files:  reading naslist");
-       if (read_naslist_file(buffer) < 0) {
-               radlog(L_ERR|L_CONS, "Errors reading naslist");
-               return -1;
-       }
-       /* old-style clients file */
-       snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CLIENTS);
-       DEBUG2("read_config_files:  reading clients");
-       if (read_clients_file(buffer) < 0) {
-               radlog(L_ERR|L_CONS, "Errors reading clients");
-               return -1;
-       }
-
-       /*
-        *      Add to that, the *new* list of clients.
-        */
-       snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
-       c = generate_clients(buffer, mainconfig.config);
-       if (!c) {
-               return -1;
-       }
-
        /*
-        *      The new list of clients takes precedence over the old one.
+        *      Old-style realms file.
         */
-       for (tail = c; tail->next != NULL; tail = tail->next) {
-         /* do nothing */
-       }
-       tail->next = mainconfig.clients;
-       mainconfig.clients = c;
-       
-       /* old-style realms file */
        snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_REALMS);
        DEBUG2("read_config_files:  reading realms");
        if (read_realms_file(buffer) < 0) {
@@ -1357,7 +1036,8 @@ int read_mainconfig(int reload)
        /*
         *      If there isn't any realms it isn't fatal..
         */
-       snprintf(buffer, sizeof(buffer), "%.200s/%.50s", radius_dir, RADIUS_CONFIG);
+       snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
+                radius_dir, mainconfig.radiusd_conf);
        if (generate_realms(buffer) < 0) {
                return -1;
        }
@@ -1378,7 +1058,7 @@ int read_mainconfig(int reload)
         */
        if ((mainconfig.debug_level > debug_flag) ||
            (mainconfig.debug_level <= old_debug_level)) {
-         debug_flag = mainconfig.debug_level;
+               debug_flag = mainconfig.debug_level;
        }
        librad_debug = debug_flag;
        old_debug_level = mainconfig.debug_level;
@@ -1388,43 +1068,6 @@ int read_mainconfig(int reload)
         *  changes.
         */
 
-       /*  Get the current maximum for core files.  */
-       if (getrlimit(RLIMIT_CORE, &core_limits) < 0) {
-               radlog(L_ERR|L_CONS, "Failed to get current core limit:  %s", strerror(errno));
-               exit(1);
-       }
-
-       if (mainconfig.allow_core_dumps) {
-               if (setrlimit(RLIMIT_CORE, &core_limits) < 0) {
-                       radlog(L_ERR|L_CONS, "Cannot update core dump limit: %s",
-                                       strerror(errno));
-                       exit(1);
-
-                       /*
-                        *  If we're running as a daemon, and core
-                        *  dumps are enabled, log that information.
-                        */
-               } else if ((core_limits.rlim_cur != 0) && !debug_flag)
-                       radlog(L_INFO|L_CONS, "Core dumps are enabled.");
-
-       } else if (!debug_flag) {
-               /*
-                *  Not debugging.  Set the core size to zero, to
-                *  prevent security breaches.  i.e. People
-                *  reading passwords from the 'core' file.
-                */
-               struct rlimit limits;
-
-               limits.rlim_cur = 0;
-               limits.rlim_max = core_limits.rlim_max;
-
-               if (setrlimit(RLIMIT_CORE, &limits) < 0) {
-                       radlog(L_ERR|L_CONS, "Cannot disable core dumps: %s",
-                                       strerror(errno));
-                       exit(1);
-               }
-       }
-
        /*
         *      The first time around, ensure that we can write to the
         *      log directory.
@@ -1436,18 +1079,11 @@ int read_mainconfig(int reload)
                 */
                radlogdir_iswritable(mainconfig.uid_name);
        }
-       switch_users();
 
-#ifdef HAVE_SYS_PRCTL_H
-#ifdef HAVE_PR_SET_DUMPABLE
-       if (mainconfig.allow_core_dumps) {
-               if (prctl(PR_SET_DUMPABLE, 1) < 0) {
-                       radlog(L_ERR|L_CONS,"Cannot enable core dumps: prctl(PR_SET_DUMPABLE) failed: '%s'",
-                              strerror(errno));
-               }
-       }
-#endif
-#endif
+       /*
+        *      We should really switch users earlier in the process.
+        */
+       switch_users();
 
        /*
         *      Sanity check the configuration for internal
@@ -1461,14 +1097,12 @@ int read_mainconfig(int reload)
         *      Initialize the old "bind_address" and "port", first.
         */
        listener = NULL;
-       if (old_listen_init(&listener) < 0) {
-               exit(1);
-       }
 
        /*
         *      Read the list of listeners.
         */
-       snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", radius_dir);
+       snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
+                radius_dir, mainconfig.radiusd_conf);
        if (listen_init(buffer, &listener) < 0) {
                exit(1);
        }
@@ -1478,14 +1112,59 @@ int read_mainconfig(int reload)
                exit(1);
        }
 
-       listen_free(mainconfig.listen);
+       listen_free(&mainconfig.listen);
        mainconfig.listen = listener;
 
+       /*
+        *      Walk through the listeners.  If we're listening on acct
+        *      or auth, read in the clients files, else ignore them.
+        */
+       for (listener = mainconfig.listen;
+            listener != NULL;
+            listener = listener->next) {
+               if ((listener->type == RAD_LISTEN_AUTH) ||
+                   (listener->type == RAD_LISTEN_ACCT)) {
+                       break;
+               }
+       }
+
+       if (listener != NULL) {
+               RADCLIENT_LIST *clients, *old_clients;
+
+               /*
+                *      Create the new clients first, and add them
+                *      to the CONF_SECTION, where they're automagically
+                *      freed if anything goes wrong.
+                */
+               snprintf(buffer, sizeof(buffer), "%.200s/%.50s",
+                        radius_dir, mainconfig.radiusd_conf);
+               clients = clients_parse_section(buffer, mainconfig.config);
+               if (!clients) {
+                       return -1;
+               }
+
+               /*
+                *      Free the old trees AFTER replacing them with
+                *      the new ones...
+                */
+               old_clients = mainconfig.clients;
+               mainconfig.clients = clients;
+               clients_free(old_clients);
+       }
+
+       rl_init_proxy();
+
+       /*  Reload the modules.  */
+       DEBUG2("radiusd:  entering modules setup");
+       if (setup_modules(reload) < 0) {
+               radlog(L_ERR|L_CONS, "Errors setting up modules");
+               return -1;
+       }
        return 0;
 }
 
 /*
- *     Free the configuration.
+ *     Free the configuration.  Called only when the server is exiting.
  */
 int free_mainconfig(void)
 {
@@ -1494,13 +1173,9 @@ int free_mainconfig(void)
         *      structures.
         */
        cf_section_free(&mainconfig.config);
+       free(mainconfig.radiusd_conf);
        realm_free(mainconfig.realms);
-       clients_free(mainconfig.clients);
-       read_naslist_file(NULL);
-
-       rl_free();
-       listen_free(mainconfig.listen);
-       paircompare_builtin_free();
+       listen_free(&mainconfig.listen);
        xlat_free();
        dict_free();
        lt_dlexit();
index 7179143..3dcd7a4 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
 #include <stdlib.h>
 #include <string.h>
-#include <stdarg.h>
-#include "radiusd.h"
-#include "rad_assert.h"
-#include "conffile.h"
-#include "modpriv.h"
-#include "modules.h"
-#include "modcall.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/modpriv.h>
+#include <freeradius-devel/modcall.h>
 
 /* mutually-recursive static functions need a prototype up front */
-static modcallable *do_compile_modgroup(int, CONF_SECTION *, const char *,
-               int, int);
+static modcallable *do_compile_modgroup(modcallable *,
+                                       int, CONF_SECTION *, const char *,
+                                       int, int);
 
 /* Actions may be a positive integer (the highest one returned in the group
  * will be returned), or the keyword "return", represented here by
  * MOD_ACTION_RETURN, to cause an immediate return.
  * There's also the keyword "reject", represented here by MOD_ACTION_REJECT
  * to cause an immediate reject. */
-#define MOD_ACTION_RETURN (-1)
-#define MOD_ACTION_REJECT (-2)
+#define MOD_ACTION_RETURN  (-1)
+#define MOD_ACTION_REJECT  (-2)
 
 /* Here are our basic types: modcallable, modgroup, and modsingle. For an
  * explanation of what they are all about, see ../../doc/README.failover */
 struct modcallable {
+       modcallable *parent;
        struct modcallable *next;
        const char *name;
+       int lineno;
        int actions[RLM_MODULE_NUMCODES];
-       enum { MOD_SINGLE, MOD_GROUP, MOD_LOAD_BALANCE, MOD_REDUNDANT_LOAD_BALANCE  } type;
+       enum { MOD_SINGLE, MOD_GROUP, MOD_LOAD_BALANCE, MOD_REDUNDANT_LOAD_BALANCE, MOD_IF, MOD_ELSE, MOD_ELSIF } type;
 };
 
 #define GROUPTYPE_SIMPLE       0
@@ -57,8 +62,8 @@ struct modcallable {
 #define GROUPTYPE_COUNT                3
 
 typedef struct {
-       modcallable mc;
-       int grouptype;
+       modcallable mc;         /* self */
+       int grouptype;  /* after mc */
        modcallable *children;
 } modgroup;
 
@@ -67,7 +72,6 @@ typedef struct {
        module_instance_t *modinst;
 } modsingle;
 
-
 static const LRAD_NAME_NUMBER grouptype_table[] = {
        { "", GROUPTYPE_SIMPLE },
        { "redundant ", GROUPTYPE_REDUNDANT },
@@ -84,8 +88,11 @@ static modsingle *mod_callabletosingle(modcallable *p)
 }
 static modgroup *mod_callabletogroup(modcallable *p)
 {
-       rad_assert((p->type==MOD_GROUP) ||
+       rad_assert((p->type==MOD_GROUP) || /* this is getting silly... */
                   (p->type==MOD_LOAD_BALANCE) ||
+                  (p->type==MOD_IF) ||
+                  (p->type==MOD_ELSE) ||
+                  (p->type==MOD_ELSIF) ||
                   (p->type==MOD_REDUNDANT_LOAD_BALANCE));
        return (modgroup *)p;
 }
@@ -114,6 +121,7 @@ static void add_child(modgroup *g, modcallable *c)
 
        rad_assert(c->next == NULL);
        *last = c;
+       c->parent = mod_grouptocallable(g);
 }
 
 /* Here's where we recognize all of our keywords: first the rcodes, then the
@@ -138,15 +146,7 @@ static const LRAD_NAME_NUMBER rcode_table[] = {
 static int compile_action(modcallable *c, const char *attr, const char *value,
                          const char *filename, int lineno)
 {
-       int rcode, action;
-
-       rcode = lrad_str2int(rcode_table, attr, -1);
-       if (rcode < 0) {
-               radlog(L_ERR|L_CONS,
-                      "%s[%d] Unknown module rcode '%s'.\n",
-                      filename, lineno, attr);
-               return 0;
-       }
+       int action;
 
        if (!strcasecmp(value, "return"))
                action = MOD_ACTION_RETURN;
@@ -168,26 +168,31 @@ static int compile_action(modcallable *c, const char *attr, const char *value,
                return 0;
        }
 
-       c->actions[rcode] = action;
+       if (strcasecmp(attr, "default") != 0) {
+               int rcode;
 
-       return 1;
-}
+               rcode = lrad_str2int(rcode_table, attr, -1);
+               if (rcode < 0) {
+                       radlog(L_ERR|L_CONS,
+                              "%s[%d] Unknown module rcode '%s'.\n",
+                              filename, lineno, attr);
+                       return 0;
+               }
+               c->actions[rcode] = action;
 
-#if 0
-static const char *action2str(int action)
-{
-       static char buf[32];
-       if(action==MOD_ACTION_RETURN)
-               return "return";
-       if(action==MOD_ACTION_REJECT)
-               return "reject";
-       snprintf(buf, sizeof buf, "%d", action);
-       return buf;
+       } else {                /* set all unset values to the default */
+               int i;
+
+               for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
+                       if (!c->actions[i]) c->actions[i] = action;
+               }
+       }
+
+       return 1;
 }
-#endif
 
 /* Some short names for debugging output */
-static const char *comp2str[] = {
+static const char * const comp2str[] = {
        "authenticate",
        "authorize",
        "preacct",
@@ -233,8 +238,16 @@ static int call_modsingle(int component, modsingle *sp, REQUEST *request,
               comp2str[component], sp->modinst->name,
               sp->modinst->entry->name, request->number);
        safe_lock(sp->modinst);
+
+       /*
+        *      For logging unresponsive children.
+        */
+       request->module = sp->modinst->name;
+
        myresult = sp->modinst->entry->module->methods[component](
                        sp->modinst->insthandle, request);
+
+       request->module = "<server-core>";
        safe_unlock(sp->modinst);
        DEBUG3("  modsingle[%s]: returned from %s (%s) for request %d",
               comp2str[component], sp->modinst->name,
@@ -244,342 +257,379 @@ static int call_modsingle(int component, modsingle *sp, REQUEST *request,
 }
 
 
+static int default_component_results[RLM_COMPONENT_COUNT] = {
+       RLM_MODULE_REJECT,      /* AUTH */
+       RLM_MODULE_NOTFOUND,    /* AUTZ */
+       RLM_MODULE_NOOP,        /* PREACCT */
+       RLM_MODULE_NOOP,        /* ACCT */
+       RLM_MODULE_FAIL,        /* SESS */
+       RLM_MODULE_NOOP,        /* PRE_PROXY */
+       RLM_MODULE_NOOP,        /* POST_PROXY */
+       RLM_MODULE_NOOP         /* POST_AUTH */
+};
+
+static const char *group_name[] = {
+       "",
+       "group",
+       "load-balance group",
+       "redundant-load-balance group",
+       "if",
+       "else",
+       "elsif"
+};
+
+static const char *modcall_spaces = "                                ";
+
+#define MODCALL_STACK_MAX (32)
+
 /*
- *     Helper function for call_modgroup, and call_modredundantloadbalance
- *
- *     Returns 0 for "stop", and "1" for continue.
+ *     Don't call the modules recursively.  Instead, do them
+ *     iteratively, and manage the call stack ourselves.
  */
-static int call_one(int component, modcallable *p, REQUEST *request,
-                   int *priority, int *result)
-{
-       int r;
+typedef struct modcall_stack {
+       int pointer;
 
-#ifdef RAD_REQUEST_OPTION_STOP_NOW
-       /*
-        *      A module has taken too long to process the request,
-        *      and we've been told to stop processing it.
-        */
-       if (request->options & RAD_REQUEST_OPTION_STOP_NOW) {
-               *result = RLM_MODULE_FAIL;
-               return 0;
-       }
-#endif
-       
-       /* Call this child by recursing into modcall */
-       r = modcall(component, p, request);
-       
-#if 0
-       DEBUG2("%s: action for %s is %s",
-              comp2str[component], lrad_int2str(rcode_table, r, "??"),
-              action2str(p->actions[r]));
-#endif
-       
-       /*
-        *      Find an action to go with the child's result. If it is
-        *      "return", break out of the loop so the rest of the
-        *      children in the list will be skipped.
-        */
-       if (p->actions[r] == MOD_ACTION_RETURN) {
-               *result = r;
-               return 0;
-       }
-       
-       /* If "reject" break out of the loop and return reject */
-       if (p->actions[r] == MOD_ACTION_REJECT) {
-               *result = RLM_MODULE_REJECT;
-               return 0;
-       }
-       
-       /*
-        *      Otherwise, the action is a number, the preference
-        *      level of this return code. If no higher preference has
-        *      been seen yet, remember this one
-        . */
-       if (p->actions[r] >= *priority) {
-               *result = r;
-               *priority = p->actions[r];
-       }
-       
-       return 1;
-}
+       int priority[MODCALL_STACK_MAX];
+       int result[MODCALL_STACK_MAX];
+       modcallable *children[MODCALL_STACK_MAX];
+       modcallable *start[MODCALL_STACK_MAX];
+} modcall_stack;
 
 
-static int call_modgroup(int component, modgroup *g, REQUEST *request,
-                        int default_result)
+/*
+ *     Call a module, iteratively, with a local stack, rather than
+ *     recursively.  What did Paul Graham say about Lisp...?
+ */
+int modcall(int component, modcallable *c, REQUEST *request)
 {
-       int myresult = default_result;
-       int priority = 0;       /* default result has lowest priority  */
-       modcallable *p;
+       int myresult;
+       modcall_stack stack;
+       modcallable *parent, *child;
+       modsingle *sp;
+       int if_taken, was_if;
 
-       /*
-        *      Catch people who have issues.
-        */
-       if (!g->children) {
-               DEBUG2("  WARNING! Asked to process empty group.  Returning %s.", lrad_int2str(rcode_table, myresult, "??"));
-               return default_result;
-       }
+       stack.pointer = 0;
 
-       /* Loop over the children */
-       for (p = g->children; p; p = p->next) {
-               if (!call_one(component, p, request, &priority, &myresult)) {
-                       break;
-               }
+       if ((component < 0) || (component >= RLM_COMPONENT_COUNT)) {
+               return RLM_MODULE_FAIL;
        }
 
-       return myresult;
-}
-
-static int call_modloadbalance(int component, modgroup *g, REQUEST *request,
-                              int default_result)
-{
-       int count = 1;
-       modcallable *p, *child = NULL;
-
-       /*
-        *      Catch people who have issues.
-        */
-       if (!g->children) {
-               DEBUG2("  WARNING! Asked to process empty load-balance group.  Returning %s.", lrad_int2str(rcode_table, default_result, "??"));
-               return default_result;
+       if (!c) {
+               return default_component_results[component];
        }
 
-       /*
-        *      Pick a random child.
-        */
+       stack.priority[0] = 0;
+       stack.children[0] = c;
+       myresult = stack.result[0] = default_component_results[component];
+       was_if = if_taken = FALSE;
 
-       /* Loop over the children */
-       for(p = g->children; p; p = p->next) {
-               if (!child) {
-                       child = p;
-                       count = 1;
-                       continue;
+       while (1) {
+               /*
+                *      A module has taken too long to process the request,
+                *      and we've been told to stop processing it.
+                */
+               if (request->options & RAD_REQUEST_OPTION_STOP_NOW) {
+                       myresult = RLM_MODULE_FAIL;
+                       break;
+               }
+
+               child = stack.children[stack.pointer];
+               rad_assert(child != NULL);
+               parent = child->parent;
+
+               if ((child->type == MOD_ELSE) || (child->type == MOD_ELSIF)) {
+                       if (!was_if) { /* error */
+                               DEBUG2("modcall:%.*s skipping %s for request %d: No preceding \"if\"",
+                                      stack.pointer, modcall_spaces,
+                                      group_name[child->type],
+                                      request->number);
+                               goto unroll;
+                       }
+                       if (if_taken) {
+                               DEBUG2("modcall:%.*s skipping %s for request %d: Preceding \"if\" was taken",
+                                      stack.pointer, modcall_spaces,
+                                      group_name[child->type],
+                                      request->number);
+                               goto unroll;
+                       }
                }
 
                /*
-                *      Keep track of how many load balancing servers
-                *      we've gone through.
+                *      "if", and the requested action wasn't the
+                *      proper return code, skip the group.
                 */
-               count++;
+               if (((child->type == MOD_IF) || (child->type == MOD_ELSIF)) &&
+                   !child->actions[myresult]) {
+                       DEBUG2("modcall:%.*s skipping %s \"%s\" for request %d, return code was %s",
+                              stack.pointer, modcall_spaces,
+                              group_name[child->type],
+                              child->name, request->number,
+                              lrad_int2str(rcode_table, myresult, "??"));
+                       stack.children[stack.pointer] = NULL;
+                       was_if = TRUE;
+                       if_taken = FALSE;
+                       goto unroll;
+               } /* else process it, as a simple group */
 
                /*
-                *      See the "camel book" for why this works.
-                *
-                *      If (rand(0..n) < 1), pick the current realm.
-                *      We add a scale factor of 65536, to avoid
-                *      floating point.
+                *      Child is a group that has children of it's own.
                 */
-               if ((count * (lrad_rand() & 0xffff)) < (uint32_t) 0x10000) {
-                       child = p;
-               }
-       }
-       rad_assert(child != NULL);
-
-       /* Call the chosen child by recursing into modcall */
-       return modcall(component, child, request);
-}
+               if (child->type != MOD_SINGLE) {
+                       int count = 1;
+                       modcallable *p, *q;
+                       modgroup *g = mod_callabletogroup(child);
+                       
+                       stack.pointer++;
 
+                       /*
+                        *      Catastrophic error.  This SHOULD have
+                        *      been caught when we were reading in the
+                        *      conf files.
+                        *
+                        *      FIXME: Do so.
+                        */
+                       if (stack.pointer >= MODCALL_STACK_MAX) {
+                               radlog(L_ERR, "Internal sanity check failed: module stack is too deep");
+                               exit(1);
+                       }
 
-/*
- *     For more than 2 modules with redundancy + load balancing
- *     across all of them, layering the "redundant" and
- *     "load-balance" groups gets too complicated.  As a result, we
- *     implement a special function to do this.
- */
-static int call_modredundantloadbalance(int component, modgroup *g, REQUEST *request,
-                                       int default_result)
-{
-       int count = 1;
-       int myresult = default_result;
-       int priority = 0;       /* default result has lowest priority  */
-       modcallable *p, *child = NULL;
+                       stack.priority[stack.pointer] = 0;
+                       stack.result[stack.pointer] = default_component_results[component];
+                       switch (child->type) {
+                       case MOD_IF:
+                       case MOD_ELSE:
+                       case MOD_ELSIF:
+                       case MOD_GROUP:
+                               stack.children[stack.pointer] = g->children;
+                               break;
+                               
+                               /*
+                                *      See the "camel book" for why
+                                *      this works.
+                                *
+                                *      If (rand(0..n) < 1), pick the
+                                *      current realm.  We add a scale
+                                *      factor of 65536, to avoid
+                                *      floating point.
+                                */
+                       case MOD_LOAD_BALANCE:
+                       case MOD_REDUNDANT_LOAD_BALANCE:
+                               q = NULL;
+                               for(p = g->children; p; p = p->next) {
+                                       if (!q) {
+                                               q = p;
+                                               count = 1;
+                                               continue;
+                                       }
+                                       
+                                       count++;
+                                       
+                                       if ((count * (lrad_rand() & 0xffff)) < (uint32_t) 0x10000) {
+                                               q = p;
+                                       }
+                               }
+                               stack.children[stack.pointer] = q;
+                               break;
+                               
+                       default:
+                               exit(1); /* internal sanity check failure */
+                               break;
+                       }
+                       
+                       
+                       stack.start[stack.pointer] = stack.children[stack.pointer];
 
-       /*
-        *      Catch people who have issues.
-        */
-       if (!g->children) {
-               DEBUG2("  WARNING! Asked to process empty redundant-load-balance group.  Returning %s.", lrad_int2str(rcode_table, default_result, "??"));
-               return default_result;
-       }
+                       DEBUG2("modcall:%.*s entering %s %s for request %d",
+                              stack.pointer, modcall_spaces,
+                              group_name[child->type],
+                              child->name, request->number);
 
-       /*
-        *      Pick a random child.
-        */
+                       /*
+                        *      Catch the special case of a NULL group.
+                        */
+                       if (!stack.children[stack.pointer]) {
+                               /*
+                                *      Print message for NULL group
+                                */
+                               DEBUG2("modcall[%s]: NULL object returns %s for request %d",
+                                      comp2str[component],
+                                      lrad_int2str(rcode_table,
+                                                   stack.result[stack.pointer],
+                                                   "??"),
+                                      request->number);
+                               goto do_return;
+                       }
 
-       /* Loop over the children */
-       for(p = g->children; p; p = p->next) {
-               if (!child) {
-                       child = p;
-                       count = 1;
+                       /*
+                        *      The child may be a group, so we want to
+                        *      recurse into it's children, rather than
+                        *      falling through to the code below.
+                        */
                        continue;
                }
 
                /*
-                *      Keep track of how many load balancing servers
-                *      we've gone through.
+                *      Process a stand-alone child, and fall through
+                *      to dealing with it's parent.
                 */
-               count++;
+               sp = mod_callabletosingle(child);
+               
+               myresult = call_modsingle(component, sp, request,
+                                         default_component_results[component]);
+               DEBUG2("  modcall[%s]: module \"%s\" returns %s for request %d",
+                      comp2str[component], child->name,
+                      lrad_int2str(rcode_table, myresult, "??"),
+                      request->number);
+
 
                /*
-                *      See the "camel book" for why this works.
+                *      FIXME: Allow modules to push a modcallable
+                *      onto this stack.  This should simplify
+                *      configuration a LOT!
+                *
+                *      Once we do that, we can't do load-time
+                *      checking of the maximum stack depth, and we've
+                *      got to cache the stack pointer before storing
+                *      myresult.
+                *
+                *      Also, if the stack changed, we need to set
+                *      children[ptr] to NULL, and process the next
+                *      entry on the stack, rather than falling
+                *      through to finalize the processing of this
+                *      entry.
                 *
-                *      If (rand(0..n) < 1), pick the current realm.
-                *      We add a scale factor of 65536, to avoid
-                *      floating point.
+                *      Don't put "myresult" on the stack here,
+                *      we have to do so with priority.
                 */
-               if ((count * (lrad_rand() & 0xffff)) < (uint32_t) 0x10000) {
-                       child = p;
-               }
-       }
-       rad_assert(child != NULL);
 
-       /*
-        *      Call the chosen child, with fail-over to the next one
-        *      if it is down.
-        */
-       p = child;
-       do {
                /*
-                *      Call the chosen entry.  If we're done, then
-                *      stop.
+                *      We roll back up the stack at this point.
                 */
-               if (!call_one(component, p, request, &priority, &myresult)) {
-                       break;
+       unroll:
+               /*
+                *      The child's action says return.  Do so.
+                */
+               if (child->actions[myresult] == MOD_ACTION_RETURN) {
+                       stack.result[stack.pointer] = myresult;
+                       stack.children[stack.pointer] = NULL;
+                       goto do_return;
                }
-               
+       
                /*
-                *      Go to the next one, and wrap around to the beginning if
-                *      we reach the end.
+                *      If "reject", break out of the loop and return
+                *      reject.
                 */
-               p = p->next;
-               if (!p) p = g->children;
-       } while (p != child);
-
-       /*
-        *      And return whatever was decided.
-        */
-       return myresult;
-}
+               if (child->actions[myresult] == MOD_ACTION_REJECT) {
+                       stack.children[stack.pointer] = NULL;
+                       stack.result[stack.pointer] = RLM_MODULE_REJECT;
+                       goto do_return;
+               }
 
-int modcall(int component, modcallable *c, REQUEST *request)
-{
-       int myresult;
+               /*
+                *      Otherwise, the action is a number, the
+                *      preference level of this return code. If no
+                *      higher preference has been seen yet, remember
+                *      this one.
+                */
+               if (child->actions[myresult] >= stack.priority[stack.pointer]) {
+                       stack.result[stack.pointer] = myresult;
+                       stack.priority[stack.pointer] = child->actions[myresult];
+               }
 
-       /* Choose a default return value appropriate for the component */
-       switch(component) {
-       case RLM_COMPONENT_AUTZ:
-               myresult = RLM_MODULE_NOTFOUND;
-               break;
-       case RLM_COMPONENT_AUTH:
-               myresult = RLM_MODULE_REJECT;
-               break;
-       case RLM_COMPONENT_PREACCT:
-               myresult = RLM_MODULE_NOOP;
-               break;
-       case RLM_COMPONENT_ACCT:
-               myresult = RLM_MODULE_NOOP;
-               break;
-       case RLM_COMPONENT_SESS:
-               myresult = RLM_MODULE_FAIL;
-               break;
-       case RLM_COMPONENT_PRE_PROXY:
-               myresult = RLM_MODULE_NOOP;
-               break;
-       case RLM_COMPONENT_POST_PROXY:
-               myresult = RLM_MODULE_NOOP;
-               break;
-       case RLM_COMPONENT_POST_AUTH:
-               myresult = RLM_MODULE_NOOP;
-               break;
-       default:
-               myresult = RLM_MODULE_FAIL;
-               break;
-       }
+               /*
+                *      No parent, we must be done.
+                */
+               if (!parent) {
+                       rad_assert(stack.pointer == 0);
+                       myresult = stack.result[0];
+                       break;
+               }
 
-       if(c == NULL) {
-               DEBUG2("modcall[%s]: NULL object returns %s for request %d",
-                      comp2str[component],
-                      lrad_int2str(rcode_table, myresult, "??"),
-                      request->number);
-               return myresult;
-       }
+               rad_assert(child != NULL);
 
-       switch (c->type) {
-       case MOD_LOAD_BALANCE:
-               {
-                       modgroup *g = mod_callabletogroup(c);
-                       
-                       DEBUG2("modcall: entering load-balance group %s for request %d",
-                              c->name, request->number);
-                       
-                       myresult = call_modloadbalance(component, g, request,
-                                                      myresult);
-                       
-                       DEBUG2("modcall: load-balance group %s returns %s for request %d",
-                              c->name,
-                              lrad_int2str(rcode_table, myresult, "??"),
-                              request->number);
-               }
-               break;
-               
-       case MOD_REDUNDANT_LOAD_BALANCE:
-               {
-                       modgroup *g = mod_callabletogroup(c);
-                       
-                       DEBUG2("modcall: entering redundant-load-balance group %s for request %d",
-                              c->name, request->number);
-                       
-                       myresult = call_modredundantloadbalance(component, g, request,
-                                                               myresult);
-                       
-                       DEBUG2("modcall: redundant-load-balance group %s returns %s for request %d",
-                              c->name,
-                              lrad_int2str(rcode_table, myresult, "??"),
-                              request->number);
-               }
-               break;
-               
-       case MOD_GROUP:
-               {
-                       modgroup *g = mod_callabletogroup(c);
-                       
-                       DEBUG2("modcall: entering group %s%s for request %d",
-                              lrad_int2str(grouptype_table, g->grouptype, ""),
-                              c->name, request->number);
-                       
-                       myresult = call_modgroup(component, g, request,
-                                                myresult);
-                       
-                       DEBUG2("modcall: leaving group %s%s (returns %s) for request %d",
-                              lrad_int2str(grouptype_table, g->grouptype, ""),
-                              c->name,
-                              lrad_int2str(rcode_table, myresult, "??"),
-                              request->number);
+               /*
+                *      Go to the "next" child, whatever that is.
+                */
+               switch (parent->type) {
+                       case MOD_IF:
+                       case MOD_ELSE:
+                       case MOD_ELSIF:
+                       case MOD_GROUP:
+                               stack.children[stack.pointer] = child->next;
+                               break;
+
+                       case MOD_LOAD_BALANCE:
+                               stack.children[stack.pointer] = NULL;
+                               break;
+
+                       case MOD_REDUNDANT_LOAD_BALANCE:
+                               if (child->next) {
+                                       stack.children[stack.pointer] = child->next;
+                               } else {
+                                       modgroup *g = mod_callabletogroup(parent);
+                                       
+                                       stack.children[stack.pointer] = g->children;
+                               }
+                               if (stack.children[stack.pointer] == stack.start[stack.pointer]) {
+                                       stack.children[stack.pointer] = NULL;
+                               }
+                               break;
+                       default:        
+                               exit(1);
                }
-               break;
-               
-       case MOD_SINGLE:
-               {
-                       modsingle *sp = mod_callabletosingle(c);
-                       
-                       myresult = call_modsingle(component, sp, request,
-                                                 myresult);
-                       
-                       DEBUG2("  modcall[%s]: module \"%s\" returns %s for request %d",
-                              comp2str[component], c->name,
+
+               /*
+                *      No child, we're done this group, and we return
+                *      "myresult" to the caller by pushing it back up
+                *      the stack.
+                */
+               if (!stack.children[stack.pointer]) {
+               do_return:
+                       rad_assert(stack.pointer > 0);
+                       myresult = stack.result[stack.pointer];
+                       stack.pointer--;
+
+                       DEBUG2("modcall:%.*s %s %s returns %s for request %d",
+                              stack.pointer, modcall_spaces,
+                              group_name[parent->type], parent->name,
                               lrad_int2str(rcode_table, myresult, "??"),
                               request->number);
+
+                       if (stack.pointer == 0) break;
+
+                       if ((parent->type == MOD_IF) ||
+                           (parent->type == MOD_ELSIF)) {
+                               if_taken = was_if = TRUE;
+                       } else {
+                               if_taken = was_if = FALSE;
+                       }
+
+                       /*
+                        *      Unroll the stack.
+                        */
+                       child = stack.children[stack.pointer];
+                       parent = child->parent;
+                       goto unroll;
                }
-               break;
 
-       default:
-               radlog(L_ERR, "Internal error processing module entry");
-               break;
-       }
+       } /* loop until done */
 
        return myresult;
 }
 
+
 #if 0
+static const char *action2str(int action)
+{
+       static char buf[32];
+       if(action==MOD_ACTION_RETURN)
+               return "return";
+       if(action==MOD_ACTION_REJECT)
+               return "reject";
+       snprintf(buf, sizeof buf, "%d", action);
+       return buf;
+}
+
 /* If you suspect a bug in the parser, you'll want to use these dump
  * functions. dump_tree should reproduce a whole tree exactly as it was found
  * in radiusd.conf, but in long form (all actions explicitly defined) */
@@ -594,7 +644,8 @@ static void dump_mc(modcallable *c, int indent)
        } else {
                modgroup *g = mod_callabletogroup(c);
                modcallable *p;
-               DEBUG("%.*sgroup {", indent, "\t\t\t\t\t\t\t\t\t\t\t");
+               DEBUG("%.*s%s {", indent, "\t\t\t\t\t\t\t\t\t\t\t",
+                     group_name[c->type]);
                for(p = g->children;p;p = p->next)
                        dump_mc(p, indent+1);
        }
@@ -614,10 +665,7 @@ static void dump_tree(int comp, modcallable *c)
        dump_mc(c, 0);
 }
 #else
-static void dump_tree(int comp UNUSED, modcallable *c UNUSED)
-{
-       return;
-}
+#define dump_tree(a, b)
 #endif
 
 /* These are the default actions. For each component, the group{} block
@@ -941,7 +989,54 @@ defaultactions[RLM_COMPONENT_COUNT][GROUPTYPE_COUNT][RLM_MODULE_NUMCODES] =
 };
 
 
-static modcallable *do_compile_modsingle(int component, CONF_ITEM *ci,
+static int condition2actions(modcallable *mc, const char *actions)
+{
+       char *p, *q;
+       char buffer[1024];
+
+       if (strlen(actions) >= sizeof(buffer)) {
+               return -1;
+       }
+
+       memset(mc->actions, 0, sizeof(mc->actions));
+
+       /*
+        *      Copy, stripping space.
+        */
+       p = buffer;
+       while (*actions) {
+               if (*actions != ' ') {
+                       *(p++) = *actions;
+               }
+               actions++;
+       }
+       *p = '\0';
+
+       p = buffer;
+
+       while (*p) {
+               int rcode;
+
+               q = strchr(p, '|');
+               if (q) *q = '\0';
+
+               rcode = lrad_str2int(rcode_table, p, -1);
+               if (rcode < 0) return -1;
+               mc->actions[rcode] = 1;
+
+               if (!q) break;
+               p = q + 1;
+       }
+
+       return 0;
+}
+
+
+/*
+ *     Compile one entry of a module call.
+ */
+static modcallable *do_compile_modsingle(modcallable *parent,
+                                        int component, CONF_ITEM *ci,
                                         const char *filename, int grouptype,
                                         const char **modname)
 {
@@ -967,31 +1062,130 @@ static modcallable *do_compile_modsingle(int component, CONF_ITEM *ci,
                 */
                if (strcmp(modrefname, "group") == 0) {
                        *modname = name2;
-                       return do_compile_modgroup(component, cs, filename,
-                                       GROUPTYPE_SIMPLE, grouptype);
+                       return do_compile_modgroup(parent, component, cs,
+                                                  filename,
+                                                  GROUPTYPE_SIMPLE,
+                                                  grouptype);
                } else if (strcmp(modrefname, "redundant") == 0) {
                        *modname = name2;
-                       return do_compile_modgroup(component, cs, filename,
-                                       GROUPTYPE_REDUNDANT, grouptype);
+                       return do_compile_modgroup(parent, component, cs,
+                                                  filename,
+                                                  GROUPTYPE_REDUNDANT,
+                                                  grouptype);
                } else if (strcmp(modrefname, "append") == 0) {
                        *modname = name2;
-                       return do_compile_modgroup(component, cs, filename,
-                                       GROUPTYPE_APPEND, grouptype);
+                       return do_compile_modgroup(parent, component, cs,
+                                                  filename,
+                                                  GROUPTYPE_APPEND,
+                                                  grouptype);
                } else if (strcmp(modrefname, "load-balance") == 0) {
                        *modname = name2;
-                       csingle= do_compile_modgroup(component, cs, filename,
-                                       GROUPTYPE_SIMPLE, grouptype);
+                       csingle= do_compile_modgroup(parent, component, cs,
+                                                    filename,
+                                                    GROUPTYPE_SIMPLE,
+                                                    grouptype);
                        if (!csingle) return NULL;
                        csingle->type = MOD_LOAD_BALANCE;
                        return csingle;
                } else if (strcmp(modrefname, "redundant-load-balance") == 0) {
                        *modname = name2;
-                       csingle= do_compile_modgroup(component, cs, filename,
-                                       GROUPTYPE_REDUNDANT, grouptype);
+                       csingle= do_compile_modgroup(parent, component, cs,
+                                                    filename,
+                                                    GROUPTYPE_REDUNDANT,
+                                                    grouptype);
                        if (!csingle) return NULL;
                        csingle->type = MOD_REDUNDANT_LOAD_BALANCE;
                        return csingle;
+               } else  if (strcmp(modrefname, "if") == 0) {
+                       if (!cf_section_name2(cs)) {
+                               radlog(L_ERR|L_CONS,
+                                      "%s[%d] 'if' without condition.\n",
+                                      filename, lineno);
+                               return NULL;
+                       }
+
+                       *modname = name2;
+                       csingle= do_compile_modgroup(parent, component, cs,
+                                                    filename,
+                                                    GROUPTYPE_SIMPLE,
+                                                    grouptype);
+                       if (!csingle) return NULL;
+                       csingle->type = MOD_IF;
+
+                       if (condition2actions(csingle, name2) < 0) {
+                               modcallable_free(&csingle);
+                               radlog(L_ERR|L_CONS,
+                                      "%s[%d] Invalid module condition rcode '%s'.\n",
+                                      filename, lineno, name2);
+                               return NULL;
+                       }
+
+                       return csingle;
+               } else  if (strcmp(modrefname, "elsif") == 0) {
+                       if (parent &&
+                           ((parent->type == MOD_LOAD_BALANCE) ||
+                            (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) {
+                               radlog(L_ERR|L_CONS,
+                                      "%s[%d] 'elsif' cannot be used in this section section.\n",
+                                      filename, lineno);
+                               return NULL;
+                       }
+
+                       if (!cf_section_name2(cs)) {
+                               radlog(L_ERR|L_CONS,
+                                      "%s[%d] 'elsif' without condition.\n",
+                                      filename, lineno);
+                               return NULL;
+                       }
+
+                       *modname = name2;
+                       csingle= do_compile_modgroup(parent, component, cs,
+                                                    filename,
+                                                    GROUPTYPE_SIMPLE,
+                                                    grouptype);
+                       if (!csingle) return NULL;
+                       csingle->type = MOD_ELSIF;
+
+                       if (condition2actions(csingle, name2) < 0) {
+                               modcallable_free(&csingle);
+                               radlog(L_ERR|L_CONS,
+                                      "%s[%d] Invalid module condition rcode '%s'.\n",
+                                      filename, lineno, name2);
+                               return NULL;
+                       }
+
+                       return csingle;
+               } else  if (strcmp(modrefname, "else") == 0) {
+                       if (parent &&
+                           ((parent->type == MOD_LOAD_BALANCE) ||
+                            (parent->type == MOD_REDUNDANT_LOAD_BALANCE))) {
+                               radlog(L_ERR|L_CONS,
+                                      "%s[%d] 'else' cannot be used in this section section.\n",
+                                      filename, lineno);
+                               return NULL;
+                       }
+
+                       if (cf_section_name2(cs)) {
+                               radlog(L_ERR|L_CONS,
+                                      "%s[%d] Cannot have conditions on 'else'.\n",
+                                      filename, lineno);
+                               return NULL;
+                       }
+
+                       *modname = name2;
+                       csingle= do_compile_modgroup(parent, component, cs,
+                                                    filename,
+                                                    GROUPTYPE_SIMPLE,
+                                                    grouptype);
+                       if (!csingle) return NULL;
+                       csingle->type = MOD_ELSE;
+                       return csingle;
                }
+
+               /*
+                *      Else it's a module reference, with updated return
+                *      codes.
+                */
        } else {
                CONF_PAIR *cp = cf_itemtopair(ci);
                lineno = cf_pair_lineno(cp);
@@ -999,13 +1193,37 @@ static modcallable *do_compile_modsingle(int component, CONF_ITEM *ci,
        }
 
        /*
-        *      FIXME: See if the module is a virtual one.  If so,
-        *      return that, rather than doing anything here.
+        *      See if the module is a virtual one.  If so, return that,
+        *      rather than doing anything here.
         */
-       this = find_module_instance(modrefname);
+       this = find_module_instance(cf_section_find("modules"), modrefname);
+       if (!this) {
+               CONF_SECTION *cs, *subcs;
+
+               /*
+                *      Then, look for it in the "instantiate" section.
+                */
+               if (((subcs = cf_section_find(NULL)) != NULL) &&
+                   ((cs = cf_section_sub_find_name2(subcs, "instantiate", NULL)) != NULL)) {
+                       subcs = cf_section_sub_find_name2(cs, NULL, modrefname);
+                       if (subcs) {
+                               /*
+                                *      As it's sole configuration, the
+                                *      virtual module takes a section which
+                                *      contains the 
+                                */
+                               return do_compile_modsingle(parent,
+                                                           component,
+                                                           cf_sectiontoitem(subcs),
+                                                           filename,
+                                                           grouptype,
+                                                           modname);
+                       }
+               }
+       }
        if (!this) {
                *modname = NULL;
-               radlog(L_ERR|L_CONS, "%s[%d] Unknown module \"%s\".", filename,
+               radlog(L_ERR|L_CONS, "%s[%d] Failed to find module \"%s\".", filename,
                       lineno, modrefname);
                return NULL;
        }
@@ -1015,8 +1233,11 @@ static modcallable *do_compile_modsingle(int component, CONF_ITEM *ci,
         *      them in.
         */
        single = rad_malloc(sizeof(*single));
+       memset(single, 0, sizeof(*single));
        csingle = mod_singletocallable(single);
+       csingle->parent = parent;
        csingle->next = NULL;
+       csingle->lineno = lineno;
        memcpy(csingle->actions, defaultactions[component][grouptype],
               sizeof csingle->actions);
        rad_assert(modrefname != NULL);
@@ -1066,9 +1287,9 @@ static modcallable *do_compile_modsingle(int component, CONF_ITEM *ci,
         */
        if (!this->entry->module->methods[component]) {
                radlog(L_ERR|L_CONS,
-                      "%s: \"%s\" modules aren't allowed in '%s' sections -- they have no such method.",
-                      filename, this->entry->module->name,
-                      component_names[component]);
+                      "%s[%d]: \"%s\" modules aren't allowed in '%s' sections -- they have no such method.",
+                      filename, lineno, this->entry->module->name,
+                      comp2str[component]);
                modcallable_free(&csingle);
                return NULL;
        }
@@ -1078,31 +1299,41 @@ static modcallable *do_compile_modsingle(int component, CONF_ITEM *ci,
        return csingle;
 }
 
-modcallable *compile_modsingle(int component, CONF_ITEM *ci,
+modcallable *compile_modsingle(modcallable *parent,
+                              int component, CONF_ITEM *ci,
                               const char *filename, const char **modname)
 {
-       modcallable *ret = do_compile_modsingle(component, ci, filename,
+       modcallable *ret = do_compile_modsingle(parent, component, ci,
+                                               filename,
                                                GROUPTYPE_SIMPLE,
                                                modname);
        dump_tree(component, ret);
        return ret;
 }
 
-static modcallable *do_compile_modgroup(int component, CONF_SECTION *cs,
+
+/*
+ *     Internal compile group code.
+ */
+static modcallable *do_compile_modgroup(modcallable *parent,
+                                       int component, CONF_SECTION *cs,
                                        const char *filename, int grouptype,
                                        int parentgrouptype)
 {
+       int i;
        modgroup *g;
        modcallable *c;
        CONF_ITEM *ci;
 
-       g = rad_malloc(sizeof *g);
+       g = rad_malloc(sizeof(*g));
+       memset(g, 0, sizeof(*g));
        g->grouptype = grouptype;
 
        c = mod_grouptocallable(g);
+       c->parent = parent;
        c->next = NULL;
-       memcpy(c->actions, defaultactions[component][parentgrouptype],
-              sizeof(c->actions));
+       c->lineno = cf_section_lineno(cs);
+       memset(c->actions, 0, sizeof(c->actions));
 
        /*
         *      Remember the name for printing, etc.
@@ -1115,11 +1346,18 @@ static modcallable *do_compile_modgroup(int component, CONF_SECTION *cs,
        c->type = MOD_GROUP;
        g->children = NULL;
 
+       /*
+        *      Loop over the children of this group.
+        */
        for (ci=cf_item_find_next(cs, NULL);
             ci != NULL;
             ci=cf_item_find_next(cs, ci)) {
 
-               if(cf_item_is_section(ci)) {
+               /*
+                *      Sections are references to other groups, or
+                *      to modules with updated return codes.
+                */
+               if (cf_item_is_section(ci)) {
                        const char *junk = NULL;
                        modcallable *single;
                        int lineno;
@@ -1127,7 +1365,8 @@ static modcallable *do_compile_modgroup(int component, CONF_SECTION *cs,
 
                        lineno = cf_section_lineno(subcs);
 
-                       single = do_compile_modsingle(component, ci, filename,
+                       single = do_compile_modsingle(c, component, ci,
+                                                     filename,
                                                      grouptype, &junk);
                        if (!single) {
                                radlog(L_ERR|L_CONS,
@@ -1157,9 +1396,12 @@ static modcallable *do_compile_modgroup(int component, CONF_SECTION *cs,
                                modcallable *single;
                                const char *junk = NULL;
 
-                               single = do_compile_modsingle(component,
-                                               cf_pairtoitem(cp), filename,
-                                               grouptype, &junk);
+                               single = do_compile_modsingle(c,
+                                                             component,
+                                                             cf_pairtoitem(cp),
+                                                             filename,
+                                                             grouptype,
+                                                             &junk);
                                if (!single) {
                                        radlog(L_ERR|L_CONS,
                                               "%s[%d] Failed to parse \"%s\" entry.\n",
@@ -1181,15 +1423,26 @@ static modcallable *do_compile_modgroup(int component, CONF_SECTION *cs,
        }
 
        /*
+        *      Set the default actions, if they haven't already been
+        *      set.
+        */
+       for (i = 0; i < RLM_MODULE_NUMCODES; i++) {
+               if (!c->actions[i]) {
+                       c->actions[i] = defaultactions[component][parentgrouptype][i];
+               }
+       }
+
+       /*
         *      FIXME: If there are no children, return NULL?
         */
        return mod_grouptocallable(g);
 }
 
-modcallable *compile_modgroup(int component, CONF_SECTION *cs,
-               const char *filename)
+modcallable *compile_modgroup(modcallable *parent,
+                             int component, CONF_SECTION *cs,
+                             const char *filename)
 {
-       modcallable *ret = do_compile_modgroup(component, cs, filename,
+       modcallable *ret = do_compile_modgroup(parent, component, cs, filename,
                                               GROUPTYPE_SIMPLE,
                                               GROUPTYPE_SIMPLE);
        dump_tree(component, ret);
@@ -1197,7 +1450,7 @@ modcallable *compile_modgroup(int component, CONF_SECTION *cs,
 }
 
 void add_to_modcallable(modcallable **parent, modcallable *this,
-                       int component, char *name)
+                       int component, const char *name)
 {
        modgroup *g;
        
@@ -1207,6 +1460,7 @@ void add_to_modcallable(modcallable **parent, modcallable *this,
                modcallable *c;
 
                g = rad_malloc(sizeof *g);
+               memset(g, 0, sizeof(*g));
                g->grouptype = GROUPTYPE_SIMPLE;
                c = mod_grouptocallable(g);
                c->next = NULL;
index c386b0b..7324b81 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2003  The FreeRADIUS server project
+ * Copyright 2003,2006  The FreeRADIUS server project
  * Copyright 2000  Alan DeKok <aland@ox.org>
  * Copyright 2000  Alan Curry <pacman@world.std.com>
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "radiusd.h"
-#include "modpriv.h"
-#include "modules.h"
-#include "modcall.h"
-#include "conffile.h"
-#include "ltdl.h"
-#include "rad_assert.h"
-
-/*
- *     Internal list of all of the modules we have loaded.
- */
-static module_list_t *module_list = NULL;
-
-/*
- *     Internal list of each module instance.
- */
-static module_instance_t *module_instance_list = NULL;
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modpriv.h>
+#include <freeradius-devel/modcall.h>
+#include <freeradius-devel/rad_assert.h>
 
 typedef struct indexed_modcallable {
-       struct indexed_modcallable *next;
+       int comp;
        int idx;
        modcallable *modulelist;
 } indexed_modcallable;
@@ -58,148 +45,150 @@ typedef struct indexed_modcallable {
 /*
  *     For each component, keep an ordered list of ones to call.
  */
-static indexed_modcallable *components[RLM_COMPONENT_COUNT];
+static lrad_hash_table_t *components;
+
+static rbtree_t *module_tree = NULL;
+
+typedef struct section_type_value_t {
+       const char      *section;
+       const char      *typename;
+       int             attr;
+} section_type_value_t;
+
 
 /*
- *     The component names.
- *
- *     Hmm... we probably should be getting these from the configuration
- *     file, too.
+ *     Ordered by component
  */
-const char *component_names[RLM_COMPONENT_COUNT] =
-{
-       "authenticate",
-       "authorize",
-       "preacct",
-       "accounting",
-       "session",
-       "pre-proxy",
-       "post-proxy",
-       "post-auth"
+static const section_type_value_t section_type_value[RLM_COMPONENT_COUNT] = {
+       { "authenticate", "Auth-Type",       PW_AUTH_TYPE },
+       { "authorize",    "Autz-Type",       PW_AUTZ_TYPE },
+       { "preacct",      "Pre-Acct-Type",   PW_PRE_ACCT_TYPE },
+       { "accounting",   "Acct-Type",       PW_ACCT_TYPE },
+       { "session",      "Session-Type",    PW_SESSION_TYPE },
+       { "pre-proxy",    "Pre-Proxy-Type",  PW_PRE_PROXY_TYPE },
+       { "post-proxy",   "Post-Proxy-Type", PW_POST_PROXY_TYPE },
+       { "post-auth",    "Post-Auth-Type",  PW_POST_AUTH_TYPE },
 };
 
 /*
  *     Delete ASAP.
  */
-static const char *old_subcomponent_names[RLM_COMPONENT_COUNT] =
-{
-       "authtype",
-       "autztype",
-       "preacctype",
-       "acctype",
-       "sesstype",
-       "pre-proxytype",
-       "post-proxytype",
-       "post-authtype"
+static const section_type_value_t old_section_type_value[] = {
+       { "authenticate", "authtype", PW_AUTH_TYPE },
+       { "authorize",    "autztype", PW_AUTZ_TYPE },
+       { "preacct",      "Pre-Acct-Type",   PW_PRE_ACCT_TYPE },/* unused */
+       { "accounting",   "acctype", PW_ACCT_TYPE },
+       { "session",      "sesstype", PW_SESSION_TYPE },
+       { "pre-proxy",    "Pre-Proxy-Type",  PW_PRE_PROXY_TYPE }, /* unused */
+       { "post-proxy",   "Post-Proxy-Type", PW_POST_PROXY_TYPE }, /* unused */
+       { "post-auth",    "post-authtype", PW_POST_AUTH_TYPE }
 };
 
-static const char *subcomponent_names[RLM_COMPONENT_COUNT] =
+
+static void indexed_modcallable_free(void *data)
 {
-       "Auth-Type",
-       "Autz-Type",
-       "Pre-Acct-Type",
-       "Acct-Type",
-       "Session-Type",
-       "Pre-Proxy-Type",
-       "Post-Proxy-Type",
-       "Post-Auth-Type"
-};
+       indexed_modcallable *c = data;
 
-static void indexed_modcallable_free(indexed_modcallable **cf)
+       modcallable_free(&c->modulelist);
+       free(c);
+}
+
+static uint32_t indexed_modcallable_hash(const void *data)
 {
-       indexed_modcallable     *c, *next;
+       uint32_t hash;
+       const indexed_modcallable *c = data;
 
-       c = *cf;
-       while (c) {
-               next = c->next;
-               modcallable_free(&c->modulelist);
-               free(c);
-               c = next;
-       }
-       *cf = NULL;
+       hash = lrad_hash(&c->comp, sizeof(c->comp));
+       return lrad_hash_update(&c->idx, sizeof(c->idx), hash);
 }
 
-static void instance_list_free(module_instance_t **i)
+static int indexed_modcallable_cmp(const void *one, const void *two)
 {
-       module_instance_t       *c, *next;
+       const indexed_modcallable *a = one;
+       const indexed_modcallable *b = two;
+
+       if (a->comp < b->comp) return -1;
+       if (a->comp >  b->comp) return +1;
 
-       c = *i;
-       while (c) {
-               next = c->next;
-               if(c->entry->module->detach)
-                       (c->entry->module->detach)(c->insthandle);
+       return a->idx - b->idx;
+}
+
+
+/*
+ *     Free a module instance.
+ */
+static void module_instance_free(void *data)
+{
+       module_instance_t *this = data;
+
+       if (this->entry->module->detach)
+               (this->entry->module->detach)(this->insthandle);
 #ifdef HAVE_PTHREAD_H
-               if (c->mutex) {
-                       /*
-                        *      FIXME
-                        *      The mutex MIGHT be locked...
-                        *      we'll check for that later, I guess.
-                        */
-                       pthread_mutex_destroy(c->mutex);
-                       free(c->mutex);
-               }
-#endif
-               free(c);
-               c = next;
+       if (this->mutex) {
+               /*
+                *      FIXME
+                *      The mutex MIGHT be locked...
+                *      we'll check for that later, I guess.
+                */
+               pthread_mutex_destroy(this->mutex);
+               free(this->mutex);
        }
-       *i = NULL;
+#endif
+       free(this);
 }
 
+
 /*
- *     Remove all of the modules.
+ *     Compare two module entries
  */
-int detach_modules(void)
+static int module_entry_cmp(const void *one, const void *two)
 {
-       module_list_t *ml, *next;
-       int i;
+       const module_entry_t *a = one;
+       const module_entry_t *b = two;
 
-       /*
-        *      Delete the internal component pointers.
-        */
-       for (i = 0; i < RLM_COMPONENT_COUNT; i++) {
-               indexed_modcallable_free(&components[i]);
-       }
+       return strcmp(a->name, b->name);
+}
 
-       instance_list_free(&module_instance_list);
+/*
+ *     Free a module entry.
+ */
+static void module_entry_free(void *data)
+{
+       module_entry_t *this = data;
 
-       ml = module_list;
-       while (ml) {
-               next = ml->next;
-               if (ml->module->destroy)
-                       (ml->module->destroy)();
-               lt_dlclose(ml->handle); /* ignore any errors */
-               free(ml);
-               ml = next;
-       }
+       lt_dlclose(this->handle);       /* ignore any errors */
+       free(this);
+}
 
-       module_list = NULL;
+
+/*
+ *     Remove the module lists.
+ */
+int detach_modules(void)
+{
+       lrad_hash_table_free(components);
+       rbtree_free(module_tree);
 
        return 0;
 }
 
+
 /*
  *     Find a module on disk or in memory, and link to it.
  */
-static module_list_t *linkto_module(const char *module_name,
-               const char *cffilename, int cflineno)
+static module_entry_t *linkto_module(const char *module_name,
+                                    const char *cffilename, int cflineno)
 {
-       module_list_t *node;
+       module_entry_t myentry;
+       module_entry_t *node;
        lt_dlhandle handle;
        char module_struct[256];
        char *p;
+       const void *module;
 
-       /*
-        *      Look through the global module library list for the
-        *      named module.
-        */
-       for (node = module_list; node != NULL; node = node->next) {
-               /*
-                *      Found the named module.  Return it.
-                */
-               if (strcmp(node->name, module_name) == 0)
-                       return node;
-
-       }
+       strlcpy(myentry.name, module_name, sizeof(myentry.name));
+       node = rbtree_finddata(module_tree, &myentry);
+       if (node) return node;
 
        /*
         *      Keep the handle around so we can dlclose() it.
@@ -207,50 +196,65 @@ static module_list_t *linkto_module(const char *module_name,
        handle = lt_dlopenext(module_name);
        if (handle == NULL) {
                radlog(L_ERR|L_CONS, "%s[%d] Failed to link to module '%s':"
-                               " %s\n", cffilename, cflineno, module_name, lt_dlerror());
+                      " %s\n", cffilename, cflineno, module_name, lt_dlerror());
                return NULL;
        }
 
-       /* make room for the module type */
-       node = (module_list_t *) rad_malloc(sizeof(module_list_t));
-
-       /* fill in the module structure */
-       node->next = NULL;
-       node->handle = handle;
-       strNcpy(node->name, module_name, sizeof(node->name));
-
        /*
         *      Link to the module's rlm_FOO{} module structure.
+        *
+        *      The module_name variable has the version number
+        *      embedded in it, and we don't want that here.
         */
-       /* module_name has the version embedded; strip it. */
        strcpy(module_struct, module_name);
        p = strrchr(module_struct, '-');
-       if (p)
-               *p = '\0';
-       node->module = (module_t *) lt_dlsym(node->handle, module_struct);
-       if (!node->module) {
+       if (p) *p = '\0';
+
+       DEBUG3("    (Loaded %s, checking if it's valid)", module_name);
+
+       /*
+        *      libltld MAY core here, if the handle it gives us contains
+        *      garbage data.
+        */
+       module = lt_dlsym(handle, module_struct);
+       if (!module) {
                radlog(L_ERR|L_CONS, "%s[%d] Failed linking to "
                                "%s structure in %s: %s\n",
                                cffilename, cflineno,
                                module_name, cffilename, lt_dlerror());
-               lt_dlclose(node->handle);       /* ignore any errors */
-               free(node);
+               lt_dlclose(handle);
                return NULL;
        }
-
-       /* call the modules initialization */
-       if (node->module->init && (node->module->init)() < 0) {
-               radlog(L_ERR|L_CONS, "%s[%d] Module initialization failed.\n",
-                               cffilename, cflineno);
-               lt_dlclose(node->handle);       /* ignore any errors */
-               free(node);
+       /*
+        *      Before doing anything else, check if it's sane.
+        */
+       if ((*(const uint32_t *) module) != RLM_MODULE_MAGIC_NUMBER) {
+               lt_dlclose(handle);
+               radlog(L_ERR|L_CONS, "%s[%d] Invalid version in module '%s'",
+                      cffilename, cflineno, module_name);
                return NULL;
+               
        }
 
+       /* make room for the module type */
+       node = rad_malloc(sizeof(*node));
+       memset(node, 0, sizeof(*node));
+       strlcpy(node->name, module_name, sizeof(node->name));
+       node->module = module;
+       node->handle = handle;
+
        DEBUG("Module: Loaded %s ", node->module->name);
 
-       node->next = module_list;
-       module_list = node;
+       /*
+        *      Add the module as "rlm_foo-version" to the configuration
+        *      section.
+        */
+       if (!rbtree_insert(module_tree, node)) {
+               radlog(L_ERR, "Failed to cache module %s", module_name);
+               lt_dlclose(handle);
+               free(node);
+               return NULL;
+       }
 
        return node;
 }
@@ -258,44 +262,15 @@ static module_list_t *linkto_module(const char *module_name,
 /*
  *     Find a module instance.
  */
-module_instance_t *find_module_instance(const char *instname)
+module_instance_t *find_module_instance(CONF_SECTION *modules,
+                                       const char *instname)
 {
-       CONF_SECTION *cs, *inst_cs;
+       CONF_SECTION *cs;
        const char *name1, *name2;
-       module_instance_t *node, **last;
+       module_instance_t *node;
        char module_name[256];
 
-       /*
-        *      Look through the global module instance list for the
-        *      named module.
-        */
-       last = &module_instance_list;
-       for (node = module_instance_list; node != NULL; node = node->next) {
-               /*
-                *      Found the named instance.  Return it.
-                */
-               if (strcmp(node->name, instname) == 0)
-                       return node;
-
-               /*
-                *      Keep a pointer to the last entry to update...
-                */
-               last = &node->next;
-       }
-
-       /*
-        *      Instance doesn't exist yet. Try to find the
-        *      corresponding configuration section and create it.
-        */
-
-       /*
-        *      Look for the 'modules' configuration section.
-        */
-       cs = cf_section_find("modules");
-       if (cs == NULL) {
-               radlog(L_ERR|L_CONS, "ERROR: Cannot find a 'modules' section in the configuration file.\n");
-               return NULL;
-       }
+       if (!modules) return NULL;
 
        /*
         *      Module instances are declared in the modules{} block
@@ -303,49 +278,38 @@ module_instance_t *find_module_instance(const char *instname)
         *      name2 from the config section, or name1 if there was
         *      no name2.
         */
-       name1 = name2 = NULL;
-       for(inst_cs=cf_subsection_find_next(cs, NULL, NULL);
-                       inst_cs != NULL;
-                       inst_cs=cf_subsection_find_next(cs, inst_cs, NULL)) {
-               name1 = cf_section_name1(inst_cs);
-               name2 = cf_section_name2(inst_cs);
-               if ( (name2 && !strcmp(name2, instname)) ||
-                    (!name2 && !strcmp(name1, instname)) )
-                       break;
-       }
-       if (inst_cs == NULL) {
+       cs = cf_section_sub_find_name2(modules, NULL, instname);
+       if (cs == NULL) {
                radlog(L_ERR|L_CONS, "ERROR: Cannot find a configuration entry for module \"%s\".\n", instname);
                return NULL;
        }
 
        /*
-        *      Found the configuration entry.
+        *      If there's already a module instance, return it.
         */
-       node = rad_malloc(sizeof(*node));
-       node->next = NULL;
-       node->insthandle = NULL;
+       node = cf_data_find(cs, "instance");
+       if (node) return node;
+
+       name1 = cf_section_name1(cs);
+       name2 = cf_section_name2(cs);
 
        /*
-        *      Link to the module by name: rlm_FOO-major.minor
+        *      Found the configuration entry.
         */
-       if (strncmp(name1, "rlm_", 4)) {
-#if 0
-               snprintf(module_name, sizeof(module_name), "rlm_%s-%d.%d",
-                        name1, RADIUSD_MAJOR_VERSION, RADIUSD_MINOR_VERSION);
-#else
-               snprintf(module_name, sizeof(module_name), "rlm_%s",
-                        name1);
-#endif
-       } else {
-               strNcpy(module_name, name1, sizeof(module_name));
+       node = rad_malloc(sizeof(*node));
+       memset(node, 0, sizeof(*node));
 
-       }
+       node->insthandle = NULL;
 
        /*
-        *  FIXME: "radiusd.conf" is wrong here; must find cf filename
+        *      Names in the "modules" section aren't prefixed
+        *      with "rlm_", so we add it here.
         */
-       node->entry = linkto_module(module_name, "radiusd.conf",
-                                   cf_section_lineno(inst_cs));
+       snprintf(module_name, sizeof(module_name), "rlm_%s", name1);
+
+       node->entry = linkto_module(module_name,
+                                   mainconfig.radiusd_conf,
+                                   cf_section_lineno(cs));
        if (!node->entry) {
                free(node);
                /* linkto_module logs any errors */
@@ -356,11 +320,11 @@ module_instance_t *find_module_instance(const char *instname)
         *      Call the module's instantiation routine.
         */
        if ((node->entry->module->instantiate) &&
-           ((node->entry->module->instantiate)(inst_cs,
-                       &node->insthandle) < 0)) {
+           ((node->entry->module->instantiate)(cs, &node->insthandle) < 0)) {
                radlog(L_ERR|L_CONS,
-                               "radiusd.conf[%d]: %s: Module instantiation failed.\n",
-                               cf_section_lineno(inst_cs), instname);
+                               "%s[%d]: %s: Module instantiation failed.\n",
+                      mainconfig.radiusd_conf, cf_section_lineno(cs),
+                      instname);
                free(node);
                return NULL;
        }
@@ -369,7 +333,7 @@ module_instance_t *find_module_instance(const char *instname)
         *      We're done.  Fill in the rest of the data structure,
         *      and link it to the module instance list.
         */
-       strNcpy(node->name, instname, sizeof(node->name));
+       strlcpy(node->name, instname, sizeof(node->name));
 
 #ifdef HAVE_PTHREAD_H
        /*
@@ -391,146 +355,150 @@ module_instance_t *find_module_instance(const char *instname)
        }
 
 #endif
-       *last = node;
+       cf_data_add(cs, "instance", node, module_instance_free);
 
        DEBUG("Module: Instantiated %s (%s) ", name1, node->name);
 
        return node;
 }
 
-static indexed_modcallable *lookup_by_index(indexed_modcallable *head, int idx)
+static indexed_modcallable *lookup_by_index(int comp, int idx)
 {
-       indexed_modcallable *p;
+       indexed_modcallable myc;
 
-       for (p = head; p != NULL; p = p->next) {
-               if( p->idx == idx)
-                       return p;
-       }
-       return NULL;
+       myc.comp = comp;
+       myc.idx = idx;
+
+       return lrad_hash_table_finddata(components, &myc);
 }
 
+/*
+ *     Create a new sublist.
+ */
 static indexed_modcallable *new_sublist(int comp, int idx)
 {
-       indexed_modcallable **head = &components[comp];
-       indexed_modcallable *node = *head;
-       indexed_modcallable **last = head;
-
-       while (node) {
-               /* It is an error to try to create a sublist that already
-                * exists. It would almost certainly be caused by accidental
-                * duplication in the config file.
-                *
-                * index 0 is the exception, because it is used when we want
-                * to collect _all_ listed modules under a single index by
-                * default, which is currently the case in all components
-                * except authenticate. */
-               if (node->idx == idx) {
-                       if (idx == 0)
-                               return node;
-                       else
-                               return NULL;
+       indexed_modcallable *c;
+
+       c = lookup_by_index(comp, idx);
+
+       /* It is an error to try to create a sublist that already
+        * exists. It would almost certainly be caused by accidental
+        * duplication in the config file.
+        *
+        * index 0 is the exception, because it is used when we want
+        * to collect _all_ listed modules under a single index by
+        * default, which is currently the case in all components
+        * except authenticate. */
+       if (c) {
+               if (idx == 0) {
+                       return c;
                }
-               last = &node->next;
-               node = node->next;
+               return NULL;
        }
 
-       node = rad_malloc(sizeof *node);
-       node->next = NULL;
-       node->modulelist = NULL;
-       node->idx = idx;
-       *last = node;
-       return node;
+       c = rad_malloc(sizeof(*c));
+       c->modulelist = NULL;
+       c->comp = comp;
+       c->idx = idx;
+
+       if (!lrad_hash_table_insert(components, c)) {
+               free(c);
+               return NULL;
+       }
+
+       return c;
 }
 
 static int indexed_modcall(int comp, int idx, REQUEST *request)
 {
+       int rcode;
        indexed_modcallable *this;
 
-       this = lookup_by_index(components[comp], idx);
+       this = lookup_by_index(comp, idx);
        if (!this) {
                if (idx != 0) DEBUG2("  ERROR: Unknown value specified for %s.  Cannot perform requested action.",
-                                    subcomponent_names[comp]);
-               /* Return a default value appropriate for the component */
-               switch(comp) {
-                       case RLM_COMPONENT_AUTZ:    return RLM_MODULE_NOTFOUND;
-                       case RLM_COMPONENT_AUTH:    return RLM_MODULE_REJECT;
-                       case RLM_COMPONENT_PREACCT: return RLM_MODULE_NOOP;
-                       case RLM_COMPONENT_ACCT:    return RLM_MODULE_NOOP;
-                       case RLM_COMPONENT_SESS:    return RLM_MODULE_FAIL;
-                       case RLM_COMPONENT_PRE_PROXY:  return RLM_MODULE_NOOP;
-                       case RLM_COMPONENT_POST_PROXY: return RLM_MODULE_NOOP;
-                       case RLM_COMPONENT_POST_AUTH:  return RLM_MODULE_NOOP;
-                       default:                    return RLM_MODULE_FAIL;
-               }
+                                    section_type_value[comp].typename);
+               request->component = section_type_value[comp].typename;
+               rcode = modcall(comp, NULL, request); /* does default action */
+       } else {
+               DEBUG2("  Processing the %s section of %s",
+                      section_type_value[comp].section,
+                      mainconfig.radiusd_conf);
+               request->component = section_type_value[comp].typename;
+               rcode = modcall(comp, this->modulelist, request);
        }
-
-       DEBUG2("  Processing the %s section of radiusd.conf",
-              component_names[comp]);
-       return modcall(comp, this->modulelist, request);
+       request->module = "<server-core>";
+       request->component = "<server-core>";
+       return rcode;
 }
 
-/* Load a flat module list, as found inside an authtype{} block */
-static int load_subcomponent_section(CONF_SECTION *cs, int comp,
-                                     const char *filename)
+/*
+ *     Load a sub-module list, as found inside an Auth-Type foo {}
+ *     block
+ */
+static int load_subcomponent_section(modcallable *parent,
+                                    CONF_SECTION *cs, int comp,
+                                    const char *filename)
 {
-       int idx;
        indexed_modcallable *subcomp;
        modcallable *ml;
        DICT_VALUE *dval;
+       const char *name2 = cf_section_name2(cs);
 
-       static int meaningless_counter = 1;
+       rad_assert(comp >= RLM_COMPONENT_AUTH);
+       rad_assert(comp <= RLM_COMPONENT_COUNT);
 
-       ml = compile_modgroup(comp, cs, filename);
-       if (!ml) {
-               return 0;
+       /*
+        *      Sanity check.
+        */
+       if (!name2) {
+               radlog(L_ERR|L_CONS,
+                      "%s[%d]: No name specified for %s block",
+                      filename, cf_section_lineno(cs),
+                      section_type_value[comp].typename);
+               return 1;
        }
 
-       /* We must assign a numeric index to this subcomponent. For
-        * auth, it is generated and placed in the dictionary by
-        * new_sectiontype_value(). The others are just numbers that are pulled
-        * out of thin air, and the names are neither put into the dictionary
-        * nor checked for uniqueness, but all that could be fixed in a few
-        * minutes, if anyone finds a real use for indexed config of
-        * components other than auth. */
-       dval = NULL;
-       if (comp==RLM_COMPONENT_AUTH) {
-               dval = dict_valbyname(PW_AUTH_TYPE, cf_section_name2(cs));
-       } else if (comp == RLM_COMPONENT_AUTZ) {
-               dval = dict_valbyname(PW_AUTZ_TYPE, cf_section_name2(cs));
-       } else if (comp == RLM_COMPONENT_ACCT) {
-               dval = dict_valbyname(PW_ACCT_TYPE, cf_section_name2(cs));
-       } else if (comp == RLM_COMPONENT_SESS) {
-               dval = dict_valbyname(PW_SESSION_TYPE, cf_section_name2(cs));
-       } else if (comp == RLM_COMPONENT_PRE_PROXY) {
-               dval = dict_valbyname(PW_PRE_PROXY_TYPE, cf_section_name2(cs));
-       } else if (comp == RLM_COMPONENT_POST_PROXY) {
-               dval = dict_valbyname(PW_POST_PROXY_TYPE, cf_section_name2(cs));
-       } else if (comp == RLM_COMPONENT_POST_AUTH) {
-               dval = dict_valbyname(PW_POST_AUTH_TYPE, cf_section_name2(cs));
-       }
+       /*
+        *      Compile the group.
+        */
+       ml = compile_modgroup(parent, comp, cs, filename);
+       if (!ml) {
+               return 0;
+       }       
 
-       if (dval) {
-               idx = dval->value;
-       } else {
-               idx = meaningless_counter++;
+       /*
+        *      We must assign a numeric index to this subcomponent.
+        *      It is generated and placed in the dictionary by
+        *      setup_modules(), when it loads the sections.  If it
+        *      isn't found, it's a serious error.
+        */
+       dval = dict_valbyname(section_type_value[comp].attr, name2);
+       if (!dval) {
+               radlog(L_ERR|L_CONS,
+                      "%s[%d] %s %s Not previously configured",
+                      filename, cf_section_lineno(cs),
+                      section_type_value[comp].typename, name2);
+               modcallable_free(&ml);
+               return 0;
        }
 
-       subcomp = new_sublist(comp, idx);
+       subcomp = new_sublist(comp, dval->value);
        if (!subcomp) {
                radlog(L_ERR|L_CONS,
-                               "%s[%d] %s %s already configured - skipping",
-                               filename, cf_section_lineno(cs),
-                               subcomponent_names[comp], cf_section_name2(cs));
+                      "%s[%d] %s %s already configured - skipping",
+                      filename, cf_section_lineno(cs),
+                      section_type_value[comp].typename, name2);
                modcallable_free(&ml);
                return 1;
        }
 
        subcomp->modulelist = ml;
-
-       return 1;
+       return 1;               /* OK */
 }
 
-static int load_component_section(CONF_SECTION *cs, int comp,
+static int load_component_section(modcallable *parent,
+                                 CONF_SECTION *cs, int comp,
                                  const char *filename)
 {
        modcallable *this;
@@ -538,14 +506,25 @@ static int load_component_section(CONF_SECTION *cs, int comp,
        int idx;
        indexed_modcallable *subcomp;
        const char *modname;
-       char *visiblename;
+       const char *visiblename;
 
-       for (modref=cf_item_find_next(cs, NULL);
-                       modref != NULL;
-                       modref=cf_item_find_next(cs, modref)) {
+       /*
+        *      Loop over the entries in the named section.
+        */
+       for (modref = cf_item_find_next(cs, NULL);
+            modref != NULL;
+            modref = cf_item_find_next(cs, modref)) {
                CONF_PAIR *cp = NULL;
                CONF_SECTION *scs = NULL;
 
+               /*
+                *      Look for Auth-Type foo {}, which are special
+                *      cases of named sections, and allowable ONLY
+                *      at the top-level.
+                *
+                *      i.e. They're not allowed in a "group" or "redundant"
+                *      subsection.
+                */
                if (cf_item_is_section(modref)) {
                        const char *sec_name;
                        scs = cf_itemtosection(modref);
@@ -553,8 +532,9 @@ static int load_component_section(CONF_SECTION *cs, int comp,
                        sec_name = cf_section_name1(scs);
 
                        if (strcmp(sec_name,
-                                  subcomponent_names[comp]) == 0) {
-                               if (!load_subcomponent_section(scs, comp,
+                                  section_type_value[comp].typename) == 0) {
+                               if (!load_subcomponent_section(parent, scs,
+                                                              comp,
                                                               filename)) {
                                        return -1; /* FIXME: memleak? */
                                }
@@ -565,26 +545,33 @@ static int load_component_section(CONF_SECTION *cs, int comp,
                         *      Allow old names, too.
                         */
                        if (strcmp(sec_name,
-                                  old_subcomponent_names[comp]) == 0) {
-                               if (!load_subcomponent_section(scs, comp,
+                                  old_section_type_value[comp].typename) == 0) {
+                               if (!load_subcomponent_section(parent, scs,
+                                                              comp,
                                                               filename)) {
                                        return -1; /* FIXME: memleak? */
                                }
                                continue;
                        }
                        cp = NULL;
-               } else {
+               } else if (cf_item_is_pair(modref)) {
                        cp = cf_itemtopair(modref);
+               } else {
+                       continue; /* ignore it */
                }
 
-               this = compile_modsingle(comp, modref, filename, &modname);
-                if (!this) {
-                        radlog(L_ERR|L_CONS,
-                               "%s[%d] Failed to parse %s section.\n",
-                               filename, cf_section_lineno(cs),
-                               cf_section_name1(cs));
-                        return -1;
-                }
+               /*
+                *      Try to compile one entry.
+                */
+               this = compile_modsingle(parent, comp, modref, filename,
+                                        &modname);
+               if (!this) {
+                       radlog(L_ERR|L_CONS,
+                              "%s[%d] Failed to parse %s section.\n",
+                              filename, cf_section_lineno(cs),
+                              cf_section_name1(cs));
+                       return -1;
+               }
 
                if (comp == RLM_COMPONENT_AUTH) {
                        DICT_VALUE *dval;
@@ -597,7 +584,6 @@ static int load_component_section(CONF_SECTION *cs, int comp,
                        } else {
                                modrefname = cf_section_name2(scs);
                                lineno = cf_section_lineno(scs);
-
                                if (!modrefname) {
                                        radlog(L_ERR|L_CONS,
                                               "%s[%d] Failed to parse %s sub-section.\n",
@@ -606,16 +592,16 @@ static int load_component_section(CONF_SECTION *cs, int comp,
                                        return -1;
                                }
                        }
-                       
+
                        dval = dict_valbyname(PW_AUTH_TYPE, modrefname);
                        if (!dval) {
                                /*
                                 *      It's a section, but nothing we
                                 *      recognize.  Die!
                                 */
-                               radlog(L_ERR|L_CONS, "%s[%d] Unknown Auth-Type \"%s\" in %s section.",
+                               radlog(L_ERR|L_CONS, "%s[%d] Unknown Auth-Type \"%s\" in %s sub-section.",
                                       filename, lineno,
-                                      modrefname, component_names[comp]);
+                                      modrefname, section_type_value[comp].section);
                                return -1;
                        }
                        idx = dval->value;
@@ -629,7 +615,7 @@ static int load_component_section(CONF_SECTION *cs, int comp,
                if (subcomp == NULL) {
                        radlog(L_INFO|L_CONS,
                                        "%s %s %s already configured - skipping",
-                                       filename, subcomponent_names[comp],
+                                       filename, section_type_value[comp].typename,
                                        modname);
                        modcallable_free(&this);
                        continue;
@@ -641,41 +627,12 @@ static int load_component_section(CONF_SECTION *cs, int comp,
                if (visiblename == NULL)
                        visiblename = cf_section_name1(cs);
                add_to_modcallable(&subcomp->modulelist, this,
-                               comp, visiblename);
+                                  comp, visiblename);
        }
 
        return 0;
 }
 
-typedef struct section_type_value_t {
-       const char      *section;
-       const char      *typename;
-       int             attr;
-} section_type_value_t;
-
-static const section_type_value_t section_type_value[] = {
-       { "authorize",    "Autz-Type",       PW_AUTZ_TYPE },
-       { "authenticate", "Auth-Type",       PW_AUTH_TYPE },
-       { "accounting",   "Acct-Type",       PW_ACCT_TYPE },
-       { "session",      "Session-Type",    PW_SESSION_TYPE },
-       { "post-auth",    "Post-Auth-Type",  PW_POST_AUTH_TYPE },
-       { "preacct",      "Pre-Acct-Type",   PW_PRE_ACCT_TYPE },
-       { "post-proxy",   "Post-Proxy-Type", PW_POST_PROXY_TYPE },
-       { "pre-proxy",    "Pre-Proxy-Type",  PW_PRE_PROXY_TYPE },
-       { NULL, NULL, 0 }
-};
-
-/*
- *     Delete ASAP.
- */
-static const section_type_value_t old_section_type_value[] = {
-       { "authorize",    "autztype", PW_AUTZ_TYPE },
-       { "authenticate", "authtype", PW_AUTH_TYPE },
-       { "accounting",   "acctype", PW_ACCT_TYPE },
-       { "session",      "sesstype", PW_SESSION_TYPE },
-       { "post-auth",    "post-authtype", PW_POST_AUTH_TYPE },
-       { NULL, NULL, 0 }
-};
 
 /*
  *     Parse the module config sections, and load
@@ -684,20 +641,17 @@ static const section_type_value_t old_section_type_value[] = {
  *     Libtool makes your life a LOT easier, especially with libltdl.
  *     see: http://www.gnu.org/software/libtool/
  */
-int setup_modules(void)
+int setup_modules(int reload)
 {
-       int comp;
-       CONF_SECTION *cs;
-
-       /*
-        *  FIXME: This should be pulled from somewhere else.
-        */
-       const char *filename="radiusd.conf";
+       int             comp;
+       CONF_SECTION    *cs, *modules;
+       int             do_component[RLM_COMPONENT_COUNT];
+       rad_listen_t    *listener;
 
        /*
-        *      No current list of modules: Go initialize libltdl.
+        *      If necessary, initialize libltdl.
         */
-       if (!module_list) {
+       if (!reload) {
                /*
                 *      Set the default list of preloaded symbols.
                 *      This is used to initialize libltdl's list of
@@ -710,8 +664,7 @@ int setup_modules(void)
                if (lt_dlinit() != 0) {
                        radlog(L_ERR|L_CONS, "Failed to initialize libraries: %s\n",
                                        lt_dlerror());
-                       exit(1); /* FIXME */
-
+                       return -1;
                }
 
                /*
@@ -725,14 +678,66 @@ int setup_modules(void)
                                lt_dlgetsearchpath());
 
                /*
-                *      Initialize the components.
+                *      Set up the internal module struct.
                 */
-               for (comp = 0; comp < RLM_COMPONENT_COUNT; comp++) {
-                       components[comp] = NULL;
+               module_tree = rbtree_create(module_entry_cmp,
+                                           module_entry_free, 0);
+               if (!module_tree) {
+                       radlog(L_ERR|L_CONS, "Failed to initialize modules\n");
+                       return -1;
                }
-
        } else {
-               detach_modules();
+               lrad_hash_table_free(components);
+       }
+
+       components = lrad_hash_table_create(indexed_modcallable_hash,
+                                           indexed_modcallable_cmp,
+                                           indexed_modcallable_free);
+       if (!components) {
+               radlog(L_ERR|L_CONS, "Failed to initialize components\n");
+               return -1;
+       }
+
+       /*
+        *      Figure out which sections to load.
+        */
+       memset(do_component, 0, sizeof(do_component));
+       for (listener = mainconfig.listen;
+            listener != NULL;
+            listener = listener->next) {
+               switch (listener->type) {
+               case RAD_LISTEN_AUTH:
+                       do_component[RLM_COMPONENT_AUTZ] = 1;
+                       do_component[RLM_COMPONENT_AUTH] = 1;
+                       do_component[RLM_COMPONENT_POST_AUTH] = 1;
+                       do_component[RLM_COMPONENT_SESS] = 1;
+                       break;
+
+               case RAD_LISTEN_DETAIL: /* just like acct */
+               case RAD_LISTEN_ACCT:
+                       do_component[RLM_COMPONENT_PREACCT] = 1;
+                       do_component[RLM_COMPONENT_ACCT] = 1;
+                       break;
+
+               case RAD_LISTEN_PROXY:
+                       do_component[RLM_COMPONENT_PRE_PROXY] = 1;
+                       do_component[RLM_COMPONENT_POST_PROXY] = 1;
+                       break;
+
+               default:
+                       rad_assert(0 == 1);
+                       break;
+               }
+       }
+
+       for (comp = RLM_COMPONENT_AUTH; comp < RLM_COMPONENT_COUNT; comp++) {
+               /*
+                *      Have the debugging messages all in one place.
+                */
+               if (!do_component[comp]) {
+                       DEBUG2("modules: Not loading %s{} section",
+                              section_type_value[comp].section);
+               }
        }
 
        /*
@@ -742,7 +747,8 @@ int setup_modules(void)
         *      let the user create new names, we've got to look for
         *      those names, and create DICT_VALUE's for them.
         */
-       for (comp = 0; section_type_value[comp].section != NULL; comp++) {
+       for (comp = RLM_COMPONENT_AUTH; comp < RLM_COMPONENT_COUNT; comp++) {
+               int             value;
                const char      *name2;
                DICT_ATTR       *dattr;
                DICT_VALUE      *dval;
@@ -750,10 +756,11 @@ int setup_modules(void)
                CONF_PAIR       *cp;
 
                /*
-                *  Big-time YUCK
+                *      Not needed, don't load it.
                 */
-               static int my_value = 32767;
-
+               if (!do_component[comp]) {
+                       continue;
+               }
                cs = cf_section_find(section_type_value[comp].section);
 
                if (!cs) continue;
@@ -765,13 +772,12 @@ int setup_modules(void)
                         *      name.
                         */
                        next = cf_subsection_find_next(cs, sub,
-                                                     section_type_value[comp].typename);
+                                                      section_type_value[comp].typename);
 
                        /*
                         *      Allow some old names, too.
                         */
                        if (!next && (comp <= 4)) {
-
                                next = cf_subsection_find_next(cs, sub,
                                                               old_section_type_value[comp].typename);
                        }
@@ -797,14 +803,28 @@ int setup_modules(void)
                                 *      Find the attribute for the value.
                         */
                        dattr = dict_attrbyvalue(section_type_value[comp].attr);
-                       if (!dattr) continue;
+                       if (!dattr) {
+                               radlog(L_ERR, "%s[%d]: No such attribute %s",
+                                      mainconfig.radiusd_conf,
+                                      cf_section_lineno(sub),
+                                      section_type_value[comp].typename);
+                               continue;
+                       }
 
                        /*
-                        *      Finally, create the new attribute.
+                        *      Create a new unique value with a
+                        *      meaningless number.  You can't look at
+                        *      it from outside of this code, so it
+                        *      doesn't matter.  The only requirement
+                        *      is that it's unique.
                         */
-                       if (dict_addvalue(name2, dattr->name, my_value++) < 0) {
+                       do {
+                               value = lrad_rand() & 0x00ffffff;
+                       } while (dict_valbyattr(dattr->attr, value));
+
+                       if (dict_addvalue(name2, dattr->name, value) < 0) {
                                radlog(L_ERR, "%s", librad_errstr);
-                               exit(1);
+                               return -1;
                        }
                } while (sub != NULL);
 
@@ -834,19 +854,37 @@ int setup_modules(void)
                                 *      Find the attribute for the value.
                         */
                        dattr = dict_attrbyvalue(section_type_value[comp].attr);
-                       if (!dattr) continue;
+                       if (!dattr) {
+                               radlog(L_ERR, "%s[%d]: No such attribute %s",
+                                      mainconfig.radiusd_conf,
+                                      cf_section_lineno(sub),
+                                      section_type_value[comp].typename);
+                               continue;
+                       }
 
                        /*
                         *      Finally, create the new attribute.
                         */
-                       if (dict_addvalue(name2, dattr->name, my_value++) < 0) {
+                       do {
+                               value = lrad_rand() & 0x00ffffff;
+                       } while (dict_valbyattr(dattr->attr, value));
+                       if (dict_addvalue(name2, dattr->name, value) < 0) {
                                radlog(L_ERR, "%s", librad_errstr);
-                               exit(1);
+                               return -1;
                        }
                } while (cp != NULL);
        } /* over the sections which can have redundent sub-sections */
 
        /*
+        *      Remember where the modules were stored.
+        */
+       modules = cf_section_find("modules");
+       if (!modules) {
+               radlog(L_ERR, "Cannot find a \"modules\" section in the configuration file!");
+               return -1;
+       }
+
+       /*
         *  Look for the 'instantiate' section, which tells us
         *  the instantiation order of the modules, and also allows
         *  us to load modules with no authorize/authenticate/etc.
@@ -866,19 +904,19 @@ int setup_modules(void)
                     ci != NULL;
                     ci=cf_item_find_next(cs, ci)) {
 
+                       /*
+                        *      Skip sections.  They'll be handled
+                        *      later, if they're referenced at all...
+                        */
                        if (cf_item_is_section(ci)) {
-                               radlog(L_ERR|L_CONS,
-                                      "%s[%d] Subsection for module instantiate is not allowed\n", filename,
-
-                                      cf_section_lineno(cf_itemtosection(ci)));
-                               exit(1);
+                               continue;
                        }
 
                        cp = cf_itemtopair(ci);
                        name = cf_pair_attr(cp);
-                       module = find_module_instance(name);
+                       module = find_module_instance(modules, name);
                        if (!module) {
-                               exit(1);
+                               return -1;
                        }
                } /* loop over items in the subsection */
        } /* if there's an 'instantiate' section. */
@@ -888,12 +926,16 @@ int setup_modules(void)
         *      configuration section, and loading it.
         */
        for (comp = 0; comp < RLM_COMPONENT_COUNT; ++comp) {
-               cs = cf_section_find(component_names[comp]);
+               cs = cf_section_find(section_type_value[comp].section);
                if (cs == NULL)
                        continue;
 
-               if (load_component_section(cs, comp, filename) < 0) {
-                       exit(1);
+               if (!do_component[comp]) {
+                       continue;
+               }
+
+               if (load_component_section(NULL, cs, comp, mainconfig.radiusd_conf) < 0) {
+                       return -1;
                }
        }
 
@@ -907,12 +949,15 @@ int setup_modules(void)
 int module_authorize(int autz_type, REQUEST *request)
 {
        /*
-        *      We have a proxied packet, and we've been told
-        *      to NOT pass proxied packets through 'authorize'
-        *      a second time.  So stop.
+        *      Older versions of the server would pass proxy requests
+        *      through the 'authorize' sections twice; once when the
+        *      packet was received from the NAS, and again after the
+        *      reply was received from the home server.  Now that we
+        *      have a 'post_proxy' section, the replies from the home
+        *      server should be sent through that, instead of through
+        *      the 'authorize' section again.
         */
-       if ((request->proxy != NULL &&
-            mainconfig.post_proxy_authorize == FALSE)) {
+       if (request->proxy != NULL) {
                DEBUG2(" authorize: Skipping authorize in post-proxy stage");
                return RLM_MODULE_NOOP;
        }
@@ -953,9 +998,6 @@ int module_checksimul(int sess_type, REQUEST *request, int maxsimul)
 {
        int rcode;
 
-       if(!components[RLM_COMPONENT_SESS])
-               return 0;
-
        if(!request->username)
                return 0;
 
diff --git a/src/main/nas.c b/src/main/nas.c
deleted file mode 100644 (file)
index 8d7bbcb..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * nas.c       Functions to do with a NASLIST. This is here because
- *             radzap needs it as well.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Copyright 2000  The FreeRADIUS server project
- * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
- * Copyright 2000  Alan DeKok <aland@ox.org>
- */
-
-static const char rcsid[] = "$Id$";
-
-#include "autoconf.h"
-#include "libradius.h"
-
-#include <sys/stat.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "radiusd.h"
-
-static NAS *naslist = NULL;
-
-/*
- *     Free a NAS list.
- */
-static void nas_free(NAS *cl)
-{
-       NAS *next;
-
-       while(cl) {
-               next = cl->next;
-               free(cl);
-               cl = next;
-       }
-}
-
-/*
- *     Read the nas file.
- */
-int read_naslist_file(char *file)
-{
-       FILE *fp;
-       char buffer[256];
-       char hostnm[256];
-       char shortnm[256];
-       char nastype[256];
-       int lineno = 0;
-       char *p;
-       NAS *nas;
-
-       nas_free(naslist);
-       naslist = NULL;
-
-       if (!file) return 0;
-
-       if ((fp = fopen(file, "r")) == NULL) {
-               /* The naslist file is no longer required.  All configuration
-                  information comes from radiusd.conf.  If naslist exists it
-                  will be used, but if it doesn't exist it will be silently
-                  ignored. */
-               return 0;
-       }
-       radlog(L_INFO, "Using deprecated naslist file.  Support for this will go away soon.");
-       while(fgets(buffer, 256, fp) != NULL) {
-               lineno++;
-               if (!feof(fp) && (strchr(buffer, '\n') == NULL)) {
-                       radlog(L_ERR, "%s[%d]: line too long", file, lineno);
-                       return -1;
-               }
-               if (buffer[0] == '#' || buffer[0] == '\n')
-                       continue;
-
-               p = buffer;
-               if (!getword(&p, hostnm, sizeof(hostnm)) ||
-                   !getword(&p, shortnm, sizeof(shortnm))) {
-                       radlog(L_ERR, "%s[%d]: unexpected end of line",
-                              file, lineno);
-                       continue;
-               }
-               (void)getword(&p, nastype, sizeof(nastype));
-
-               /*
-                *      Double-check lengths to be sure they're sane
-                */
-               if (strlen(hostnm) >= sizeof(nas->longname)) {
-                       radlog(L_ERR, "%s[%d]: host name of length %d is greater than the allowed maximum of %d.",
-                              file, lineno,
-                              (int) strlen(hostnm),
-                              (int) sizeof(nas->longname) - 1);
-                       return -1;
-               }
-               if (strlen(shortnm) > sizeof(nas->shortname)) {
-                       radlog(L_ERR, "%s[%d]: short name of length %d is greater than the allowed maximum of %d.",
-                              file, lineno,
-                              (int) strlen(shortnm),
-                              (int) sizeof(nas->shortname) - 1);
-                       return -1;
-               }
-               if (strlen(nastype) >= sizeof(nas->nastype)) {
-                       radlog(L_ERR, "%s[%d]: NAS type of length %d is greater than the allowed maximum of %d.",
-                              file, lineno,
-                              (int) strlen(nastype),
-                              (int) sizeof(nas->nastype) - 1);
-                       return -1;
-               }
-
-               /*
-                *      It should be OK now, let's create the buffer.
-                */
-               nas = rad_malloc(sizeof(NAS));
-               memset(nas, 0, sizeof(*nas));
-
-               strcpy(nas->nastype, nastype);
-               strcpy(nas->shortname, shortnm);
-
-               if (strcmp(hostnm, "DEFAULT") == 0) {
-                       nas->ipaddr = 0;
-                       strcpy(nas->longname, hostnm);
-               } else {
-                       nas->ipaddr = ip_getaddr(hostnm);
-                       ip_hostname(nas->longname, sizeof(nas->longname),
-                                       nas->ipaddr);
-               }
-
-               nas->next = naslist;
-               naslist = nas;
-       }
-       fclose(fp);
-
-       return 0;
-}
-
-
-/*
- *     Find a nas by IP address.
- *     If it can't be found, return the DEFAULT nas, instead.
- */
-NAS *nas_find(uint32_t ipaddr)
-{
-       NAS *nas;
-       NAS *default_nas;
-
-       default_nas = NULL;
-
-       for (nas = naslist; nas; nas = nas->next) {
-               if (ipaddr == nas->ipaddr)
-                       return nas;
-               if (strcmp(nas->longname, "DEFAULT") == 0)
-                       default_nas = nas;
-       }
-
-       return default_nas;
-}
-
-
-/*
- *     Find a nas by name.
- *     If it can't be found, return the DEFAULT nas, instead.
- */
-NAS *nas_findbyname(char *nasname)
-{
-       NAS     *nas;
-       NAS     *default_nas;
-
-       default_nas = NULL;
-
-       for (nas = naslist; nas; nas = nas->next) {
-               if (strcmp(nasname, nas->shortname) == 0 ||
-                               strcmp(nasname, nas->longname) == 0)
-                       return nas;
-               if (strcmp(nas->longname, "DEFAULT") == 0)
-                       default_nas = nas;
-       }
-
-       return default_nas;
-}
-
-
-/*
- *     Find the name of a nas (prefer short name).
- */
-const char *nas_name(uint32_t ipaddr)
-{
-       NAS *nas;
-
-       if ((nas = nas_find(ipaddr)) != NULL) {
-               if (nas->shortname[0])
-                       return nas->shortname;
-               else
-                       return nas->longname;
-       }
-
-       return "UNKNOWN-NAS";
-}
-
-/*
- *     Find the name of a nas (prefer short name) based on the request.
- */
-const char *nas_name2(RADIUS_PACKET *packet)
-{
-       NAS *nas;
-
-       if ((nas = nas_find(packet->src_ipaddr)) != NULL) {
-               if (nas->shortname[0])
-                       return nas->shortname;
-               else
-                       return nas->longname;
-       }
-
-       return "UNKNOWN-NAS";
-}
-
-/*
- *     Find the name of a nas (prefer short name) based on ipaddr,
- *     store in passed buffer.  If NAS is unknown, return dotted quad.
- */
-char * nas_name3(char *buf, size_t buflen, uint32_t ipaddr)
-{
-       NAS *nas;
-
-       if ((nas = nas_find(ipaddr)) != NULL) {
-               if (nas->shortname[0]) {
-                       strNcpy(buf, (char *)nas->shortname, buflen);
-                       return buf;
-               }
-               else {
-                       strNcpy(buf, (char *)nas->longname, buflen);
-                       return buf;
-               }
-       }
-       ip_ntoa(buf, ipaddr);
-       return buf;
-}
-
-
index e0c7f31..4610906 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
  * Copyright 2000  Chris Parker <cparker@starnetusa.com>
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <sys/socket.h>
 
@@ -38,17 +38,14 @@ static const char rcsid[] = "$Id$";
 #include <ctype.h>
 #include <string.h>
 
-#include "radiusd.h"
-#include "rad_assert.h"
-#include "modules.h"
-#include "request_list.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/request_list.h>
 
 /*
  *     We received a response from a remote radius server.
- *     Find the original request, then return.
- *     Returns:   1 replication don't reply
- *                0 proxy found
- *               -1 error don't reply
+ *     Call the post-proxy modules.
  */
 int proxy_receive(REQUEST *request)
 {
@@ -67,7 +64,7 @@ int proxy_receive(REQUEST *request)
         */
        vp = pairfind(request->config_items, PW_POST_PROXY_TYPE);
        if (vp) {
-               DEBUG2("  Found Post-Proxy-Type %s", vp->strvalue);
+               DEBUG2("  Found Post-Proxy-Type %s", vp->vp_strvalue);
                post_proxy_type = vp->lvalue;
        }
        rcode = module_post_proxy(post_proxy_type, request);
@@ -91,6 +88,19 @@ int proxy_receive(REQUEST *request)
          */
         pairfree(&request->proxy->vps);
 
+       /*
+        *      FIXME: If the packet is an Access-Challenge,
+        *      THEN add it to a cache, which does:
+        *
+        *      (src IP, State) -> (home server ip/port)
+        *
+        *      This allows the load-balancing code to
+        *      work for EAP...
+        *
+        *      Alternately, we can delete the State from the home
+        *      server, and use our own..  that might be better.
+        */
+
         return rcode;
 }
 
@@ -106,8 +116,8 @@ static void proxy_addinfo(REQUEST *request)
                radlog(L_ERR|L_CONS, "no memory");
                exit(1);
        }
-       sprintf((char *)proxy_pair->strvalue, "%d", request->packet->id);
-       proxy_pair->length = strlen((char *)proxy_pair->strvalue);
+       sprintf(proxy_pair->vp_strvalue, "%d", request->packet->id);
+       proxy_pair->length = strlen(proxy_pair->vp_strvalue);
 
        pairadd(&request->proxy->vps, proxy_pair);
 }
@@ -124,11 +134,17 @@ static void proxy_addinfo(REQUEST *request)
 static REALM *proxy_realm_ldb(REQUEST *request, const char *realm_name,
                              int accounting)
 {
-       int             redone = 0;
        REALM           *cl, *lb;
        uint32_t        count;
 
- redo:
+       /*
+        *      FIXME: If the packet contains a State attribute,
+        *      AND the realm is load-balance,
+        *      AND there is a matching
+        *      State attribute in the cached entry, THEN proxy it to
+        *      that realm.
+        */
+
        lb = NULL;
        count = 0;
        for (cl = mainconfig.realms; cl; cl = cl->next) {
@@ -200,25 +216,6 @@ static REALM *proxy_realm_ldb(REQUEST *request, const char *realm_name,
        } /* loop over the realms */
 
        /*
-        *      All are dead, see if we have to wake
-        */
-       if (!redone && !lb && mainconfig.wake_all_if_all_dead) {
-               for (cl = mainconfig.realms; cl; cl = cl->next) {
-                       if(strcasecmp(cl->realm,realm_name) == 0) {
-                               if (!accounting && !cl->active) {
-                                       cl->active = TRUE;
-                               }
-                               else if (accounting &&
-                                        !cl->acct_active) {
-                                       cl->acct_active = TRUE;
-                               }
-                       }
-               }
-               redone = 1;
-               goto redo;
-       }
-
-       /*
         *      Return the load-balanced realm.
         */
        return lb;
@@ -238,7 +235,6 @@ int proxy_send(REQUEST *request)
        int pre_proxy_type = 0;
        VALUE_PAIR *realmpair;
        VALUE_PAIR *strippedname;
-       VALUE_PAIR *delaypair;
        VALUE_PAIR *vp;
        REALM *realm;
        char *realmname;
@@ -290,7 +286,7 @@ int proxy_send(REQUEST *request)
                return RLM_MODULE_NOOP;
        }
 
-       realmname = (char *)realmpair->strvalue;
+       realmname = (char *)realmpair->vp_strvalue;
 
        /*
         *      Look for the realm, using the load balancing
@@ -315,15 +311,30 @@ int proxy_send(REQUEST *request)
         *      Accounting-Request: look for LOCAL realm.
         */
        if (((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
-            (realm->ipaddr == htonl(INADDR_NONE))) ||
+            (realm->ipaddr.af == AF_INET) &&
+            (realm->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE))) ||
            ((request->packet->code == PW_ACCOUNTING_REQUEST) &&
-            (realm->acct_ipaddr == htonl(INADDR_NONE)))) {
+            (realm->acct_ipaddr.af == AF_INET) &&
+            (realm->acct_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)))) {
                DEBUG2(" WARNING: Cancelling proxy to Realm %s, as the realm is local.",
                       realm->realm);
                return RLM_MODULE_NOOP;
        }
 
        /*
+        *      This is mainly for radrelay.  Don't proxy packets back
+        *      to servers which sent them to us.
+        */
+       if ((request->packet->code == PW_ACCOUNTING_REQUEST) &&
+           (request->listener->type == RAD_LISTEN_DETAIL) &&
+           (realm->acct_ipaddr.af == AF_INET) &&
+           (request->packet->src_ipaddr.af == AF_INET) &&
+           (realm->acct_ipaddr.ipaddr.ip4addr.s_addr == request->packet->src_ipaddr.ipaddr.ip4addr.s_addr)) {
+               DEBUG2("    rlm_realm: Packet came from realm %s, proxy cancelled", realm->realm);
+               return RLM_MODULE_NOOP;
+       }
+
+       /*
         *      Allocate the proxy packet, only if it wasn't already
         *      allocated by a module.  This check is mainly to support
         *      the proxying of EAP-TTLS and EAP-PEAP tunneled requests.
@@ -404,8 +415,8 @@ int proxy_send(REQUEST *request)
                        vp->next = request->proxy->vps;
                        request->proxy->vps = vp;
                }
-               memcpy(vp->strvalue, strippedname->strvalue,
-                      sizeof(vp->strvalue));
+               memcpy(vp->vp_strvalue, strippedname->vp_strvalue,
+                      sizeof(vp->vp_strvalue));
                vp->length = strippedname->length;
 
                /*
@@ -427,7 +438,7 @@ int proxy_send(REQUEST *request)
                        exit(1);
                }
                vp->length = AUTH_VECTOR_LEN;
-               memcpy(vp->strvalue, request->packet->vector, AUTH_VECTOR_LEN);
+               memcpy(vp->vp_strvalue, request->packet->vector, AUTH_VECTOR_LEN);
                pairadd(&(request->proxy->vps), vp);
        }
 
@@ -454,42 +465,46 @@ int proxy_send(REQUEST *request)
         */
        memcpy(request->proxysecret, realm->secret, sizeof(request->proxysecret));
        request->proxy_try_count = mainconfig.proxy_retry_count - 1;
-       request->proxy_next_try = request->timestamp + mainconfig.proxy_retry_delay;
-       delaypair = pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME);
-       request->proxy->timestamp = request->timestamp - (delaypair ? delaypair->lvalue : 0);
+
+       vp = NULL;
+       if (request->packet->code == PW_ACCOUNTING_REQUEST) {
+               vp = pairfind(request->proxy->vps, PW_ACCT_DELAY_TIME);
+       }
+       if (vp) {
+               request->proxy->timestamp = request->timestamp - vp->lvalue;
+       } else {
+               request->proxy->timestamp = request->timestamp;
+       }
+       request->proxy_start_time = request->timestamp;
 
        /*
-        *  Do pre-proxying
+        *      Do pre-proxying.
         */
        vp = pairfind(request->config_items, PW_PRE_PROXY_TYPE);
        if (vp) {
-               DEBUG2("  Found Pre-Proxy-Type %s", vp->strvalue);
+               DEBUG2("  Found Pre-Proxy-Type %s", vp->vp_strvalue);
                pre_proxy_type = vp->lvalue;
        }
        rcode = module_pre_proxy(pre_proxy_type, request);
-
-       /*
-        *      Do NOT free request->proxy->vps, the pairs are needed
-        *      for the retries! --Pac.
-        */
-
+       switch (rcode) {
        /*
-        *      Delay sending the proxy packet until after we've
-        *      done the work above, playing with the request.
-        *
-        *      After this point, it becomes dangerous to play
-        *      with the request data structure, as the reply MAY
-        *      come in and get processed before we're done with it here.
-        *
         *      Only proxy the packet if the pre-proxy code succeeded.
         */
-       if ((rcode == RLM_MODULE_OK) ||
-           (rcode == RLM_MODULE_NOOP) ||
-           (rcode == RLM_MODULE_UPDATED)) {
+       case RLM_MODULE_NOOP:
+       case RLM_MODULE_OK:
+       case RLM_MODULE_UPDATED:
+               /*
+                *      Delay sending the proxy packet until after we've
+                *      done the work above, playing with the request.
+                *
+                *      After this point, it becomes dangerous to play with
+                *      the request data structure, as the reply MAY come in
+                *      and get processed before we're done with it here.
+                */
                request->options |= RAD_REQUEST_OPTION_PROXIED;
 
                /*
-                *      IF it's a fake request, don't send the proxy
+                *      If it's a fake request, don't send the proxy
                 *      packet.  The outer tunnel session will take
                 *      care of doing that.
                 */
@@ -508,13 +523,43 @@ int proxy_send(REQUEST *request)
                                return RLM_MODULE_FAIL; /* caller doesn't reply */
                        }
 
-                       rad_send(request->proxy, NULL,
-                                (char *)request->proxysecret);
+                       /*
+                        *      We're still running, encode & sign the
+                        *      packet outside of the critical section.
+                        */
+                       if (request->child_pid != NO_SUCH_CHILD_PID) {
+                               rad_encode(request->proxy, NULL,
+                                          (char *)request->proxysecret);
+                               rad_sign(request->proxy, NULL,
+                                        (char *)request->proxysecret);
+                       } else {
+                               request->proxy_listener->send(request->proxy_listener,
+                                                             request);
+                       }
                }
                rcode = RLM_MODULE_HANDLED; /* caller doesn't reply */
-       } else {
+               break;
+       /*
+        *      The module handled the request, don't reply.
+        */
+       case RLM_MODULE_HANDLED:
+               break;
+       /*
+        *      Neither proxy, nor reply to invalid requests.
+        */
+       case RLM_MODULE_FAIL:
+       case RLM_MODULE_INVALID:
+       case RLM_MODULE_NOTFOUND:
+       case RLM_MODULE_REJECT:
+       case RLM_MODULE_USERLOCK:
+       default:
                rcode = RLM_MODULE_FAIL; /* caller doesn't reply */
+               break;
        }
 
+       /*
+        *      Do NOT free request->proxy->vps, the pairs are needed
+        *      for the retries!
+        */
        return rcode;
 }
index 08369aa..b059581 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
-static const char rcsid[] = "$Id$";
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -35,11 +37,6 @@ static const char rcsid[] = "$Id$";
 #include <string.h>
 #include <ctype.h>
 #include <netdb.h>
-#include <sys/socket.h>
-
-#ifdef HAVE_NETINET_IN_H
-#      include <netinet/in.h>
-#endif
 
 #ifdef HAVE_SYS_SELECT_H
 #      include <sys/select.h>
@@ -51,10 +48,10 @@ static const char rcsid[] = "$Id$";
 
 #include <assert.h>
 
-#include "conf.h"
-#include "radpaths.h"
-#include "missing.h"
-#include "libradius.h"
+#include <freeradius-devel/conf.h>
+#include <freeradius-devel/radpaths.h>
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
 
 static int retries = 10;
 static float timeout = 3;
@@ -66,16 +63,18 @@ static int totallost = 0;
 
 static int server_port = 0;
 static int packet_code = 0;
-static uint32_t server_ipaddr = 0;
+static lrad_ipaddr_t server_ipaddr;
 static int resend_count = 1;
 static int done = 1;
 
+static lrad_ipaddr_t client_ipaddr;
+static int client_port = 0;
+
 static int sockfd;
-static int radius_id[256];
 static int last_used_id = -1;
 
 static rbtree_t *filename_tree = NULL;
-static rbtree_t *request_tree = NULL;
+static lrad_packet_list_t *pl = NULL;
 
 static int sleep_time = -1;
 
@@ -116,6 +115,8 @@ static void NEVER_RETURNS usage(void)
        fprintf(stderr, "  -t timeout  Wait 'timeout' seconds before retrying (may be a floating point number).\n");
        fprintf(stderr, "  -v          Show program version information.\n");
        fprintf(stderr, "  -x          Debugging mode.\n");
+       fprintf(stderr, "  -4          Use IPv4 address of server\n");
+       fprintf(stderr, "  -6          Use IPv6 address of server.\n");
 
        exit(1);
 }
@@ -197,7 +198,7 @@ static radclient_t *radclient_init(const char *filename)
 
                radclient->request = rad_alloc(1);
                if (!radclient->request) {
-                       librad_perror("radclient: X");
+                       librad_perror("radclient: Y");
                        radclient_free(radclient);
                        return NULL; /* memory leak "start" */
                }
@@ -209,7 +210,7 @@ static radclient_t *radclient_init(const char *filename)
                /*
                 *      Read the VP's.
                 */
-               radclient->request->vps = readvp2(fp, &filedone, "radclient: X");
+               radclient->request->vps = readvp2(fp, &filedone, "radclient:");
                if (!radclient->request->vps) {
                        radclient_free(radclient);
                        return start; /* done: return the list */
@@ -218,13 +219,15 @@ static radclient_t *radclient_init(const char *filename)
                /*
                 *      Keep a copy of the the User-Password attribute.
                 */
-               if ((vp = pairfind(radclient->request->vps, PW_PASSWORD)) != NULL) {
-                       strNcpy(radclient->password, (char *)vp->strvalue, sizeof(radclient->password));
+               if ((vp = pairfind(radclient->request->vps, PW_USER_PASSWORD)) != NULL) {
+                       strlcpy(radclient->password, vp->vp_strvalue,
+                               sizeof(radclient->password));
                        /*
                         *      Otherwise keep a copy of the CHAP-Password attribute.
                         */
                } else if ((vp = pairfind(radclient->request->vps, PW_CHAP_PASSWORD)) != NULL) {
-                       strNcpy(radclient->password, (char *)vp->strvalue, sizeof(radclient->password));
+                       strlcpy(radclient->password, vp->vp_strvalue,
+                               sizeof(radclient->password));
                } else {
                        radclient->password[0] = '\0';
                }
@@ -249,6 +252,30 @@ static radclient_t *radclient_init(const char *filename)
                                radclient->request->dst_port = (vp->lvalue & 0xffff);
                                break;
 
+                       case PW_PACKET_DST_IP_ADDRESS:
+                               radclient->request->dst_ipaddr.af = AF_INET;
+                               radclient->request->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->lvalue;
+                               break;
+
+                       case PW_PACKET_DST_IPV6_ADDRESS:
+                               radclient->request->dst_ipaddr.af = AF_INET6;
+                               radclient->request->dst_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
+                               break;
+
+                       case PW_PACKET_SRC_PORT:
+                               radclient->request->src_port = (vp->lvalue & 0xffff);
+                               break;
+
+                       case PW_PACKET_SRC_IP_ADDRESS:
+                               radclient->request->src_ipaddr.af = AF_INET;
+                               radclient->request->src_ipaddr.ipaddr.ip4addr.s_addr = vp->lvalue;
+                               break;
+
+                       case PW_PACKET_SRC_IPV6_ADDRESS:
+                               radclient->request->src_ipaddr.af = AF_INET6;
+                               radclient->request->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr;
+                               break;
+
                        case PW_DIGEST_REALM:
                        case PW_DIGEST_NONCE:
                        case PW_DIGEST_METHOD:
@@ -260,10 +287,11 @@ static radclient_t *radclient_init(const char *filename)
                        case PW_DIGEST_NONCE_COUNT:
                        case PW_DIGEST_USER_NAME:
                                /* overlapping! */
-                               memmove(&vp->strvalue[2], &vp->strvalue[0], vp->length);
-                               vp->strvalue[0] = vp->attribute - PW_DIGEST_REALM + 1;
+                               memmove(&vp->vp_octets[2], &vp->vp_octets[0],
+                                       vp->length);
+                               vp->vp_octets[0] = vp->attribute - PW_DIGEST_REALM + 1;
                                vp->length += 2;
-                               vp->strvalue[1] = vp->length;
+                               vp->vp_octets[1] = vp->length;
                                vp->attribute = PW_DIGEST_ATTRIBUTES;
                                break;
                        }
@@ -296,8 +324,14 @@ static int radclient_sane(radclient_t *radclient)
        if (radclient->request->dst_port == 0) {
                radclient->request->dst_port = server_port;
        }
-       radclient->request->dst_ipaddr = server_ipaddr;
-
+       if (radclient->request->dst_ipaddr.af == AF_UNSPEC) {
+               if (server_ipaddr.af == AF_UNSPEC) {
+                       fprintf(stderr, "radclient: No server was given, but request %d in file %s did not contain Packet-Dst-IP-Address\n",
+                               radclient->packet_number, radclient->filename);
+                       return -1;
+               }
+               radclient->request->dst_ipaddr = server_ipaddr;
+       }
        if (radclient->request->code == 0) {
                if (packet_code == -1) {
                        fprintf(stderr, "radclient: Request was \"auto\", but request %d in file %s did not contain Packet-Type\n",
@@ -307,7 +341,7 @@ static int radclient_sane(radclient_t *radclient)
 
                radclient->request->code = packet_code;
        }
-       radclient->request->sockfd = sockfd;
+       radclient->request->sockfd = -1;
 
        return 0;
 }
@@ -358,40 +392,10 @@ static int filename_walk(void *context, void *data)
 
 
 /*
- *     Compare two RADIUS_PACKET data structures, based on a number
- *     of criteria.
- */
-static int request_cmp(const void *one, const void *two)
-{
-       const radclient_t *a = one;
-       const radclient_t *b = two;
-
-       /*
-        *      The following code looks unreasonable, but it's
-        *      the only way to make the comparisons work.
-        */
-       if (a->request->id < b->request->id) return -1;
-       if (a->request->id > b->request->id) return +1;
-
-       if (a->request->dst_ipaddr < b->request->dst_ipaddr) return -1;
-       if (a->request->dst_ipaddr > b->request->dst_ipaddr) return +1;
-
-       if (a->request->dst_port < b->request->dst_port) return -1;
-       if (a->request->dst_port > b->request->dst_port) return +1;
-
-       /*
-        *      Everything's equal.  Say so.
-        */
-       return 0;
-}
-
-/*
- *     "Free" a request.
+ *     Deallocate packet ID, etc.
  */
-static void request_free(void *data)
+static void deallocate_id(radclient_t *radclient)
 {
-       radclient_t *radclient = (radclient_t *) data;
-
        if (!radclient || !radclient->request ||
            (radclient->request->id < 0)) {
                return;
@@ -400,7 +404,7 @@ static void request_free(void *data)
        /*
         *      One more unused RADIUS ID.
         */
-       radius_id[radclient->request->id] = 0;
+       lrad_packet_list_id_free(pl, radclient->request);
        radclient->request->id = -1;
 
        /*
@@ -417,13 +421,72 @@ static void request_free(void *data)
 }
 
 
+static void print_hex(RADIUS_PACKET *packet)
+{
+       int i;
+
+       if (!packet->data) return;
+
+       printf("  Code:\t\t%u\n", packet->data[0]);
+       printf("  Id:\t\t%u\n", packet->data[1]);
+       printf("  Length:\t%u\n", ((packet->data[2] << 8) |
+                                  (packet->data[3])));
+       printf("  Vector:\t");
+       for (i = 4; i < 20; i++) {
+               printf("%02x", packet->data[i]);
+       }
+       printf("\n");
+       
+       if (packet->data_len > 20) {
+               int total;
+               const uint8_t *ptr;
+               printf("  Data:");
+
+               total = packet->data_len - 20;
+               ptr = packet->data + 20;
+
+               while (total > 0) {
+                       int attrlen;
+
+                       printf("\t\t");
+                       if (total < 2) { /* too short */
+                               printf("%02x\n", *ptr);
+                               break;
+                       }
+
+                       if (ptr[1] > total) { /* too long */
+                               for (i = 0; i < total; i++) {
+                                       printf("%02x ", ptr[i]);
+                               }
+                               break;
+                       }
+
+                       printf("%02x  %02x  ", ptr[0], ptr[1]);
+                       attrlen = ptr[1] - 2;
+                       ptr += 2;
+                       total -= 2;
+
+                       for (i = 0; i < attrlen; i++) {
+                               if ((i > 0) && ((i & 0x0f) == 0x00))
+                                       printf("\t\t\t");
+                               printf("%02x ", ptr[i]);
+                               if ((i & 0x0f) == 0x0f) printf("\n");
+                       }
+
+                       if ((attrlen & 0x0f) != 0x00) printf("\n");
+
+                       ptr += attrlen;
+                       total -= attrlen;
+               }
+       }
+       fflush(stdout);
+}
+
 /*
  *     Send one packet.
  */
 static int send_one_packet(radclient_t *radclient)
 {
-       int i;
-
        assert(radclient->done == 0);
 
        /*
@@ -439,29 +502,33 @@ static int send_one_packet(radclient_t *radclient)
         *      Haven't sent the packet yet.  Initialize it.
         */
        if (radclient->request->id == -1) {
-               int found = 0;
+               int i, rcode;
 
                assert(radclient->reply == NULL);
 
                /*
-                *      Find a free packet Id
-                */
-               for (i = 0; i < 256; i++) {
-                       if (radius_id[(last_used_id + i) & 0xff] == 0) {
-                               last_used_id = (last_used_id + i) & 0xff;
-                               radius_id[last_used_id] = 1;
-                               radclient->request->id = last_used_id++;
-                               found = 1;
-                               break;
-                       }
-               }
-
-               /*
                 *      Didn't find a free packet ID, we're not done,
                 *      we don't sleep, and we stop trying to process
                 *      this packet.
                 */
-               if (!found) {
+       retry:
+               rcode = lrad_packet_list_id_alloc(pl, radclient->request);
+               if (rcode < 0) {
+                       int mysockfd;
+
+                       mysockfd = lrad_socket(&client_ipaddr, 0);
+                       if (!mysockfd) {
+                               fprintf(stderr, "radclient: Can't open new socket\n");
+                               exit(1);
+                       }
+                       if (!lrad_packet_list_socket_add(pl, mysockfd)) {
+                               fprintf(stderr, "radclient: Can't add new socket\n");
+                               exit(1);
+                       }
+                       goto retry;
+               }
+
+               if (rcode == 0) {
                        done = 0;
                        sleep_time = 0;
                        return 0;
@@ -470,8 +537,9 @@ static int send_one_packet(radclient_t *radclient)
                assert(radclient->request->id != -1);
                assert(radclient->request->data == NULL);
 
-               librad_md5_calc(radclient->request->vector, radclient->request->vector,
-                               sizeof(radclient->request->vector));
+               for (i = 0; i < 4; i++) {
+                       *((uint32_t *) radclient->request->vector) = lrad_rand();
+               }
 
                /*
                 *      Update the password, so it can be encrypted with the
@@ -480,15 +548,24 @@ static int send_one_packet(radclient_t *radclient)
                if (radclient->password[0] != '\0') {
                        VALUE_PAIR *vp;
 
-                       if ((vp = pairfind(radclient->request->vps, PW_PASSWORD)) != NULL) {
-                               strNcpy((char *)vp->strvalue, radclient->password, sizeof(vp->strvalue));
-                               vp->length = strlen(vp->strvalue);
+                       if ((vp = pairfind(radclient->request->vps, PW_USER_PASSWORD)) != NULL) {
+                               strlcpy(vp->vp_strvalue, radclient->password,
+                                       sizeof(vp->vp_strvalue));
+                               vp->length = strlen(vp->vp_strvalue);
 
                        } else if ((vp = pairfind(radclient->request->vps, PW_CHAP_PASSWORD)) != NULL) {
-                               strNcpy((char *)vp->strvalue, radclient->password, sizeof(vp->strvalue));
-                               vp->length = strlen(vp->strvalue);
-
-                               rad_chap_encode(radclient->request, (char *) vp->strvalue, radclient->request->id, vp);
+                         /*
+                          *    FIXME: AND there's no CHAP-Challenge,
+                          *           AND vp->length != 17
+                          *           AND rad_chap_encode() != vp->vp_octets
+                          */
+                               strlcpy(vp->vp_strvalue, radclient->password,
+                                       sizeof(vp->vp_strvalue));
+                               vp->length = strlen(vp->vp_strvalue);
+
+                               rad_chap_encode(radclient->request,
+                                               vp->vp_octets,
+                                               radclient->request->id, vp);
                                vp->length = 17;
                        }
                }
@@ -500,9 +577,10 @@ static int send_one_packet(radclient_t *radclient)
                /*
                 *      Duplicate found.  Serious error!
                 */
-               if (rbtree_insert(request_tree, radclient) == 0) {
+               if (!lrad_packet_list_insert(pl, &radclient->request)) {
                        assert(0 == 1);
                }
+               
 
        } else {                /* radclient->request->id >= 0 */
                time_t now = time(NULL);
@@ -534,18 +612,16 @@ static int send_one_packet(radclient_t *radclient)
                 *      We're not trying later, maybe the packet is done.
                 */
                if (radclient->tries == retries) {
-                       rbnode_t *node;
                        assert(radclient->request->id >= 0);
                        
                        /*
                         *      Delete the request from the tree of
                         *      outstanding requests.
                         */
-                       node = rbtree_find(request_tree, radclient);
-                       assert(node != NULL);
-                       
-                       fprintf(stderr, "radclient: no response from server for ID %d\n", radclient->request->id);
-                       rbtree_delete(request_tree, node);
+                       lrad_packet_list_yank(pl, radclient->request);
+
+                       fprintf(stderr, "radclient: no response from server for ID %d socket %d\n", radclient->request->id, radclient->request->sockfd);
+                       deallocate_id(radclient);
                        
                        /*
                         *      Normally we mark it "done" when we've received
@@ -574,6 +650,8 @@ static int send_one_packet(radclient_t *radclient)
                        radclient->request->id, librad_errstr);
        }
 
+       if (librad_debug > 2) print_hex(radclient->request);
+
        return 0;
 }
 
@@ -584,14 +662,15 @@ static int recv_one_packet(int wait_time)
 {
        fd_set          set;
        struct timeval  tv;
-       radclient_t     myclient, *radclient;
-       RADIUS_PACKET   myrequest, *reply;
-       rbnode_t        *node;
-
+       radclient_t     *radclient;
+       RADIUS_PACKET   *reply, **request_p;
+       volatile int max_fd;
 
        /* And wait for reply, timing out as necessary */
        FD_ZERO(&set);
-       FD_SET(sockfd, &set);
+
+       max_fd = lrad_packet_list_fd_set(pl, &set);
+       if (max_fd < 0) exit(1); /* no sockets to listen on! */
 
        if (wait_time <= 0) {
                tv.tv_sec = 0;
@@ -603,54 +682,51 @@ static int recv_one_packet(int wait_time)
        /*
         *      No packet was received.
         */
-       if (select(sockfd + 1, &set, NULL, NULL, &tv) != 1) {
+       if (select(max_fd, &set, NULL, NULL, &tv) <= 0) {
                return 0;
        }
 
        /*
         *      Look for the packet.
         */
-       reply = rad_recv(sockfd);
+       reply = lrad_packet_list_recv(pl, &set);
        if (!reply) {
                fprintf(stderr, "radclient: received bad packet: %s\n",
                        librad_errstr);
                return -1;      /* bad packet */
        }
 
-       myclient.request = &myrequest;
-       myrequest.id = reply->id;
-       myrequest.dst_ipaddr = reply->src_ipaddr;
-       myrequest.dst_port = reply->src_port;
+       if (librad_debug > 2) print_hex(reply);
 
-       node = rbtree_find(request_tree, &myclient);
-       if (!node) {
-               fprintf(stderr, "radclient: received response to request we did not send.\n");
+       request_p = lrad_packet_list_find_byreply(pl, reply);
+       if (!request_p) {
+               fprintf(stderr, "radclient: received response to request we did not send. (id=%d socket %d)\n", reply->id, reply->sockfd);
                rad_free(&reply);
                return -1;      /* got reply to packet we didn't send */
        }
-
-       radclient = rbtree_node2data(request_tree, node);
-       assert(radclient != NULL);
-       rbtree_delete(request_tree, node);
-       assert(radclient->request->id == -1);
-       assert(radclient->request->data == NULL);
-
-       assert(radclient->reply == NULL);
-       radclient->reply = reply;
+       radclient = lrad_packet2myptr(radclient_t, request, request_p);
 
        /*
-        *      FIXME: Do stuff to process the reply.
+        *      Fails the signature validation: not a real reply.
+        *      FIXME: Silently drop it and listen for another packet.
         */
-       if (rad_verify(reply, radclient->request, secret) != 0) {
+       if (rad_verify(reply, radclient->request, secret) < 0) {
                librad_perror("rad_verify");
                totallost++;
                goto packet_done; /* shared secret is incorrect */
        }
 
+       lrad_packet_list_yank(pl, radclient->request);
+       deallocate_id(radclient);
+       radclient->reply = reply;
+
+       /*
+        *      If this fails, we're out of memory.
+        */
        if (rad_decode(reply, radclient->request, secret) != 0) {
                librad_perror("rad_decode");
                totallost++;
-               goto packet_done; /* shared secret is incorrect */
+               goto packet_done;
        }
 
        /* libradius debug already prints out the value pairs for us */
@@ -673,13 +749,14 @@ packet_done:
         *      mark it done.
         */
        if (radclient->resend == resend_count) {
-               assert((node = rbtree_find(request_tree, radclient)) == NULL);
+               assert(lrad_packet_list_find(pl, radclient->request) == NULL);
                radclient->done = 1;
        }
 
        return 0;
 }
 
+
 static int getport(const char *name)
 {
        struct  servent         *svp;
@@ -703,6 +780,7 @@ int main(int argc, char **argv)
        int persec = 0;
        int parallel = 1;
        radclient_t     *this;
+       int force_af = AF_UNSPEC;
 
        librad_debug = 0;
 
@@ -712,13 +790,13 @@ int main(int argc, char **argv)
                exit(1);
        }
 
-       request_tree = rbtree_create(request_cmp, request_free, 0);
-       if (!request_tree) {
-               fprintf(stderr, "radclient: Out of memory\n");
-               exit(1);
-       }
-
-       while ((c = getopt(argc, argv, "c:d:f:hi:n:p:qr:sS:t:vx")) != EOF) switch(c) {
+       while ((c = getopt(argc, argv, "46c:d:f:hi:n:p:qr:sS:t:vx")) != EOF) switch(c) {
+               case '4':
+                       force_af = AF_INET;
+                       break;
+               case '6':
+                       force_af = AF_INET6;
+                       break;
                case 'c':
                        if (!isdigit((int) *optarg))
                                usage();
@@ -730,7 +808,7 @@ int main(int argc, char **argv)
                case 'f':
                        rbtree_insert(filename_tree, optarg);
                        break;
-               case 'i':
+               case 'i':       /* currently broken */
                        if (!isdigit((int) *optarg))
                                usage();
                        last_used_id = atoi(optarg);
@@ -744,6 +822,13 @@ int main(int argc, char **argv)
                        if (persec <= 0) usage();
                        break;
 
+                       /*
+                        *      Note that sending MANY requests in
+                        *      parallel can over-run the kernel
+                        *      queues, and Linux will happily discard
+                        *      packets.  So even if the server responds,
+                        *      the client may not see the response.
+                        */
                case 'p':
                        parallel = atoi(optarg);
                        if (parallel <= 0) usage();
@@ -820,21 +905,45 @@ int main(int argc, char **argv)
        }
 
        /*
-        *      Strip port from hostname if needed.
+        *      Resolve hostname.
         */
-       if ((p = strchr(argv[1], ':')) != NULL) {
-               *p++ = 0;
-               server_port = atoi(p);
-       }
+       server_ipaddr.af = force_af;
+       if (strcmp(argv[1], "-") != 0) {
+               const char *hostname = argv[1];
+               const char *portname = argv[1];
+               char buffer[256];
+
+               if (*argv[1] == '[') { /* IPv6 URL encoded */
+                       p = strchr(argv[1], ']');
+                       if ((p - argv[1]) >= sizeof(buffer)) {
+                               usage();
+                       }
+                       
+                       memcpy(buffer, argv[1] + 1, p - argv[1] - 1);
+                       buffer[p - argv[1] - 1] = '\0';
 
-       /*
-        *      Grab the socket.
-        */
-       if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-               perror("radclient: socket: ");
-               exit(1);
+                       hostname = buffer;
+                       portname = p + 1;
+
+               }
+               p = strchr(portname, ':');
+               if (p && (strchr(p + 1, ':') == NULL)) {
+                       *p = '\0';
+                       portname = p + 1;
+               } else {
+                       portname = NULL;
+               }
+
+               if (ip_hton(hostname, force_af, &server_ipaddr) < 0) {
+                       fprintf(stderr, "radclient: Failed to find IP address for host %s: %s\n", hostname, strerror(errno));
+                       exit(1);
+               }
+
+               /*
+                *      Strip port from hostname if needed.
+                */
+               if (portname) server_port = atoi(portname);
        }
-       memset(radius_id, 0, sizeof(radius_id));
 
        /*
         *      See what kind of request we want to send.
@@ -880,15 +989,6 @@ int main(int argc, char **argv)
        }
 
        /*
-        *      Resolve hostname.
-        */
-       server_ipaddr = ip_getaddr(argv[1]);
-       if (server_ipaddr == INADDR_NONE) {
-               fprintf(stderr, "radclient: Failed to find IP address for host %s\n", argv[1]);
-               exit(1);
-       }
-
-       /*
         *      Add the secret.
         */
        if (argv[3]) secret = argv[3];
@@ -916,17 +1016,46 @@ int main(int argc, char **argv)
        }
 
        /*
+        *      Bind to the first specified IP address and port.
+        *      This means we ignore later ones.
+        */
+       if (radclient_head->request->src_ipaddr.af == AF_UNSPEC) {
+               memset(&client_ipaddr, 0, sizeof(client_ipaddr));
+               client_ipaddr.af = server_ipaddr.af;
+               client_port = 0;
+       } else {
+               client_ipaddr = radclient_head->request->src_ipaddr;
+               client_port = radclient_head->request->src_port;
+       }
+       sockfd = lrad_socket(&client_ipaddr, client_port);
+       if (sockfd < 0) {
+               fprintf(stderr, "radclient: socket: %s\n", librad_errstr);
+               exit(1);
+       }
+
+       pl = lrad_packet_list_create(1);
+       if (!pl) {
+               fprintf(stderr, "radclient: Out of memory\n");
+               exit(1);
+       }
+
+       if (!lrad_packet_list_socket_add(pl, sockfd)) {
+               fprintf(stderr, "radclient: Out of memory\n");
+               exit(1);
+       }
+
+       /*
         *      Walk over the list of packets, sanity checking
         *      everything.
         */
        for (this = radclient_head; this != NULL; this = this->next) {
+               this->request->src_ipaddr = client_ipaddr;
+               this->request->src_port = client_port;
                if (radclient_sane(this) != 0) {
                        exit(1);
                }
        }
 
-       if (last_used_id < 0) last_used_id = getpid() & 0xff;
-
        /*
         *      Walk over the packets to send, until
         *      we're all done.
@@ -1038,7 +1167,7 @@ int main(int argc, char **argv)
                /*
                 *      Still have outstanding requests.
                 */
-               if (rbtree_num_elements(request_tree) > 0) {
+               if (lrad_packet_list_num_elements(pl) > 0) {
                        done = 0;
                } else {
                        sleep_time = 0;
@@ -1057,7 +1186,8 @@ int main(int argc, char **argv)
        } while (!done);
 
        rbtree_free(filename_tree);
-       rbtree_free(request_tree);
+       lrad_packet_list_free(pl);
+       dict_free();
 
        if (do_summary) {
                printf("\n\t   Total approved auths:  %d\n", totalapp);
index 7151a95..5879741 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Jochen Friedrich <jochen@scram.de>
  */
 
-static const char rcsid[] =
-"$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
+#include <freeradius-devel/autoconf.h>
 
 #ifdef WITH_SNMP
 
-#include "libradius.h"
-
 #ifdef HAVE_NETINET_IN_H
 #      include <netinet/in.h>
 #endif
 
 #include <string.h>
 
-#include "smux.h"
-#include "radius_snmp.h"
-#include "radiusd.h"
-#include "conffile.h"
+#include <freeradius-devel/smux.h>
+#include <freeradius-devel/radius_snmp.h>
+#include <freeradius-devel/radiusd.h>
 
 extern int need_reload;
 
@@ -48,14 +45,14 @@ extern int need_reload;
  */
 rad_snmp_t             rad_snmp;
 
-\f
+
 #define RADACCOID 1,3,6,1,2,1,67,2,1,1,1
 #define RADAUTHOID 1,3,6,1,2,1,67,1,1,1,1
 #define RADIUSOID 1,3,6,1,4,1,3317,1,3,1
 
-static oid radacc_oid [] = { RADACCOID };
-static oid radauth_oid [] = { RADAUTHOID };
-static oid radius_oid [] = { RADIUSOID };
+static const oid radacc_oid [] = { RADACCOID };
+static const oid radauth_oid [] = { RADAUTHOID };
+static const oid radius_oid [] = { RADIUSOID };
 
 #define COUNTER ASN_COUNTER
 #define INTEGER ASN_INTEGER
@@ -142,7 +139,7 @@ static const unsigned char *radAuthEntry(struct variable *vp,
        size_t  *var_len,
        WriteMethod **write_method);
 
-static struct variable radiusacc_variables[] =
+static const struct variable radiusacc_variables[] =
 {
        {RADIUSACCSERVIDENT, STRING, RONLY, radAccServ, 1, {1}},
        {RADIUSACCSERVUPTIME, TIMETICKS, RONLY, radAccServ, 1, {2}},
@@ -169,7 +166,7 @@ static struct variable radiusacc_variables[] =
        {RADIUSACCSERVUNKNOWNTYPES, COUNTER, RONLY, radAccEntry, 3, {14,1,11}},
 };
 
-static struct variable radiusauth_variables[] =
+static const struct variable radiusauth_variables[] =
 {
        {RADIUSAUTHSERVIDENT, STRING, RONLY, radAuthServ, 1, {1}},
        {RADIUSAUTHSERVUPTIME, TIMETICKS, RONLY, radAuthServ, 1, {2}},
@@ -198,10 +195,9 @@ static struct variable radiusauth_variables[] =
        {RADIUSAUTHSERVUNKNOWNTYPES, COUNTER, RONLY, radAuthEntry, 3, {15,1,12}},
 };
 
-\f
 static RADCLIENT *
-get_client(struct variable *v, oid objid[], size_t *objid_len, int exact) {
-
+get_client(struct variable *v, oid objid[], size_t *objid_len, int exact)
+{
        RADCLIENT *c;
        int i, len;
 
@@ -218,15 +214,8 @@ get_client(struct variable *v, oid objid[], size_t *objid_len, int exact) {
                        return NULL;
 
                i = objid[v->namelen]-1;
-               c = mainconfig.clients;
-               while (i && c)
-               {
-                       c = c->next;
-                       i--;
-               }
-               if (c)
-                       return c;
-               return NULL;
+
+               return client_findbynumber(mainconfig.clients, i);
        }
        i = objid[v->namelen]-1;
        *objid_len = v->namelen + 1;
@@ -234,23 +223,19 @@ get_client(struct variable *v, oid objid[], size_t *objid_len, int exact) {
                objid[v->namelen]=1;
                return mainconfig.clients;
        }
-       c = mainconfig.clients->next;
-       while (i && c) {
-               c = c->next;
-               i--;
-       }
+
+       c = client_findbynumber(mainconfig.clients, i);
        if (c) {
                objid[v->namelen]++;
-               return c;
-       } else
-               return NULL;
+       }
+       return c;
 }
 
 static int
-radServReset (int action, u_char *var_val, u_char var_val_type,
-               size_t var_val_len, const unsigned char *statP, oid *name,
-               size_t name_len) {
-
+radServReset(int action, u_char *var_val, u_char var_val_type,
+            size_t var_val_len, UNUSED const unsigned char *statP,
+            UNUSED oid *name, UNUSED size_t name_len)
+{
        long i;
        int big = SNMP_MAX_LEN;
 
@@ -369,7 +354,7 @@ radAccEntry(struct variable *vp, oid *name, size_t *length, int exact,
                        return (unsigned char *)&(c->ipaddr);
 
                case RADIUSACCCLIENTID:
-                       if (strlen(c->shortname)) {
+                       if (c->shortname && c->shortname[0]) {
                                *var_len = strlen(c->shortname);
                                return c->shortname;
                        }
@@ -504,11 +489,11 @@ radAuthEntry(struct variable *vp, oid      *name, size_t *length, int exact,
                        return (unsigned char *)&(c->ipaddr);
 
                case RADIUSAUTHCLIENTID:
-                       if (strlen(c->shortname)) {
+                       if (c->shortname && c->shortname[0]) {
                                *var_len = strlen(c->shortname);
-                                       return c->shortname;
+                               return c->shortname;
                        }
-               *var_len = strlen(c->longname);
+                       *var_len = strlen(c->longname);
                        return c->longname;
 
                case RADIUSAUTHSERVACCESSREQUESTS:
@@ -542,7 +527,7 @@ radAuthEntry(struct variable *vp, oid        *name, size_t *length, int exact,
        return NULL;
 }
 
-static CONF_PARSER snmp_config[] = {
+static const CONF_PARSER snmp_config[] = {
        { "smux_password", PW_TYPE_STRING_PTR, 0, &rad_snmp.smux_password, "" },
        { "snmp_write_access",  PW_TYPE_BOOLEAN, 0, &rad_snmp.snmp_write_access, "no" },
        { NULL, -1, 0, NULL, NULL }
index 3066ffd..ce19e46 100644 (file)
@@ -15,9 +15,9 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000,2001,2002,2003,2004  The FreeRADIUS server project
+ * Copyright 2000-2004,2006  The FreeRADIUS server project
  * Copyright 1999,2000  Miquel van Smoorenburg <miquels@cistron.nl>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  * Copyright 2000  Alan Curry <pacman-radius@cqc.com>
  * Copyright 2000  Chad Miller <cmiller@surfsouth.com>
  */
 
-/* don't look here for the version, run radiusd -v or look in version.c */
-static const char rcsid[] =
-"$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <sys/file.h>
 
@@ -57,10 +55,6 @@ static const char rcsid[] =
 #      include <sys/select.h>
 #endif
 
-#ifdef HAVE_SYSLOG_H
-#      include <syslog.h>
-#endif
-
 #ifdef HAVE_SYS_WAIT_H
 #      include <sys/wait.h>
 #endif
@@ -71,12 +65,13 @@ static const char rcsid[] =
 #      define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
 #endif
 
-#include "radiusd.h"
-#include "rad_assert.h"
-#include "conffile.h"
-#include "modules.h"
-#include "request_list.h"
-#include "radius_snmp.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/request_list.h>
+#include <freeradius-devel/radius_snmp.h>
+
+#define SLEEP_FOREVER (65536)
 
 /*
  *  Global variables.
@@ -85,27 +80,22 @@ const char *progname = NULL;
 const char *radius_dir = NULL;
 const char *radacct_dir = NULL;
 const char *radlog_dir = NULL;
-radlog_dest_t radlog_dest = RADLOG_FILES;
 const char *radlib_dir = NULL;
-int syslog_facility;
 int log_stripped_names;
 int debug_flag = 0;
 int log_auth_detail = FALSE;
 int need_reload = FALSE;
-int sig_hup_block = FALSE;
+
 const char *radiusd_version = "FreeRADIUS Version " RADIUSD_VERSION ", for host " HOSTINFO ", built on " __DATE__ " at " __TIME__;
 
-static time_t time_now;
+time_t time_now;
 static pid_t radius_pid;
+static int debug_memory = 0;
 
 /*
  *  Configuration items.
  */
-static int dont_fork = FALSE;
-static time_t start_time = 0;
-static int spawn_flag = TRUE;
 static int do_exit = 0;
-static int debug_memory = 0;
 
 /*
  *     Static functions.
@@ -115,694 +105,29 @@ static void usage(int);
 static void sig_fatal (int);
 static void sig_hup (int);
 
-static int rad_status_server(REQUEST *request);
-
-/*
- *  Parse a string into a syslog facility level.
- */
-static int str2fac(const char *s)
-{
-#ifdef LOG_KERN
-       if(!strcmp(s, "kern"))
-               return LOG_KERN;
-       else
-#endif
-#ifdef LOG_USER
-       if(!strcmp(s, "user"))
-               return LOG_USER;
-       else
-#endif
-#ifdef LOG_MAIL
-       if(!strcmp(s, "mail"))
-               return LOG_MAIL;
-       else
-#endif
-#ifdef LOG_DAEMON
-       if(!strcmp(s, "daemon"))
-               return LOG_DAEMON;
-       else
-#endif
-#ifdef LOG_AUTH
-       if(!strcmp(s, "auth"))
-               return LOG_AUTH;
-       else
-#endif
-#ifdef LOG_SYSLOG
-       if(!strcmp(s, "auth"))
-               return LOG_AUTH;
-       else
-#endif
-#ifdef LOG_LPR
-       if(!strcmp(s, "lpr"))
-               return LOG_LPR;
-       else
-#endif
-#ifdef LOG_NEWS
-       if(!strcmp(s, "news"))
-               return LOG_NEWS;
-       else
-#endif
-#ifdef LOG_UUCP
-       if(!strcmp(s, "uucp"))
-               return LOG_UUCP;
-       else
-#endif
-#ifdef LOG_CRON
-       if(!strcmp(s, "cron"))
-               return LOG_CRON;
-       else
-#endif
-#ifdef LOG_AUTHPRIV
-       if(!strcmp(s, "authpriv"))
-               return LOG_AUTHPRIV;
-       else
-#endif
-#ifdef LOG_FTP
-       if(!strcmp(s, "ftp"))
-               return LOG_FTP;
-       else
-#endif
-#ifdef LOG_LOCAL0
-       if(!strcmp(s, "local0"))
-               return LOG_LOCAL0;
-       else
-#endif
-#ifdef LOG_LOCAL1
-       if(!strcmp(s, "local1"))
-               return LOG_LOCAL1;
-       else
-#endif
-#ifdef LOG_LOCAL2
-       if(!strcmp(s, "local2"))
-               return LOG_LOCAL2;
-       else
-#endif
-#ifdef LOG_LOCAL3
-       if(!strcmp(s, "local3"))
-               return LOG_LOCAL3;
-       else
-#endif
-#ifdef LOG_LOCAL4
-       if(!strcmp(s, "local4"))
-               return LOG_LOCAL4;
-       else
-#endif
-#ifdef LOG_LOCAL5
-       if(!strcmp(s, "local5"))
-               return LOG_LOCAL5;
-       else
-#endif
-#ifdef LOG_LOCAL6
-       if(!strcmp(s, "local6"))
-               return LOG_LOCAL6;
-       else
-#endif
-#ifdef LOG_LOCAL7
-       if(!strcmp(s, "local7"))
-               return LOG_LOCAL7;
-       else
-#endif
-       {
-               fprintf(stderr, "%s: Error: Unknown syslog facility: %s\n",
-                       progname, s);
-               exit(1);
-       }
-
-       /* this should never be reached */
-       return LOG_DAEMON;
-}
-
-
-/*
- *     Check if an incoming request is "ok"
- *
- *     It takes packets, not requests.  It sees if the packet looks
- *     OK.  If so, it does a number of sanity checks on it.
-  */
-static RAD_REQUEST_FUNP packet_ok(RADIUS_PACKET *packet,
-                                 rad_listen_t *listener)
-{
-       REQUEST         *curreq;
-       RAD_REQUEST_FUNP fun = NULL;
-
-       /*
-        *      Some sanity checks, based on the packet code.
-        */
-       switch(packet->code) {
-               case PW_AUTHENTICATION_REQUEST:
-                       /*
-                        *      Check for requests sent to the wrong
-                        *      port, and ignore them, if so.
-                        */
-                       if (listener->type != RAD_LISTEN_AUTH) {
-                               RAD_SNMP_INC(rad_snmp.auth.total_packets_dropped);
-                               radlog(L_ERR, "Authentication-Request sent to a non-authentication port from "
-                                       "client %s:%d - ID %d : IGNORED",
-                                       client_name(packet->src_ipaddr),
-                                      packet->src_port, packet->id);
-                               return NULL;
-                       }
-                       fun = rad_authenticate;
-                       break;
-
-               case PW_ACCOUNTING_REQUEST:
-                       /*
-                        *      Check for requests sent to the wrong
-                        *      port, and ignore them, if so.
-                        */
-                       if (listener->type != RAD_LISTEN_ACCT) {
-                               RAD_SNMP_INC(rad_snmp.acct.total_packets_dropped);
-                               radlog(L_ERR, "Accounting-Request packet sent to a non-accounting port from "
-                                      "client %s:%d - ID %d : IGNORED",
-                                      client_name(packet->src_ipaddr),
-                                      packet->src_port, packet->id);
-                               return NULL;
-                       }
-                       fun = rad_accounting;
-                       break;
-
-               case PW_AUTHENTICATION_ACK:
-               case PW_ACCESS_CHALLENGE:
-               case PW_AUTHENTICATION_REJECT:
-                       /*
-                        *      Replies NOT sent to the proxy port get
-                        *      an error message logged, and the
-                        *      packet is dropped.
-                        */
-                       if (listener->type != RAD_LISTEN_PROXY) {
-                               RAD_SNMP_INC(rad_snmp.auth.total_packets_dropped);
-                               radlog(L_ERR, "Authentication reply packet code %d sent to a non-proxy reply port from "
-                                      "client %s:%d - ID %d : IGNORED",
-                                      packet->code,
-                                      client_name(packet->src_ipaddr),
-                                      packet->src_port, packet->id);
-                               return NULL;
-                       }
-                       fun = rad_authenticate;
-                       break;
-
-               case PW_ACCOUNTING_RESPONSE:
-                       /*
-                        *      Replies NOT sent to the proxy port get
-                        *      an error message logged, and the
-                        *      packet is dropped.
-                        */
-                       if (listener->type != RAD_LISTEN_PROXY) {
-                               RAD_SNMP_INC(rad_snmp.acct.total_packets_dropped);
-                               radlog(L_ERR, "Accounting reply packet code %d sent to a non-proxy reply port from "
-                                      "client %s:%d - ID %d : IGNORED",
-                                      packet->code,
-                                      client_name(packet->src_ipaddr),
-                                      packet->src_port, packet->id);
-                               return 0;
-                       }
-                       fun = rad_accounting;
-                       break;
-
-               case PW_STATUS_SERVER:
-                       if (!mainconfig.status_server) {
-                               DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
-                               return NULL;
-                       }
-                       fun = rad_status_server;
-                       break;
-
-               case PW_PASSWORD_REQUEST:
-                       RAD_SNMP_INC(rad_snmp.auth.total_unknown_types);
-
-                       /*
-                        *  We don't support this anymore.
-                        */
-                       radlog(L_ERR, "Deprecated password change request from client %s:%d - ID %d : IGNORED",
-                                       client_name(packet->src_ipaddr),
-                              packet->src_port, packet->id);
-                       return NULL;
-                       break;
-
-               default:
-                       RAD_SNMP_INC(rad_snmp.auth.total_unknown_types);
-
-                       radlog(L_ERR, "Unknown packet code %d from client %s:%d "
-                              "- ID %d : IGNORED", packet->code,
-                              client_name(packet->src_ipaddr),
-                              packet->src_port, packet->id);
-                       return NULL;
-                       break;
-
-       } /* switch over packet types */
-
-       /*
-        *      Don't handle proxy replies here.  They need to
-        *      return the *old* request, so we can re-process it.
-        */
-       if (listener->type == RAD_LISTEN_PROXY) {
-               return fun;
-       }
-
-       /*
-        *      If there is no existing request of id, code, etc.,
-        *      then we can return, and let it be processed.
-        */
-       if ((curreq = rl_find(packet)) == NULL) {
-               /*
-                *      Count the total number of requests, to see if
-                *      there are too many.  If so, return with an
-                *      error.
-                */
-               if (mainconfig.max_requests) {
-                       int request_count = rl_num_requests();
-
-                       /*
-                        *      This is a new request.  Let's see if
-                        *      it makes us go over our configured
-                        *      bounds.
-                        */
-                       if (request_count > mainconfig.max_requests) {
-                               radlog(L_ERR, "Dropping request (%d is too many): "
-                                      "from client %s:%d - ID: %d", request_count,
-                                      client_name(packet->src_ipaddr),
-                                      packet->src_port, packet->id);
-                               radlog(L_INFO, "WARNING: Please check the radiusd.conf file.\n"
-                                      "\tThe value for 'max_requests' is probably set too low.\n");
-                               return NULL;
-                       } /* else there were a small number of requests */
-               } /* else there was no configured limit for requests */
-
-               /*
-                *      FIXME: Add checks for system load.  If the
-                *      system is busy, start dropping requests...
-                *
-                *      We can probably keep some statistics
-                *      ourselves...  if there are more requests
-                *      coming in than we can handle, start dropping
-                *      some.
-                */
-
-               return fun;
-       }
-
-       /*
-        *      "fake" requests MUST NEVER be in the request list.
-        *
-        *      They're used internally in the server.  Any reply
-        *      is a reply to the local server, and any proxied packet
-        *      gets sent outside of the tunnel.
-        */
-       rad_assert((curreq->options & RAD_REQUEST_OPTION_FAKE_REQUEST) == 0);
-
-       /*
-        *      The current request isn't finished, which
-        *      means that the NAS sent us a new packet, while
-        *      we are still processing the old request.
-        */
-       if (!curreq->finished) {
-               /*
-                *      If the authentication vectors are identical,
-                *      then the NAS is re-transmitting it, trying to
-                *      kick us into responding to the request.
-                */
-               if (memcmp(curreq->packet->vector, packet->vector,
-                          sizeof(packet->vector)) == 0) {
-                       RAD_SNMP_INC(rad_snmp.auth.total_dup_requests);
-
-                       /*
-                        *      It's not finished because the request
-                        *      was proxied, but there was no reply
-                        *      from the home server.
-                        */
-                       if (curreq->proxy && !curreq->proxy_reply) {
-                               /*
-                                *      We're taking care of sending
-                                *      duplicate proxied packets, so
-                                *      we ignore any duplicate
-                                *      requests from the NAS.
-                                *
-                                *      FIXME: Make it ALWAYS synchronous!
-                                */
-                               if (!mainconfig.proxy_synchronous) {
-                                       RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
-
-                                       DEBUG2("Ignoring duplicate packet from client "
-                                              "%s:%d - ID: %d, due to outstanding proxied request %d.",
-                                              client_name(packet->src_ipaddr),
-                                              packet->src_port, packet->id,
-                                              curreq->number);
-                                       return NULL;
-
-                                       /*
-                                        *      We ARE proxying the request,
-                                        *      and we have NOT received a
-                                        *      proxy reply yet, and we ARE
-                                        *      doing synchronous proxying.
-                                        *
-                                        *      In that case, go kick
-                                        *      the home RADIUS server
-                                        *      again.
-                                        */
-                               } else {
-                                       char buffer[64];
-
-                                       DEBUG2("Sending duplicate proxied request to home server %s:%d - ID: %d",
-                                              ip_ntoa(buffer, curreq->proxy->dst_ipaddr),
-                                              curreq->proxy->dst_port,
-
-                                              curreq->proxy->id);
-                               }
-                               curreq->proxy_next_try = time_now + mainconfig.proxy_retry_delay;
-                               rad_send(curreq->proxy, curreq->packet,
-                                        curreq->proxysecret);
-                               return NULL;
-                       } /* else the packet was not proxied */
-
-                       /*
-                        *      Someone's still working on it, so we
-                        *      ignore the duplicate request.
-                        */
-                       radlog(L_ERR, "Discarding duplicate request from "
-                              "client %s:%d - ID: %d due to unfinished request %d",
-                              client_name(packet->src_ipaddr),
-                              packet->src_port, packet->id,
-                              curreq->number);
-                       return NULL;
-               } /* else the authentication vectors were different */
-
-               /*
-                *      The authentication vectors are different, so
-                *      the NAS has given up on us, as we've taken too
-                *      long to process the request.  This is a
-                *      SERIOUS problem!
-                */
-               RAD_SNMP_TYPE_INC(listener, total_packets_dropped);
-
-               radlog(L_ERR, "Dropping conflicting packet from "
-                      "client %s:%d - ID: %d due to unfinished request %d",
-                      client_name(packet->src_ipaddr),
-                      packet->src_port, packet->id,
-                      curreq->number);
-               return NULL;
-       }
-
-       /*
-        *      The old request is finished.  We now check the
-        *      authentication vectors.  If the client has sent us a
-        *      request with identical code && ID, but different
-        *      vector, then they MUST have gotten our response, so we
-        *      can delete the original request, and process the new
-        *      one.
-        *
-        *      If the vectors are the same, then it's a duplicate
-        *      request, and we can send a duplicate reply.
-        */
-       if (memcmp(curreq->packet->vector, packet->vector,
-                  sizeof(packet->vector)) == 0) {
-               RAD_SNMP_INC(rad_snmp.auth.total_dup_requests);
-
-               /*
-                *      If the packet has been delayed, then silently
-                *      send a response, and clear the delayed flag.
-                *
-                *      Note that this means if the NAS kicks us while
-                *      we're delaying a reject, then the reject may
-                *      be sent sooner than otherwise.
-                *
-                *      This COULD be construed as a bug.  Maybe what
-                *      we want to do is to ignore the duplicate
-                *      packet, and send the reject later.
-                */
-               if (curreq->options & RAD_REQUEST_OPTION_DELAYED_REJECT) {
-                       curreq->options &= ~RAD_REQUEST_OPTION_DELAYED_REJECT;
-                       rad_send(curreq->reply, curreq->packet, curreq->secret);
-                       return NULL;
-               }
-
-               /*
-                *      Maybe we've saved a reply packet.  If so,
-                *      re-send it.  Otherwise, just complain.
-                */
-               if (curreq->reply->code != 0) {
-                       DEBUG2("Sending duplicate reply "
-                              "to client %s:%d - ID: %d",
-                              client_name(packet->src_ipaddr),
-                              packet->src_port, packet->id);
-                       rad_send(curreq->reply, curreq->packet, curreq->secret);
-                       return NULL;
-               }
-
-               /*
-                *      Else we never sent a reply to the NAS,
-                *      as we decided somehow we didn't like the request.
-                *
-                *      This shouldn't happen, in general...
-                */
-               DEBUG2("Discarding duplicate request from client %s:%d - ID: %d",
-                      client_name(packet->src_ipaddr),
-                      packet->src_port, packet->id);
-               return NULL;
-       } /* else the vectors were different, so we discard the old request. */
-
-       /*
-        *      'packet' has the same source IP, source port, code,
-        *      and Id as 'curreq', but a different authentication
-        *      vector.  We can therefore delete 'curreq', as we were
-        *      only keeping it around to send out duplicate replies,
-        *      if the first reply got lost in the network.
-        */
-       rl_delete(curreq);
-
-       /*
-        *      The request is OK.  We can process it...
-        *
-        *      Don't bother checking the maximum nubmer of requests
-        *      here.  we've just deleted one, so we KNOW we're under
-        *      the limit if we add one more.
-        */
-       return fun;
-}
-
-
-/*
- *  Do a proxy check of the REQUEST list when using the new proxy code.
- */
-static REQUEST *proxy_ok(RADIUS_PACKET *packet)
-{
-       REALM *cl;
-       REQUEST *oldreq;
-       char buffer[32];
-
-       /*
-        *      Find the original request in the request list
-        */
-       oldreq = rl_find_proxy(packet);
-
-       /*
-        *      If we haven't found the original request which was
-        *      sent, to get this reply.  Complain, and discard this
-        *      request, as there's no way for us to send it to a NAS.
-        */
-       if (!oldreq) {
-               radlog(L_PROXY, "No outstanding request was found for proxy reply from home server %s:%d - ID %d",
-                      ip_ntoa(buffer, packet->src_ipaddr),
-                      packet->src_port, packet->id);
-               return NULL;
-       }
-
-       /*
-        *      The proxy reply has arrived too late, as the original
-        *      (old) request has timed out, been rejected, and marked
-        *      as finished.  The client has already received a
-        *      response, so there is nothing that can be done. Delete
-        *      the tardy reply from the home server, and return NULL.
-        */
-       if ((oldreq->reply->code != 0) ||
-           (oldreq->finished)) {
-               radlog(L_ERR, "Reply from home server %s:%d  - ID: %d arrived too late for request %d. Try increasing 'retry_delay' or 'max_request_time'",
-                      ip_ntoa(buffer, packet->src_ipaddr),
-                      packet->src_port, packet->id,
-                      oldreq->number);
-               return NULL;
-       }
-
-       /*
-        *      If there is already a reply, maybe this one is a
-        *      duplicate?
-        */
-       if (oldreq->proxy_reply) {
-               if (memcmp(oldreq->proxy_reply->vector,
-                          packet->vector,
-                          sizeof(oldreq->proxy_reply->vector)) == 0) {
-                       radlog(L_ERR, "Discarding duplicate reply from home server %s:%d  - ID: %d for request %d",
-                              ip_ntoa(buffer, packet->src_ipaddr),
-                              packet->src_port, packet->id,
-                              oldreq->number);
-               } else {
-                       /*
-                        *      ? The home server gave us a new *
-                        *      proxy reply, which doesn't match * the
-                        *      old one.  Delete it
-                        !  */
-                       DEBUG2("Ignoring conflicting proxy reply");
-               }
-
-               /*
-                *      We've already received a reply, so
-                *      we discard this one, as we don't want
-                *      to do duplicate work.
-                */
-               return NULL;
-       } /* else there wasn't a proxy reply yet, so we can process it */
-
-       /*
-        *       Refresh the old request, and update it with the proxy
-        *       reply.
-        *
-        *      ? Can we delete the proxy request here?  * Is there
-        *      any more need for it?
-        *
-        *      FIXME: we probably shouldn't be updating the time
-        *      stamp here.
-        */
-       oldreq->timestamp = time_now;
-       oldreq->proxy_reply = packet;
-
-       /*
-        *      Now that we've verified the packet IS actually
-        *      from that realm, and not forged, we can go mark the
-        *      realms for this home server as active.
-        *
-        *      If we had done this check in the 'find realm by IP address'
-        *      function, then an attacker could force us to use a home
-        *      server which was inactive, by forging reply packets
-        *      which didn't match any request.  We would think that
-        *      the reply meant the home server was active, would
-        *      re-activate the realms, and THEN bounce the packet
-        *      as garbage.
-        */
-       for (cl = mainconfig.realms; cl != NULL; cl = cl->next) {
-               if (oldreq->proxy_reply->src_ipaddr == cl->ipaddr) {
-                       if (oldreq->proxy_reply->src_port == cl->auth_port) {
-                               cl->active = TRUE;
-                               cl->last_reply = oldreq->timestamp;
-                       } else if (oldreq->proxy_reply->src_port == cl->acct_port) {
-                               cl->acct_active = TRUE;
-                               cl->last_reply = oldreq->timestamp;
-                       }
-               }
-       }
-
-       return oldreq;
-}
-
-/*
- *     Do more checks, this time on the REQUEST data structure.
- *
- *     The main purpose of this code is to handle proxied requests.
- */
-static REQUEST *request_ok(RADIUS_PACKET *packet, uint8_t *secret,
-                          rad_listen_t *listener)
-{
-       REQUEST         *request = NULL;
-
-       /*
-        *      If the request has come in on the proxy FD, then
-        *      it's a proxy reply, so pass it through the code which
-        *      tries to find the original request, which we should
-        *      process, rather than processing the reply as a "new"
-        *      request.
-        */
-       if (listener->type == RAD_LISTEN_PROXY) {
-               /*
-                *      Find the old request, based on the current
-                *      packet.
-                */
-               request = proxy_ok(packet);
-               if (!request) {
-                       return NULL;
-               }
-               rad_assert(request->magic == REQUEST_MAGIC);
-
-               /*
-                *      We must have passed through the code below
-                *      for the original request, which adds the
-                *      reply packet to it.
-                */
-               rad_assert(request->reply != NULL);
-
-       } else {                /* remember the new request */
-               /*
-                *      A unique per-request counter.
-                */
-               static int request_num_counter = 0;
-
-               request = request_alloc(); /* never fails */
-               request->packet = packet;
-               request->number = request_num_counter++;
-               strNcpy(request->secret, (char *)secret,
-                       sizeof(request->secret));
-
-               /*
-                *      Remember the request.
-                */
-               rl_add(request);
-
-               /*
-                *      ADD IN "server identifier" from "listen"
-                *      directive!
-                */
-
-               /*
-                *      The request passes many of our sanity checks.
-                *      From here on in, if anything goes wrong, we
-                *      send a reject message, instead of dropping the
-                *      packet.
-                *
-                *      Build the reply template from the request
-                *      template.
-                */
-               rad_assert(request->reply == NULL);
-               if ((request->reply = rad_alloc(0)) == NULL) {
-                       radlog(L_ERR, "No memory");
-                       exit(1);
-               }
-               request->reply->sockfd = request->packet->sockfd;
-               request->reply->dst_ipaddr = request->packet->src_ipaddr;
-               request->reply->src_ipaddr = request->packet->dst_ipaddr;
-               request->reply->dst_port = request->packet->src_port;
-               request->reply->src_port = request->packet->dst_port;
-               request->reply->id = request->packet->id;
-               request->reply->code = 0; /* UNKNOWN code */
-               memcpy(request->reply->vector, request->packet->vector,
-                      sizeof(request->reply->vector));
-               request->reply->vps = NULL;
-               request->reply->data = NULL;
-               request->reply->data_len = 0;
-       }
-
-       return request;
-}
-
-
 /*
  *     The main guy.
  */
 int main(int argc, char *argv[])
 {
        REQUEST *request;
-       RADIUS_PACKET *packet;
-       u_char *secret;
        unsigned char buffer[4096];
        fd_set readfds;
        int argval;
        int pid;
        int max_fd;
        int status;
-       struct timeval *tv = NULL;
+       int sleep_time = SLEEP_FOREVER;
+       int spawn_flag = TRUE;
+       int dont_fork = FALSE;
+       int sig_hup_block = FALSE;
+       time_t last_cleaned_lists = 0;
+
 #ifdef HAVE_SIGACTION
        struct sigaction act;
 #endif
        rad_listen_t *listener;
 
-       syslog_facility = LOG_DAEMON;
-
 #ifdef OSFC2
        set_auth_parameters(argc,argv);
 #endif
@@ -820,14 +145,25 @@ int main(int argc, char *argv[])
         *      Ensure that the configuration is initialized.
         */
        memset(&mainconfig, 0, sizeof(mainconfig));
+       mainconfig.myip.af = AF_UNSPEC;
+       mainconfig.port = -1;
+       mainconfig.radiusd_conf = strdup("radiusd.conf");
+
 #ifdef HAVE_SIGACTION
        memset(&act, 0, sizeof(act));
        act.sa_flags = 0 ;
        sigemptyset( &act.sa_mask ) ;
 #endif
 
+       /*
+        *      Don't put output anywhere until we get told a little
+        *      more.
+        */
+       mainconfig.radlog_fd = -1;
+       mainconfig.log_file = NULL;
+
        /*  Process the options.  */
-       while ((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:mp:sSvxXyz")) != EOF) {
+       while ((argval = getopt(argc, argv, "Aa:bcd:fg:hi:l:mn:p:sSvxXyz")) != EOF) {
 
                switch(argval) {
 
@@ -836,7 +172,7 @@ int main(int argc, char *argv[])
                                break;
 
                        case 'a':
-                               if (radacct_dir) xfree(radacct_dir);
+                               if (radacct_dir) free(radacct_dir);
                                radacct_dir = strdup(optarg);
                                break;
 
@@ -845,7 +181,7 @@ int main(int argc, char *argv[])
                                break;
 
                        case 'd':
-                               if (radius_dir) xfree(radius_dir);
+                               if (radius_dir) free(radius_dir);
                                radius_dir = strdup(optarg);
                                break;
 
@@ -858,35 +194,55 @@ int main(int argc, char *argv[])
                                break;
 
                        case 'i':
-                               if ((mainconfig.myip = ip_getaddr(optarg)) == INADDR_NONE) {
-                                       fprintf(stderr, "radiusd: %s: host unknown\n",
-                                               optarg);
+                               if (ip_hton(optarg, AF_UNSPEC, &mainconfig.myip) < 0) {
+                                       fprintf(stderr, "radiusd: Invalid IP Address or hostname \"%s\"\n", optarg);
                                        exit(1);
                                }
                                break;
 
                        case 'l':
+                               if ((strcmp(optarg, "stdout") == 0) ||
+                                   (strcmp(optarg, "stderr") == 0) ||
+                                   (strcmp(optarg, "syslog") == 0)) {
+                                       fprintf(stderr, "radiusd: -l %s is unsupported.  Use log_destination in radiusd.conf\n", optarg);
+                                       exit(1);
+                               }
+                               if (radlog_dir) free(radlog_dir);
                                radlog_dir = strdup(optarg);
                                break;
 
-                               /*
-                                *  We should also have this as a configuration
-                                *  file directive.
-                                */
                        case 'g':
-                               syslog_facility = str2fac(optarg);
+                               fprintf(stderr, "radiusd: -g is unsupported.  Use log_destination in radiusd.conf.\n");
+                               exit(1);
                                break;
 
                        case 'm':
                                debug_memory = 1;
                                break;
 
+                       case 'n':
+                               if ((strchr(optarg, '/') != NULL) ||
+                                   (strchr(optarg, '.') != NULL) ||
+                                   (strlen(optarg) > 45)) usage(1);
+
+                               snprintf(buffer, sizeof(buffer), "%s.conf",
+                                        optarg);
+                               if (mainconfig.radiusd_conf)
+                                       free(mainconfig.radiusd_conf);
+                               mainconfig.radiusd_conf = strdup(buffer);
+                               break;
+
                        case 'S':
                                log_stripped_names++;
                                break;
 
                        case 'p':
-                               fprintf(stderr, "Ignoring deprecated command-line option -p");
+                               mainconfig.port = atoi(optarg);
+                               if ((mainconfig.port <= 0) ||
+                                   (mainconfig.port >= 65536)) {
+                                       fprintf(stderr, "radiusd: Invalid port number %s\n", optarg);
+                                       exit(1);
+                               }
                                break;
 
                        case 's':       /* Single process mode */
@@ -909,7 +265,8 @@ int main(int argc, char *argv[])
                                mainconfig.log_auth = TRUE;
                                mainconfig.log_auth_badpass = TRUE;
                                mainconfig.log_auth_goodpass = TRUE;
-                               radlog_dir = strdup("stdout");
+                               mainconfig.radlog_dest = RADLOG_STDOUT;
+                               mainconfig.radlog_fd = STDOUT_FILENO;
                                break;
 
                        case 'x':
@@ -932,72 +289,12 @@ int main(int argc, char *argv[])
                }
        }
 
-       /*
-        *      Get our PID.
-        */
-       radius_pid = getpid();
-
        /*  Read the configuration files, BEFORE doing anything else.  */
        if (read_mainconfig(0) < 0) {
                exit(1);
        }
 
        /*
-        *      If we're NOT debugging, trap fatal signals, so we can
-        *      easily clean up after ourselves.
-        *
-        *      If we ARE debugging, don't trap them, so we can
-        *      dump core.
-        */
-       if ((mainconfig.allow_core_dumps == FALSE) && (debug_flag == 0)) {
-#ifdef SIGSEGV
-#ifdef HAVE_SIGACTION
-               act.sa_handler = sig_fatal;
-               sigaction(SIGSEGV, &act, NULL);
-#else
-               signal(SIGSEGV, sig_fatal);
-#endif
-#endif
-       }
-
-       /*  Reload the modules.  */
-       DEBUG2("radiusd:  entering modules setup");
-       if (setup_modules() < 0) {
-               radlog(L_ERR|L_CONS, "Errors setting up modules");
-               exit(1);
-       }
-
-#ifdef HAVE_SYSLOG_H
-       /*
-        *  If they asked for syslog, then give it to them.
-        *  Also, initialize the logging facility with the
-        *  configuration that they asked for.
-        */
-       if (strcmp(radlog_dir, "syslog") == 0) {
-               openlog(progname, LOG_PID, syslog_facility);
-               radlog_dest = RADLOG_SYSLOG;
-       }
-       /* Do you want a warning if -g is used without a -l to activate it? */
-#endif
-       if (strcmp(radlog_dir, "stdout") == 0) {
-               radlog_dest = RADLOG_STDOUT;
-       } else if (strcmp(radlog_dir, "stderr") == 0) {
-               radlog_dest = RADLOG_STDERR;
-       }
-
-       /*  Initialize the request list.  */
-       rl_init();
-
-       /*
-        *  Register built-in compare functions.
-        */
-       pair_builtincompare_init();
-
-#ifdef WITH_SNMP
-       if (mainconfig.do_snmp) radius_snmp_init();
-#endif
-
-       /*
         *  Disconnect from session
         */
        if (debug_flag == 0 && dont_fork == FALSE) {
@@ -1010,7 +307,7 @@ int main(int argc, char *argv[])
                /*
                 *  The parent exits, so the child can run in the background.
                 */
-               if(pid > 0) {
+               if (pid > 0) {
                        exit(0);
                }
 #ifdef HAVE_SETSID
@@ -1019,6 +316,28 @@ int main(int argc, char *argv[])
        }
 
        /*
+        *      If we're NOT debugging, trap fatal signals, so we can
+        *      easily clean up after ourselves.
+        *
+        *      If we ARE debugging, don't trap them, so we can
+        *      dump core.
+        */
+       if ((mainconfig.allow_core_dumps == FALSE) && (debug_flag == 0)) {
+#ifdef SIGSEGV
+#ifdef HAVE_SIGACTION
+               act.sa_handler = sig_fatal;
+               sigaction(SIGSEGV, &act, NULL);
+#else
+               signal(SIGSEGV, sig_fatal);
+#endif
+#endif
+       }
+
+#ifdef WITH_SNMP
+       if (mainconfig.do_snmp) radius_snmp_init();
+#endif
+
+       /*
         *  Ensure that we're using the CORRECT pid after forking,
         *  NOT the one we started with.
         */
@@ -1053,7 +372,7 @@ int main(int argc, char *argv[])
         *      If we're running as a daemon, close the default file
         *      descriptors, AFTER forking.
         */
-       if (debug_flag == FALSE) {
+       if (!debug_flag) {
                int devnull;
 
                devnull = open("/dev/null", O_RDWR);
@@ -1063,24 +382,22 @@ int main(int argc, char *argv[])
                        exit(1);
                }
                dup2(devnull, STDIN_FILENO);
+               if (mainconfig.radlog_dest == RADLOG_STDOUT) {
+                       mainconfig.radlog_fd = dup(STDOUT_FILENO);
+               }
                dup2(devnull, STDOUT_FILENO);
+               if (mainconfig.radlog_dest == RADLOG_STDERR) {
+                       mainconfig.radlog_fd = dup(STDERR_FILENO);
+               }
                dup2(devnull, STDERR_FILENO);
                close(devnull);
        }
 
-#ifdef HAVE_PTHREAD_H
-       /*
-        *  If we're spawning children, set up the thread pool.
-        */
-       if (spawn_flag == TRUE) {
-               thread_pool_init();
-       }
-#else
        /*
-        *      Without threads, we ALWAYS run in single-server mode.
+        *      It's called the thread pool, but it does a little
+        *      more than that.
         */
-       spawn_flag = FALSE;
-#endif
+       thread_pool_init(spawn_flag);
 
        /*
         *  Use linebuffered or unbuffered stdout if
@@ -1095,26 +412,22 @@ int main(int argc, char *argv[])
        for (listener = mainconfig.listen;
             listener != NULL;
             listener = listener->next) {
-               if (listener->ipaddr == INADDR_ANY) {
-                       strcpy((char *)buffer, "*");
-               } else {
-                       ip_ntoa((char *)buffer, listener->ipaddr);
-               }
-               
+               listener->print(listener, buffer, sizeof(buffer));
                switch (listener->type) {
                case RAD_LISTEN_AUTH:
-                       DEBUG("Listening on authentication %s:%d",
-                             buffer, listener->port);
+                       DEBUG("Listening on authentication address %s", buffer);
                        break;
 
                case RAD_LISTEN_ACCT:
-                       DEBUG("Listening on accounting %s:%d",
-                             buffer, listener->port);
+                       DEBUG("Listening on accounting address %s", buffer);
                        break;
 
                case RAD_LISTEN_PROXY:
-                       DEBUG("Listening on proxy %s:%d",
-                             buffer, listener->port);
+                       DEBUG("Listening on proxy address %s", buffer);
+                       break;
+
+               case RAD_LISTEN_DETAIL:
+                       DEBUG("Listening on detail file %s", buffer);
                        break;
 
                default:
@@ -1154,7 +467,6 @@ int main(int argc, char *argv[])
        }
 
        radlog(L_INFO, "Ready to process requests.");
-       start_time = time(NULL);
 
        /*
         *  Receive user requests
@@ -1186,11 +498,6 @@ int main(int argc, char *argv[])
                         */
 
                        /*
-                        *      Detach any modules.
-                        */
-                       detach_modules();
-
-                       /*
                         *      FIXME: clean up any active REQUEST
                         *      handles.
                         */
@@ -1208,6 +515,12 @@ int main(int argc, char *argv[])
                         *      Free the configuration items.
                         */
                        free_mainconfig();
+
+                       /*
+                        *      Detach any modules.
+                        */
+                       detach_modules();
+
                        free(radius_dir);
 
                        /*
@@ -1236,9 +549,9 @@ int main(int argc, char *argv[])
                                 */
                                sig_hup_block = TRUE;
                                if( (total_active_threads() == 0) ||
-                                    (max_wait >= 5) ) {
-                                 sig_hup_block = FALSE;
-                                 break;
+                                   (max_wait >= 5) ) {
+                                       sig_hup_block = FALSE;
+                                       break;
                                }
                                sleep(1);
                                max_wait++;
@@ -1248,13 +561,6 @@ int main(int argc, char *argv[])
                                exit(1);
                        }
 
-                       /*  Reload the modules.  */
-                       DEBUG2("radiusd:  entering modules setup");
-                       if (setup_modules() < 0) {
-                               radlog(L_ERR|L_CONS, "Errors setting up modules");
-                               exit(1);
-                       }
-
                        need_reload = FALSE;
                        radlog(L_INFO, "Ready to process requests.");
                }
@@ -1268,6 +574,8 @@ int main(int argc, char *argv[])
                for (listener = mainconfig.listen;
                     listener != NULL;
                     listener = listener->next) {
+                       if (listener->fd < 0) continue;
+
                        FD_SET(listener->fd, &readfds);
                        if (listener->fd > max_fd) max_fd = listener->fd;
                }
@@ -1279,7 +587,19 @@ int main(int argc, char *argv[])
                        if (rad_snmp.smux_fd > max_fd) max_fd = rad_snmp.smux_fd;
                }
 #endif
-               status = select(max_fd + 1, &readfds, NULL, NULL, tv);
+
+               if (sleep_time == SLEEP_FOREVER) {
+                       DEBUG2("Nothing to do.  Sleeping until we see a request.");
+                       status = select(max_fd + 1, &readfds, NULL, NULL, NULL);
+               } else {
+                       struct timeval tv;
+
+                       DEBUG2("Waking up in %d seconds...", sleep_time);
+
+                       tv.tv_sec = sleep_time;
+                       tv.tv_usec = 0;
+                       status = select(max_fd + 1, &readfds, NULL, NULL, &tv);
+               }
                if (status == -1) {
                        /*
                         *      On interrupts, we clean up the request
@@ -1289,7 +609,19 @@ int main(int argc, char *argv[])
                         *      catches that, and exits.
                         */
                        if (errno == EINTR) {
-                               tv = rl_clean_list(time(NULL));
+#ifdef MEMORY_USE_DEBUGGING
+                               /*
+                                *      Run the server in debugging mode,
+                                *      without threads, and give it a
+                                *      SIGHUP.  It will clean up after
+                                *      itself, and any memory left over
+                                *      should be allocated by C libraries,
+                                *      and the like.
+                                */
+                               detach_modules();
+                               free_mainconfig();
+                               exit(1);
+#endif
                                continue;
                        }
                        radlog(L_ERR, "Unexpected error in select(): %s",
@@ -1318,129 +650,38 @@ int main(int argc, char *argv[])
                     listener = listener->next) {
                        RAD_REQUEST_FUNP fun;
 
-                       if (!FD_ISSET(listener->fd, &readfds))
+                       if ((listener->fd >= 0) &&
+                           !FD_ISSET(listener->fd, &readfds))
                                continue;
+
                        /*
                         *  Receive the packet.
                         */
                        if (sig_hup_block != FALSE) {
-                         continue;
-                       }
-                       packet = rad_recv(listener->fd);
-                       if (packet == NULL) {
-                               radlog(L_ERR, "%s", librad_errstr);
                                continue;
                        }
 
                        /*
-                        *      If the destination IP is unknown, check
-                        *      if the listener has a known IP.  If so,
-                        *      use that.
-                        */
-                       if ((packet->dst_ipaddr == htonl(INADDR_ANY)) &&
-                           (packet->dst_ipaddr != listener->ipaddr)) {
-                               packet->dst_ipaddr = listener->ipaddr;
-                       }
-
-                       /*
-                        *      Fill in the destination port.
-                        */
-                       packet->dst_port = listener->port;
-
-                       RAD_SNMP_TYPE_INC(listener, total_requests);
-
-                       /*
-                        *      FIXME: Move this next check into
-                        *      the packet_ok() function, and add
-                        *      a 'secret' to the RAIDUS_PACKET
-                        *      data structure.  This involves changing
-                        *      a bunch of code, but it's probably the
-                        *      best thing to do.
-                        */
-
-                       /*
-                        *  Check if we know this client for
-                        *  authentication and accounting.  Check if we know
-                        *  this proxy for proxying.
-                        */
-                       if (listener->type != RAD_LISTEN_PROXY) {
-                               RADCLIENT *cl;
-                               if ((cl = client_find(packet->src_ipaddr)) == NULL) {
-                                       RAD_SNMP_TYPE_INC(listener, total_invalid_requests);
-
-                                       radlog(L_ERR, "Ignoring request from unknown client %s:%d",
-                                       ip_ntoa((char *)buffer, packet->src_ipaddr),
-                                       packet->src_port);
-                                       rad_free(&packet);
-                                       continue;
-                               }
-                               secret = cl->secret;
-                       } else {    /* It came in on the proxy port */
-                               REALM *rl;
-                               if ((rl = realm_findbyaddr(packet->src_ipaddr,packet->src_port)) == NULL) {
-                                       radlog(L_ERR, "Ignoring request from unknown home server %s:%d",
-                                       ip_ntoa((char *)buffer, packet->src_ipaddr),
-                                       packet->src_port);
-                                       rad_free(&packet);
-                                       continue;
-                               }
-
-                               /*
-                                *      The secret isn't needed here,
-                                *      as it's already in the old request
-                                */
-                               secret = NULL;
-                       }
-
-                       /*
-                        *      Do some simple checks before we process
-                        *      the request.
+                        *      Do per-socket receive processing of the
+                        *      packet.
                         */
-                       if ((fun = packet_ok(packet, listener)) == NULL) {
-                               rad_free(&packet);
+                       if (!listener->recv(listener, &fun, &request)) {
                                continue;
                        }
                        
                        /*
-                        *      Allocate a new request for packets from
-                        *      our clients, OR find the old request,
-                        *      for packets which are replies from a home
-                        *      server.
-                        */
-                       request = request_ok(packet, secret, listener);
-                       if (!request) {
-                               rad_free(&packet);
-                               continue;
-                       }
-
-                       /*
                         *      Drop the request into the thread pool,
                         *      and let the thread pool take care of
                         *      doing something with it.
                         */
-#ifdef HAVE_PTHREAD_H
-                       if (spawn_flag) {
-                               if (!thread_pool_addrequest(request, fun)) {
-                                       /*
-                                        *      FIXME: Maybe just drop
-                                        *      the packet on the floor?
-                                        */
-                                       request_reject(request);
-                                       request->finished = TRUE;
-                               }
-                       } else
-#endif
-                         {
-                                 rad_respond(request, fun);
-
-                                 /*
-                                  *    Requests that care about child
-                                  *    process exit codes have already
-                                  *    either called rad_waitpid(), or
-                                  *    they've given up.
-                                  */
-                                 wait(NULL);
-                         }
+                       if (!thread_pool_addrequest(request, fun)) {
+                               /*
+                                *      FIXME: Maybe just drop
+                                *      the packet on the floor?
+                                */
+                               request_reject(request, REQUEST_FAIL_NO_THREADS);
+                               request->finished = TRUE;
+                       }
                } /* loop over listening sockets*/
 
 #ifdef WITH_SNMP
@@ -1471,11 +712,26 @@ int main(int argc, char *argv[])
 #endif
 
                /*
-                *  After processing all new requests,
-                *  check if we've got to delete old requests
-                *  from the request list.
+                *      Loop through the request lists once per
+                *      second, to clean up old requests.
                 */
-               tv = rl_clean_list(time_now);
+               if (last_cleaned_lists != time_now) {
+                       last_cleaned_lists = time_now;
+
+                       DEBUG2("--- Walking the entire request list ---");
+                       sleep_time = SLEEP_FOREVER;
+                       for (listener = mainconfig.listen;
+                            listener != NULL;
+                            listener = listener->next) {
+                               int next;
+                               
+                               next = listener->update(listener, time_now);
+                               if (next < sleep_time) {
+                                       sleep_time = next;
+                               }
+                       }
+               }
+
 #ifdef HAVE_PTHREAD_H
 
                /*
@@ -1486,435 +742,11 @@ int main(int argc, char *argv[])
                        thread_pool_clean(time_now);
                }
 #endif
-
-
        } /* loop forever */
 }
 
 
 /*
- * FIXME:  The next two functions should all
- * be in a module.  But not until we have
- * more control over module execution.
- * -jcarneal
- */
-
-/*
- *  Lowercase the string value of a pair.
- */
-static int rad_lowerpair(REQUEST *request UNUSED, VALUE_PAIR *vp) {
-       if (vp == NULL) {
-               return -1;
-       }
-
-       rad_lowercase((char *)vp->strvalue);
-       DEBUG2("rad_lowerpair:  %s now '%s'", vp->name, vp->strvalue);
-       return 0;
-}
-
-/*
- *  Remove spaces in a pair.
- */
-static int rad_rmspace_pair(REQUEST *request UNUSED, VALUE_PAIR *vp) {
-       if (vp == NULL) {
-               return -1;
-       }
-
-       rad_rmspace((char *)vp->strvalue);
-       vp->length = strlen((char *)vp->strvalue);
-       DEBUG2("rad_rmspace_pair:  %s now '%s'", vp->name, vp->strvalue);
-
-       return 0;
-}
-
-/*
- *  Respond to a request packet.
- *
- *  Maybe we reply, maybe we don't.
- *  Maybe we proxy the request to another server, or else maybe
- *  we replicate it to another server.
- */
-int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun)
-{
-       RADIUS_PACKET *packet, *original;
-       const char *secret;
-       int finished = FALSE;
-       int reprocess = 0;
-
-       rad_assert(request->magic == REQUEST_MAGIC);
-
-       /*
-        *      Don't decode the packet if it's an internal "fake"
-        *      request.  Instead, just skip ahead to processing it.
-        */
-       if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {
-               goto skip_decode;
-       }
-
-       /*
-        *  Put the decoded packet into it's proper place.
-        */
-       if (request->proxy_reply != NULL) {
-               packet = request->proxy_reply;
-               secret = request->proxysecret;
-               original = request->proxy;
-       } else {
-               packet = request->packet;
-               secret = request->secret;
-               original = NULL;
-       }
-
-       /*
-        *  Decode the packet, verifying it's signature,
-        *  and parsing the attributes into structures.
-        *
-        *  Note that we do this CPU-intensive work in
-        *  a child thread, not the master.  This helps to
-        *  spread the load a little bit.
-        *
-        *  Internal requests (ones that never go on the
-        *  wire) have ->data==NULL (data is the wire
-        *  format) and don't need to be "decoded"
-        */
-       if (packet->data) {
-               if (rad_verify(packet, original, secret) < 0) {
-                       radlog(L_ERR, "%s Dropping packet without response.", librad_errstr);
-                       /* Since accounting packets get this set in
-                        * request_reject but no response is sent...
-                        */
-                       request->options |= RAD_REQUEST_OPTION_REJECTED;
-                       goto finished_request;
-               }
-
-               if (rad_decode(packet, original, secret) < 0) {
-                       radlog(L_ERR, "%s", librad_errstr);
-                       request_reject(request);
-                       goto finished_request;
-               }
-       }
-
-       /*
-        *  For proxy replies, remove non-allowed
-        *  attributes from the list of VP's.
-        */
-       if (request->proxy) {
-               int rcode;
-               rcode = proxy_receive(request);
-               switch (rcode) {
-                default:  /* Don't Do Anything */
-                       break;
-                case RLM_MODULE_FAIL:
-                       /* on error just continue with next request */
-                       goto next_request;
-                case RLM_MODULE_HANDLED:
-                       /* if this was a replicated request, mark it as
-                        * finished first, because it was postponed
-                        */
-                       goto finished_request;
-               }
-
-       } else {
-               /*
-                *      This is the initial incoming request which
-                *      we're processing.
-                *
-                *      Some requests do NOT get cached, as they
-                *      CANNOT possibly have duplicates.  Set the
-                *      magic option here.
-                *
-                *      Status-Server messages are easy to generate,
-                *      so we toss them as soon as we see a reply.
-                *
-                *      Accounting-Request packets WITHOUT an
-                *      Acct-Delay-Time attribute are NEVER
-                *      duplicated, as RFC 2866 Section 4.1 says that
-                *      the Acct-Delay-Time MUST be updated when the
-                *      packet is re-sent, which means the packet
-                *      changes, so it MUST have a new identifier and
-                *      Request Authenticator.  */
-               if ((request->packet->code == PW_STATUS_SERVER) ||
-                   ((request->packet->code == PW_ACCOUNTING_REQUEST) &&
-                    (pairfind(request->packet->vps, PW_ACCT_DELAY_TIME) == NULL))) {
-                       request->options |= RAD_REQUEST_OPTION_DONT_CACHE;
-               }
-       }
-
- skip_decode:
-       /*
-        *      We should have a User-Name attribute now.
-        */
-       if (request->username == NULL) {
-               request->username = pairfind(request->packet->vps,
-                               PW_USER_NAME);
-       }
-
-       /*
-        *  FIXME:  All this lowercase/nospace junk will be moved
-        *  into a module after module failover is fully in place
-        *
-        *  See if we have to lower user/pass before processing
-        */
-       if(strcmp(mainconfig.do_lower_user, "before") == 0)
-               rad_lowerpair(request, request->username);
-       if(strcmp(mainconfig.do_lower_pass, "before") == 0)
-               rad_lowerpair(request,
-                             pairfind(request->packet->vps, PW_PASSWORD));
-
-       if(strcmp(mainconfig.do_nospace_user, "before") == 0)
-               rad_rmspace_pair(request, request->username);
-       if(strcmp(mainconfig.do_nospace_pass, "before") == 0)
-               rad_rmspace_pair(request,
-                                pairfind(request->packet->vps, PW_PASSWORD));
-
-       (*fun)(request);
-
-       /*
-        *      If the request took too long to process, don't do
-        *      anything else.
-        */
-       if (request->options & RAD_REQUEST_OPTION_REJECTED) {
-               finished = TRUE;
-               goto postpone_request;
-       }
-
-       /*
-        *      Reprocess if we rejected last time
-        */
-       if ((fun == rad_authenticate) &&
-           (request->reply->code == PW_AUTHENTICATION_REJECT)) {
-         /* See if we have to lower user/pass after processing */
-         if (strcmp(mainconfig.do_lower_user, "after") == 0) {
-                 rad_lowerpair(request, request->username);
-                 reprocess = 1;
-         }
-         if (strcmp(mainconfig.do_lower_pass, "after") == 0) {
-               rad_lowerpair(request,
-                             pairfind(request->packet->vps, PW_PASSWORD));
-               reprocess = 1;
-         }
-         if (strcmp(mainconfig.do_nospace_user, "after") == 0) {
-                 rad_rmspace_pair(request, request->username);
-                 reprocess = 1;
-         }
-         if (strcmp(mainconfig.do_nospace_pass, "after") == 0) {
-                 rad_rmspace_pair(request,
-                                  pairfind(request->packet->vps, PW_PASSWORD));
-                 reprocess = 1;
-         }
-
-         /*
-          *    If we're re-processing the request, re-set it.
-          */
-         if (reprocess) {
-                 pairfree(&request->config_items);
-                 pairfree(&request->reply->vps);
-                 request->reply->code = 0;
-                 (*fun)(request);
-         }
-       }
-
-       /*
-        *      Status-Server requests NEVER get proxied.
-        */
-       if (mainconfig.proxy_requests) {
-               if ((request->packet->code != PW_STATUS_SERVER) &&
-                   ((request->options & RAD_REQUEST_OPTION_PROXIED) == 0)) {
-                       int rcode;
-
-                       /*
-                        *      Try to proxy this request.
-                        */
-                       rcode = proxy_send(request);
-
-                       switch (rcode) {
-                       default:
-                               break;
-
-                       /*
-                        *  There was an error trying to proxy the request.
-                        *  Drop it on the floor.
-                        */
-                       case RLM_MODULE_FAIL:
-                               DEBUG2("Error trying to proxy request %d: Rejecting it", request->number);
-                               request_reject(request);
-                               goto finished_request;
-                               break;
-
-                       /*
-                        *  The pre-proxy module has decided to reject
-                        *  the request.  Do so.
-                        */
-                       case RLM_MODULE_REJECT:
-                               DEBUG2("Request %d rejected in proxy_send.", request->number);
-                               request_reject(request);
-                               goto finished_request;
-                               break;
-
-                       /*
-                        *  If the proxy code has handled the request,
-                        *  then postpone more processing, until we get
-                        *  the reply packet from the home server.
-                        */
-                       case RLM_MODULE_HANDLED:
-                               goto postpone_request;
-                               break;
-                       }
-
-                       /*
-                        *  Else rcode==RLM_MODULE_NOOP
-                        *  and the proxy code didn't do anything, so
-                        *  we continue handling the request here.
-                        */
-               }
-       } else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
-                  (request->reply->code == 0)) {
-               /*
-                *  We're not configured to reply to the packet,
-                *  and we're not proxying, so the DEFAULT behaviour
-                *  is to REJECT the user.
-                */
-               DEBUG2("There was no response configured: rejecting request %d", request->number);
-               request_reject(request);
-               goto finished_request;
-       }
-
-       /*
-        *  If we have a reply to send, copy the Proxy-State
-        *  attributes from the request to the tail of the reply,
-        *  and send the packet.
-        */
-       rad_assert(request->magic == REQUEST_MAGIC);
-       if (request->reply->code != 0) {
-               VALUE_PAIR *vp = NULL;
-
-               /*
-                *      Perform RFC limitations on outgoing replies.
-                */
-               rfc_clean(request->reply);
-
-               /*
-                *      Need to copy Proxy-State from request->packet->vps
-                */
-               vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
-               if (vp) pairadd(&(request->reply->vps), vp);
-
-               /*
-                *  If the request isn't an authentication reject, OR
-                *  it's a reject, but the reject_delay is zero, then
-                *  send it immediately.
-                *
-                *  Otherwise, delay the authentication reject to shut
-                *  up DoS attacks.
-                */
-               if ((request->reply->code != PW_AUTHENTICATION_REJECT) ||
-                   (mainconfig.reject_delay == 0)) {
-                       /*
-                        *      Send the response. IF it's a real request.
-                        */
-                       if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) == 0) {
-                               rad_send(request->reply, request->packet,
-                                        request->secret);
-                       }
-                       /*
-                        *      Otherwise, it's a tunneled request.
-                        *      Don't do anything.
-                        */
-               } else {
-                       DEBUG2("Delaying request %d for %d seconds",
-                              request->number, mainconfig.reject_delay);
-                       request->options |= RAD_REQUEST_OPTION_DELAYED_REJECT;
-               }
-       }
-
-       /*
-        *  We're done processing the request, set the
-        *  request to be finished, clean up as necessary,
-        *  and forget about the request.
-        */
-
-finished_request:
-
-       /*
-        *      Don't decode the packet if it's an internal "fake"
-        *      request.  Instead, just skip ahead to processing it.
-        */
-       if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {
-               goto skip_free;
-       }
-
-       /*
-        *  We're done handling the request.  Free up the linked
-        *  lists of value pairs.  This might take a long time,
-        *  so it's more efficient to do it in a child thread,
-        *  instead of in the main handler when it eventually
-        *  gets around to deleting the request.
-        *
-        *  Also, no one should be using these items after the
-        *  request is finished, and the reply is sent.  Cleaning
-        *  them up here ensures that they're not being used again.
-        *
-        *  Hmm... cleaning them up in the child thread also seems
-        *  to make the server run more efficiently!
-        *
-        *  If we've delayed the REJECT, then do NOT clean up the request,
-        *  as we haven't created the REJECT message yet.
-        */
-       if ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) == 0) {
-               if (request->packet) {
-                       pairfree(&request->packet->vps);
-                       request->username = NULL;
-                       request->password = NULL;
-               }
-
-               /*
-                *  If we've sent a reply to the NAS, then this request is
-                *  pretty much finished, and we have no more need for any
-                *  of the value-pair's in it, including the proxy stuff.
-                */
-               if (request->reply->code != 0) {
-                       pairfree(&request->reply->vps);
-               }
-       }
-
-       pairfree(&request->config_items);
-       if (request->proxy) {
-               pairfree(&request->proxy->vps);
-       }
-       if (request->proxy_reply) {
-               pairfree(&request->proxy_reply->vps);
-       }
-
- skip_free:
-       DEBUG2("Finished request %d", request->number);
-       finished = TRUE;
-
-       /*
-        *  Go to the next request, without marking
-        *  the current one as finished.
-        *
-        *  Hmm... this may not be the brightest thing to do.
-        */
-next_request:
-       DEBUG2("Going to the next request");
-
-postpone_request:
-#ifdef HAVE_PTHREAD_H
-       /*
-        *  We are finished with the child thread.  The thread is detached,
-        *  so that when it exits, there's nothing more for the server
-        *  to do.
-        *
-        *  If we're running with thread pools, then this frees up the
-        *  thread in the pool for another request.
-        */
-       request->child_pid = NO_SUCH_CHILD_PID;
-#endif
-       request->finished = finished; /* do as the LAST thing before exiting */
-       return 0;
-}
-
-
-/*
  *  Display the syntax for starting this program.
  */
 static void NEVER_RETURNS usage(int status)
@@ -1922,23 +754,21 @@ static void NEVER_RETURNS usage(int status)
        FILE *output = status?stderr:stdout;
 
        fprintf(output,
-                       "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-p port] [-AcfnsSvXxyz]\n", progname);
+                       "Usage: %s [-a acct_dir] [-d db_dir] [-l log_dir] [-i address] [-AcfnsSvXxyz]\n", progname);
        fprintf(output, "Options:\n\n");
        fprintf(output, "  -a acct_dir     use accounting directory 'acct_dir'.\n");
        fprintf(output, "  -A              Log auth detail.\n");
-       fprintf(output, "  -d db_dir       Use database directory 'db_dir'.\n");
+       fprintf(output, "  -d raddb_dir    Configuration files are in \"raddbdir/*\".\n");
        fprintf(output, "  -f              Run as a foreground process, not a daemon.\n");
        fprintf(output, "  -h              Print this help message.\n");
-       fprintf(output, "  -i address      Listen only in the given IP address.\n");
-       fprintf(output, "  -l log_dir      Log messages to 'log_dir'.  Special values are:\n");
-       fprintf(output, "                  stdout == log all messages to standard output.\n");
-       fprintf(output, "                  syslog == log all messages to the system logger.\n");
-       fprintf(output, "  -p port         Bind to 'port', and not to the radius/udp, or 1646/udp.\n");
+       fprintf(output, "  -i ipaddr       Listen on ipaddr ONLY\n");
+       fprintf(output, "  -l log_dir      Log file is \"log_dir/radius.log\" (not used in debug mode)\n");
+       fprintf(output, "  -p port         Listen on port ONLY\n");
        fprintf(output, "  -s              Do not spawn child processes to handle requests.\n");
        fprintf(output, "  -S              Log stripped names.\n");
        fprintf(output, "  -v              Print server version information.\n");
-       fprintf(output, "  -X              Turn on full debugging. (Means: -sfxxyz -l stdout)\n");
-       fprintf(output, "  -x              Turn on partial debugging. (-xx gives more debugging).\n");
+       fprintf(output, "  -X              Turn on full debugging.\n");
+       fprintf(output, "  -x              Turn on additional debugging. (-xx gives more debugging).\n");
        fprintf(output, "  -y              Log authentication failures, with password.\n");
        fprintf(output, "  -z              Log authentication successes, with password.\n");
        exit(status);
@@ -1951,6 +781,9 @@ static void NEVER_RETURNS usage(int status)
 static void sig_fatal(int sig)
 {
        switch(sig) {
+               case SIGSEGV:
+                       /* We can't really do anything intelligent here so just die */
+                       _exit(1);
                case SIGTERM:
                        do_exit = 1;
                        break;
@@ -1976,6 +809,7 @@ static void sig_fatal(int sig)
 static void sig_hup(int sig)
 {
        sig = sig; /* -Wunused */
+
        reset_signal(SIGHUP, sig_hup);
 
        /*
@@ -1992,31 +826,3 @@ static void sig_hup(int sig)
        }
 #endif
 }
-
-
-/*
- *     Process and reply to a server-status request.
- *     Like rad_authenticate and rad_accounting this should
- *     live in it's own file but it's so small we don't bother.
- */
-static int rad_status_server(REQUEST *request)
-{
-       char            reply_msg[64];
-       time_t          t;
-       VALUE_PAIR      *vp;
-
-       /*
-        *      Reply with an ACK. We might want to add some more
-        *      interesting reply attributes, such as server uptime.
-        */
-       t = request->timestamp - start_time;
-       sprintf(reply_msg, "FreeRADIUS up %d day%s, %02d:%02d",
-               (int)(t / 86400), (t / 86400) == 1 ? "" : "s",
-               (int)((t / 3600) % 24), (int)(t / 60) % 60);
-       request->reply->code = PW_AUTHENTICATION_ACK;
-
-       vp = pairmake("Reply-Message", reply_msg, T_OP_SET);
-       pairadd(&request->reply->vps, vp); /* don't need to check if !vp */
-
-       return 0;
-}
diff --git a/src/main/radrelay.c b/src/main/radrelay.c
deleted file mode 100644 (file)
index 04adece..0000000
+++ /dev/null
@@ -1,1089 +0,0 @@
-/*
- * radrelay.c  This program tails a detail logfile, reads the log
- *             entries, forwards them to a remote radius server,
- *             and moves the processed records to another file.
- *
- *             Used to replicate accounting records to one (central)
- *             server - works even if remote server has extended
- *             downtime, and/or if this program is restarted.
- *
- *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Copyright 2001 Cistron Internet Services B.V.
- * Copyright 2002 Simon Ekstrand <simon@routemeister.net>
- *
- */
-char radrelay_rcsid[] =
-"$Id$";
-
-#include "autoconf.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <time.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-
-#include "radiusd.h"
-#include "conf.h"
-#include "radpaths.h"
-#include "missing.h"
-#include "conffile.h"
-
-const char *progname;
-
-int debug_flag = 0;
-const char *radlog_dir = NULL;
-radlog_dest_t radlog_dest = RADLOG_FILES;
-
-const char *radius_dir = NULL;
-const char *radacct_dir = NULL;
-const char *radlib_dir = NULL;
-uint32_t myip = INADDR_ANY;
-int log_stripped_names;
-struct main_config_t mainconfig;
-
-/*
- *     Possible states for request->state
- */
-#define                STATE_EMPTY     0
-#define                STATE_BUSY1     1
-#define                STATE_BUSY2     2
-#define                STATE_FULL      3
-
-/*
- *     Possible states for the loop() function.
- */
-#define                STATE_RUN       0
-#define                STATE_BACKLOG   1
-#define                STATE_WAIT      2
-#define                STATE_SHUTDOWN  3
-#define                STATE_CLOSE     4
-
-#define                NR_SLOTS                64
-#define                DEFAULT_SLEEP           50
-#define                DEFAULT_SLEEP_EVERY     1
-
-/*
- *     A relay request.
- */
-struct relay_request {
-       int             state;                          /* REQ_* state */
-       time_t          retrans;                        /* when to retrans */
-       unsigned int    retrans_num;                    /* Number of retransmissions */
-       time_t          timestamp;                      /* orig recv time */
-       uint32_t        client_ip;                      /* Client-IP-Addr */
-       RADIUS_PACKET   *req;                           /* Radius request */
-};
-
-struct relay_misc {
-       int             sockfd;                         /* Main socket descriptor */
-       uint32_t        dst_addr;                       /* Destination address */
-       short           dst_port;                       /* Destination port */
-       uint32_t        src_addr;                       /* Source address */
-       char            detail[1024];                   /* Detail file */
-       char            *secret;                        /* Secret */
-       char            f_secret[256];                  /* File secret */
-       int             sleep_time;                     /* Time to sleep between sending packets */
-       int             sleep_every;                    /* Sleep every so many packets */
-       int             records_print;                  /* Print statistics after so many records */
-};
-
-struct relay_stats {
-       time_t          startup;
-       uint32_t        records_read;                   /* Records read */
-       uint32_t        packets_sent;                   /* Packets sent */
-       uint32_t        last_print_records;             /* Records on last statistics printout */
-};
-
-/*
- * Used for reading the client configurations from the config files.
- */
-char *c_secret = NULL;
-char *c_shortname = NULL;
-
-struct relay_request slots[NR_SLOTS];
-char id_map[256];
-int request_head = 0;
-int got_sigterm = 0;
-int debug = 0;
-
-
-int get_radius_id(void);
-void sigterm_handler(int sig);
-void ms_sleep(int msec);
-int isdateline(char *d);
-int read_one(FILE *fp, struct relay_request *req);
-int do_recv(struct relay_misc *r_args);
-int do_send(struct relay_request *r, char *secret);
-int detail_move(char *from, char *to);
-void loop(struct relay_misc *r_args);
-int find_shortname(char *shortname, char **host, char **secret);
-void usage(void);
-
-
-/*
- * Get a radius id which is not
- * currently being used (outstanding request)
- * Since NR_SLOTS < 256 we can't
- * have more outstanding requests than radius ids
- */
-int get_radius_id()
-{
-       unsigned int id = 0;
-
-       for(id = 0; id < 256; id++){
-               if (id_map[id] == 0)
-                       break;
-       }
-       if (id == 256 || id_map[id] != 0){
-               fprintf(stdout, "get_radius_id(): No IDs available. Something is very wrong\n");
-               return -1;
-       }
-       id_map[id] = 1;
-       fprintf(stdout, "get_radius_id(): Assign RADIUS ID = %d\n",id);
-
-       return id;
-}
-
-void sigterm_handler(int sig)
-{
-       signal(sig, sigterm_handler);
-       got_sigterm = 1;
-}
-
-
-/*
- *     Sleep a number of milli seconds
- */
-inline void ms_sleep(int msec)
-{
-       struct timeval tv;
-
-       tv.tv_sec  = (msec / 1000);
-       tv.tv_usec = (msec % 1000) * 1000;
-       select(0, NULL, NULL, NULL, &tv);
-}
-
-/*
- *     Does this (remotely) look like "Tue Jan 23 06:55:48 2001" ?
- */
-inline int isdateline(char *d)
-{
-       int y;
-
-       return sscanf(d, "%*s %*s %*d %*d:%*d:%*d %d", &y);
-}
-
-
-/*
- *     Read one request from the detail file.
- *     Note that the file is locked during the read, and that
- *     we return *with the file locked* if we reach end-of-file.
- *
- *     STATE_EMPTY:    Slot is empty.
- *     STATE_BUSY1:    Looking for start of a detail record (timestamp)
- *     STATE_BUSY2:    Reading the A/V pairs of a detail record.
- *     STATE_FULL:     Read the complete record.
- *
- */
-int read_one(FILE *fp, struct relay_request *r_req)
-{
-       VALUE_PAIR *vp;
-       char *s;
-       char buf[2048];
-       char key[32], val[32];
-       int skip;
-       long fpos;
-       int x;
-       unsigned int i = 0;
-
-       /* Never happens */
-       if (r_req->state == STATE_FULL)
-               return 0;
-
-       if (r_req->state == STATE_EMPTY) {
-               r_req->state = STATE_BUSY1;
-       }
-
-       /*
-        * Try to lock the detail-file.
-        * If lockf is used we want to lock the _whole_ file, hence the
-        * fseek to the start of the file.
-        */
-       fpos = ftell(fp);
-       fseek(fp, 0L, SEEK_SET);
-       do {
-               x = rad_lockfd_nonblock(fileno(fp), 0);
-               if (x == -1)
-                       ms_sleep(100);
-       } while (x == -1 && i++ < 20);
-
-       if (x == -1)
-               return 0;
-
-redo:
-       s = NULL;
-       fseek(fp, fpos, SEEK_SET);
-       fpos = ftell(fp);
-       while ((s = fgets(buf, sizeof(buf), fp)) != NULL) {
-               /*
-                * Eek! We've just read a broken attribute.
-                * This does seem to happen every once in a long while
-                * due to some quirk involving threading, multiple processes
-                * going for the detail file lock at once and writes not
-                * being flushed properly. Things should be ok next time
-                * around.
-                */
-               if (!strlen(buf)) {
-                       fprintf(stdout, "read_one: ZERO BYTE\n");
-                       fseek(fp, fpos + 1, SEEK_SET);
-                       break;
-               } else if (buf[strlen(buf) - 1] != '\n') {
-                       fprintf(stdout, "read_one: BROKEN ATTRIBUTE\n");
-                       fseek(fp, fpos + strlen(buf), SEEK_SET);
-                       break;
-               }
-               if (r_req->state == STATE_BUSY1) {
-                       if (isdateline(buf)) {
-                               r_req->state = STATE_BUSY2;
-                       }
-               } else if (r_req->state == STATE_BUSY2) {
-                       if (buf[0] != ' ' && buf[0] != '\t') {
-                               r_req->state = STATE_FULL;
-                               break;
-                       }
-                       /*
-                        *      Found A/V pair, but we skip non-protocol
-                        *      values.
-                        */
-                       skip = 0;
-                       if (sscanf(buf, "%31s = %31s", key, val) == 2) {
-                               if (!strcasecmp(key, "Timestamp")) {
-                                       r_req->timestamp = atoi(val);
-                                       skip++;
-                               } else
-                               if (!strcasecmp(key, "Client-IP-Address")) {
-                                       r_req->client_ip = ip_getaddr(val);
-                                       skip++;
-                               } else
-                               if (!strcasecmp(key, "Request-Authenticator"))
-                                       skip++;
-                       }
-                       if (!skip) {
-                               vp = NULL;
-                               if (userparse(buf, &vp) > 0 &&
-                                   (vp != NULL) &&
-                                   (vp->attribute < 256 ||
-                                    vp->attribute > 65535) &&
-                                   vp->attribute != PW_VENDOR_SPECIFIC) {
-                                       pairadd(&(r_req->req->vps), vp);
-                               } else {
-                                 pairfree(&vp);
-                               }
-                       }
-               }
-               fpos = ftell(fp);
-       }
-       clearerr(fp);
-
-       if (r_req->state == STATE_FULL) {
-               /*
-                *      w00 - we just completed reading a record in full.
-                */
-
-               /*
-                * Check that we have an Acct-Status-Type attribute. If not
-                * reject the record
-                */
-               if (pairfind(r_req->req->vps, PW_ACCT_STATUS_TYPE) == NULL){
-                       fprintf(stdout, "read_one: No Acct-Status-Type attribute present. Rejecting record.\n");
-                       r_req->state = STATE_BUSY1;
-                       if (r_req->req->vps != NULL) {
-                               pairfree(&r_req->req->vps);
-                               r_req->req->vps = NULL;
-                       }
-                       if (r_req->req->data != NULL) {
-                               free (r_req->req->data);
-                               r_req->req->data = NULL;
-                       }
-                       r_req->retrans = 0;
-                       r_req->retrans_num = 0;
-                       r_req->timestamp = 0;
-                       r_req->client_ip = 0;
-                       goto redo;
-               }
-               if (r_req->timestamp == 0)
-                       r_req->timestamp = time(NULL);
-               if ((vp = pairfind(r_req->req->vps, PW_ACCT_DELAY_TIME)) != NULL) {
-                       r_req->timestamp -= vp->lvalue;
-                       vp->lvalue = 0;
-               }
-               r_req->req->id = get_radius_id();
-       }
-
-       if (s == NULL) {
-               /*
-                *      Apparently we reached end of file. If we didn't
-                *      partially read a record, we let the caller know
-                *      we're at end of file.
-                */
-               if (r_req->state == STATE_BUSY1) {
-                       r_req->state = STATE_EMPTY;
-               }
-               if (r_req->state == STATE_EMPTY || r_req->state == STATE_FULL)
-                       return EOF;
-       }
-
-       fpos = ftell(fp);
-       fseek(fp, 0L, SEEK_SET);
-       rad_unlockfd(fileno(fp), 0);
-       fseek(fp, fpos, SEEK_SET);
-
-       return 0;
-}
-
-/*
- *     Receive answers from the remote server.
- */
-int do_recv(struct relay_misc *r_args)
-{
-       RADIUS_PACKET *rep;
-       struct relay_request *r;
-       int i;
-
-       /*
-        *      Receive packet and validate it's length.
-        */
-       rep = rad_recv(r_args->sockfd);
-       if (rep == NULL) {
-               librad_perror("radrelay:");
-               return -1;
-       }
-
-       /*
-        *      Must be an accounting response.
-        *      FIXME: check if this is the right server!
-        */
-       if (rep->code != PW_ACCOUNTING_RESPONSE) {
-               rad_free(&rep);
-               return -1;
-       }
-
-       /*
-        *      Decode packet into radius attributes.
-        */
-
-       /*
-        *      Now find it in the outstanding requests.
-        */
-       for (i = 0; i < NR_SLOTS; i++) {
-               r = slots + i;
-               if (r->state == STATE_FULL && r->req->id == rep->id) {
-                       if (rad_verify(rep, r->req, r_args->secret) != 0) {
-                               librad_perror("rad_verify");
-                               rad_free(&rep);
-                               return -1;
-                       }
-                       if (rad_decode(rep, r->req, r_args->secret) != 0) {
-                               librad_perror("rad_decode");
-                               rad_free(&rep);
-                               return -1;
-                       }
-                       /*
-                        *      Got it. Clear slot.
-                        *      FIXME: check reponse digest ?
-                        */
-                       id_map[r->req->id] = 0;
-                       fprintf(stdout, "do_recv: Free RADIUS ID = %d\n",r->req->id);
-                       if (r->req->vps != NULL) {
-                               pairfree(&r->req->vps);
-                               r->req->vps = NULL;
-                       }
-                       if (r->req->data != NULL) {
-                               free (r->req->data);
-                               r->req->data = NULL;
-                       }
-                       r->state = STATE_EMPTY;
-                       r->retrans = 0;
-                       r->retrans_num = 0;
-                       r->timestamp = 0;
-                       r->client_ip = 0;
-                       break;
-               }
-       }
-
-       rad_free(&rep);
-
-       return 0;
-}
-
-/*
- *     Send accounting packet to remote server.
- */
-int do_send(struct relay_request *r, char *secret)
-{
-       VALUE_PAIR *vp;
-       time_t now;
-
-       /*
-        *      Prevent loops.
-        */
-       if (r->client_ip == r->req->dst_ipaddr) {
-               fprintf(stdout, "do_send: Client-IP == Dest-IP. Droping packet.\n");
-               fprintf(stdout, "do_send: Free RADIUS ID = %d\n",r->req->id);
-               id_map[r->req->id] = 0;
-               if (r->req->vps != NULL) {
-                       pairfree(&r->req->vps);
-                       r->req->vps = NULL;
-               }
-               if (r->req->data != NULL) {
-                       free (r->req->data);
-                       r->req->data = NULL;
-               }
-               r->state = STATE_EMPTY;
-               r->retrans = 0;
-               r->retrans_num = 0;
-               r->timestamp = 0;
-               r->client_ip = 0;
-               return 0;
-       }
-
-       /*
-        *      Has the time come for this packet ?
-        */
-       now = time(NULL);
-       if (r->retrans > now)
-               return 0;
-       /*
-        * If we are resending a packet we *need* to
-        * change the radius packet id since the request
-        * authenticator is different (due to different
-        * Acct-Delay-Time value).
-        * Otherwise the radius server may consider the
-        * packet a duplicate and we 'll get caught in a
-        * loop.
-        */
-       if (r->retrans > 0){
-               id_map[r->req->id] = 0;
-               r->req->id = get_radius_id();
-               if (r->req->data != NULL){
-                       free(r->req->data);
-                       r->req->data = NULL;
-               }
-               r->retrans_num++;
-       }
-       if (r->retrans_num > 20)
-               r->retrans = now + 70;
-       else
-               r->retrans = now + 3 + (3 * r->retrans_num);
-
-       /*
-        *      Find the Acct-Delay-Time attribute. If it's
-        *      not there, add one.
-        */
-       if ((vp = pairfind(r->req->vps, PW_ACCT_DELAY_TIME)) == NULL) {
-               vp = paircreate(PW_ACCT_DELAY_TIME, PW_TYPE_INTEGER);
-               pairadd(&(r->req->vps), vp);
-       }
-       vp->lvalue = (now - r->timestamp);
-
-       /*
-        *      Rebuild the entire packet every time from
-        *      scratch - the signature changed because
-        *      Acct-Delay-Time changed.
-        */
-       rad_send(r->req, NULL, secret);
-
-       return 1;
-}
-
-/*
- *     Rename a file, then recreate the old file with the
- *     same permissions and zero size.
- */
-int detail_move(char *from, char *to)
-{
-       struct stat st;
-       int n;
-       int oldmask;
-
-       if (stat(from, &st) < 0)
-               return -1;
-       if (rename(from, to) < 0)
-               return -1;
-
-       oldmask = umask(0);
-       if ((n = open(from, O_CREAT|O_RDWR, st.st_mode)) >= 0)
-               close(n);
-       umask(oldmask);
-
-       return 0;
-}
-
-
-/*
- *     Open detail file, collect records, send them to the
- *     remote accounting server, yadda yadda yadda.
- *
- *     STATE_RUN:      Reading from detail file, sending to server.
- *     STATE_BACKLOG:  Reading from the detail.work file, for example
- *                     after a crash or restart. Sending to server.
- *     STATE_WAIT:     Waiting for all outstanding requests to be handled.
- *     STATE_CLOSE:    Reached end of detail.work file, waiting for
- *                     outstanding requests, and removing the file.
- *     STATE_SHUTDOWN: Got SIG_TERM, waiting for outstanding requests
- *                     and exiting program.
- */
-void loop(struct relay_misc *r_args)
-{
-       FILE *fp = NULL;
-       struct relay_request *r;
-       struct timeval tv;
-       struct relay_stats stats;
-       fd_set readfds;
-       char work[1030];
-       time_t now, uptime, last_rename = 0;
-       int i, n;
-       int state = STATE_RUN;
-       int id;
-       long fpos;
-
-       strNcpy(work, r_args->detail, sizeof(work) - 6);
-       strcat(work, ".work");
-
-       id = ((int)getpid() & 0xff);
-
-       memset(&stats,0,sizeof(struct relay_stats));
-       stats.startup = time(NULL);
-
-       /*
-        * Initialize all our slots, might as well do this right away.
-        */
-       for (i = 0; i < NR_SLOTS; i++) {
-               if ((slots[i].req = rad_alloc(1)) == NULL) {
-                       librad_perror("radrelay");
-                       exit(1);
-               }
-               slots[i].state = STATE_EMPTY;
-               slots[i].retrans = 0;
-               slots[i].retrans_num = 0;
-               slots[i].timestamp = 0;
-               slots[i].client_ip = 0;
-               slots[i].req->sockfd = r_args->sockfd;
-               slots[i].req->dst_ipaddr = r_args->dst_addr;
-               slots[i].req->dst_port = r_args->dst_port;
-               slots[i].req->src_ipaddr = r_args->src_addr;
-               slots[i].req->code = PW_ACCOUNTING_REQUEST;
-               slots[i].req->vps = NULL;
-               slots[i].req->data = NULL;
-       }
-
-       while(1) {
-               if (got_sigterm) state = STATE_SHUTDOWN;
-
-               /*
-                *      Open detail file - if needed, and if we can.
-                */
-               if (state == STATE_RUN && fp == NULL) {
-                       if ((fp = fopen(work, "r+")) != NULL)
-                               state = STATE_BACKLOG;
-                       else
-                               fp = fopen(r_args->detail, "r+");
-                       if (fp == NULL) {
-                               fprintf(stderr, "%s: Unable to open detail file - %s\n", progname, r_args->detail);
-                               perror("fopen");
-                               return;
-                       }
-
-               }
-
-               /*
-                *      If "request_head" points to a free or not-completely-
-                *      filled slot, we can read from the detail file.
-                */
-               r = &slots[request_head];
-               if (fp && (state == STATE_RUN || state == STATE_BACKLOG) &&
-                   r->state != STATE_FULL) {
-                       if (read_one(fp, r) == EOF) do {
-
-                               /*
-                                *      We've reached end of the <detail>.work
-                                *      It's going to be closed as soon as all
-                                *      outstanting requests are handled
-                                */
-                               if (state == STATE_BACKLOG) {
-                                       state = STATE_CLOSE;
-                                       break;
-                               }
-
-                               /*
-                                *      End of file. See if the file has
-                                *      any size, and if we renamed less
-                                *      than 10 seconds ago or not.
-                                */
-                               now = time(NULL);
-                               if (ftell(fp) == 0 || now < last_rename + 10) {
-                                       fpos = ftell(fp);
-                                       fseek(fp, 0L, SEEK_SET);
-                                       rad_unlockfd(fileno(fp), 0);
-                                       fseek(fp, fpos, SEEK_SET);
-                                       break;
-                               }
-                               last_rename = now;
-
-                               /*
-                                *      We rename the file to <file>.work
-                                *      and create an empty new file.
-                                */
-                               if (detail_move(r_args->detail, work) == 0) {
-                                       if (debug_flag > 0)
-                                               fprintf(stderr, "Moving %s to %s\n",
-                                                       r_args->detail, work);
-                                       /*
-                                        *      rlm_detail might still write
-                                        *      something to <detail>.work if
-                                        *      it opens <detail> before it is
-                                        *      renamed (race condition)
-                                        */
-                                       ms_sleep(1000);
-                                       state = STATE_BACKLOG;
-                               }
-                               fpos = ftell(fp);
-                               fseek(fp, 0L, SEEK_SET);
-                               rad_unlockfd(fileno(fp), 0);
-                               fseek(fp, fpos, SEEK_SET);
-                       } while(0);
-                       if (r_args->records_print && state == STATE_RUN){
-                               stats.records_read++;
-                               if (stats.last_print_records - stats.records_read >= r_args->records_print){
-                                       now = time(NULL);
-                                       uptime = (stats.startup == now) ? 1 : now - stats.startup;
-                                       fprintf(stderr, "%s: Running and Processing Records.\n",progname);
-                                       fprintf(stderr, "Seconds since startup: %ld\n",uptime);
-                                       fprintf(stderr, "Records Read: %d\n",stats.records_read);
-                                       fprintf(stderr, "Packets Sent: %d\n",stats.packets_sent);
-                                       fprintf(stderr, "Record Rate since startup: %.2f\n",
-                                               (double)stats.records_read / uptime);
-                                       fprintf(stderr, "Packet Rate since startup: %.2f\n",
-                                               (double)stats.packets_sent / uptime);
-                                       stats.last_print_records = stats.records_read;
-                               }
-                       }
-                       if (r->state == STATE_FULL)
-                               request_head = (request_head + 1) % NR_SLOTS;
-               }
-
-               /*
-                *      Perhaps we can receive something.
-                */
-               tv.tv_sec = 0;
-               tv.tv_usec = 25000;
-               FD_ZERO(&readfds);
-               FD_SET(r_args->sockfd, &readfds);
-               n = 0;
-               while (select(r_args->sockfd + 1, &readfds, NULL, NULL, &tv) > 0) {
-                       do_recv(r_args);
-                       if (n++ >= NR_SLOTS) break;
-               }
-
-               /*
-                *      If we're in STATE_WAIT and all slots are
-                *      finally empty, we can remove the <detail>.work
-                */
-               if (state == STATE_WAIT || state == STATE_CLOSE || state == STATE_SHUTDOWN) {
-                       for (i = 0; i < NR_SLOTS; i++)
-                               if (slots[i].state != STATE_EMPTY)
-                                       break;
-                       if (i == NR_SLOTS) {
-                               if (state == STATE_CLOSE) {
-                                       if (fp) fclose(fp);
-                                       fp = NULL;
-                                       if (debug_flag > 0)
-                                               fprintf(stderr, "Unlink file %s\n", work);
-                                       unlink(work);
-                               }
-                               else if (state == STATE_SHUTDOWN) {
-                                       for (i = 0; i < NR_SLOTS; i++) {
-                                               rad_free(&slots[i].req);
-                                       }
-                                       exit(0);
-                               }
-                               state = STATE_RUN;
-                       }
-               }
-
-               /*
-                *      See if there's anything to send.
-                */
-               n=0;
-               for (i = 0; i < NR_SLOTS; i++) {
-                       if (slots[i].state == STATE_FULL) {
-                               n += do_send(&slots[i], r_args->secret);
-                               if ((n % r_args->sleep_every) == 0)
-                                       ms_sleep(r_args->sleep_time);
-                               if (n > NR_SLOTS / 2)
-                                       break;
-                       }
-               }
-               if (r_args->records_print)
-                       stats.packets_sent += n;
-       }
-}
-
-/*
- * Search through the "client" config sections (usually in clients.conf).
- * This is an easy way to find a secret and an host.
- */
-int find_shortname(char *shortname, char **host, char **secret)
-{
-       CONF_SECTION *maincs, *cs;
-       char buffer[256];
-
-       /* Lets go look for the new configuration files */
-       memset(&mainconfig, 0, sizeof(mainconfig)); /* for radlog() */
-       snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", radius_dir);
-       if ((maincs = conf_read(NULL, 0, buffer, NULL)) == NULL) {
-               return -1;
-       }
-
-       /*
-        * Find the first 'client' section.
-        */
-       cs = cf_section_sub_find(maincs, "client");
-       if (cs) {
-               c_shortname = cf_section_value_find(cs, "shortname");
-               c_secret = cf_section_value_find(cs, "secret");
-               /*
-                * Keep searching for 'client' sections until they run out
-                * or we find one that matches.
-                */
-               while (cs && strcmp(shortname, c_shortname)) {
-                       cs = cf_subsection_find_next(cs, cs, "client");
-                       if (cs) {
-                               c_shortname = cf_section_value_find(cs, "shortname");
-                               c_secret = cf_section_value_find(cs, "secret");
-                       }
-               };
-       };
-
-       if (cs) {
-               *host = cf_section_name2(cs);
-               *secret = c_secret;
-               if (host && secret)
-                       return 0;
-       }
-
-       return -1;
-}
-
-void usage(void)
-{
-       fprintf(stderr, "Usage: radrelay [-a accounting_dir] [-d radius_dir] [-i local_ip] [-s secret]\n");
-       fprintf(stderr, "[-e sleep_every packets] [-t sleep_time (ms)] [-S secret_file] [-fx]\n");
-       fprintf(stderr, "[-R records_print] <[-n shortname] [-r remote-server[:port]]> detailfile\n");
-       fprintf(stderr, " -a accounting_dir     Base accounting directory.\n");
-       fprintf(stderr, " -d radius_dir         Base radius (raddb) directory.\n");
-       fprintf(stderr, " -f                    Stay in the foreground (don't fork).\n");
-       fprintf(stderr, " -h                    This help.\n");
-       fprintf(stderr, " -i local_ip           Use local_ip as source address.\n");
-       fprintf(stderr, " -n shortname          Use the [shortname] entry from clients.conf for\n");
-       fprintf(stderr, "                       ip-adress and secret.\n");
-       fprintf(stderr, " -t sleep_time         Sleep so much time (in ms) between sending packets. Default: %dms.\n",
-                                               DEFAULT_SLEEP);
-       fprintf(stderr, " -e sleep_every        Sleep after sending so many packets. Default: %d\n",
-                                               DEFAULT_SLEEP_EVERY);
-       fprintf(stderr, " -R records_print      If in foreground mode, print statistics after so many records read.\n");
-       fprintf(stderr, " -r remote-server      The destination address/hostname.\n");
-       fprintf(stderr, " -s secret             Server secret.\n");
-       fprintf(stderr, " -S secret_file        Read server secret from file.\n");
-       fprintf(stderr, " -x                    Debug mode (-xx gives more debugging).\n");
-
-       exit(1);
-}
-
-int main(int argc, char **argv)
-{
-       struct servent *svp;
-       char *server_name;
-       char *shortname;
-       char *p;
-       int c;
-       int i;
-       int dontfork = 0;
-       struct relay_misc r_args;
-       FILE *sfile_fp;
-
-       progname = argv[0];
-
-       r_args.sockfd = -1;
-       r_args.dst_addr = 0;
-       r_args.dst_port = 0;
-       r_args.src_addr = 0;
-       memset((char *) r_args.detail, 0, 1024);
-       memset((char *) r_args.f_secret, 0, 256);
-       r_args.secret = NULL;
-       r_args.sleep_time = DEFAULT_SLEEP;
-       r_args.sleep_every = DEFAULT_SLEEP_EVERY;
-
-       shortname = NULL;
-       server_name = NULL;
-
-       radius_dir = strdup(RADIUS_DIR);
-
-       librad_debug = 0;
-
-       /*
-        *      Make sure there are stdin/stdout/stderr fds.
-        */
-       while ((c = open("/dev/null", O_RDWR)) < 3 && c >= 0);
-       if (c >= 3) close(c);
-
-       /*
-        *      Process the options.
-        */
-       while ((c = getopt(argc, argv, "a:d:fhi:t:e:n:r:R:s:S:x")) != EOF) switch(c) {
-               case 'a':
-                       if (strlen(optarg) > 1021) {
-                               fprintf(stderr, "%s: acct_dir to long\n", progname);
-                               exit(1);
-                       }
-                       strncpy(r_args.detail, optarg, 1021);
-                       break;
-               case 'd':
-                       if (radius_dir)
-                               free(radius_dir);
-                       radius_dir = strdup(optarg);
-                       break;
-               case 'f':
-                       dontfork = 1;
-                       break;
-               case 'n':
-                       shortname = optarg;
-                       break;
-               case 't':
-                       r_args.sleep_time = atoi(optarg);
-                       break;
-               case 'e':
-                       r_args.sleep_every = atoi(optarg);
-                       break;
-               case 'R':
-                       if (!dontfork){
-                               fprintf(stderr, "%s: Not in foreground mode. Can't print statistics.\n",progname);
-                               usage();
-                       }
-                       r_args.records_print = atoi(optarg);
-                       break;
-               case 'r':
-                       server_name = optarg;
-                       break;
-               case 's':
-                       r_args.secret = optarg;
-                       break;
-               case 'x':
-                       /*
-                        * If -x is called once we enable internal radrelay
-                        * debugging, if it's called twice we also active
-                        * lib_rad debugging (fairly verbose).
-                        */
-                       if (debug == 1)
-                               librad_debug = 1;
-                       debug = 1;
-                       dontfork = 1;
-                       break;
-               case 'S':
-                       sfile_fp = fopen(optarg, "r");
-                       if (sfile_fp == NULL) {
-                               fprintf(stderr, "Error opening %s: %s\n",
-                                       optarg, strerror(errno));
-                               exit(1);
-                       }
-
-                       if (fgets(r_args.f_secret, 256, sfile_fp) == NULL) {
-                               fprintf(stderr, "Error reading from %s: %s\n",
-                                       optarg, strerror(errno));
-                               fclose(sfile_fp);
-                               exit(1);
-                       }
-                       fclose(sfile_fp);
-
-                       for (c = 0; c < strlen(r_args.f_secret); c++)
-                               if (r_args.f_secret[c] == ' ' ||
-                                   r_args.f_secret[c] == '\n')
-                                       r_args.f_secret[c] = '\0';
-
-                       if (strlen(r_args.f_secret) < 2) {
-                               fprintf(stderr, "Secret in %s is to short\n",
-                                       optarg);
-                               exit(1);
-                       }
-
-                       r_args.secret = r_args.f_secret;
-                       break;
-               case 'i':
-                       if ((r_args.src_addr = ip_getaddr(optarg)) == 0) {
-                               fprintf(stderr, "%s: unknown host %s\n",
-                                       progname, optarg);
-                               exit(1);
-                       }
-                       break;
-               case 'h':
-               default:
-                       usage();
-                       break;
-       }
-
-       /*
-        *      No detail file: die.
-        */
-       if (argc == optind) {
-               usage();
-       }
-
-       argc -= (optind - 1);
-       argv += (optind - 1);
-       if (shortname && server_name)
-               usage();
-       if (!shortname && !server_name)
-               usage();
-       if (r_args.secret != NULL && shortname != NULL)
-               usage();
-
-       /*
-        * If we've been given a shortname, try to fetch the secret and
-        * adress from the config files.
-        */
-       if (shortname != NULL) {
-               if (find_shortname(shortname, &server_name, &r_args.secret) == -1) {
-                       fprintf(stderr, "Couldn't find %s in configuration files.\n", shortname);
-                       exit(1);
-               }
-       }
-
-       /*
-        * server_name should already be set either by the -r or the -s
-        * commandline argument.
-        */
-       if ((p = strrchr(server_name, ':')) != NULL) {
-               *p = 0;
-               p++;
-               r_args.dst_port = ntohs(atoi(p));
-       }
-       if (r_args.dst_port == 0) {
-               svp = getservbyname ("radacct", "udp");
-               r_args.dst_port = svp ? ntohs(svp->s_port) : PW_ACCT_UDP_PORT;
-       } else {
-               r_args.dst_port = ntohs(r_args.dst_port);
-       }
-       r_args.dst_addr = ip_getaddr(server_name);
-       if (r_args.dst_addr == 0) {
-               fprintf(stderr, "%s: unknown host\n",
-                       server_name);
-               exit(1);
-       }
-
-       if (r_args.secret == NULL || r_args.secret[0] == 0) {
-               fprintf(stderr, "No secret available for server %s\n",
-                       server_name);
-               exit(1);
-       }
-
-       /*
-        * Find what detail file to read from.
-        *
-        * FIXME: We should be able to expand dates etc. based on the pathname,
-        * just like the detail module does.
-        */
-       if (r_args.detail[0] == '\0') {
-               if (strlen(RADIR) > 1021) {
-                       fprintf(stderr, "acct_dir to long\n");
-                       exit(1);
-               }
-               strncpy(r_args.detail, RADIR, 1021);
-       }
-       if (chdir(r_args.detail) == -1) {
-               perror("chdir");
-               exit(1);
-       }
-
-       if (strlen(argv[1]) + strlen(r_args.detail) > 1023) {
-               fprintf(stderr, "Detail file path to long");
-               exit(1);
-       } else {
-               if (r_args.detail[strlen(r_args.detail) - 1] != '/')
-                       r_args.detail[strlen(r_args.detail)] = '/';
-               strncat (r_args.detail, argv[1], 1023 - strlen(r_args.detail));
-       }
-
-       /*
-        *      Initialize dictionary.
-        */
-       if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) {
-               librad_perror("radrelay");
-               exit(1);
-       }
-
-       /*
-        *      Open a socket to the remote server.
-        */
-       if ((r_args.sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-               fprintf(stderr, "Error opening socket: %s", strerror(errno));
-               exit(1);
-       }
-
-       signal(SIGTERM, sigterm_handler);
-
-       if (!dontfork) {
-               if (fork() != 0)
-                       exit(0);
-               close(0);
-               close(1);
-               close(2);
-               (void)open("/dev/null", O_RDWR);
-               dup(0);
-               dup(0);
-               signal(SIGHUP,  SIG_IGN);
-               signal(SIGINT,  SIG_IGN);
-               signal(SIGQUIT, SIG_IGN);
-#ifdef HAVE_SETSID
-               setsid();
-#endif
-       }
-
-       /*
-        * Initialize the radius id map
-        */
-       for(i=0;i<256;i++)
-               id_map[i] = 0;
-
-       /*
-        *      Call main processing loop.
-        */
-       loop(&r_args);
-
-       return 0;
-}
diff --git a/src/main/radsniff.c b/src/main/radsniff.c
new file mode 100644 (file)
index 0000000..fe8c1c5
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ *  radsniff.c Display the RADIUS traffic on the network.
+ *
+ *  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 2006  The FreeRADIUS server project
+ *  Copyright 2006  Nicolas Baradakis <nicolas.baradakis@cegetel.net>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#include <pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#define _LIBRADIUS 1
+#include <freeradius-devel/radpaths.h>
+#include <freeradius-devel/conf.h>
+#include <freeradius-devel/libradius.h>
+#include <freeradius-devel/radsniff.h>
+
+static const char *radius_secret = "testing123";
+static VALUE_PAIR *filter_vps = NULL;
+
+static const char *packet_codes[] = {
+  "",
+  "Access-Request",
+  "Access-Accept",
+  "Access-Reject",
+  "Accounting-Request",
+  "Accounting-Response",
+  "Accounting-Status",
+  "Password-Request",
+  "Password-Accept",
+  "Password-Reject",
+  "Accounting-Message",
+  "Access-Challenge",
+  "Status-Server",
+  "Status-Client",
+  "14",
+  "15",
+  "16",
+  "17",
+  "18",
+  "19",
+  "20",
+  "Resource-Free-Request",
+  "Resource-Free-Response",
+  "Resource-Query-Request",
+  "Resource-Query-Response",
+  "Alternate-Resource-Reclaim-Request",
+  "NAS-Reboot-Request",
+  "NAS-Reboot-Response",
+  "28",
+  "Next-Passcode",
+  "New-Pin",
+  "Terminate-Session",
+  "Password-Expired",
+  "Event-Request",
+  "Event-Response",
+  "35",
+  "36",
+  "37",
+  "38",
+  "39",
+  "Disconnect-Request",
+  "Disconnect-ACK",
+  "Disconnect-NAK",
+  "CoF-Request",
+  "CoF-ACK",
+  "CoF-NAK",
+  "46",
+  "47",
+  "48",
+  "49",
+  "IP-Address-Allocate",
+  "IP-Address-Release"
+};
+
+/*
+ *     Stolen from rad_recv() in ../lib/radius.c
+ */
+static RADIUS_PACKET *init_packet(const uint8_t *data, size_t data_len)
+{
+       RADIUS_PACKET           *packet;
+
+       /*
+        *      Allocate the new request data structure
+        */
+       if ((packet = malloc(sizeof(*packet))) == NULL) {
+               librad_log("out of memory");
+               return NULL;
+       }
+       memset(packet, 0, sizeof(*packet));
+
+       packet->data = data;
+       packet->data_len = data_len;
+
+       if (!rad_packet_ok(packet)) {
+               rad_free(&packet);
+               return NULL;
+       }
+
+       /*
+        *      Explicitely set the VP list to empty.
+        */
+       packet->vps = NULL;
+
+       return packet;
+}
+
+static int filter_packet(RADIUS_PACKET *packet)
+{
+       VALUE_PAIR *check_item;
+       VALUE_PAIR *vp;
+       unsigned int pass, fail;
+       int compare;
+
+       pass = fail = 0;
+       for (vp = packet->vps; vp != NULL; vp = vp->next) {
+               for (check_item = filter_vps;
+                    check_item != NULL;
+                    check_item = check_item->next)
+                       if ((check_item->attribute == vp->attribute)
+                        && (check_item->operator != T_OP_SET)) {
+                               compare = paircmp(check_item, vp);
+                               if (compare == 1)
+                                       pass++;
+                               else
+                                       fail++;
+                       }
+       }
+       if (fail == 0 && pass != 0) {
+               return 0;
+       }
+
+       return 1;
+}
+
+static void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const uint8_t *packet)
+{
+       /* Just a counter of how many packets we've had */
+       static int count = 1;
+       /* Define pointers for packet's attributes */
+       const struct ethernet_header *ethernet;  /* The ethernet header */
+       const struct ip_header *ip;              /* The IP header */
+       const struct udp_header *udp;            /* The UDP header */
+       const uint8_t *payload;                     /* Packet payload */
+       /* And define the size of the structures we're using */
+       int size_ethernet = sizeof(struct ethernet_header);
+       int size_ip = sizeof(struct ip_header);
+       int size_udp = sizeof(struct udp_header);
+       /* For FreeRADIUS */
+       RADIUS_PACKET *request;
+
+       args = args;            /* -Wunused */
+
+       /* Define our packet's attributes */
+       ethernet = (const struct ethernet_header*)(packet);
+       ip = (const struct ip_header*)(packet + size_ethernet);
+       udp = (const struct udp_header*)(packet + size_ethernet + size_ip);
+       payload = (const uint8_t *)(packet + size_ethernet + size_ip + size_udp);
+
+       /* Read the RADIUS packet structure */
+       request = init_packet(payload, header->len - size_ethernet - size_ip - size_udp);
+       if (request == NULL) {
+               librad_perror("check");
+               return;
+       }
+       request->src_ipaddr.ipaddr.ip4addr.s_addr = ip->ip_src.s_addr;
+       request->src_port = ntohs(udp->udp_sport);
+       request->dst_ipaddr.ipaddr.ip4addr.s_addr = ip->ip_dst.s_addr;
+       request->dst_port = ntohs(udp->udp_dport);
+
+       /*
+        *      Decode the data without bothering to check the signatures.
+        */
+       if (rad_decode(request, NULL, radius_secret) != 0) {
+               librad_perror("decode");
+               return;
+       }
+       if (filter_vps && filter_packet(request)) {
+               /* printf("Packet number %d doesn't match\n", count++); */
+               return;
+       }
+
+       /* Print the RADIUS packet */
+       printf("Packet number %d has just been sniffed\n", count++);
+       printf("\tFrom:    %s:%d\n", inet_ntoa(ip->ip_src), ntohs(udp->udp_sport));
+       printf("\tTo:      %s:%d\n", inet_ntoa(ip->ip_dst), ntohs(udp->udp_dport));
+       printf("\tType:    %s\n", packet_codes[request->code]);
+       if (request->vps != NULL) {
+               vp_printlist(stdout, request->vps);
+               pairfree(&request->vps);
+       }
+       free(request);
+}
+
+static void NEVER_RETURNS usage(int status)
+{
+       FILE *output = status ? stderr : stdout;
+       fprintf(output, "usage: radsniff [options]\n");
+       fprintf(output, "options:\n");
+       fprintf(output, "\t-c count\tNumber of packets to capture.\n");
+       fprintf(output, "\t-d directory\tDirectory where the dictionaries are found\n");
+       fprintf(output, "\t-f filter\tPCAP filter. (default is udp port 1812 or 1813 or 1814)\n");
+       fprintf(output, "\t-h\t\tPrint this help message.\n");
+       fprintf(output, "\t-i interface\tInterface to capture.\n");
+       fprintf(output, "\t-p port\tList for packets on port.\n");
+       fprintf(output, "\t-r filter\tRADIUS attribute filter.\n");
+       fprintf(output, "\t-s secret\tRADIUS secret.\n");
+       exit(status);
+}
+
+int main(int argc, char *argv[])
+{
+       char *dev;                      /* sniffing device */
+       char errbuf[PCAP_ERRBUF_SIZE];  /* error buffer */
+       pcap_t *descr;                  /* sniff handler */
+       struct bpf_program fp;          /* hold compiled program */
+       bpf_u_int32 maskp;              /* subnet mask */
+       bpf_u_int32 netp;               /* ip */
+       char buffer[1024];
+       char *pcap_filter = NULL;
+       char *radius_filter = NULL;
+       int packet_count = -1;          /* how many packets to sniff */
+       int opt;
+       LRAD_TOKEN parsecode;
+       const char *radius_dir = RADIUS_DIR;
+       int port = 1812;
+
+       /* Default device */
+       dev = pcap_lookupdev(errbuf);
+
+       /* Get options */
+       while ((opt = getopt(argc, argv, "c:d:f:hi:p:r:s:")) != EOF) {
+               switch (opt)
+               {
+               case 'c':
+                       packet_count = atoi(optarg);
+                       if (packet_count <= 0) {
+                               fprintf(stderr, "radsniff: Invalid number of packets \"%s\"\n", optarg);
+                               exit(1);
+                       }
+                       break;
+               case 'd':
+                       radius_dir = optarg;
+                       break;
+               case 'f':
+                       pcap_filter = optarg;
+                       break;
+               case 'h':
+                       usage(0);
+                       break;
+               case 'i':
+                       dev = optarg;
+                       break;
+               case 'p':
+                       port = atoi(optarg);
+                       break;
+               case 'r':
+                       radius_filter = optarg;
+                       parsecode = userparse(radius_filter, &filter_vps);
+                       if (parsecode == T_OP_INVALID || filter_vps == NULL) {
+                               fprintf(stderr, "radsniff: Invalid RADIUS filter \"%s\"\n", optarg);
+                               exit(1);
+                       }
+                       break;
+               case 's':
+                       radius_secret = optarg;
+                       break;
+               default:
+                       usage(1);
+               }
+       }
+
+       if (!pcap_filter) {
+               pcap_filter = buffer;
+               snprintf(buffer, sizeof(buffer), "udp port %d or %d or %d",
+                        port, port + 1, port + 2);
+       }
+
+        if (dict_init(radius_dir, RADIUS_DICTIONARY) < 0) {
+                librad_perror("radsniff");
+                return 1;
+        }
+       /* Set our device */
+       pcap_lookupnet(dev, &netp, &maskp, errbuf);
+
+       /* Print device to the user */
+       printf("Device: [%s]\n", dev);
+       if (packet_count > 0) {
+               printf("Num of packets: [%d]\n", packet_count);
+       }
+       printf("PCAP filter: [%s]\n", pcap_filter);
+       if (filter_vps != NULL) {
+               printf("RADIUS filter:\n");
+               vp_printlist(stdout, filter_vps);
+       }
+       printf("RADIUS secret: [%s]\n", radius_secret);
+
+       /* Open the device so we can spy */
+       descr = pcap_open_live(dev, SNAPLEN, 1, 0, errbuf);
+       if (descr == NULL)
+       {
+               printf("radsniff: pcap_open_live failed (%s)\n", errbuf);
+               exit(1);
+       }
+
+       /* Apply the rules */
+       if( pcap_compile(descr, &fp, pcap_filter, 0, netp) == -1)
+       {
+               printf("radsniff: pcap_compile failed\n");
+               exit(1);
+       }
+       if (pcap_setfilter(descr, &fp) == -1)
+       {
+               printf("radsniff: pcap_setfilter failed\n");
+               exit(1);
+       }
+
+       /* Now we can set our callback function */
+       pcap_loop(descr, packet_count, got_packet, NULL);
+       pcap_close(descr);
+
+       printf("Done sniffing\n");
+       return 0;
+}
index d940698..9a9dce9 100644 (file)
@@ -1,3 +1,4 @@
+/*@-skipposixheaders@*/
 /*
  * radwho.c    Show who is logged in on the terminal servers.
  *             Can also be installed as fingerd on the UNIX
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
 
-static const char rcsid[] =
-"$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdlib.h>
 #include <string.h>
@@ -35,14 +35,10 @@ static const char rcsid[] =
 #include <sys/stat.h>
 #include <sys/utsname.h>
 #include <ctype.h>
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
 
-#include "sysutmp.h"
-#include "radutmp.h"
-#include "radiusd.h"
-#include "conffile.h"
+#include <freeradius-devel/sysutmp.h>
+#include <freeradius-devel/radutmp.h>
+#include <freeradius-devel/radiusd.h>
 
 /*
  *     FIXME: put in header file.
@@ -55,13 +51,13 @@ static const char rcsid[] =
  */
 static const char *hdr1 =
 "Login      Name              What  TTY  When      From      Location";
-static const char *rfmt1 = "%-10.10s %-17.17s %-5.5s %s%-3d %-9.9s %-9.9s %-.19s%s";
+static const char *rfmt1 = "%-10.10s %-17.17s %-5.5s %s%-3u %-9.9s %-9.9s %-.19s%s";
 static const char *rfmt1r = "%s,%s,%s,%s%u,%s,%s,%s%s";
 
 static const char *hdr2 =
 "Login      Port    What      When          From       Location";
-static const char *rfmt2 = "%-10.10s %s%-5d  %-6.6s %-13.13s %-10.10s %-.28s%s";
-static const char *rfmt2r = "%s,%s%d,%s,%s,%s,%s%s";
+static const char *rfmt2 = "%-10.10s %s%-5u  %-6.6s %-13.13s %-10.10s %-.28s%s";
+static const char *rfmt2r = "%s,%s%u,%s,%s,%s,%s%s";
 
 static const char *eol = "\n";
 static int showname = -1;
@@ -78,8 +74,6 @@ const char *radlib_dir = NULL;
 uint32_t myip = INADDR_ANY;
 int log_stripped_names;
 
-radlog_dest_t radlog_dest = RADLOG_STDOUT;
-
 /*
  *     Global, for log.c to use.
  */
@@ -105,7 +99,7 @@ static FILE *safe_popen(const char *cmd, const char *mode)
        /*
         *      Change all suspect characters into a space.
         */
-       strncpy(buf, cmd, sizeof(buf));
+       strlcpy(buf, cmd, sizeof(buf));
        buf[sizeof(buf) - 1] = 0;
        for (p = buf; *p; p++) {
                if (isalnum((int) *p))
@@ -226,10 +220,10 @@ static char *dotime(time_t t)
        char *s = ctime(&t);
 
        if (showname) {
-               strncpy(s + 4, s + 11, 5);
+               strlcpy(s + 4, s + 11, 5);
                s[9] = 0;
        } else {
-               strncpy(s + 4, s + 8, 8);
+               strlcpy(s + 4, s + 8, 8);
                s[12] = 0;
        }
 
@@ -242,9 +236,14 @@ static char *dotime(time_t t)
  */
 static const char *hostname(char *buf, size_t buflen, uint32_t ipaddr)
 {
+       /*
+        *      WTF is this code for?
+        */
        if (ipaddr == 0 || ipaddr == (uint32_t)-1 || ipaddr == (uint32_t)-2)
                return "";
-       return ip_hostname(buf, buflen, ipaddr);
+
+       return inet_ntop(AF_INET, &ipaddr, buf, buflen);
+
 }
 
 
@@ -326,8 +325,7 @@ int main(int argc, char **argv)
                        showname = 0;
                        break;
                case 'N':
-                       nas_ip_address = ip_addr(optarg);
-                       if (nas_ip_address == INADDR_NONE) {
+                       if (inet_pton(AF_INET, optarg, &nas_ip_address) < 0) {
                                usage(1);
                        }
                        break;
@@ -386,7 +384,7 @@ int main(int argc, char **argv)
 
                printf("Acct-Status-Type = Accounting-Off\n");
                printf("NAS-IP-Address = %s\n",
-                      ip_hostname(buffer, sizeof(buffer), nas_ip_address));
+                      hostname(buffer, sizeof(buffer), nas_ip_address));
                printf("Acct-Delay-Time = 0\n");
                exit(0);        /* don't bother printing anything else */
        }
@@ -395,10 +393,11 @@ int main(int argc, char **argv)
         *      Initialize mainconfig
         */
        memset(&mainconfig, 0, sizeof(mainconfig));
+       mainconfig.radlog_dest = RADLOG_STDOUT;
 
         /* Read radiusd.conf */
        snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", radius_dir);
-       maincs = conf_read(NULL, 0, buffer, NULL);
+       maincs = cf_file_read(buffer);
        if (!maincs) {
                fprintf(stderr, "%s: Error reading radiusd.conf.\n", argv[0]);
                exit(1);
@@ -532,8 +531,8 @@ int main(int argc, char **argv)
                        if (zap) printf("Acct-Status-Type = Stop\n");
 
                        printf("NAS-IP-Address = %s\n",
-                              ip_hostname(buffer, sizeof(buffer),
-                                          rt.nas_address));
+                              hostname(buffer, sizeof(buffer),
+                                       rt.nas_address));
                        printf("NAS-Port = %u\n", rt.nas_port);
 
                        switch (rt.proto) {
@@ -551,8 +550,8 @@ int main(int argc, char **argv)
                        }
                        if (rt.framed_address != INADDR_NONE) {
                                printf("Framed-IP-Address = %s\n",
-                                      ip_hostname(buffer, sizeof(buffer),
-                                                  rt.framed_address));
+                                      hostname(buffer, sizeof(buffer),
+                                               rt.framed_address));
                        }
                        
                        /*
@@ -589,7 +588,7 @@ int main(int argc, char **argv)
                               proto(rt.proto, rt.porttype),
                               portind, portno,
                               dotime(rt.time),
-                              ip_hostname(nasname, sizeof(nasname), rt.nas_address),
+                              hostname(nasname, sizeof(nasname), rt.nas_address),
                               hostname(othername, sizeof(othername), rt.framed_address), eol);
                } else {
                        printf((rawoutput == 0? rfmt2: rfmt2r),
@@ -597,7 +596,7 @@ int main(int argc, char **argv)
                               portind, portno,
                               proto(rt.proto, rt.porttype),
                               dotime(rt.time),
-                              ip_hostname(nasname, sizeof(nasname), rt.nas_address),
+                              hostname(nasname, sizeof(nasname), rt.nas_address),
                               hostname(othername, sizeof(othername), rt.framed_address),
                               eol);
                }
diff --git a/src/main/radzap b/src/main/radzap
new file mode 100755 (executable)
index 0000000..d3d8450
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+#      $Id$
+#
+
+usage() {
+       echo "Usage: radzap [options] server[:port] secret" >&2
+        echo "       -d raddb_directory: directory where radiusd.conf is located"
+        echo "       -N nas_ip_address: IP address of the NAS to zap."
+       echo "       -P nas_port: NAS port that the user is logged into."
+       echo "       -u username: Name of user to zap (case insensitive)."
+       echo "       -U username: like -u, but case-sensitive."
+       echo "       -x : more debugging output"
+       exit ${1:-0}
+}
+
+while test "$#" != "0"
+do
+  case $1 in
+      -h) usage;;
+
+      -d) RADDB="-d $2";shift;shift;;
+
+      -N) NAS_IP_ADDR="-N $2";shift;shift;;
+
+      -P) NAS_PORT="-P $2";shift;shift;;
+
+      -u) USER_NAME="-u $2";shift;shift;;
+
+      -U) USER_NAME="-U $2";shift;shift;;
+
+      -x) DEBUG="-x";shift;;
+
+      *) break;;
+
+  esac
+done
+
+if test "$#" != "2"; then
+    usage 1 >&2
+fi
+
+
+SERVER=$1
+SECRET=$2
+
+#
+#  Radzap is now a wrapper around radwho & radclient.
+#
+radwho -ZR $RADDB $NAS_IP_ADDR $NAS_PORT $USER_NAME | radclient $DEBUG $RADDB -f - $SERVER acct $SECRET
diff --git a/src/main/radzap.c b/src/main/radzap.c
deleted file mode 100644 (file)
index 74860fb..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * radzap.c    Zap a user from the radutmp and radwtmp file.
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Copyright 2000  The FreeRADIUS server project
- * Copyright 2000  Alan DeKok <aland@ox.org>
- */
-
-#include "autoconf.h"
-#include "libradius.h"
-
-#include <sys/file.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <netdb.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#ifdef HAVE_NETINET_IN_H
-#  include <netinet/in.h>
-#endif
-
-#include "radiusd.h"
-#include "radutmp.h"
-#include "conffile.h"
-
-const char *progname;
-const char *radlog_dir = NULL;
-const char *radius_dir = NULL;
-const char *radacct_dir = NULL;
-const char *radlib_dir = NULL;
-radlog_dest_t radlog_dest = RADLOG_FILES;
-int debug_flag = 0;
-int acct_port;
-int log_stripped_names;
-struct main_config_t mainconfig;
-uint32_t radiusip = INADDR_NONE;
-static void usage(void);
-
-struct radutmp_config_t {
-  char *radutmp_fn;
-} radutmpconfig;
-
-static CONF_PARSER module_config[] = {
-  { "filename", PW_TYPE_STRING_PTR, 0, &radutmpconfig.radutmp_fn,  RADUTMP },
-  { NULL, -1, 0, NULL, NULL }
-};
-
-#define LOCK_LEN sizeof(struct radutmp)
-
-static int radutmp_lookup(struct radutmp *u, uint32_t nasaddr,
-               uint32_t port, const char *user)
-{
-       int fd;
-
-       if ((fd = open(radutmpconfig.radutmp_fn, O_RDONLY|O_CREAT, 0644)) >= 0) {
-               /*
-                *      Lock the utmp file.
-                */
-               rad_lockfd(fd, LOCK_LEN);
-
-               /*
-                *      Find the entry for this NAS / portno combination.
-                */
-               while (read(fd, u, sizeof(*u)) == sizeof(*u)) {
-                       if ((nasaddr != 0 && nasaddr != u->nas_address) ||
-                                       (port != u->nas_port) ||
-                                       (user != NULL &&
-                                       strncmp(u->login, user, sizeof u->login) != 0) ||
-                                       u->type != P_LOGIN)
-                               continue;
-                       /*
-                        *      Match. Zap it.
-                        */
-                       close(fd);
-                       return 1;
-               }
-               close(fd);
-       }
-       return 0;
-}
-static int do_accton_packet(uint32_t nasaddr);
-static int do_stop_packet(const struct radutmp *u);
-
-/*
- *  Display the syntax for starting this program.
- */
-static void usage(void)
-{
-        fprintf(stderr,
-                        "Usage: %s [-d raddb] [-p acct_port] [-r servername|serverip] termserver [port] [user]\n", progname);
-        fprintf(stderr, "Options:\n\n");
-       fprintf(stderr, "  -d raddb        Set the raddb directory (default is %s)\n", RADIUS_DIR);
-        fprintf(stderr, "  -p acct_port    Accounting port on radius server\n");
-        fprintf(stderr, "  -r radserver    Radius server name or IP address\n");
-        fprintf(stderr, "  termserver      Terminal Server (NAS) name or IP address to match, can be '' for any\n");
-        fprintf(stderr, "  [port]          Terminal Server port to match\n");
-        fprintf(stderr, "  [user]          Login account to match\n");
-        exit(1);
-}
-
-
-/*
- *     Zap a user from the radutmp and radwtmp file.
- */
-int main(int argc, char **argv)
-{
-       CONF_SECTION *cs;
-       NAS *nas;
-       uint32_t ip = 0;
-       uint32_t nas_port = ~0;
-       char *user = NULL;
-       char *s;
-       char buf[256];
-       struct radutmp u;
-       int argval;
-
-       progname = argv[0];
-
-       radius_dir = strdup(RADIUS_DIR);
-
-        /*  Process the options.  */
-        while ((argval = getopt(argc, argv, "d:p:r:")) != EOF) {
-
-                switch(argval) {
-
-                       case 'd':
-                               if (radius_dir) free(radius_dir);
-                               radius_dir = strdup(optarg);
-                               break;
-                        case 'p':
-                               acct_port = atoi(optarg);
-                                break;
-
-                        case 'r':
-                                if ((radiusip = ip_getaddr(optarg)) == INADDR_NONE) {
-                                        fprintf(stderr, "%s: %s: radius server unknown\n",
-                                                progname, optarg);
-                                        exit(1);
-                               }
-                                break;
-
-                        default:
-                                usage();
-                                exit(1);
-                }
-        }
-
-
-       if (argc == optind) {   /* no terminal server specified */
-               usage();
-                exit(1);
-       }
-
-       if (argc > optind + 1) {        /* NAS port given */
-               s = argv[optind+1];
-               if (*s == 's' || *s == 'S') s++;
-               nas_port = strtoul(s, NULL, 10);
-       }
-
-       if (argc > optind + 2) {        /* username (login) given */
-               user = argv[optind+2];
-       }
-
-       /*
-        *      Find the IP address of the terminal server.
-        */
-       if ((nas = nas_findbyname(argv[optind])) == NULL && argv[optind][0] != 0) {
-               if ((ip = ip_getaddr(argv[optind])) == INADDR_NONE) {
-                       fprintf(stderr, "%s: host not found.\n", argv[optind]);
-                       exit(1);
-               }
-       }
-       if (nas != NULL)
-               ip = nas->ipaddr;
-
-       /*
-        *      Ensure that the configuration is initialized.
-        */
-       memset(&mainconfig, 0, sizeof(mainconfig));
-
-        /* Read radiusd.conf */
-       if (read_mainconfig(0) < 0) {
-               fprintf(stderr, "%s: Error reading radiusd.conf.\n", argv[0]);
-               exit(1);
-       }
-
-        /* Read the radutmp section of radiusd.conf */
-        cs = cf_section_sub_find(cf_section_find("modules"), "radutmp");
-        if(!cs) {
-                fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf!\n",
-                        argv[0]);
-                exit(1);
-        }
-
-        cf_section_parse(cs, NULL, module_config);
-
-       printf("%s: zapping termserver %s, port %u",
-               progname, ip_hostname(buf, sizeof(buf), ip), nas_port);
-       if (user != NULL)
-               printf(", user %s", user);
-       printf("\n");
-
-       if (nas_port == ~0) {
-               return do_accton_packet(ip);
-       }
-
-       if (!radutmp_lookup(&u, ip, nas_port, user)) {
-               fprintf(stderr, "Entry not found\n");
-               return 1;
-       }
-
-       return do_stop_packet(&u);
-}
-
-static int getport(const char *name)
-{
-       struct servent *svp;
-
-       svp = getservbyname(name, "udp");
-       if (svp == NULL) {
-               return 0;
-       }
-
-       return ntohs(svp->s_port);
-}
-
-static const char *getsecret(uint32_t server)
-{
-       RADCLIENT *cl;
-
-       cl = client_find(server);
-       if (cl == NULL) {
-               char buf[32];
-               radlog(L_ERR|L_CONS, "No clients entry for %s",
-                      ip_ntoa(buf,server));
-               exit(1);
-       }
-       return (const char *)cl->secret;
-}
-
-/* Packet-fabrication macros. Don't stare directly at them without protective
- * eye gear */
-#define PAIR(n,v,t,e) do { \
-  if(!(vp=paircreate(n, t))) { \
-    radlog(L_ERR|L_CONS, "no memory"); \
-    pairfree(&req->vps); \
-    return 1; \
-  } \
-  vp->e=v; \
-  pairadd(&req->vps, vp); \
-} while(0)
-#define INTPAIR(n,v) PAIR(n,v,PW_TYPE_INTEGER,lvalue)
-#define IPPAIR(n,v) PAIR(n,v,PW_TYPE_IPADDR,lvalue)
-#define STRINGPAIR(n,v) do { \
-  if(!(vp=paircreate(n, PW_TYPE_STRING))) { \
-    radlog(L_ERR|L_CONS, "no memory"); \
-    pairfree(&req->vps); \
-    return 1; \
-  } \
-  strNcpy((char *)vp->strvalue, v, sizeof vp->strvalue); \
-  vp->length=strlen(v); \
-  pairadd(&req->vps, vp); \
-} while(0)
-
-static int do_packet(int allports, uint32_t nasaddr, const struct radutmp *u)
-{
-       int i, retries=5, timeout=3;
-       struct timeval tv;
-       RADIUS_PACKET *req, *rep = NULL;
-       VALUE_PAIR *vp;
-       const char *secret;
-
-       if ((req = rad_alloc(1)) == NULL) {
-               librad_perror("radzap");
-               exit(1);
-       }
-       req->id = getpid() & 0xFF;
-       req->code = PW_ACCOUNTING_REQUEST;
-       req->dst_port = acct_port;
-       if(req->dst_port == 0)
-               req->dst_port = getport("radacct");
-       if(req->dst_port == 0)
-               req->dst_port = PW_ACCT_UDP_PORT;
-       if (radiusip == INADDR_NONE) {
-               req->dst_ipaddr = ip_getaddr("localhost");
-       }
-       else {
-               req->dst_ipaddr = radiusip;
-       }
-       if(!req->dst_ipaddr)
-               req->dst_ipaddr = 0x7f000001;
-       req->vps = NULL;
-       secret = getsecret(req->dst_ipaddr);
-
-       if(allports != 0) {
-               INTPAIR(PW_ACCT_STATUS_TYPE, PW_STATUS_ACCOUNTING_OFF);
-               IPPAIR(PW_NAS_IP_ADDRESS, nasaddr);
-               INTPAIR(PW_ACCT_DELAY_TIME, 0);
-       } else {
-               char login[sizeof u->login+1];
-               char session_id[sizeof u->session_id+1];
-               strNcpy(login, u->login, sizeof login);
-               strNcpy(session_id, u->session_id, sizeof session_id);
-               INTPAIR(PW_ACCT_STATUS_TYPE, PW_STATUS_STOP);
-               IPPAIR(PW_NAS_IP_ADDRESS, u->nas_address);
-               INTPAIR(PW_ACCT_DELAY_TIME, 0);
-               STRINGPAIR(PW_USER_NAME, login);
-               INTPAIR(PW_NAS_PORT, u->nas_port);
-               STRINGPAIR(PW_ACCT_SESSION_ID, session_id);
-               if(u->proto=='P') {
-                       INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
-                       INTPAIR(PW_FRAMED_PROTOCOL, PW_PPP);
-               } else if(u->proto=='S') {
-                       INTPAIR(PW_SERVICE_TYPE, PW_FRAMED_USER);
-                       INTPAIR(PW_FRAMED_PROTOCOL, PW_SLIP);
-               } else {
-                       INTPAIR(PW_SERVICE_TYPE, PW_LOGIN_USER); /* A guess, really */
-               }
-               IPPAIR(PW_FRAMED_IP_ADDRESS, u->framed_address);
-               INTPAIR(PW_ACCT_SESSION_TIME, 0);
-               INTPAIR(PW_ACCT_INPUT_OCTETS, 0);
-               INTPAIR(PW_ACCT_OUTPUT_OCTETS, 0);
-               INTPAIR(PW_ACCT_INPUT_PACKETS, 0);
-               INTPAIR(PW_ACCT_OUTPUT_PACKETS, 0);
-       }
-       if ((req->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-               perror("radzap: socket: ");
-               exit(1);
-       }
-
-       for (i = 0; i < retries; i++) {
-               fd_set rdfdesc;
-
-               rad_send(req, NULL, secret);
-
-               /* And wait for reply, timing out as necessary */
-               FD_ZERO(&rdfdesc);
-               FD_SET(req->sockfd, &rdfdesc);
-
-               tv.tv_sec = (int)timeout;
-               tv.tv_usec = 1000000 * (timeout - (int)timeout);
-
-               /* Something's wrong if we don't get exactly one fd. */
-               if (select(req->sockfd + 1, &rdfdesc, NULL, NULL, &tv) != 1) {
-                       continue;
-               }
-
-               rep = rad_recv(req->sockfd);
-               if (rep != NULL) {
-                       break;
-               } else {        /* NULL: couldn't receive the packet */
-                       librad_perror("radzap:");
-                       exit(1);
-               }
-       }
-
-       /* No response or no data read (?) */
-       if (i == retries) {
-               fprintf(stderr, "%s: no response from server\n", progname);
-               exit(1);
-       }
-
-       if (rad_decode(rep, req, secret) != 0) {
-               librad_perror("rad_decode");
-               exit(1);
-       }
-
-       vp_printlist(stdout, rep->vps);
-       return 0;
-}
-
-static int do_accton_packet(uint32_t nasaddr)
-{
-       return do_packet(1, nasaddr, 0);
-}
-
-static int do_stop_packet(const struct radutmp *u)
-{
-       return do_packet(0, 0, u);
-}
index 0a1ca48..0173ea6 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2003-2004  The FreeRADIUS server project
+ * Copyright 2003-2004,2006  The FreeRADIUS server project
  */
-static const char rcsid[] = "$Id$";
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdlib.h>
 #include <string.h>
+#include <signal.h>
 
-#include "radiusd.h"
-#include "rad_assert.h"
-#include "request_list.h"
-#include "radius_snmp.h"
-
-
-/*
- *     We keep the incoming requests in an array, indexed by ID.
- *
- *     Each array element contains a linked list of containers of
- *     active requests, a count of the number of requests, and a time
- *     at which the first request in the list must be serviced.
- *
- *     Note that we ALSO keep a tree view of the same data, below.
- *     Both views are needed for the server to work optimally.
- */
-typedef struct REQNODE {
-       struct REQNODE *prev, *next;
-       REQUEST *req;
-} REQNODE;
-
-typedef struct REQUESTINFO {
-       REQNODE *first_request;
-       REQNODE *last_request;
-       int request_count;
-       time_t last_cleaned_list;
-} REQUESTINFO;
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/request_list.h>
+#include <freeradius-devel/radius_snmp.h>
 
-static REQUESTINFO     request_list[256];
-
-/*
- *     Remember the next request at which we start walking
- *     the list.
- */
-static REQUEST *last_request = NULL;
-
-/*
- *     It MAY make more sense here to key off of the packet ID, just
- *     like the request_list.  Then again, saving another 8 lookups
- *     (on average) isn't much of a problem.
- *
- *     The "request_cmp" function keys off of the packet ID first,
- *     so the first 8 layers of the tree will be the fanned-out
- *     tree for packet ID's.
- */
-static rbtree_t                *request_tree;
+struct request_list_t {
+       lrad_packet_list_t *pl;
+};
 
 #ifdef HAVE_PTHREAD_H
 static pthread_mutex_t proxy_mutex;
@@ -85,217 +49,51 @@ static pthread_mutex_t     proxy_mutex;
 #define pthread_mutex_unlock(_x)
 #endif
 
-/*
- *     We keep track of packets we're proxying, keyed by
- *     source socket, and destination ip/port, and Id.
- */
-static rbtree_t                *proxy_tree;
-
-/*
- *     We keep track of free/used Id's, by destination ip/port.
- *
- *     We need a different tree than above, because this one is NOT
- *     keyed by Id.  Instead, we use this one to allocate Id's.
- */
-static rbtree_t                *proxy_id_tree;
+static lrad_packet_list_t *proxy_list = NULL;
 
 /*
  *     We keep the proxy FD's here.  The RADIUS Id's are marked
  *     "allocated" per Id, via a bit per proxy FD.
  */
 static int             proxy_fds[32];
-
-static uint32_t                proxy_ipaddr;
-
-/*
- *     We can use 256 RADIUS Id's per dst ipaddr/port, per server
- *     socket.  So, to allocate them, we key off of dst ipaddr/port,
- *     and then search the RADIUS Id's, looking for an unused socket.
- *
- *     We do NOT key off of socket fd's, here, either.  Instead,
- *     we look for a free Id from a sockfd, any sockfd.
- */
-typedef struct proxy_id_t {
-       uint32_t        dst_ipaddr;
-       int             dst_port;
-
-       /*
-        *      FIXME: Allocate more proxy sockets when this gets full.
-        */
-       int             index;
-       uint32_t        mask;   /* of FD's we know about. */
-       uint32_t        id[1];  /* really id[256] */
-} proxy_id_t;
-
-
-/*
- *     Find a matching entry in the proxy ID tree.
- */
-static int proxy_id_cmp(const void *one, const void *two)
-{
-       const proxy_id_t *a = one;
-       const proxy_id_t *b = two;
-
-       /*
-        *      The following comparisons look weird, but it's
-        *      the only way to make the comparisons work.
-        */
-       if (a->dst_ipaddr < b->dst_ipaddr) return -1;
-       if (a->dst_ipaddr > b->dst_ipaddr) return +1;
-
-       if (a->dst_port < b->dst_port) return -1;
-       if (a->dst_port > b->dst_port) return +1;
-       
-       /*
-        *      Everything's equal.  Say so.
-        */
-       return 0;
-}
-
-
-/*
- *     Compare two REQUEST data structures, based on a number
- *     of criteria.
- */
-static int request_cmp(const void *one, const void *two)
-{
-       const REQUEST *a = one;
-       const REQUEST *b = two;
-
-       /*
-        *      The following comparisons look weird, but it's
-        *      the only way to make the comparisons work.
-        */
-
-       /*
-        *      If the packets didn't arrive on the same socket,
-        *      they're not identical, no matter what their src/dst
-        *      ip/ports say.
-        */
-       if (a->packet->sockfd < b->packet->sockfd) return -1;
-       if (a->packet->sockfd > b->packet->sockfd) return +1;
-
-       if (a->packet->id < b->packet->id) return -1;
-       if (a->packet->id > b->packet->id) return +1;
-
-       if (a->packet->code < b->packet->code) return -1;
-       if (a->packet->code > b->packet->code) return +1;
-
-       if (a->packet->src_ipaddr < b->packet->src_ipaddr) return -1;
-       if (a->packet->src_ipaddr > b->packet->src_ipaddr) return +1;
-
-       if (a->packet->src_port < b->packet->src_port) return -1;
-       if (a->packet->src_port > b->packet->src_port) return +1;
-
-       /*
-        *      Hmm... we may be listening on IPADDR_ANY, in which case
-        *      the destination IP is important, too.
-        */
-       if (a->packet->dst_ipaddr < b->packet->dst_ipaddr) return -1;
-       if (a->packet->dst_ipaddr > b->packet->dst_ipaddr) return +1;
-
-       if (a->packet->dst_port < b->packet->dst_port) return -1;
-       if (a->packet->dst_port > b->packet->dst_port) return +1;
-
-       /*
-        *      Everything's equal.  Say so.
-        */
-       return 0;
-}
+static rad_listen_t    *proxy_listeners[32];
 
 /*
- *     Compare two REQUEST data structures, based on a number
- *     of criteria, for proxied packets.
+ *     Initialize the request list.
  */
-static int proxy_cmp(const void *one, const void *two)
+request_list_t *rl_init(void)
 {
-       const REQUEST *a = one;
-       const REQUEST *b = two;
-
-       rad_assert(a->magic == REQUEST_MAGIC);
-       rad_assert(b->magic == REQUEST_MAGIC);
-
-       rad_assert(a->proxy != NULL);
-       rad_assert(b->proxy != NULL);
-
-       /*
-        *      The following code looks unreasonable, but it's
-        *      the only way to make the comparisons work.
-        */
-       if (a->proxy->sockfd < b->proxy->sockfd) return -1;
-       if (a->proxy->sockfd > b->proxy->sockfd) return +1;
-
-       if (a->proxy->id < b->proxy->id) return -1;
-       if (a->proxy->id > b->proxy->id) return +1;
-
-       /*
-        *      We've got to check packet codes, too.  But
-        *      this should be done later, by someone else...
-        */
-
-       if (a->proxy->dst_ipaddr < b->proxy->dst_ipaddr) return -1;
-       if (a->proxy->dst_ipaddr > b->proxy->dst_ipaddr) return +1;
-
-       if (a->proxy->dst_port < b->proxy->dst_port) return -1;
-       if (a->proxy->dst_port > b->proxy->dst_port) return +1;
+       request_list_t *rl = rad_malloc(sizeof(*rl));
 
        /*
-        *      FIXME: Check the Proxy-State attribute, too.
-        *      This will help cut down on duplicates.
+        *      Initialize the request_list[] array.
         */
+       memset(rl, 0, sizeof(*rl));
 
-       /*
-        *      Everything's equal.  Say so.
-        */
-       return 0;
-}
-
-
-void rl_free(void)
-{
-       int i;
-
-       for (i = 0; i < 256; i++) {
-               while (request_list[i].first_request) {
-                       rl_delete(request_list[i].first_request->req);
-               }
+       rl->pl = lrad_packet_list_create(0);
+       if (!rl->pl) {
+               rad_assert("FAIL" == NULL);
        }
 
-       rbtree_free(request_tree);
-       rbtree_free(proxy_id_tree);
-       rbtree_free(proxy_tree);
+       return rl;
 }
 
-
-/*
- *     Initialize the request list.
- */
-int rl_init(void)
+int rl_init_proxy(void)
 {
        /*
-        *      Initialize the request_list[] array.
+        *      Hacks, so that multiple users can call rl_init,
+        *      and it won't get excited.
+        *
+        *      FIXME: Move proxy stuff to another struct entirely.
         */
-       memset(request_list, 0, sizeof(request_list));
-
-       request_tree = rbtree_create(request_cmp, NULL, 0);
-       if (!request_tree) {
-               rad_assert("FAIL" == NULL);
-       }
+       if (proxy_list) return 0;
 
        /*
         *      Create the tree for managing proxied requests and
         *      responses.
         */
-       proxy_tree = rbtree_create(proxy_cmp, NULL, 1);
-       if (!proxy_tree) {
-               rad_assert("FAIL" == NULL);
-       }
-
-       /*
-        *      Create the tree for allocating proxy ID's.
-        */
-       proxy_id_tree = rbtree_create(proxy_id_cmp, NULL, 0);
-       if (!proxy_id_tree) {
+       proxy_list = lrad_packet_list_create(1);
+       if (!proxy_list) {
                rad_assert("FAIL" == NULL);
        }
 
@@ -312,15 +110,6 @@ int rl_init(void)
        }
 #endif
 
-       /*
-        *      The Id allocation table is done by bits, so we have
-        *      32 bits per Id.  These bits indicate which entry
-        *      in the proxy_fds array is used for that Id.
-        *
-        *      This design allows 256*32 = 8k requests to be
-        *      outstanding to a home server, before something goes
-        *      wrong.
-        */
        {
                int i;
                rad_listen_t *listener;
@@ -334,8 +123,13 @@ int rl_init(void)
                     listener != NULL;
                     listener = listener->next) {
                        if (listener->type == RAD_LISTEN_PROXY) {
-                               proxy_ipaddr = listener->ipaddr;
+                               /*
+                                *      FIXME: This works only because we
+                                *      start off with one proxy socket.
+                                */
                                proxy_fds[listener->fd & 0x1f] = listener->fd;
+                               proxy_listeners[listener->fd & 0x1f] = listener;
+                               lrad_packet_list_socket_add(proxy_list, listener->fd);
                                break;
                        }
                }
@@ -344,104 +138,64 @@ int rl_init(void)
        return 1;
 }
 
-
-/*
- *     Delete a request from the proxy trees.
- */
-static void rl_delete_proxy(REQUEST *request, rbnode_t *node)
+static int rl_free_entry(void *ctx, void *data)
 {
-       proxy_id_t      myid, *entry;
-
-       rad_assert(node != NULL);
-
-       rbtree_delete(proxy_tree, node);
-       
-       myid.dst_ipaddr = request->proxy->dst_ipaddr;
-       myid.dst_port = request->proxy->dst_port;
+       ctx = ctx;              /* -Wunused */
+       REQUEST *request = lrad_packet2myptr(REQUEST, packet, data);
 
+#ifdef HAVE_PTHREAD_H 
        /*
-        *      Find the Id in the array of allocated Id's,
-        *      and delete it.
+        *      If someone is processing this request, kill
+        *      them, and mark the request as not being used.
+        *
+        *      FIXME: Move the request to the "dead pool",
+        *      and don't kill the thread.
         */
-       entry = rbtree_finddata(proxy_id_tree, &myid);
-       if (entry) {
-               int i;
-
-               DEBUG3(" proxy: de-allocating %08x:%d %d",
-                      entry->dst_ipaddr,
-                      entry->dst_port,
-                      request->proxy->id);
-
-               /*
-                *      Find the proxy socket associated with this
-                *      Id.  We loop over all 32 proxy fd's, but we
-                *      partially index by proxy fd's, which means
-                *      that we almost always break out of the loop
-                *      quickly.
-                */
-               for (i = 0; i < 32; i++) {
-                       int offset;
-
-                       offset = (request->proxy->sockfd + i) & 0x1f;
-                 
-                       if (proxy_fds[offset] == request->proxy->sockfd) {
-                               
-                               entry->id[request->proxy->id] &= ~(1 << offset);
-                               break;
-                       }
-               } /* else die horribly? */
-       } else {
-               /*
-                *      Hmm... not sure what to do here.
-                */
-               DEBUG3(" proxy: FAILED TO FIND %08x:%d %d",
-                      myid.dst_ipaddr,
-                      myid.dst_port,
-                      request->proxy->id);
+       if (request->child_pid != NO_SUCH_CHILD_PID) {
+               pthread_kill(request->child_pid, SIGKILL);
+               request->child_pid = NO_SUCH_CHILD_PID;
        }
+#endif
+       request_free(&request);
+
+       return 0;
 }
 
 
 /*
- *     Delete a particular request.
+ *     Delete everything in the request list.
+ *
+ *     This should be called only when debugging the server...
  */
-void rl_delete(REQUEST *request)
+void rl_deinit(request_list_t *rl)
 {
-       int id;
-       REQNODE *prev, *next;
-
-       prev = ((REQNODE *) request->container)->prev;
-       next = ((REQNODE *) request->container)->next;
+       if (!rl) return;
 
-       id = request->packet->id;
+       if (proxy_list) {
+               lrad_packet_list_free(proxy_list);
+               proxy_list = NULL;
+       }
 
        /*
-        *      Update the last request we touched.
-        *
-        *      This is so the periodic "walk & clean list"
-        *      function, below, doesn't walk over all requests
-        *      all of the time.  Rather, it tries to amortize
-        *      the cost...
+        *      Delete everything in the table, too.
         */
-       if (last_request == request) {
-               last_request = rl_next(last_request);
-       }
-
+       lrad_packet_list_walk(rl->pl, NULL, rl_free_entry);
 
-       if (prev == NULL) {
-               request_list[id].first_request = next;
-       } else {
-               prev->next = next;
-       }
+       lrad_packet_list_free(rl->pl);
 
-       if (next == NULL) {
-               request_list[id].last_request = prev;
-       } else {
-               next->prev = prev;
-       }
+       /*
+        *      Just to ensure no one is using the memory.
+        */
+       memset(rl, 0, sizeof(*rl));
+       free(rl);
+}
 
-       free(request->container);
 
+/*
+ *     Yank a request from the tree, without free'ing it.
+ */
+void rl_yank(request_list_t *rl, REQUEST *request)
+{
 #ifdef WITH_SNMP
        /*
         *      Update the SNMP statistics.
@@ -480,72 +234,41 @@ void rl_delete(REQUEST *request)
 #endif
 
        /*
-        *      Delete the request from the tree.
+        *      Delete the request from the list.
         */
-       {
-               rbnode_t *node;
-
-               node = rbtree_find(request_tree, request);
-               rad_assert(node != NULL);
-               rbtree_delete(request_tree, node);
-
-
-               /*
-                *      If there's a proxied packet, and we're still
-                *      waiting for a reply, then delete the packet
-                *      from the list of outstanding proxied requests.
-                */
-               if (request->proxy &&
-                   (request->proxy_outstanding > 0)) {
-                       pthread_mutex_lock(&proxy_mutex);
-                       node = rbtree_find(proxy_tree, request);
-                       rl_delete_proxy(request, node);
-                       pthread_mutex_unlock(&proxy_mutex);
-               }
+       lrad_packet_list_yank(rl->pl, request->packet);
+       
+       /*
+        *      If there's a proxied packet, and we're still
+        *      waiting for a reply, then delete the packet
+        *      from the list of outstanding proxied requests.
+        */
+       if (request->proxy &&
+           (request->proxy_outstanding > 0)) {
+               pthread_mutex_lock(&proxy_mutex);
+               lrad_packet_list_yank(proxy_list, request->proxy);
+               lrad_packet_list_id_free(proxy_list, request->proxy);
+               pthread_mutex_unlock(&proxy_mutex);
        }
+}
 
+
+/*
+ *     Delete a request from the tree.
+ */
+void rl_delete(request_list_t *rl, REQUEST *request)
+{
+       rl_yank(rl, request);
        request_free(&request);
-       request_list[id].request_count--;
 }
 
+
 /*
  *     Add a request to the request list.
  */
-void rl_add(REQUEST *request)
+int rl_add(request_list_t *rl, REQUEST *request)
 {
-       int id = request->packet->id;
-       REQNODE *node;
-
-       rad_assert(request->container == NULL);
-
-       request->container = rad_malloc(sizeof(REQNODE));
-       node = (REQNODE *) request->container;
-       node->req = request;
-
-       node->prev = NULL;
-       node->next = NULL;
-
-       if (!request_list[id].first_request) {
-               rad_assert(request_list[id].request_count == 0);
-
-               request_list[id].first_request = node;
-               request_list[id].last_request = node;
-       } else {
-               rad_assert(request_list[id].request_count != 0);
-
-               node->prev = request_list[id].last_request;
-               request_list[id].last_request->next = node;
-               request_list[id].last_request = node;
-       }
-
-       /*
-        *      Insert the request into the tree.
-        */
-       if (rbtree_insert(request_tree, request) == 0) {
-               rad_assert("FAIL" == NULL);
-       }
-
-       request_list[id].request_count++;
+       return lrad_packet_list_insert(rl->pl, &request->packet);
 }
 
 /*
@@ -558,21 +281,17 @@ void rl_add(REQUEST *request)
  *     We MUST NOT have two requests with identical (id/code/IP/port), and
  *     different vectors.  This is a serious error!
  */
-REQUEST *rl_find(RADIUS_PACKET *packet)
+REQUEST *rl_find(request_list_t *rl, RADIUS_PACKET *packet)
 {
-       REQUEST myrequest;
+       RADIUS_PACKET **packet_p;
 
-       myrequest.packet = packet;
+       packet_p = lrad_packet_list_find(rl->pl, packet);
+       if (!packet_p) return NULL;
 
-       return rbtree_finddata(request_tree, &myrequest);
+       return lrad_packet2myptr(REQUEST, packet, packet_p);
 }
 
 /*
- *     See mainconfig.c
- */
-extern int proxy_new_listener(void);
-
-/*
  *     Add an entry to the proxy tree.
  *
  *     This is the ONLY function in this source file which may be called
@@ -580,255 +299,92 @@ extern int proxy_new_listener(void);
  */
 int rl_add_proxy(REQUEST *request)
 {
-       int             i, found, proxy;
-       uint32_t        mask;
-       proxy_id_t      myid, *entry;
-
-       myid.dst_ipaddr = request->proxy->dst_ipaddr;
-       myid.dst_port = request->proxy->dst_port;
+       int i, proxy;
+       char buf[128];
 
-       /*
-        *      Proxied requests get sent out the proxy FD ONLY.
-        *
-        *      FIXME: Once we allocate multiple proxy FD's, move this
-        *      code to below, so we can have more than 256 requests
-        *      outstanding.
-        */
        request->proxy_outstanding = 1;
+       request->proxy->sockfd = -1;
 
        pthread_mutex_lock(&proxy_mutex);
 
-       /*
-        *      Assign a proxy ID.
-        */
-       entry = rbtree_finddata(proxy_id_tree, &myid);
-       if (!entry) {   /* allocate it */
-               entry = rad_malloc(sizeof(*entry) + sizeof(entry->id) * 255);
-               
-               entry->dst_ipaddr = request->proxy->dst_ipaddr;
-               entry->dst_port = request->proxy->dst_port;
-               entry->index = 0;
-
-               DEBUG3(" proxy: creating %08x:%d",
-                      entry->dst_ipaddr,
-                      entry->dst_port);
-               
-               /*
-                *      Insert the new home server entry into
-                *      the tree.
-                *
-                *      FIXME: We don't (currently) delete the
-                *      entries, so this is technically a
-                *      memory leak.
-                */
-               if (rbtree_insert(proxy_id_tree, entry) == 0) {
-                       DEBUG2("ERROR: Failed to insert entry into proxy Id tree");
-                       free(entry);
-                       return 0;
-               }
-
-               /*
-                *      Clear out bits in the array which DO have
-                *      proxy Fd's associated with them.  We do this
-                *      by getting the mask of bits which have proxy
-                *      fd's...  */
-               mask = 0;
-               for (i = 0; i < 32; i++) {
-                       if (proxy_fds[i] != -1) {
-                               mask |= (1 << i);
-                       }
-               }
-               rad_assert(mask != 0);
-
-               /*
-                *      Set bits here indicate that the Fd is in use.
-                */
-               entry->mask = mask;
-
-               mask = ~mask;
-
-               /*
-                *      Set the bits which are unused (and therefore
-                *      allocated).  The clear bits indicate that the Id
-                *      for that FD is unused.
-                */
-               for (i = 0; i < 256; i++) {
-                       entry->id[i] = mask;
-               }
-       } /* else the entry already existed in the proxy Id tree */
-       
- retry:
-       /*
-        *      Try to find a free Id.
-        */
-       found = -1;
-       for (i = 0; i < 256; i++) {
-               /*
-                *      Some bits are still zero..
-                */
-               if (entry->id[(i + entry->index) & 0xff] != (uint32_t) ~0) {
-                       found = (i + entry->index) & 0xff;
-                       break;
-               }
-
-               /*
-                *      Hmm... do we want to re-use Id's, when we
-                *      haven't seen all of the responses?
-                */
-       }
-       
-       /*
-        *      No free Id, try to get a new FD.
-        */
-       if (found < 0) {
-               /*
-                *      First, see if there were FD's recently allocated,
-                *      which we don't know about.
-                */
-               mask = 0;
-               for (i = 0; i < 32; i++) {
-                       if (proxy_fds[i] < 0) continue;
-
-                       mask |= (1 << i);
-               }
+       if (!lrad_packet_list_id_alloc(proxy_list, request->proxy)) {
+               int found;
+               rad_listen_t *proxy_listener;
 
                /*
-                *      There ARE more FD's than we know about.
-                *      Update the masks for Id's, and re-try.
-                */
-               if (entry->mask != mask) {
-                       /*
-                        *      New mask always has more bits than
-                        *      the old one, but never fewer bits.
-                        */
-                       rad_assert((entry->mask & mask) == entry->mask);
-
-                       /*
-                        *      Clear the bits we already know about,
-                        *      and then or in those bits into the
-                        *      global mask.
-                        */
-                       mask ^= entry->mask;
-                       entry->mask |= mask;
-                       mask = ~mask;
-                       
-                       /*
-                        *      Clear the bits in the Id's for the new
-                        *      FD's.
-                        */
-                       for (i = 0; i < 256; i++) {
-                               entry->id[i] &= mask;
-                       }
-                       
-                       /*
-                        *      And try again to allocate an Id.
-                        */
-                       goto retry;
-               } /* else no new Fd's were allocated. */
-
-               /*
-                *      If all Fd's are allocated, die.
-                */
-               if (~mask == 0) {
-                       radlog(L_ERR|L_CONS, "ERROR: More than 8000 proxied requests outstanding for home server %08x:%d",
-                              ntohs(entry->dst_ipaddr), entry->dst_port);
-                       return 0;
-               }
-               
-               /*
                 *      Allocate a new proxy Fd.  This function adds it
                 *      into the list of listeners.
                 */
-               proxy = proxy_new_listener();
-               if (proxy < 0) {
+               proxy_listener = proxy_new_listener();
+               if (!proxy_listener) {
+                       pthread_mutex_unlock(&proxy_mutex);
                        DEBUG2("ERROR: Failed to create a new socket for proxying requests.");
                        return 0;
                }
 
                /*
-                *
+                *      Cache it locally.
                 */
                found = -1;
+               proxy = proxy_listener->fd;
                for (i = 0; i < 32; i++) {
                        /*
                         *      Found a free entry.  Save the socket,
                         *      and remember where we saved it.
                         */
                        if (proxy_fds[(proxy + i) & 0x1f] == -1) {
-                               proxy_fds[(proxy + i) & 0x1f] = proxy;
                                found = (proxy + i) & 0x1f;
+                               proxy_fds[found] = proxy;
+                               proxy_listeners[found] = proxy_listener;
                                break;
                        }
                }
-               rad_assert(found >= 0); /* i.e. the mask had free bits. */
-
-               mask = 1 << found;
-               entry->mask |= mask;
-               mask = ~mask;
+               rad_assert(found >= 0);
 
-               /*
-                *      Clear the relevant bits in the mask.
-                */
-               for (i = 0; i < 256; i++) {
-                       entry->id[i] &= mask;
+               if (!lrad_packet_list_socket_add(proxy_list, proxy_listener->fd)) {
+                       pthread_mutex_unlock(&proxy_mutex);
+                       DEBUG2("ERROR: Failed to create a new socket for proxying requests.");
+                       return 0; /* leak proxy_listener */
+                       
+               }
+                   
+               if (!lrad_packet_list_id_alloc(proxy_list, request->proxy)) {
+                       pthread_mutex_unlock(&proxy_mutex);
+                       DEBUG2("ERROR: Failed to create a new socket for proxying requests.");
+                       return 0;
                }
-
-               /*
-                *      Pick a random Id to start from, as we've
-                *      just guaranteed that it's free.
-                */
-               found = lrad_rand() & 0xff;
        }
-       
-       /*
-        *      Mark next (hopefully unused) entry.
-        */
-       entry->index = (found + 1) & 0xff;
-       
+
        /*
-        *      We now have to find WHICH proxy fd to use.
+        *      FIXME: Hack until we get rid of rad_listen_t, and put
+        *      the information into the packet_list.
         */
        proxy = -1;
        for (i = 0; i < 32; i++) {
-               /*
-                *      FIXME: pick a random socket to use?
-                */
-               if ((entry->id[found] & (1 << i)) == 0) {
+               if (proxy_fds[i] == request->proxy->sockfd) {
                        proxy = i;
                        break;
                }
        }
-
-       /*
-        *      There was no bit clear, which we had just checked above...
-        */
-       if (proxy < 0) {
-               pthread_mutex_unlock(&proxy_mutex);
-               return 0;
-       }
-
-       /*
-        *      Mark the Id as allocated, for thei Fd.
-        */
-       entry->id[found] |= (1 << proxy);
-       request->proxy->id = found;
-       request->proxy->src_ipaddr = proxy_ipaddr;
+       rad_assert(proxy >= 0);
 
        rad_assert(proxy_fds[proxy] != -1);
-       request->proxy->sockfd = proxy_fds[proxy];
+       request->proxy_listener = proxy_listeners[proxy];
 
-       DEBUG3(" proxy: allocating %08x:%d %d",
-              entry->dst_ipaddr,
-              entry->dst_port,
-              request->proxy->id);
-       
-       if (!rbtree_insert(proxy_tree, request)) {
-               DEBUG2("ERROR: Failed to insert entry into proxy tree");
+       if (!lrad_packet_list_insert(proxy_list, &request->proxy)) {
+               pthread_mutex_unlock(&proxy_mutex);
+               DEBUG2("ERROR: Failed to insert entry into proxy list");
                return 0;
        }
        
        pthread_mutex_unlock(&proxy_mutex);
 
+       DEBUG3(" proxy: allocating destination %s port %d - Id %d",
+              inet_ntop(request->proxy->dst_ipaddr.af,
+                        &request->proxy->dst_ipaddr.ipaddr, buf, sizeof(buf)),
+              request->proxy->dst_port,
+              request->proxy->id);
+       
        return 1;
 }
 
@@ -843,223 +399,119 @@ int rl_add_proxy(REQUEST *request)
  *     We MUST NOT have two requests with identical (id/code/IP/port), and
  *     different vectors.  This is a serious error!
  */
-REQUEST *rl_find_proxy(RADIUS_PACKET *packet)
+REQUEST *rl_find_proxy(RADIUS_PACKET *reply)
 {
-       rbnode_t        *node;
-       REQUEST         myrequest, *maybe = NULL;
-       RADIUS_PACKET   myproxy;
-
-       /*
-        *      If we use the socket FD as an indicator,
-        *      then that implicitely contains information
-        *      as to our src ipaddr/port, so we don't need
-        *      to use that in the comparisons.
-        */
-       myproxy.sockfd = packet->sockfd;
-       myproxy.id = packet->id;
-       myproxy.dst_ipaddr = packet->src_ipaddr;
-       myproxy.dst_port = packet->src_port;
-
-#ifndef NDEBUG
-       myrequest.magic = REQUEST_MAGIC;
-#endif
-       myrequest.proxy = &myproxy;
+       RADIUS_PACKET **proxy_p;
+       REQUEST *request;
 
        pthread_mutex_lock(&proxy_mutex);
-        node = rbtree_find(proxy_tree, &myrequest);
+       proxy_p = lrad_packet_list_find_byreply(proxy_list, reply);
 
-       if (node) {
-               maybe = rbtree_node2data(proxy_tree, node);
-               rad_assert(maybe->proxy_outstanding > 0);
-               maybe->proxy_outstanding--;
-               
-               /*
-                *      Received all of the replies we expect.
-                *      delete it from both trees.
-                */
-               if (maybe->proxy_outstanding == 0) {
-                       rl_delete_proxy(&myrequest, node);
-               }
+       if (!proxy_p) {
+               pthread_mutex_unlock(&proxy_mutex);
+               return NULL;
        }
-       pthread_mutex_unlock(&proxy_mutex);
-
-       return maybe;
-}
-
-
-/*
- *     Walk over all requests, performing a callback for each request.
- */
-int rl_walk(RL_WALK_FUNC walker, void *data)
-{
-       int id, rcode;
-       REQNODE *curreq, *next;
 
+       request = lrad_packet2myptr(REQUEST, proxy, proxy_p);
+       rad_assert(request->proxy_outstanding > 0);
+       request->proxy_outstanding--;
+               
        /*
-        *      Walk over all 256 ID's.
+        *      Received all of the replies we expect.
+        *      delete it from the managed list.
         */
-       for (id = 0; id < 256; id++) {
-
-               /*
-                *      Walk over the request list for each ID.
-                */
-               for (curreq = request_list[id].first_request;
-                               curreq != NULL ;
-                               curreq = next) {
-                       /*
-                        *      The callback MIGHT delete the current
-                        *      request, so we CANNOT depend on curreq->next
-                        *      to be there, when going to the next element
-                        *      in the 'for' loop.
-                        */
-                       next = curreq->next;
-
-                       rcode = walker(curreq->req, data);
-                       if (rcode != RL_WALK_CONTINUE) {
-                               return rcode;
-                       }
-               }
+       if (request->proxy_outstanding == 0) {
+               lrad_packet_list_yank(proxy_list, request->proxy);
+               lrad_packet_list_id_free(proxy_list, request->proxy);
        }
+       pthread_mutex_unlock(&proxy_mutex);
 
-       return 0;
+       return request;
 }
 
 
 /*
- *     Walk from one request to the next.
+ *     Return the number of requests in the request list.
  */
-REQUEST *rl_next(REQUEST *request)
+int rl_num_requests(request_list_t *rl)
 {
-       int id, start_id;
-       int count;
-
-       /*
-        *      If we were passed a request, then go to the "next" one.
-        */
-       if (request != NULL) {
-               rad_assert(request->magic == REQUEST_MAGIC);
-
-               /*
-                *      It has a "next", return it.
-                */
-               if (((REQNODE *)request->container)->next != NULL) {
-                       return ((REQNODE *)request->container)->next->req;
-               } else {
-                       /*
-                        *      No "next", increment the ID, and look
-                        *      at that one.
-                        */
-                       start_id = request->packet->id + 1;
-                       start_id &= 0xff;
-                       count = 255;
-               }
-       } else {
-               /*
-                *      No input request, start looking at ID 0.
-                */
-               start_id = 0;
-               count = 256;
-       }
-
-       /*
-        *      Check all ID's, wrapping around at 255.
-        */
-       for (id = start_id; id < (start_id + count); id++) {
-
-               /*
-                *      This ID has a request, return it.
-                */
-               if (request_list[id & 0xff].first_request != NULL) {
-                       rad_assert(request_list[id&0xff].first_request->req != request);
-
-                       return request_list[id & 0xff].first_request->req;
-               }
-       }
-
-       /*
-        *      No requests at all in the list. Nothing to do.
-        */
-       DEBUG3("rl_next:  returning NULL");
-       return NULL;
+       return lrad_packet_list_num_elements(rl->pl);
 }
 
 
 /*
- *     Return the number of requests in the request list.
+ *     See also radiusd.c
  */
-int rl_num_requests(void)
-{
-       int id;
-       int request_count = 0;
-
-       for (id = 0; id < 256; id++) {
-               request_count += request_list[id].request_count;
-       }
-
-       return request_count;
-}
-
-
+#define SLEEP_FOREVER (65536)
 typedef struct rl_walk_t {
        time_t  now;
-       time_t  smallest;
+       int     sleep_time;
+       request_list_t *rl;
 } rl_walk_t;
 
 
 /*
- *  Refresh a request, by using proxy_retry_delay, cleanup_delay,
- *  max_request_time, etc.
+ *  Refresh a request, by using cleanup_delay, max_request_time, etc.
  *
  *  When walking over the request list, all of the per-request
  *  magic is done here.
  */
-static int refresh_request(REQUEST *request, void *data)
+static int refresh_request(void *ctx, void *data)
 {
-       rl_walk_t *info = (rl_walk_t *) data;
-       time_t difference;
+       int time_passed;
+       rl_walk_t *info = (rl_walk_t *) ctx;
        child_pid_t child_pid;
+       request_list_t *rl = info->rl;
+       REQUEST *request = lrad_packet2myptr(REQUEST, packet, data);
 
        rad_assert(request->magic == REQUEST_MAGIC);
 
+       time_passed = (int) (info->now - request->timestamp);
+       
        /*
-        *  If the request is marked as a delayed reject, AND it's
-        *  time to send the reject, then do so now.
+        *      If the request is marked as a delayed reject, AND it's
+        *      time to send the reject, then do so now.
         */
        if (request->finished &&
            ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) != 0)) {
                rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
+               if (time_passed < mainconfig.reject_delay) {
+                       goto reject_delay;
+               }
 
-               difference = info->now - request->timestamp;
-               if (difference >= (time_t) mainconfig.reject_delay) {
+       reject_packet:
+               /*
+                *      Clear the 'delayed reject' bit, so that we
+                *      don't do this again, and fall through to
+                *      setting cleanup delay.
+                */
+               request->listener->send(request->listener, request);
+               request->options &= ~RAD_REQUEST_OPTION_DELAYED_REJECT;
 
-                       /*
-                        *  Clear the 'delayed reject' bit, so that we
-                        *  don't do this again.
-                        */
-                       request->options &= ~RAD_REQUEST_OPTION_DELAYED_REJECT;
-                       rad_send(request->reply, request->packet,
-                                request->secret);
-               }
+               /*
+                *      FIXME: Beware interaction with cleanup_delay,
+                *      where we might send a reject, and immediately
+                *      there-after clean it up!
+                */
        }
 
        /*
-        *  If the request has finished processing, AND it's child has
-        *  been cleaned up, AND it's time to clean up the request,
-        *  OR, it's an accounting request.  THEN, go delete it.
-        *
-        *  If this is a request which had the "don't cache" option
-        *  set, then delete it immediately, as it CANNOT have a
-        *  duplicate.
+        *      If the request is finished, THEN
+        *      check that more than cleanup_delay seconds have passed
+        *      since it was received
+        *      OR, if this is a request which had the "don't cache"
+        *      option set, then it CANNOT have a duplicate
+        *      SO, clean it up
         */
        if (request->finished &&
-           ((request->timestamp + mainconfig.cleanup_delay <= info->now) ||
-            ((request->options & RAD_REQUEST_OPTION_DONT_CACHE) != 0))) {
+           ((time_passed >= mainconfig.cleanup_delay) ||
+           ((request->options & RAD_REQUEST_OPTION_DONT_CACHE) != 0))) {
                rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
-
                /*
                 *  Request completed, delete it, and unlink it
                 *  from the currently 'alive' list of requests.
                 */
+       cleanup:
                DEBUG2("Cleaning up request %d ID %d with timestamp %08lx",
                                request->number, request->packet->id,
                                (unsigned long) request->timestamp);
@@ -1067,15 +519,15 @@ static int refresh_request(REQUEST *request, void *data)
                /*
                 *  Delete the request.
                 */
-               rl_delete(request);
-               return RL_WALK_CONTINUE;
+               rl_delete(rl, request);
+               return 0;
        }
 
        /*
-        *  Maybe the child process handling the request has hung:
-        *  kill it, and continue.
+        *      If more than max_request_time has passed since
+        *      we received the request, kill it.
         */
-       if ((request->timestamp + mainconfig.max_request_time) <= info->now) {
+       if (time_passed >= mainconfig.max_request_time) {
                int number;
 
                child_pid = request->child_pid;
@@ -1100,15 +552,27 @@ static int refresh_request(REQUEST *request, void *data)
                if (request->proxy && !request->proxy_reply) {
                        rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
 
-                       radlog(L_ERR, "Rejecting request %d due to lack of any response from home server %s:%d",
+                       radlog(L_ERR, "Rejecting request %d due to lack of any response from home server %s port %d",
                               request->number,
-                              client_name(request->packet->src_ipaddr),
+                              client_name_old(&request->packet->src_ipaddr),
                               request->packet->src_port);
-                       request_reject(request);
+                       request_reject(request, REQUEST_FAIL_HOME_SERVER);
                        request->finished = TRUE;
-                       return RL_WALK_CONTINUE;
+                       return 0;
                }
 
+#ifdef DELETE_BLOCKED_REQUESTS
+       /*
+        * Calling pthread_cancel() without a cancel handler is an
+        * exceedingly bad idea.  This code is left here in case
+        * we implement per-module cancel handlers later.
+        * See freeradius-devel archives,
+        * "cancelling requests due to max_request_time"
+        *
+        * If implemented, just remove the #ifdef's for DELETE_BLOCKED_REQUESTS
+        * scattered throughout the code (this file and others), and
+        * add the option back to radiusd.conf.in.
+        */
                if (mainconfig.kill_unresponsive_children) {
                        if (child_pid != NO_SUCH_CHILD_PID) {
                                /*
@@ -1126,8 +590,10 @@ static int refresh_request(REQUEST *request, void *data)
                         *      Maybe we haven't killed it.  In that
                         *      case, print a warning.
                         */
-               } else if ((child_pid != NO_SUCH_CHILD_PID) &&
-                          ((request->options & RAD_REQUEST_OPTION_LOGGED_CHILD) == 0)) {
+               } else
+#endif
+               if ((child_pid != NO_SUCH_CHILD_PID) &&
+                       ((request->options & RAD_REQUEST_OPTION_LOGGED_CHILD) == 0)) {
                        radlog(L_ERR, "WARNING: Unresponsive child (id %lu) for request %d",
                               (unsigned long)child_pid, number);
 
@@ -1140,192 +606,73 @@ static int refresh_request(REQUEST *request, void *data)
                }
 
                /*
-                *  Send a reject message for the request, mark it
-                *  finished, and forget about the child.
+                *      Send a reject message for the request, mark it
+                *      finished, and forget about the child.
                 */
-               request_reject(request);
+               request_reject(request, REQUEST_FAIL_SERVER_TIMEOUT);
+               
                request->child_pid = NO_SUCH_CHILD_PID;
+
+#ifdef DELETE_BLOCKED_REQUESTS
                if (mainconfig.kill_unresponsive_children)
                        request->finished = TRUE;
-               return RL_WALK_CONTINUE;
-       } /* the request has been in the queue for too long */
-
-       /*
-        *  If the request is still being processed, then due to the
-        *  above check, it's still within it's time limit.  In that
-        *  case, don't do anything.
-        */
-       if (request->child_pid != NO_SUCH_CHILD_PID) {
-               return RL_WALK_CONTINUE;
-       }
-
-       /*
-        *  The request is finished.
-        */
-       if (request->finished) goto setup_timeout;
-
-       /*
-        *  We're not proxying requests at all.
-        */
-       if (!mainconfig.proxy_requests) goto setup_timeout;
-
-       /*
-        *  We're proxying synchronously, so we don't retry it here.
-        *  Some other code takes care of retrying the proxy requests.
-        */
-       if (mainconfig.proxy_synchronous) goto setup_timeout;
-
-       /*
-        *  The proxy retry delay is zero, meaning don't retry.
-        */
-       if (mainconfig.proxy_retry_delay == 0) goto setup_timeout;
-
-       /*
-        *  There is no proxied request for this packet, so there's
-        *  no proxy retries.
-        */
-       if (!request->proxy) goto setup_timeout;
-
-       /*
-        *  We've already seen the proxy reply, so we don't need
-        *  to send another proxy request.
-        */
-       if (request->proxy_reply) goto setup_timeout;
-
-       /*
-        *  It's not yet time to re-send this proxied request.
-        */
-       if (request->proxy_next_try > info->now) goto setup_timeout;
+#endif
+               return 0;
+       } /* else the request is still allowed to be in the queue */
 
        /*
-        *  If the proxy retry count is zero, then
-        *  we've sent the last try, and have NOT received
-        *  a reply from the end server.  In that case,
-        *  we don't bother trying again, but just mark
-        *  the request as finished, and go to the next one.
+        *      If the request is finished, set the cleanup delay.
         */
-       if (request->proxy_try_count == 0) {
-               rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
-               request_reject(request);
-               realm_disable(request->proxy->dst_ipaddr,request->proxy->dst_port);
-               request->finished = TRUE;
+       if (request->finished) {
+               time_passed = mainconfig.cleanup_delay - time_passed;
                goto setup_timeout;
        }
 
        /*
-        *  We're trying one more time, so count down
-        *  the tries, and set the next try time.
+        *      Accounting request.  Don't re-send them, since the NAS
+        *      will take care of doing that, and we're not a NAS.
+        *      Instead, simply clean them up once we're pretty sure
+        *      that the home server won't be responding.
         */
-       request->proxy_try_count--;
-       request->proxy_next_try = info->now + mainconfig.proxy_retry_delay;
-
-       /*
-        *      Don't restransmit accounting requests.
-        *      Only the originating NAS should do this.
-        */
-       if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
-               goto setup_timeout;
+       if ((request->packet->code == PW_ACCOUNTING_REQUEST) &&
+           request->proxy && !request->proxy_reply &&
+           (request->child_pid == NO_SUCH_CHILD_PID) &&
+           ((info->now - request->proxy_start_time) > (mainconfig.proxy_retry_delay * 2))) {
+               goto cleanup;
        }
 
-       /*
-        *  Assert that we have NOT seen the proxy reply yet.
-        *
-        *  If we HAVE seen it, then we SHOULD NOT be bugging the
-        *  home server!
-        */
-       rad_assert(request->proxy_reply == NULL);
-
-       /*
-        *  Send the proxy packet.
-        */
-       request->proxy_outstanding++;
-       rad_send(request->proxy, NULL, request->proxysecret);
-
-setup_timeout:
-       /*
-        *  Don't do more long-term checks, if we've got to wake
-        *  up now.
-        */
-       if (info->smallest == 0) {
-               return RL_WALK_CONTINUE;
-       }
 
        /*
-        *  The request is finished.  Wake up when it's time to
-        *  clean it up.
+        *      Set reject delay, if appropriate.
         */
-       if (request->finished) {
-               difference = (request->timestamp + mainconfig.cleanup_delay) - info->now;
-
-               /*
-                *  If the request is marked up to be rejected later,
-                *  then wake up later.
-                */
-               if ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) != 0) {
-                       if (difference >= (time_t) mainconfig.reject_delay) {
-                               difference = (time_t) mainconfig.reject_delay;
-                       }
-               }
-
-       } else if (request->proxy && !request->proxy_reply) {
-               /*
-                *  The request is NOT finished, but there is an
-                *  outstanding proxy request, with no matching
-                *  proxy reply.
-                *
-                *  Wake up when it's time to re-send
-                *  the proxy request.
-                *
-                *  But in synchronous proxy, we don't retry but we update
-                *  the next retry time as NAS has not resent the request
-                *  in the given retry window.
-                */
-               if (mainconfig.proxy_synchronous) {
-                       /*
-                        *      If the retry_delay * count has passed,
-                        *      then mark the realm dead.
-                        */
-                       if (info->now > (request->timestamp + (mainconfig.proxy_retry_delay * mainconfig.proxy_retry_count))) {
-                               rad_assert(request->child_pid == NO_SUCH_CHILD_PID);
-                               request_reject(request);
-                               
-                               realm_disable(request->proxy->dst_ipaddr,
-                                             request->proxy->dst_port);
-                               request->finished = TRUE;
-                               goto setup_timeout;
-                       }
-                       request->proxy_next_try = info->now + mainconfig.proxy_retry_delay;
-               }
-               difference = request->proxy_next_try - info->now;
-       } else {
+       if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
+           (mainconfig.reject_delay > 0)) {
+       reject_delay:
+               time_passed = mainconfig.reject_delay - time_passed;
+               
                /*
-                *  The request is NOT finished.
-                *
-                *  Wake up when it's time to kill the errant
-                *  thread/process.
+                *      This catches a corner case, apparently.
                 */
-               difference = (request->timestamp + mainconfig.max_request_time) - info->now;
+               if ((request->reply->code == PW_AUTHENTICATION_REJECT) &&
+                   (time_passed == 0)) goto reject_packet;
+               if (time_passed <= 0) time_passed = 1;
+               goto setup_timeout;
        }
 
        /*
-        *  If the server is CPU starved, then we CAN miss a time
-        *  for servicing requests.  In which case the 'difference'
-        *  value will be negative.  select() doesn't like that,
-        *  so we fix it.
+        *      The request is still alive, wake up when it's
+        *      taken too long.
         */
-       if (difference < 0) {
-               difference = 0;
-       }
+       time_passed = mainconfig.max_request_time - time_passed;
 
-       /*
-        *  Update the 'smallest' time.
-        */
-       if ((info->smallest < 0) ||
-               (difference < info->smallest)) {
-               info->smallest = difference;
+setup_timeout:         
+       if (time_passed < 0) time_passed = 1;
+
+       if (time_passed < info->sleep_time) {
+               info->sleep_time = time_passed;
        }
 
-       return RL_WALK_CONTINUE;
+       return 0;
 }
 
 
@@ -1336,158 +683,21 @@ setup_timeout:
  *  - marking any requests which are finished, and expired
  *  - killing any processes which are NOT finished after a delay
  *  - deleting any marked requests.
+ *
+ *     Returns the number of millisends to sleep, before processing
+ *     something.
  */
-struct timeval *rl_clean_list(time_t now)
+int rl_clean_list(request_list_t *rl, time_t now)
 {
-       /*
-        *  Static variables, so that we don't do all of this work
-        *  more than once per second.
-        *
-        *  Note that we have 'tv' and 'last_tv'.  'last_tv' is
-        *  pointed to by 'last_tv_ptr', and depending on the
-        *  system implementation of select(), it MAY be modified.
-        *
-        *  In that was, we want to use the ORIGINAL value, from
-        *  'tv', and wipe out the (possibly modified) last_tv.
-        */
-       static time_t last_cleaned_list = 0;
-       static struct timeval tv, *last_tv_ptr = NULL;
-       static struct timeval last_tv;
-
        rl_walk_t info;
 
        info.now = now;
-       info.smallest = -1;
+       info.sleep_time = SLEEP_FOREVER;
+       info.rl = rl;
 
-       /*
-        *  If we've already set up the timeout or cleaned the
-        *  request list this second, then don't do it again.  We
-        *  simply return the sleep delay from last time.
-        *
-        *  Note that if we returned NULL last time, there was nothing
-        *  to do.  BUT we've been woken up since then, which can only
-        *  happen if we received a packet.  And if we've received a
-        *  packet, then there's some work to do in the future.
-        *
-        *  FIXME: We can probably use gettimeofday() for finer clock
-        *  resolution, as the current method will cause it to sleep
-        *  too long...
-        */
-       if ((last_tv_ptr != NULL) &&
-           (last_cleaned_list == now) &&
-           (tv.tv_sec != 0)) {
-               int i;
+       lrad_packet_list_walk(rl->pl, &info, refresh_request);
 
-               /*
-                *  If we're NOT walking the entire request list,
-                *  then we want to iteratively check the request
-                *  list.
-                *
-                *  If there is NO previous request, go look for one.
-                */
-               if (!last_request)
-                       last_request = rl_next(last_request);
+       if (info.sleep_time < 0) info.sleep_time = 0;
 
-               /*
-                *  On average, there will be one request per
-                *  'cleanup_delay' requests, which needs to be
-                *  serviced.
-                *
-                *  And only do this servicing, if we have a request
-                *  to service.
-                */
-               if (last_request)
-                       for (i = 0; i < mainconfig.cleanup_delay; i++) {
-                               REQUEST *next;
-
-                               /*
-                                *  This function call MAY delete the
-                                *  request pointed to by 'last_request'.
-                                */
-                               next = rl_next(last_request);
-                               refresh_request(last_request, &info);
-                               last_request = next;
-
-                               /*
-                                *  Nothing to do any more, exit.
-                                */
-                               if (!last_request)
-                                       break;
-                       }
-
-               last_tv = tv;
-               DEBUG2("Waking up in %d seconds...",
-                               (int) last_tv_ptr->tv_sec);
-               return last_tv_ptr;
-       }
-       last_cleaned_list = now;
-       last_request = NULL;
-       DEBUG2("--- Walking the entire request list ---");
-
-       /*
-        *  Hmmm... this is Big Magic.  We make it seem like
-        *  there's an additional second to wait, for a whole
-        *  host of reasons which I can't explain adequately,
-        *  but which cause the code to Just Work Right.
-        */
-       info.now--;
-
-       rl_walk(refresh_request, &info);
-
-       /*
-        *  We haven't found a time at which we need to wake up.
-        *  Return NULL, so that the select() call will sleep forever.
-        */
-       if (info.smallest < 0) {
-               /*
-                *  If we're not proxying, then there really isn't anything
-                *  to do.
-                *
-                *  If we ARE proxying, then we can safely sleep
-                *  forever if we're told to NEVER send proxy retries
-                *  ourselves, until the NAS kicks us again.
-                *
-                *  Otherwise, there are no outstanding requests, then
-                *  we can sleep forever.  This happens when we get
-                *  woken up with a bad packet.  It's discarded, so if
-                *  there are no live requests, we can safely sleep
-                *  forever.
-                */
-               if ((!mainconfig.proxy_requests) ||
-                   mainconfig.proxy_synchronous ||
-                   (rl_num_requests() == 0)) {
-                       DEBUG2("Nothing to do.  Sleeping until we see a request.");
-                       last_tv_ptr = NULL;
-                       return NULL;
-               }
-
-               /*
-                *  We ARE proxying.  In that case, we avoid a race condition
-                *  where a child thread handling a request proxies the
-                *  packet, and sets the retry delay.  In that case, we're
-                *  supposed to wake up in N seconds, but we can't, as
-                *  we're sleeping forever.
-                *
-                *  Instead, we prevent the problem by waking up anyhow
-                *  at the 'proxy_retry_delay' time, even if there's
-                *  nothing to do.  In the worst case, this will cause
-                *  the server to wake up every N seconds, to do a small
-                *  amount of unnecessary work.
-                */
-               info.smallest = mainconfig.proxy_retry_delay;
-       }
-       /*
-        *  Set the time (in seconds) for how long we're
-        *  supposed to sleep.
-        */
-       tv.tv_sec = info.smallest;
-       tv.tv_usec = 0;
-       DEBUG2("Waking up in %d seconds...", (int) info.smallest);
-
-       /*
-        *  Remember how long we should sleep for.
-        */
-       last_tv = tv;
-       last_tv_ptr = &last_tv;
-       return last_tv_ptr;
+       return info.sleep_time;
 }
diff --git a/src/main/request_process.c b/src/main/request_process.c
new file mode 100755 (executable)
index 0000000..a9cdf35
--- /dev/null
@@ -0,0 +1,571 @@
+/*
+ * proxy.c     Proxy stuff.
+ *
+ * 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 2000,2006  The FreeRADIUS server project
+ * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
+ * Copyright 2000  Chris Parker <cparker@starnetusa.com>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#include <sys/socket.h>
+
+#ifdef HAVE_NETINET_IN_H
+#      include <netinet/in.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/modules.h>
+
+
+/*
+ *     Reprocess the request in possibly a child thread, only through
+ *     a subsection of the post-proxy section of radiusd.conf.
+ */
+static int process_post_proxy_fail(REQUEST *request)
+{
+       VALUE_PAIR *vps;
+
+       /*
+        *
+        */
+
+
+       /*
+        *      Hmm... this code is copied from below, which isn't good,
+        *      and is similar to the code in rad_respond.
+        */
+       switch (request->packet->code) {
+               /*
+                *  Accounting requests, etc. get dropped on the floor.
+                */
+       default:
+       case PW_ACCOUNTING_REQUEST:
+       case PW_STATUS_SERVER:
+               break;
+               
+               /*
+                *  Authentication requests get their Proxy-State
+                *  attributes copied over, and an otherwise blank
+                *  reject message sent.
+                */
+       case PW_AUTHENTICATION_REQUEST:
+               request->reply->code = PW_AUTHENTICATION_REJECT;
+               
+               /*
+                *  Need to copy Proxy-State from request->packet->vps
+                */
+               vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
+               if (vps != NULL)
+                       pairadd(&(request->reply->vps), vps);
+               break;
+       }
+       
+       /*
+        *      Send the reply.  The sender takes care of quenching
+        *      packets.
+        */
+       request->listener->send(request->listener, request);
+
+       return 0;               /* ignored for now */
+}
+
+/*
+ *     For debugging
+ */
+static const LRAD_NAME_NUMBER request_fail_reason[] = {
+       { "no threads available to handle the request",
+         REQUEST_FAIL_NO_THREADS },
+
+       { "malformed RADIUS packet",
+         REQUEST_FAIL_DECODE},
+
+       { "pre-proxying failed",
+         REQUEST_FAIL_PROXY},
+
+       { "sending of the proxy packet failed",
+         REQUEST_FAIL_PROXY_SEND},
+
+       { "failure to be told how to respond",
+         REQUEST_FAIL_NO_RESPONSE},
+
+       { "no response from the home server",
+         REQUEST_FAIL_HOME_SERVER},
+       
+       { "no response from the home server after multiple tries",
+         REQUEST_FAIL_HOME_SERVER2},
+       
+       { "no response from the home server for a long period of time",
+         REQUEST_FAIL_HOME_SERVER3},
+
+       { "we were told to reject the request",
+         REQUEST_FAIL_NORMAL_REJECT},
+
+       { NULL, REQUEST_FAIL_UNKNOWN }
+};
+
+
+/*
+ *  Reject a request, by sending a trivial reply packet.
+ */
+ void request_reject(REQUEST *request, request_fail_t reason)
+{
+       VALUE_PAIR *vps;
+
+       /*
+        *      Already rejected.  Don't do anything.
+        */
+       if (request->options & RAD_REQUEST_OPTION_REJECTED) {
+               return;
+       }
+
+       DEBUG2("Server rejecting request %d due to %s.",
+              request->number, lrad_int2str(request_fail_reason,
+                                            reason, "unknown"));
+
+       /*
+        *      Remember that it was rejected.
+        */
+       request->options |= RAD_REQUEST_OPTION_REJECTED;
+
+       switch (reason) {
+       case REQUEST_FAIL_NO_THREADS:
+               DEBUG("WARNING: We recommend that you fix any TIMEOUT errors, or increase the value for \"max_servers\".");
+               break;
+
+       case REQUEST_FAIL_DECODE:
+               DEBUG("WARNING: Someone may be attacking your RADIUS server.");
+               break;
+
+       case REQUEST_FAIL_NO_RESPONSE:
+               DEBUG("WARNING: You did not configure the server to accept, or reject the user.  Double-check Auth-Type.");
+               break;
+
+               /*
+                *      If the home server goes down for some reason,
+                *      we want to be able to know when.  We do this
+                *      by calling a sub-section of the post_proxy section,
+                *      and processing any modules we find there.
+                *
+                *      Note that this subsection CAN edit the response
+                *      to the NAS.
+                */
+       case REQUEST_FAIL_HOME_SERVER: /* Hmm... we may want only one */
+       case REQUEST_FAIL_HOME_SERVER2:
+       case REQUEST_FAIL_HOME_SERVER3:
+               /*
+                *      Conditionally disable the home server we sent
+                *      packets to.
+                */
+               realm_disable(request);
+               
+               /*
+                *      Not supposed to re-process it, 
+                */
+               if (mainconfig.proxy_fail_type) {
+                       DICT_VALUE      *val;
+
+                       val = dict_valbyname(PW_POST_PROXY_TYPE, mainconfig.proxy_fail_type);
+                       if (!val) {
+                               DEBUG("ERROR: No such post-proxy type of \"%s\", cancelling post-proxy-failure call.", mainconfig.proxy_fail_type);
+                               return;
+                       }
+                       
+                       request->options |= RAD_REQUEST_OPTION_REPROCESS;
+                       
+                       thread_pool_addrequest(request, process_post_proxy_fail);
+                       return;
+               }
+               break;
+
+       case REQUEST_FAIL_SERVER_TIMEOUT:
+               radlog(L_ERR, "TIMEOUT for request %d in module %s, component %s",
+                      request->number,
+                      request->module ? request->module : "<server core>",
+                      request->component ? request->component : "<server core>");
+               request->options |= RAD_REQUEST_OPTION_STOP_NOW;
+               break;
+
+       default:                /* no additional messages, or things to do */
+               break;
+       }
+
+       switch (request->packet->code) {
+               /*
+                *  Accounting requests, etc. get dropped on the floor.
+                */
+               default:
+               case PW_ACCOUNTING_REQUEST:
+               case PW_STATUS_SERVER:
+                       break;
+
+               /*
+                *  Authentication requests get their Proxy-State
+                *  attributes copied over, and an otherwise blank
+                *  reject message sent.
+                */
+               case PW_AUTHENTICATION_REQUEST:
+                       request->reply->code = PW_AUTHENTICATION_REJECT;
+
+                       /*
+                        *  Need to copy Proxy-State from request->packet->vps
+                        */
+                       vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
+                       if (vps != NULL)
+                               pairadd(&(request->reply->vps), vps);
+                       break;
+       }
+
+       /*
+        *      Reject the request.  The sender will take care of delaying
+        *      or quenching rejects.
+        */
+       request->listener->send(request->listener, request);
+}
+
+
+/*
+ *  Respond to a request packet.
+ *
+ *  Maybe we reply, maybe we don't.
+ *  Maybe we proxy the request to another server, or else maybe
+ *  we replicate it to another server.
+ */
+int rad_respond(REQUEST *request, RAD_REQUEST_FUNP fun)
+{
+       RADIUS_PACKET *packet, *original;
+       const char *secret;
+       int finished = FALSE;
+
+       rad_assert(request->magic == REQUEST_MAGIC);
+
+       /*
+        *      Don't decode the packet if it's an internal "fake"
+        *      request.  Instead, just skip ahead to processing it.
+        */
+       if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {
+               goto skip_decode;
+       }
+
+       /*
+        *      Re-process the request.
+        */
+       if ((request->options & RAD_REQUEST_OPTION_REPROCESS) != 0) {
+               goto skip_decode;
+       }
+
+       /*
+        *  Put the decoded packet into it's proper place.
+        */
+       if (request->proxy_reply != NULL) {
+               packet = request->proxy_reply;
+               secret = request->proxysecret;
+               original = request->proxy;
+       } else {
+               packet = request->packet;
+               secret = request->secret;
+               original = NULL;
+       }
+
+       /*
+        *  Decode the packet, verifying it's signature,
+        *  and parsing the attributes into structures.
+        *
+        *  Note that we do this CPU-intensive work in
+        *  a child thread, not the master.  This helps to
+        *  spread the load a little bit.
+        *
+        *  Internal requests (ones that never go on the
+        *  wire) have ->data==NULL (data is the wire
+        *  format) and don't need to be "decoded"
+        */
+       if (packet->data) {
+               int decoderesult;
+
+               /*
+                *      Fails verification: silently discard it.
+                */
+               decoderesult = rad_verify(packet, original, secret);
+               if (decoderesult < 0) {
+                       radlog(L_ERR, "%s Dropping packet without response.", librad_errstr);
+                       /* Since accounting packets get this set in
+                        * request_reject but no response is sent...
+                        */
+                       request->options |= RAD_REQUEST_OPTION_REJECTED;
+                       goto finished_request;
+               }
+
+               /*
+                *      Can't decode it.  This usually means we're out
+                *      of memory.
+                */
+               decoderesult = rad_decode(packet, original, secret);
+               if (decoderesult < 0) {
+                       radlog(L_ERR, "%s", librad_errstr);
+                       request_reject(request, REQUEST_FAIL_DECODE);
+                       goto finished_request;
+               }
+       }
+
+       /*
+        *  For proxy replies, remove non-allowed
+        *  attributes from the list of VP's.
+        */
+       if (request->proxy) {
+               int rcode;
+               rcode = proxy_receive(request);
+               switch (rcode) {
+                default:  /* Don't Do Anything */
+                       break;
+                case RLM_MODULE_FAIL:
+                       /* on error just continue with next request */
+                       goto next_request;
+                case RLM_MODULE_HANDLED:
+                       /* if this was a replicated request, mark it as
+                        * finished first, because it was postponed
+                        */
+                       goto finished_request;
+               }
+
+       } else {
+               /*
+                *      This is the initial incoming request which
+                *      we're processing.
+                *
+                *      Some requests do NOT get cached, as they
+                *      CANNOT possibly have duplicates.  Set the
+                *      magic option here.
+                *
+                *      Status-Server messages are easy to generate,
+                *      so we toss them as soon as we see a reply.
+                *
+                *      Accounting-Request packets WITHOUT an
+                *      Acct-Delay-Time attribute are NEVER
+                *      duplicated, as RFC 2866 Section 4.1 says that
+                *      the Acct-Delay-Time MUST be updated when the
+                *      packet is re-sent, which means the packet
+                *      changes, so it MUST have a new identifier and
+                *      Request Authenticator.  */
+               if ((request->packet->code == PW_STATUS_SERVER) ||
+                   ((request->packet->code == PW_ACCOUNTING_REQUEST) &&
+                    (pairfind(request->packet->vps, PW_ACCT_DELAY_TIME) == NULL))) {
+                       request->options |= RAD_REQUEST_OPTION_DONT_CACHE;
+               }
+       }
+
+ skip_decode:
+       /*
+        *      We should have a User-Name attribute now.
+        */
+       if (request->username == NULL) {
+               request->username = pairfind(request->packet->vps,
+                               PW_USER_NAME);
+       }
+
+       (*fun)(request);
+
+       /*
+        *      If the request took too long to process, don't do
+        *      anything else.
+        */
+       if (request->options & RAD_REQUEST_OPTION_STOP_NOW) {
+               finished = TRUE;
+               goto postpone_request;
+       }
+
+       /*
+        *      If the request took too long to process, don't do
+        *      anything else.
+        */
+       if (request->options & RAD_REQUEST_OPTION_REJECTED) {
+               finished = TRUE;
+               goto postpone_request;
+       }
+
+       /*
+        *      Status-Server requests NEVER get proxied.
+        */
+       if (mainconfig.proxy_requests) {
+               if ((request->packet->code != PW_STATUS_SERVER) &&
+                   ((request->options & RAD_REQUEST_OPTION_PROXIED) == 0)) {
+                       int rcode;
+
+                       /*
+                        *      Try to proxy this request.
+                        */
+                       rcode = proxy_send(request);
+
+                       switch (rcode) {
+                       default:
+                               break;
+
+                       /*
+                        *  There was an error trying to proxy the request.
+                        *  Drop it on the floor.
+                        */
+                       case RLM_MODULE_FAIL:
+                               DEBUG2("Error trying to proxy request %d: Rejecting it", request->number);
+                               request_reject(request, REQUEST_FAIL_PROXY);
+                               goto finished_request;
+                               break;
+
+                       /*
+                        *  The pre-proxy module has decided to reject
+                        *  the request.  Do so.
+                        */
+                       case RLM_MODULE_REJECT:
+                               DEBUG2("Request %d rejected in proxy_send.", request->number);
+                               request_reject(request, REQUEST_FAIL_PROXY_SEND);
+                               goto finished_request;
+                               break;
+
+                       /*
+                        *  If the proxy code has handled the request,
+                        *  then postpone more processing, until we get
+                        *  the reply packet from the home server.
+                        */
+                       case RLM_MODULE_HANDLED:
+                               goto postpone_request;
+                               break;
+                       }
+
+                       /*
+                        *  Else rcode==RLM_MODULE_NOOP
+                        *  and the proxy code didn't do anything, so
+                        *  we continue handling the request here.
+                        */
+               }
+       } else if ((request->packet->code == PW_AUTHENTICATION_REQUEST) &&
+                  (request->reply->code == 0)) {
+               /*
+                *  We're not configured to reply to the packet,
+                *  and we're not proxying, so the DEFAULT behaviour
+                *  is to REJECT the user.
+                */
+               request_reject(request, REQUEST_FAIL_NO_RESPONSE);
+               goto finished_request;
+       }
+
+       /*
+        *  If we have a reply to send, copy the Proxy-State
+        *  attributes from the request to the tail of the reply,
+        *  and send the packet.
+        */
+       rad_assert(request->magic == REQUEST_MAGIC);
+       if (request->reply->code != 0) {
+               VALUE_PAIR *vp = NULL;
+
+               /*
+                *      Need to copy Proxy-State from request->packet->vps
+                */
+               vp = paircopy2(request->packet->vps, PW_PROXY_STATE);
+               if (vp) pairadd(&(request->reply->vps), vp);
+       }
+
+       /*
+        *      ALWAYS call the sender to send the reply.  The sender
+        *      will take care of doing the appropriate work to
+        *      suppress packets which aren't supposed to be sent over
+        *      the wire, or to be delayed.
+        */
+       request->listener->send(request->listener, request);
+
+       /*
+        *  We're done processing the request, set the
+        *  request to be finished, clean up as necessary,
+        *  and forget about the request.
+        */
+
+finished_request:
+
+       /*
+        *      Don't decode the packet if it's an internal "fake"
+        *      request.  Instead, just skip ahead to processing it.
+        */
+       if ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) != 0) {
+               goto skip_free;
+       }
+
+       /*
+        *  We're done handling the request.  Free up the linked
+        *  lists of value pairs.  This might take a long time,
+        *  so it's more efficient to do it in a child thread,
+        *  instead of in the main handler when it eventually
+        *  gets around to deleting the request.
+        *
+        *  Also, no one should be using these items after the
+        *  request is finished, and the reply is sent.  Cleaning
+        *  them up here ensures that they're not being used again.
+        *
+        *  Hmm... cleaning them up in the child thread also seems
+        *  to make the server run more efficiently!
+        *
+        *  If we've delayed the REJECT, then do NOT clean up the request,
+        *  as we haven't created the REJECT message yet.
+        */
+       if ((request->options & RAD_REQUEST_OPTION_DELAYED_REJECT) == 0) {
+               if (request->packet) {
+                       pairfree(&request->packet->vps);
+                       request->username = NULL;
+                       request->password = NULL;
+               }
+
+               /*
+                *  If we've sent a reply to the NAS, then this request is
+                *  pretty much finished, and we have no more need for any
+                *  of the value-pair's in it, including the proxy stuff.
+                */
+               if (request->reply->code != 0) {
+                       pairfree(&request->reply->vps);
+               }
+       }
+
+       pairfree(&request->config_items);
+       if (request->proxy) {
+               pairfree(&request->proxy->vps);
+       }
+       if (request->proxy_reply) {
+               pairfree(&request->proxy_reply->vps);
+       }
+
+ skip_free:
+       DEBUG2("Finished request %d", request->number);
+       finished = TRUE;
+
+       /*
+        *  Go to the next request, without marking
+        *  the current one as finished.
+        *
+        *  Hmm... this may not be the brightest thing to do.
+        */
+next_request:
+       DEBUG2("Going to the next request");
+
+postpone_request:
+       return finished;
+}
index 98d15c1..54dee87 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include       "autoconf.h"
+#include       <freeradius-devel/autoconf.h>
 
 #include       <stdio.h>
 #include       <stdlib.h>
 #include       <netinet/in.h>
 #endif
 
-#include       "radiusd.h"
-#include       "rad_assert.h"
-#include       "modules.h"
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/rad_assert.h>
 
-/* End a session by faking a Stop packet to all accounting modules */
+/*
+ *     End a session by faking a Stop packet to all accounting modules.
+ */
 int session_zap(REQUEST *request, uint32_t nasaddr, unsigned int port,
                const char *user,
-               const char *sessionid, uint32_t cliaddr, char proto)
+               const char *sessionid, uint32_t cliaddr, char proto,
+               int session_time)
 {
        REQUEST *stopreq;
        VALUE_PAIR *vp, *userpair;
@@ -74,7 +78,7 @@ int session_zap(REQUEST *request, uint32_t nasaddr, unsigned int port,
                pairfree(&(stopreq->packet->vps)); \
                return 0; \
        } \
-       strNcpy((char *)vp->strvalue, v, sizeof vp->strvalue); \
+       strlcpy((char *)vp->vp_strvalue, v, sizeof vp->vp_strvalue); \
        vp->length = strlen(v); \
        pairadd(&(stopreq->packet->vps), vp); \
        } while(0)
@@ -97,7 +101,7 @@ int session_zap(REQUEST *request, uint32_t nasaddr, unsigned int port,
        }
        if(cliaddr != 0)
                IPPAIR(PW_FRAMED_IP_ADDRESS, cliaddr);
-       INTPAIR(PW_ACCT_SESSION_TIME, 0);
+       INTPAIR(PW_ACCT_SESSION_TIME, session_time);
        INTPAIR(PW_ACCT_INPUT_OCTETS, 0);
        INTPAIR(PW_ACCT_OUTPUT_OCTETS, 0);
        INTPAIR(PW_ACCT_INPUT_PACKETS, 0);
@@ -119,6 +123,11 @@ int session_zap(REQUEST *request, uint32_t nasaddr, unsigned int port,
 
 /*
  *     Check one terminal server to see if a user is logged in.
+ *
+ *     Return values:
+ *             0 The user is off-line.
+ *             1 The user is logged in.
+ *             2 Some error occured.
  */
 int rad_check_ts(uint32_t nasaddr, unsigned int portnum, const char *user,
                 const char *session_id)
@@ -129,11 +138,15 @@ int rad_check_ts(uint32_t nasaddr, unsigned int portnum, const char *user,
        char    address[16];
        char    port[11];
        RADCLIENT *cl;
+       lrad_ipaddr_t ipaddr;
+
+       ipaddr.af = AF_INET;
+       ipaddr.ipaddr.ip4addr.s_addr = nasaddr;
 
        /*
         *      Find NAS type.
         */
-       cl = client_find(nasaddr);
+       cl = client_find_old(&ipaddr);
        if (!cl) {
                /*
                 *  Unknown NAS, so trusting radutmp.
@@ -146,7 +159,7 @@ int rad_check_ts(uint32_t nasaddr, unsigned int portnum, const char *user,
        /*
         *  No nastype, or nas type 'other', trust radutmp.
         */
-       if ((cl->nastype[0] == '\0') ||
+       if (!cl->nastype || (cl->nastype[0] == '\0') ||
            (strcmp(cl->nastype, "other") == 0)) {
                DEBUG2("checkrad: No NAS type, or type \"other\" not checking");
                return 1;
@@ -157,7 +170,7 @@ int rad_check_ts(uint32_t nasaddr, unsigned int portnum, const char *user,
         */
        if ((pid = rad_fork()) < 0) { /* do wait for the fork'd result */
                radlog(L_ERR, "Accounting: Failed in fork(): Cannot run checkrad\n");
-               return -1;
+               return 2;
        }
 
        if (pid > 0) {
@@ -182,8 +195,6 @@ int rad_check_ts(uint32_t nasaddr, unsigned int portnum, const char *user,
                return WEXITSTATUS(status);
        }
 
-       closefrom(3);
-
        /*
         *  We don't close fd's 0, 1, and 2.  If we're in debugging mode,
         *  then they should go to stdout (etc), along with the other
@@ -192,6 +203,7 @@ int rad_check_ts(uint32_t nasaddr, unsigned int portnum, const char *user,
         *  If we're not in debugging mode, then the code in radiusd.c
         *  takes care of connecting fd's 0, 1, and 2 to /dev/null.
         */
+       closefrom(3);
 
        ip_ntoa(address, nasaddr);
        snprintf(port, 11, "%u", portnum);
@@ -212,5 +224,5 @@ int rad_check_ts(uint32_t nasaddr, unsigned int portnum, const char *user,
         *      Exit - 2 means "some error occured".
         */
        exit(2);
-       return -1;
+       return 2;
 }
index 78c4c1f..600c804 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 1999  Jochen Friedrich <jochen@scram.de>
  * Copyright 1999  Kunihiro Ishiguro <kunihiro@zebra.org>
  */
 
-static const char rcsid[] =
-"$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
+#include <freeradius-devel/autoconf.h>
 
 #ifdef WITH_SNMP
 
-#include "libradius.h"
-
 #include <sys/socket.h>
 #include <sys/file.h>
 
@@ -45,9 +43,9 @@ static const char rcsid[] =
 #include <fcntl.h>
 #include <ctype.h>
 
-#include "radiusd.h"
-#include "radius_snmp.h"
-#include "smux.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/radius_snmp.h>
+#include <freeradius-devel/smux.h>
 
 #define min(A,B) ((A) < (B) ? (A) : (B))
 
@@ -1093,7 +1091,7 @@ smux_init (oid defoid[], size_t defoid_len)
 
 /* Register subtree to smux master tree. */
 void
-smux_register_mib(const char *descr, struct variable *var, size_t width,
+smux_register_mib(UNUSED const char *descr, struct variable *var, size_t width,
                int num, oid name[], size_t namelen)
 {
        struct subtree *tree, *tt;
index 1fbfc9b..fe686a9 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
 
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#ifdef HAVE_PTHREAD_H
+#include <freeradius-devel/autoconf.h>
 
 #include <stdlib.h>
 #include <string.h>
 #include <sys/wait.h>
 #endif
 
-#include "radiusd.h"
-#include "rad_assert.h"
-#include "conffile.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/modules.h>
 
-static const char rcsid[] =
-"$Id$";
+#ifdef HAVE_PTHREAD_H
 
 #ifdef HAVE_OPENSSL_CRYPTO_H
 #include <openssl/crypto.h>
@@ -74,6 +74,15 @@ static const char rcsid[] =
 #define THREAD_CANCELLED       (2)
 #define THREAD_EXITED          (3)
 
+#define NUM_FIFOS               (2)
+
+/*
+ *     Ordered this way because we prefer proxy, then ongoing, then
+ *     start.
+ */
+#define FIFO_START   (1)
+#define FIFO_PROXY   (0)
+
 /*
  *  A data structure which contains the information about
  *  the current thread.
@@ -104,7 +113,6 @@ typedef struct request_queue_t {
        RAD_REQUEST_FUNP  fun;
 } request_queue_t;
 
-
 typedef struct thread_fork_t {
        pid_t           pid;
        int             status;
@@ -122,6 +130,7 @@ typedef struct THREAD_POOL {
        THREAD_HANDLE *tail;
 
        int total_threads;
+       int active_threads;     /* protected by queue_mutex */
        int max_thread_num;
        int start_threads;
        int max_threads;
@@ -131,11 +140,8 @@ typedef struct THREAD_POOL {
        unsigned long request_count;
        time_t time_last_spawned;
        int cleanup_delay;
+       int spawn_flag;
 
-       /*
-        *      If threaded, we have to pay more attention to
-        *      child PID's when we fork...
-        */
        pthread_mutex_t wait_mutex;
        lrad_hash_table_t *waiters;
 
@@ -148,13 +154,12 @@ typedef struct THREAD_POOL {
        /*
         *      To ensure only one thread at a time touches the queue.
         */
-       pthread_mutex_t mutex;
+       pthread_mutex_t queue_mutex;
 
-       int             active_threads;
-       int             queue_head; /* first filled entry */
-       int             queue_tail; /* first empty entry */
-       int             queue_size;
-       request_queue_t *queue;
+       int             max_queue_size;
+       int             num_queued;
+       int             fifo_state;
+       lrad_fifo_t     *fifo[NUM_FIFOS];
 } THREAD_POOL;
 
 static THREAD_POOL thread_pool;
@@ -171,6 +176,7 @@ static const CONF_PARSER thread_config[] = {
        { "max_spare_servers",       PW_TYPE_INTEGER, 0, &thread_pool.max_spare_threads,       "10" },
        { "max_requests_per_server", PW_TYPE_INTEGER, 0, &thread_pool.max_requests_per_thread, "0" },
        { "cleanup_delay",           PW_TYPE_INTEGER, 0, &thread_pool.cleanup_delay,           "5" },
+       { "max_queue_size",          PW_TYPE_INTEGER, 0, &thread_pool.max_queue_size,           "65536" },
        { NULL, -1, 0, NULL, NULL }
 };
 
@@ -189,14 +195,18 @@ static const CONF_PARSER thread_config[] = {
  *     to add them at some point.
  */
 
-static  pthread_mutex_t *ssl_mutexes = NULL;
+static pthread_mutex_t *ssl_mutexes = NULL;
 
-
-static unsigned long ssl_id_function (void) {
-       return (unsigned long)pthread_self();
+static unsigned long ssl_id_function(void)
+{
+       return (unsigned long) pthread_self();
 }
 
-static void ssl_locking_function (int mode, int n, const char *file, int line) {
+static void ssl_locking_function(int mode, int n, const char *file, int line)
+{
+       file = file;            /* -Wunused */
+       line = line;            /* -Wunused */
+
        if (mode & CRYPTO_LOCK) {
                pthread_mutex_lock(&(ssl_mutexes[n]));
        } else {
@@ -204,16 +214,17 @@ static void ssl_locking_function (int mode, int n, const char *file, int line) {
        }
 }
 
-static int setup_ssl_mutexes (void) {
+static int setup_ssl_mutexes(void)
+{
        int i;
 
-       ssl_mutexes = (pthread_mutex_t *)rad_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
-       if(!ssl_mutexes) {
+       ssl_mutexes = rad_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
+       if (!ssl_mutexes) {
                radlog(L_ERR, "Error allocating memory for SSL mutexes!");
                return 0;
        }
 
-       for(i = 0; i < CRYPTO_num_locks(); i++) {
+       for (i = 0; i < CRYPTO_num_locks(); i++) {
                pthread_mutex_init(&(ssl_mutexes[i]), NULL);
        }
 
@@ -222,7 +233,6 @@ static int setup_ssl_mutexes (void) {
 
        return 1;
 }
-
 #endif
 
 
@@ -248,6 +258,7 @@ static void reap_children(void)
        int status;
        thread_fork_t mytf, *tf;
 
+
        pthread_mutex_lock(&thread_pool.wait_mutex);
 
        do {
@@ -265,7 +276,6 @@ static void reap_children(void)
        pthread_mutex_unlock(&thread_pool.wait_mutex);
 }
 
-
 /*
  *     Add a request to the list of waiting requests.
  *     This function gets called ONLY from the main handler thread...
@@ -274,83 +284,56 @@ static void reap_children(void)
  */
 static int request_enqueue(REQUEST *request, RAD_REQUEST_FUNP fun)
 {
-       int num_entries;
+       int fifo = FIFO_START;
+       request_queue_t *entry;
 
-       pthread_mutex_lock(&thread_pool.mutex);
+       pthread_mutex_lock(&thread_pool.queue_mutex);
 
        thread_pool.request_count++;
 
        /*
-        *      If the queue is empty, re-set the indices to zero,
-        *      for no particular reason...
+        *      FIXME: Handle proxy replies separately?
         */
-       if ((thread_pool.queue_head == thread_pool.queue_tail) &&
-           (thread_pool.queue_head != 0)) {
-               thread_pool.queue_head = thread_pool.queue_tail = 0;
+       if (thread_pool.num_queued >= thread_pool.max_queue_size) {
+               pthread_mutex_unlock(&thread_pool.queue_mutex);
+               
+               /*
+                *      Mark the request as done.
+                */
+               radlog(L_ERR|L_CONS, "!!! ERROR !!! The server is blocked: discarding new request %d", request->number);
+               request->finished = TRUE;
+               return 0;
        }
 
        /*
-        *      If the queue is full, die.
+        *      Requests get handled in priority.  First, we handle
+        *      replies from a home server, to finish ongoing requests.
+        *
+        *      Then, we handle requests with State, to finish
+        *      multi-packet transactions.
         *
-        *      The math is to take into account the fact that it's a
-        *      circular queue.
+        *      Finally, we handle new requests.
         */
-       num_entries = ((thread_pool.queue_tail + thread_pool.queue_size) -
-                      thread_pool.queue_head) % thread_pool.queue_size;
-       if (num_entries == (thread_pool.queue_size - 1)) {
-               int i;
-               request_queue_t *new_queue;
-
-               /*
-                *      If the queue becomes larger than 65536,
-                *      there's a serious problem.
-                */
-               if (thread_pool.queue_size >= 65536) {
-                       pthread_mutex_unlock(&thread_pool.mutex);
+       if (request->proxy_reply) {
+               fifo = FIFO_PROXY;
+       } else {
+               fifo = FIFO_START;
+       }
 
-                       /*
-                        *      Mark the request as done.
-                        */
-                       radlog(L_ERR|L_CONS, "!!! ERROR !!! The server is blocked: discarding new request %d", request->number);
-                       request->finished = TRUE;
-                       return 0;
-               }
+       entry = rad_malloc(sizeof(*entry));
+       entry->request = request;
+       entry->fun = fun;
 
-               /*
-                *      Malloc a new queue, doubled in size, copy the
-                *      data from the current queue over to it, zero
-                *      out the second half of the queue, free the old
-                *      one, and replace thread_pool.queue with the
-                *      new one.
-                */
-               new_queue = rad_malloc(sizeof(*new_queue) * thread_pool.queue_size * 2);
-               /*
-                *      Copy the queue element by element
-                */
-               for (i = 0; i < thread_pool.queue_size; i++) {
-                       new_queue[i] = thread_pool.queue[(i + thread_pool.queue_head) % thread_pool.queue_size];
-               }
-               memset(new_queue + thread_pool.queue_size,
-                      0, sizeof(*new_queue) * thread_pool.queue_size);
-
-               free(thread_pool.queue);
-               thread_pool.queue = new_queue;
-               thread_pool.queue_tail = ((thread_pool.queue_tail + thread_pool.queue_size) - thread_pool.queue_head) % thread_pool.queue_size;
-               thread_pool.queue_head = 0;
-               thread_pool.queue_size *= 2;
+       if (!lrad_fifo_push(thread_pool.fifo[fifo], entry)) {
+               pthread_mutex_unlock(&thread_pool.queue_mutex);
+               radlog(L_ERR, "!!! ERROR !!! Failed inserting request %d into the queue", request->number);
+               request->finished = TRUE;
+               return 0;
        }
 
-       /*
-        *      Add the data to the queue tail, increment the tail,
-        *      and signal the semaphore that there's another request
-        *      in the queue.
-        */
-       thread_pool.queue[thread_pool.queue_tail].request = request;
-       thread_pool.queue[thread_pool.queue_tail].fun = fun;
-       thread_pool.queue_tail++;
-       thread_pool.queue_tail &= (thread_pool.queue_size - 1);
+       thread_pool.num_queued++;
 
-       pthread_mutex_unlock(&thread_pool.mutex);
+       pthread_mutex_unlock(&thread_pool.queue_mutex);
 
        /*
         *      There's one more request in the queue.
@@ -361,7 +344,6 @@ static int request_enqueue(REQUEST *request, RAD_REQUEST_FUNP fun)
         *      the mutex, it will be unlocked, and there won't be
         *      contention.
         */
-
        sem_post(&thread_pool.semaphore);
 
        return 1;
@@ -370,124 +352,68 @@ static int request_enqueue(REQUEST *request, RAD_REQUEST_FUNP fun)
 /*
  *     Remove a request from the queue.
  */
-static void request_dequeue(REQUEST **request, RAD_REQUEST_FUNP *fun)
+static int request_dequeue(REQUEST **request, RAD_REQUEST_FUNP *fun)
 {
+       int fifo_state;
+       request_queue_t *entry;
+
        reap_children();
 
-       pthread_mutex_lock(&thread_pool.mutex);
+       pthread_mutex_lock(&thread_pool.queue_mutex);
 
-       /*
-        *      Head & tail are the same.  There's nothing in
-        *      the queue.
-        */
-       if (thread_pool.queue_head == thread_pool.queue_tail) {
-               pthread_mutex_unlock(&thread_pool.mutex);
+       fifo_state = thread_pool.fifo_state;
+
+ retry:
+       do {
+               /*
+                *      Pop an entry from the current queue, and go to
+                *      the next queue.
+                */
+               entry = lrad_fifo_pop(thread_pool.fifo[fifo_state]);
+               fifo_state++;
+               if (fifo_state >= NUM_FIFOS) fifo_state = 0;
+       } while ((fifo_state != thread_pool.fifo_state) && !entry);
+
+       if (!entry) {
+               pthread_mutex_unlock(&thread_pool.queue_mutex);
                *request = NULL;
                *fun = NULL;
-               return;
+               return 0;
        }
 
-       *request = thread_pool.queue[thread_pool.queue_head].request;
-       *fun = thread_pool.queue[thread_pool.queue_head].fun;
+       rad_assert(thread_pool.num_queued > 0);
+       thread_pool.num_queued--;
+       *request = entry->request;
+       *fun = entry->fun;
+       free(entry);
 
        rad_assert(*request != NULL);
        rad_assert((*request)->magic == REQUEST_MAGIC);
        rad_assert(*fun != NULL);
 
-       thread_pool.queue_head++;
-       thread_pool.queue_head &= (thread_pool.queue_size - 1);
-
        /*
-        *      FIXME: Check the request timestamp.  If it's more than
-        *      "clean_delay" seconds old, then discard the request,
-        *      log an error, and try to de-queue another request.
+        *      If the request has sat in the queue for too long,
+        *      kill it.
         *
         *      The main clean-up code won't delete the request from
-        *      the request list, because it's not marked "finished"
+        *      the request list, until it's marked "finished"
         */
+       if ((*request)->options & RAD_REQUEST_OPTION_STOP_NOW) {
+               (*request)->finished = 1;
+               goto retry;
+       }
 
        /*
         *      The thread is currently processing a request.
         */
        thread_pool.active_threads++;
+       thread_pool.fifo_state = fifo_state;
 
-       pthread_mutex_unlock(&thread_pool.mutex);
-
-       /*
-        *      If the request is currently being processed, then that
-        *      MAY be OK, if it's a proxy reply.  In that case,
-        *      sending the packet may result in a reply being
-        *      received before that thread clears the child_pid.
-        *
-        *      In that case, we busy-wait for the request to be free.
-        *
-        *      We COULD push it onto the queue and try to grab
-        *      another request, but what if this is the only request?
-        *      What if there are multiple such packets with race
-        *      conditions?  We don't want to thrash the queue...
-        *
-        *      This busy-wait is less than optimal, but it's simple,
-        *      fail-safe, and it works.
-        */
-       if ((*request)->child_pid != NO_SUCH_CHILD_PID) {
-               int count, ok;
-               struct timeval tv;
-#ifdef HAVE_PTHREAD_SIGMASK
-               sigset_t set, old_set;
-
-               /*
-                *      Block a large number of signals which could
-                *      cause the select to return EINTR
-                */
-               sigemptyset(&set);
-               sigaddset(&set, SIGPIPE);
-               sigaddset(&set, SIGCONT);
-               sigaddset(&set, SIGSTOP);
-               sigaddset(&set, SIGCHLD);
-               pthread_sigmask(SIG_BLOCK, &set, &old_set);
-#endif
-
-               rad_assert((*request)->proxy_reply != NULL);
-
-               ok = FALSE;
-
-               /*
-                *      Sleep for 100 milliseconds.  If the other thread
-                *      doesn't get serviced in this time, to clear
-                *      the "child_pid" entry, then the server is too
-                *      busy, so we die.
-                */
-               for (count = 0; count < 10; count++) {
-                       tv.tv_sec = 0;
-                       tv.tv_usec = 10000; /* sleep for 10 milliseconds */
-
-                       /*
-                        *      Portable sleep that's thread-safe.
-                        *
-                        *      Don't worry about interrupts, as they're
-                        *      blocked above.
-                        */
-                       select(0, NULL, NULL, NULL, &tv);
-                       if ((*request)->child_pid == NO_SUCH_CHILD_PID) {
-                               ok = TRUE;
-                               break;
-                       }
-               }
-
-#ifdef HAVE_PTHREAD_SIGMASK
-               /*
-                *      Restore the original thread signal mask.
-                */
-               pthread_sigmask(SIG_SETMASK, &old_set, NULL);
-#endif
+       pthread_mutex_unlock(&thread_pool.queue_mutex);
 
-               if (!ok) {
-                       radlog(L_ERR, "FATAL!  Server is too busy to process requests");
-                       exit(1);
-               }
-       }
+       rad_assert((*request)->child_pid == NO_SUCH_CHILD_PID);
 
-       return;
+       return 1;
 }
 
 
@@ -525,6 +451,8 @@ static void *request_handler_thread(void *arg)
         *      Loop forever, until told to exit.
         */
        do {
+               int finished;
+
                /*
                 *      Wait to be signalled.
                 */
@@ -554,8 +482,7 @@ static void *request_handler_thread(void *arg)
                 *      It may be empty, in which case we fail
                 *      gracefully.
                 */
-               request_dequeue(&self->request, &fun);
-               if (!self->request) continue;
+               if (!request_dequeue(&self->request, &fun)) continue;
 
                self->request->child_pid = self->pthread_id;
                self->request_count++;
@@ -567,16 +494,37 @@ static void *request_handler_thread(void *arg)
                /*
                 *      Respond, and reset request->child_pid
                 */
-               rad_respond(self->request, fun);
-               self->request = NULL;
+               finished = rad_respond(self->request, fun);
 
                /*
                 *      Update the active threads.
                 */
-               pthread_mutex_lock(&thread_pool.mutex);
+               pthread_mutex_lock(&thread_pool.queue_mutex);
+
+               /*
+                *      We haven't replied to the client, but we HAVE
+                *      sent a proxied packet, and we have NOT
+                *      received a proxy response.  In that case, send
+                *      the proxied packet now.  Doing this in the mutex
+                *      avoids race conditions.
+                *
+                *      FIXME: this work should really depend on a
+                *      "state", and "next handler", rather than
+                *      horrid hacks like thise.
+                */
+               if (!self->request->reply->data &&
+                   self->request->proxy && self->request->proxy->data
+                   && !self->request->proxy_reply)
+                       self->request->proxy_listener->send(self->request->proxy_listener,
+                                                           self->request);
+
+               self->request->child_pid = NO_SUCH_CHILD_PID;
+               self->request->finished = finished;
+               self->request = NULL;
+               
                rad_assert(thread_pool.active_threads > 0);
                thread_pool.active_threads--;
-               pthread_mutex_unlock(&thread_pool.mutex);
+               pthread_mutex_unlock(&thread_pool.queue_mutex);
        } while (self->status != THREAD_CANCELLED);
 
        DEBUG2("Thread %d exiting...", self->thread_num);
@@ -599,9 +547,11 @@ static void *request_handler_thread(void *arg)
 }
 
 /*
- *     Take a THREAD_HANDLE, and delete it from the thread pool.
+ *     Take a THREAD_HANDLE, delete it from the thread pool and
+ *     free its resources.
  *
- *     This function is called ONLY from the main server thread.
+ *     This function is called ONLY from the main server thread,
+ *     ONLY after the thread has exited.
  */
 static void delete_thread(THREAD_HANDLE *handle)
 {
@@ -610,6 +560,8 @@ static void delete_thread(THREAD_HANDLE *handle)
 
        rad_assert(handle->request == NULL);
 
+       DEBUG2("Deleting thread %d", handle->thread_num);
+
        prev = handle->prev;
        next = handle->next;
        rad_assert(thread_pool.total_threads > 0);
@@ -632,16 +584,8 @@ static void delete_thread(THREAD_HANDLE *handle)
                next->prev = prev;
        }
 
-       DEBUG2("Deleting thread %d", handle->thread_num);
-
        /*
-        *      This thread has exited.  Delete any additional
-        *      resources associated with it.
-        */
-
-       /*
-        *      Free the memory, now that we're sure the thread
-        *      exited.
+        *      Free the handle, now that it's no longer referencable.
         */
        free(handle);
 }
@@ -743,15 +687,13 @@ static THREAD_HANDLE *spawn_thread(time_t now)
  */
 int total_active_threads(void)
 {
-        int rcode = 0;
-       THREAD_HANDLE *handle;
-
-       for (handle = thread_pool.head; handle != NULL; handle = handle->next){
-               if (handle->request != NULL) {
-                       rcode ++;
-               }
-       }
-       return (rcode);
+       /*
+        *      We don't acquire the mutex, so this is just an estimate.
+        *      We can't return with the lock held, so there's no point
+        *      in getting the guaranteed correct value; by the time
+        *      the caller sees it, it can be wrong again.
+        */
+       return thread_pool.active_threads;
 }
 
 
@@ -776,7 +718,7 @@ static int pid_cmp(const void *one, const void *two)
  *
  *     FIXME: What to do on a SIGHUP???
  */
-int thread_pool_init(void)
+int thread_pool_init(int spawn_flag)
 {
        int             i, rcode;
        CONF_SECTION    *pool_cf;
@@ -786,6 +728,12 @@ int thread_pool_init(void)
        now = time(NULL);
 
        /*
+        *      We're not spawning new threads, don't do
+        *      anything.
+        */
+       if (!spawn_flag) return 0;
+
+       /*
         *      After a SIGHUP, we don't over-write the previous values.
         */
        if (!pool_initialized) {
@@ -798,13 +746,14 @@ int thread_pool_init(void)
                thread_pool.total_threads = 0;
                thread_pool.max_thread_num = 1;
                thread_pool.cleanup_delay = 5;
+               thread_pool.spawn_flag = spawn_flag;
 
                if ((pthread_mutex_init(&thread_pool.wait_mutex,NULL) != 0)) {
-                       radlog(L_ERR, "FATAL: Failed to initialize mutex: %s",
+                       radlog(L_ERR, "FATAL: Failed to initialize wait mutex: %s",
                               strerror(errno));
                        exit(1);
                }               
-
+               
                /*
                 *      Create the hash table of child PID's
                 */
@@ -819,6 +768,9 @@ int thread_pool_init(void)
 
        pool_cf = cf_section_find("thread");
        if (pool_cf != NULL) {
+               /*
+                *      FIXME: Check for errors?
+                */
                cf_section_parse(pool_cf, NULL, thread_config);
        }
 
@@ -833,6 +785,7 @@ int thread_pool_init(void)
        /*
         *      Initialize the queue of requests.
         */
+       memset(&thread_pool.semaphore, 0, sizeof(thread_pool.semaphore));
        rcode = sem_init(&thread_pool.semaphore, 0, SEMAPHORE_LOCKED);
        if (rcode != 0) {
                radlog(L_ERR|L_CONS, "FATAL: Failed to initialize semaphore: %s",
@@ -840,31 +793,30 @@ int thread_pool_init(void)
                exit(1);
        }
 
-       rcode = pthread_mutex_init(&thread_pool.mutex,NULL);
+       rcode = pthread_mutex_init(&thread_pool.queue_mutex,NULL);
        if (rcode != 0) {
-               radlog(L_ERR, "FATAL: Failed to initialize mutex: %s",
+               radlog(L_ERR, "FATAL: Failed to initialize queue mutex: %s",
                       strerror(errno));
                exit(1);
        }
 
        /*
-        *      Queue head & tail are set to zero by the memset,
-        *      above.
-        *
-        *      Allocate an initial queue, always as a power of 2.
+        *      Allocate multiple fifos.
         */
-       thread_pool.queue_size = 256;
-       thread_pool.queue = rad_malloc(sizeof(*thread_pool.queue) *
-                                      thread_pool.queue_size);
-       memset(thread_pool.queue, 0, (sizeof(*thread_pool.queue) *
-                                     thread_pool.queue_size));
+       for (i = 0; i < NUM_FIFOS; i++) {
+               thread_pool.fifo[i] = lrad_fifo_create(65536, NULL);
+               if (!thread_pool.fifo[i]) {
+                       radlog(L_ERR, "FATAL: Failed to set up request fifo");
+                       exit(1);
+               }
+       }
 
 #ifdef HAVE_OPENSSL_CRYPTO_H
        /*
         *      If we're linking with OpenSSL too, then we need
         *      to set up the mutexes and enable the thread callbacks.
         */
-       if(!setup_ssl_mutexes()) {
+       if (!setup_ssl_mutexes()) {
                radlog(L_ERR, "FATAL: Failed to set up SSL mutexes");
                exit(1);
        }
@@ -897,13 +849,34 @@ int thread_pool_init(void)
 int thread_pool_addrequest(REQUEST *request, RAD_REQUEST_FUNP fun)
 {
        /*
+        *      We've been told not to spawn threads, so don't.
+        */
+       if (!thread_pool.spawn_flag) {
+               request->finished = rad_respond(request, fun);
+               
+               /*
+                *      Requests that care about child process exit
+                *      codes have already either called
+                *      rad_waitpid(), or they've given up.
+                */
+               wait(NULL);
+               return 1;
+       }
+
+       /*
         *      Add the new request to the queue.
         */
        if (!request_enqueue(request, fun)) return 0;
 
        /*
         *      If the thread pool is busy handling requests, then
-        *      try to spawn another one.
+        *      try to spawn another one.  We don't acquire the mutex
+        *      before reading active_threads, so our thread count is
+        *      just an estimate.  It's fine to go ahead and spawn an
+        *      extra thread in that case.
+        *      NOTE: the log message may be in error since active_threads
+        *      is an estimate, but it's only in error about the thread
+        *      count, not about the fact that we can't create a new one.
         */
        if (thread_pool.active_threads == thread_pool.total_threads) {
                if (spawn_thread(request->timestamp) == NULL) {
@@ -948,7 +921,7 @@ int thread_pool_clean(time_t now)
 
        /*
         *      We don't need a mutex lock here, as we're reading
-        *      the location, and not modifying it.  We want a close
+        *      active_threads, and not modifying it.  We want a close
         *      approximation of the number of active threads, and this
         *      is good enough.
         */
@@ -1123,6 +1096,7 @@ pid_t rad_fork(void)
        return child_pid;
 }
 
+
 /*
  *     Wait 10 seconds at most for a child to exit, then give up.
  */
@@ -1154,7 +1128,7 @@ pid_t rad_waitpid(pid_t pid, int *status)
                        pthread_mutex_unlock(&thread_pool.wait_mutex);
                        return pid;
                }
-               usleep(100000);
+               usleep(100000); /* sleep for 1/10 of a second */
        }
        
        /*
@@ -1167,4 +1141,22 @@ pid_t rad_waitpid(pid_t pid, int *status)
        return 0;
 }
 
-#endif
+#else /* HAVE_PTHREAD_H */
+/*
+ *     "thread" code when we don't have threads.
+ */
+int thread_pool_init(int spawn_flag)
+{
+       return 0;
+}
+
+/*
+ *     call "radrespond".
+ */
+int thread_pool_addrequest(REQUEST *request, RAD_REQUEST_FUNP fun)
+{
+       rad_respond(request, fun);
+       return 1;
+}
+
+#endif /* HAVE_PTHREAD_H */
index a881ae9..8bc3362 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -42,8 +42,8 @@ static const char rcsid[] = "$Id$";
 #include <netinet/in.h>
 #endif
 
-#include "radiusd.h"
-#include "rad_assert.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
 
 /*
  *     The signal() function in Solaris 2.5.1 sets SA_NODEFER in
@@ -172,6 +172,28 @@ void *request_data_get(REQUEST *request,
 
 
 /*
+ *     Get opaque data from a request without removing it.
+ */
+void *request_data_reference(REQUEST *request,
+                      void *unique_ptr, int unique_int)
+{
+       request_data_t **last;
+
+       for (last = &(request->data); *last != NULL; last = &((*last)->next)) {
+               if (((*last)->unique_ptr == unique_ptr) &&
+                   ((*last)->unique_int == unique_int)) {
+                       request_data_t *this = *last;
+                       void *ptr = this->opaque;
+
+                       return ptr;
+               }
+       }
+
+       return NULL;            /* wasn't found, too bad... */
+}
+
+
+/*
  *     Free a REQUEST struct.
  */
 void request_free(REQUEST **request_ptr)
@@ -315,11 +337,6 @@ void *rad_malloc(size_t size)
        return ptr;
 }
 
-void xfree(const char *ptr)
-{
-       free((char *)ptr);
-}
-
 /*
  *     Logs an error message and aborts the program
  *
@@ -385,8 +402,9 @@ REQUEST *request_alloc_fake(REQUEST *oldreq)
    *   Fill in the fake request packet.
    */
   request->packet->sockfd = -1;
-  request->packet->src_ipaddr = htonl(INADDR_LOOPBACK);
-  request->packet->dst_ipaddr = htonl(INADDR_LOOPBACK);
+  request->packet->src_ipaddr.af = AF_INET;
+  request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK);
+  request->packet->dst_ipaddr = request->packet->src_ipaddr;
   request->packet->src_port = request->number >> 8;
   request->packet->dst_port = 0;
 
@@ -413,133 +431,91 @@ REQUEST *request_alloc_fake(REQUEST *oldreq)
 
 
 /*
- *  Perform any RFC specified cleaning of outgoing replies
+ *     Copy a quoted string.
  */
-void rfc_clean(RADIUS_PACKET *packet)
+int rad_copy_string(char *to, const char *from)
 {
-       VALUE_PAIR *vps = NULL;
+       int length = 0;
+       char quote = *from;
 
-       switch (packet->code) {
-               /*
-                *      In the default case, we just move all of the
-                *      attributes over.
-                */
-       default:
-               vps = packet->vps;
-               packet->vps = NULL;
-               break;
+       do {
+               if (*from == '\\') {
+                       *(to++) = *(from++);
+                       length++;
+               }
+               *(to++) = *(from++);
+               length++;
+       } while (*from && (*from != quote));
 
-               /*
-                *      Accounting responses can only contain
-                *      Proxy-State and VSA's.  Note that we do NOT
-                *      move the Proxy-State attributes over, as the
-                *      Proxy-State attributes in this packet are NOT
-                *      the right ones to use.  The reply function
-                *      takes care of copying those attributes from
-                *      the original request, which ARE the right ones
-                *      to use.
-                */
-       case PW_ACCOUNTING_RESPONSE:
-               pairmove2(&vps, &(packet->vps), PW_VENDOR_SPECIFIC);
-               break;
+       if (*from != quote) return -1; /* not properly quoted */
 
-               /*
-                *      Authentication REJECT's can have only
-                *      EAP-Message, Message-Authenticator
-                *      Reply-Message and Proxy-State.
-                *
-                *      We delete everything other than these.
-                *      Proxy-State is added below, just before the
-                *      reply is sent.
-                */
-       case PW_AUTHENTICATION_REJECT:
-               pairmove2(&vps, &(packet->vps), PW_EAP_MESSAGE);
-               pairmove2(&vps, &(packet->vps), PW_MESSAGE_AUTHENTICATOR);
-               pairmove2(&vps, &(packet->vps), PW_REPLY_MESSAGE);
-               break;
-       }
+       *(to++) = quote;
+       length++;
+       *to = '\0';
 
-       /*
-        *      Move the newly cleaned attributes over.
-        */
-       pairfree(&packet->vps);
-       packet->vps = vps;
-
-       /*
-        *      FIXME: Perform other, more generic sanity checks.
-        */
+       return length;
 }
 
 
 /*
- *  Reject a request, by sending a trivial reply packet.
+ *     Copy a %{} string.
  */
- void request_reject(REQUEST *request)
+int rad_copy_variable(char *to, const char *from)
 {
-       VALUE_PAIR *vps;
-
-       /*
-        *      Already rejected.  Don't do anything.
-        */
-       if (request->options & RAD_REQUEST_OPTION_REJECTED) {
-               return;
-       }
-
-       DEBUG2("Server rejecting request %d.", request->number);
-       switch (request->packet->code) {
-               /*
-                *  Accounting requests, etc. get dropped on the floor.
-                */
-               default:
-               case PW_ACCOUNTING_REQUEST:
-               case PW_STATUS_SERVER:
+       int length = 0;
+       int sublen;
+
+       *(to++) = *(from++);
+       length++;
+
+       while (*from) {
+               switch (*from) {
+               case '"':
+               case '\'':
+                       sublen = rad_copy_string(to, from);
+                       if (sublen < 0) return sublen;
+                       from += sublen;
+                       to += sublen;
                        break;
 
-               /*
-                *  Authentication requests get their Proxy-State
-                *  attributes copied over, and an otherwise blank
-                *  reject message sent.
-                */
-               case PW_AUTHENTICATION_REQUEST:
-                       request->reply->code = PW_AUTHENTICATION_REJECT;
+               case '}':       /* end of variable expansion */
+                       *(to++) = *(from++);
+                       *to = '\0';
+                       length++;
+                       return length; /* proper end of variable */
 
-                       /*
-                        *  Perform RFC limitations on outgoing replies.
-                        */
-                       rfc_clean(request->reply);
+               case '\\':
+                       *(to++) = *(from++);
+                       *(to++) = *(from++);
+                       length += 2;
+                       break;
 
-                       /*
-                        *  Need to copy Proxy-State from request->packet->vps
-                        */
-                       vps = paircopy2(request->packet->vps, PW_PROXY_STATE);
-                       if (vps != NULL)
-                               pairadd(&(request->reply->vps), vps);
+               case '%':       /* start of variable expansion */
+                       if (from[1] == '{') {
+                               *(to++) = *(from++);
+                               length++;
+                               
+                               sublen = rad_copy_variable(to, from);
+                               if (sublen < 0) return sublen;
+                               from += sublen;
+                               to += sublen;
+                               length += sublen;
+                       } /* else FIXME: catch %%{ ?*/
+
+                       /* FALL-THROUGH */
                        break;
-       }
 
-       /*
-        *      If a reply exists, send it.
-        *
-        *      But DON'T send a RADIUS packet for a fake request.
-        */
-       if ((request->reply->code != 0) &&
-           ((request->options & RAD_REQUEST_OPTION_FAKE_REQUEST) == 0)) {
-               /*
-                *      If we're not delaying authentication rejects,
-                *      then send the response immediately.  Otherwise,
-                *      mark the request as delayed, and do NOT send a
-                *      response.
-                */
-               if (mainconfig.reject_delay == 0) {
-                       rad_send(request->reply, request->packet,
-                                    request->secret);
-               } else {
-                       request->options |= RAD_REQUEST_OPTION_DELAYED_REJECT;
+               default:
+                       *(to++) = *(from++);
+                       length++;
+                       break;
                }
-       }
+       } /* loop over the input string */
 
        /*
-        *      Remember that it was rejected.
+        *      We ended the string before a trailing '}'
         */
-       request->options |= RAD_REQUEST_OPTION_REJECTED;
+
+       return -1;
 }
+
index a7aab2e..7c5bae1 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -52,7 +52,7 @@ static const char rcsid[] = "$Id$";
 #endif
 #endif
 
-#include "radiusd.h"
+#include <freeradius-devel/radiusd.h>
 
 struct cmp {
        int attribute;
@@ -67,21 +67,13 @@ static struct cmp *cmp;
 /*
  *     Compare 2 attributes. May call the attribute compare function.
  */
-static int paircompare(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,
+static int compare_pair(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,
                       VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
 {
        int ret = -2;
        struct cmp *c;
 
        /*
-        *      Sanity check.
-        */
-#if 0
-       if (request->attribute != check->attribute)
-               return -2;
-#endif
-
-       /*
         *      Check for =* and !* and return appropriately
         */
        if( check->operator == T_OP_CMP_TRUE )
@@ -91,12 +83,16 @@ static int paircompare(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,
 
        /*
         *      See if there is a special compare function.
+        *
+        *      FIXME: use new RB-Tree code.
         */
        for (c = cmp; c; c = c->next)
                if (c->attribute == check->attribute)
                        return (c->compare)(c->instance, req, request, check,
                                check_pairs, reply_pairs);
 
+       if (!request) return -1; /* doesn't exist, don't compare it */
+
        switch(check->type) {
 #ifdef ASCEND_BINARY
                /*
@@ -110,20 +106,40 @@ static int paircompare(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,
                                ret = 1; /* NOT equal */
                                break;
                        }
-                       ret = memcmp(request->strvalue, check->strvalue,
+                       ret = memcmp(request->vp_strvalue, check->vp_strvalue,
                                        request->length);
                        break;
                case PW_TYPE_STRING:
-                       ret = strcmp((char *)request->strvalue,
-                                       (char *)check->strvalue);
+                       if (check->flags.caseless) {
+                               ret = strcasecmp((char *)request->vp_strvalue,
+                                                (char *)check->vp_strvalue);
+                       } else {
+                               ret = strcmp((char *)request->vp_strvalue,
+                                            (char *)check->vp_strvalue);
+                       }
                        break;
                case PW_TYPE_INTEGER:
                case PW_TYPE_DATE:
                        ret = request->lvalue - check->lvalue;
                        break;
                case PW_TYPE_IPADDR:
-                       ret = ntohl(request->lvalue) - ntohl(check->lvalue);
+                       ret = ntohl(request->vp_ipaddr) - ntohl(check->vp_ipaddr);
+                       break;
+               case PW_TYPE_IPV6ADDR:
+                       ret = memcmp(&request->vp_ipv6addr, &check->vp_ipv6addr,
+                                    sizeof(request->vp_ipv6addr));
+                       break;
+                       
+               case PW_TYPE_IPV6PREFIX:
+                       ret = memcmp(&request->vp_ipv6prefix, &check->vp_ipv6prefix,
+                                    sizeof(request->vp_ipv6prefix));
                        break;
+               
+               case PW_TYPE_IFID:
+                       ret = memcmp(&request->vp_ifid, &check->vp_ifid,
+                                    sizeof(request->vp_ifid));
+                       break;
+
                default:
                        break;
        }
@@ -211,7 +227,7 @@ void paircompare_unregister(int attr, RAD_COMPARE_FUNC fun)
  *
  *     Return 0 on match.
  */
-int paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **reply)
+int paircompare(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **reply)
 {
        VALUE_PAIR *check_item;
        VALUE_PAIR *auth_item;
@@ -256,8 +272,8 @@ int paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **r
                         *
                         *      This hack makes CHAP-Password work..
                         */
-                       case PW_PASSWORD:
-                               if (pairfind(request, PW_PASSWORD) == NULL) {
+                       case PW_USER_PASSWORD:
+                               if (pairfind(request, PW_USER_PASSWORD) == NULL) {
                                        continue;
                                }
                                break;
@@ -303,11 +319,11 @@ int paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **r
                 */
                if (check_item->flags.do_xlat) {
                        int rcode;
-                       char buffer[sizeof(check_item->strvalue)];
+                       char buffer[sizeof(check_item->vp_strvalue)];
 
                        check_item->flags.do_xlat = 0;
                        rcode = radius_xlat(buffer, sizeof(buffer),
-                                           check_item->strvalue,
+                                           check_item->vp_strvalue,
                                            req, NULL);
 
                        /*
@@ -319,12 +335,12 @@ int paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **r
                /*
                 *      OK it is present now compare them.
                 */
-               compare = paircompare(req, auth_item, check_item, check, reply);
+               compare = compare_pair(req, auth_item, check_item, check, reply);
 
                switch (check_item->operator) {
                        case T_OP_EQ:
                        default:
-                               radlog(L_ERR,  "Invalid operator for item %s: "
+                               radlog(L_INFO,  "Invalid operator for item %s: "
                                                "reverting to '=='", check_item->name);
                                /*FALLTHRU*/
                        case T_OP_CMP_TRUE:    /* compare always == 0 */
@@ -357,15 +373,22 @@ int paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **r
                        case T_OP_REG_EQ:
                        {
                                int i;
-                               regmatch_t rxmatch[9];
+                               regmatch_t rxmatch[REQUEST_MAX_REGEX + 1];
+
+                               if ((auth_item->type == PW_TYPE_IPADDR) &&
+                                   (auth_item->vp_strvalue[0] == '\0')) {
+                                 inet_ntop(AF_INET, &(auth_item->lvalue),
+                                           auth_item->vp_strvalue,
+                                           sizeof(auth_item->vp_strvalue));
+                               }
 
                                /*
                                 *      Include substring matches.
                                 */
-                               regcomp(&reg, (char *)check_item->strvalue,
+                               regcomp(&reg, (char *)check_item->vp_strvalue,
                                        REG_EXTENDED);
                                compare = regexec(&reg,
-                                                 (char *)auth_item->strvalue,
+                                                 (char *)auth_item->vp_strvalue,
                                                  REQUEST_MAX_REGEX + 1,
                                                  rxmatch, 0);
                                regfree(&reg);
@@ -375,7 +398,7 @@ int paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **r
                                 */
                                for (i = 0; i <= REQUEST_MAX_REGEX; i++) {
                                        char *p;
-                                       char buffer[sizeof(check_item->strvalue)];
+                                       char buffer[sizeof(check_item->vp_strvalue)];
 
                                        /*
                                         *      Didn't match: delete old
@@ -401,7 +424,7 @@ int paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **r
                                         *      Copy substring into buffer.
                                         */
                                        memcpy(buffer,
-                                              auth_item->strvalue + rxmatch[i].rm_so,
+                                              auth_item->vp_strvalue + rxmatch[i].rm_so,
                                               rxmatch[i].rm_eo - rxmatch[i].rm_so);
                                        buffer[rxmatch[i].rm_eo - rxmatch[i].rm_so] = '\0';
 
@@ -424,8 +447,15 @@ int paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **r
                                break;
 
                        case T_OP_REG_NE:
-                               regcomp(&reg, (char *)check_item->strvalue, REG_EXTENDED|REG_NOSUB);
-                               compare = regexec(&reg, (char *)auth_item->strvalue,
+                               if ((auth_item->type == PW_TYPE_IPADDR) &&
+                                   (auth_item->vp_strvalue[0] == '\0')) {
+                                 inet_ntop(AF_INET, &(auth_item->lvalue),
+                                           auth_item->vp_strvalue,
+                                           sizeof(auth_item->vp_strvalue));
+                               }
+
+                               regcomp(&reg, (char *)check_item->vp_strvalue, REG_EXTENDED|REG_NOSUB);
+                               compare = regexec(&reg, (char *)auth_item->vp_strvalue,
                                                0, NULL, 0);
                                regfree(&reg);
                                if (compare == 0) result = -1;
@@ -450,303 +480,14 @@ int paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **r
 }
 
 /*
- *      Compare two attributes simply.  Calls paircompare.
+ *      Compare two attributes simply.  Calls compare_pair.
  */
 
 int simplepaircmp(REQUEST *req, VALUE_PAIR *first, VALUE_PAIR *second)
 {
-       return paircompare( req, first, second, NULL, NULL );
-}
-
-
-/*
- *     Compare a Connect-Info and a Connect-Rate
- */
-static int connectcmp(void *instance,
-                     REQUEST *req UNUSED,
-                     VALUE_PAIR *request,
-                     VALUE_PAIR *check,
-                     VALUE_PAIR *check_pairs,
-                     VALUE_PAIR **reply_pairs)
-{
-       int rate;
-
-       instance = instance;
-       check_pairs = check_pairs; /* shut the compiler up */
-       reply_pairs = reply_pairs;
-
-       rate = atoi((char *)request->strvalue);
-       return rate - check->lvalue;
-}
-
-
-/*
- *     Compare a portno with a range.
- */
-static int portcmp(void *instance,
-                  REQUEST *req UNUSED, VALUE_PAIR *request, VALUE_PAIR *check,
-       VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
-{
-       char buf[MAX_STRING_LEN];
-       char *s, *p;
-       uint32_t lo, hi;
-       uint32_t port = request->lvalue;
-
-       instance = instance;
-       check_pairs = check_pairs; /* shut the compiler up */
-       reply_pairs = reply_pairs;
-
-       if ((strchr((char *)check->strvalue, ',') == NULL) &&
-                       (strchr((char *)check->strvalue, '-') == NULL)) {
-               return (request->lvalue - check->lvalue);
-       }
-
-       /* Same size */
-       strcpy(buf, (char *)check->strvalue);
-       s = strtok(buf, ",");
-
-       while (s != NULL) {
-               if ((p = strchr(s, '-')) != NULL)
-                       p++;
-               else
-                       p = s;
-               lo = strtoul(s, NULL, 10);
-               hi = strtoul(p, NULL, 10);
-               if (lo <= port && port <= hi) {
-                       return 0;
-               }
-               s = strtok(NULL, ",");
-       }
-
-       return -1;
-}
-
-/*
- *     Compare prefix/suffix.
- *
- *     If they compare:
- *     - if PW_STRIP_USER_NAME is present in check_pairs,
- *       strip the username of prefix/suffix.
- *     - if PW_STRIP_USER_NAME is not present in check_pairs,
- *       add a PW_STRIPPED_USER_NAME to the request.
- */
-static int presufcmp(void *instance,
-                    REQUEST *req UNUSED,
-                    VALUE_PAIR *request, VALUE_PAIR *check,
-       VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
-{
-       VALUE_PAIR *vp;
-       char *name = (char *)request->strvalue;
-       char rest[MAX_STRING_LEN];
-       int len, namelen;
-       int ret = -1;
-
-       instance = instance;
-       reply_pairs = reply_pairs; /* shut the compiler up */
-
-#if 0 /* DEBUG */
-       printf("Comparing %s and %s, check->attr is %d\n",
-               name, check->strvalue, check->attribute);
-#endif
-
-       len = strlen((char *)check->strvalue);
-       switch (check->attribute) {
-               case PW_PREFIX:
-                       ret = strncmp(name, (char *)check->strvalue, len);
-                       if (ret == 0 && rest)
-                               strcpy(rest, name + len);
-                       break;
-               case PW_SUFFIX:
-                       namelen = strlen(name);
-                       if (namelen < len)
-                               break;
-                       ret = strcmp(name + namelen - len,
-                                       (char *)check->strvalue);
-                       if (ret == 0 && rest) {
-                               strNcpy(rest, name, namelen - len + 1);
-                       }
-                       break;
-       }
-       if (ret != 0)
-               return ret;
-
-       if ((vp = pairfind(check_pairs, PW_STRIP_USER_NAME)) != NULL) {
-               if (vp->lvalue == 1) {
-                       /*
-                        *      I don't think we want to update the User-Name
-                        *      attribute in place... - atd
-                        */
-                       strcpy((char *)request->strvalue, rest);
-                       request->length = strlen(rest);
-               } else {
-                       return ret;
-               }
-       } else {
-               if ((vp = pairfind(check_pairs, PW_STRIPPED_USER_NAME)) != NULL){
-                       strcpy((char *)vp->strvalue, rest);
-                       vp->length = strlen(rest);
-               } else if ((vp = paircreate(PW_STRIPPED_USER_NAME,
-                               PW_TYPE_STRING)) != NULL) {
-                       strcpy((char *)vp->strvalue, rest);
-                       vp->length = strlen(rest);
-                       pairadd(&request, vp);
-               } /* else no memory! Die, die!: FIXME!! */
-       }
-
-       return ret;
-}
-
-
-/*
- *     Compare the current time to a range.
- */
-static int timecmp(void *instance,
-                  REQUEST *req UNUSED,
-                  VALUE_PAIR *request, VALUE_PAIR *check,
-       VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
-{
-       instance = instance;
-       request = request;      /* shut the compiler up */
-       check_pairs = check_pairs;
-       reply_pairs = reply_pairs;
-
-       if (timestr_match((char *)check->strvalue,
-                         req ? req->timestamp : time(NULL)) >= 0) {
-               return 0;
-       }
-       return -1;
+       return compare_pair( req, first, second, NULL, NULL );
 }
 
-/*
- *     Matches if there is NO SUCH ATTRIBUTE as the one named
- *     in check->strvalue.  If there IS such an attribute, it
- *     doesn't match.
- *
- *     This is ugly, and definitely non-optimal.  We should be
- *     doing the lookup only ONCE, and storing the result
- *     in check->lvalue...
- */
-static int attrcmp(void *instance,
-                  REQUEST *req UNUSED,
-                  VALUE_PAIR *request, VALUE_PAIR *check,
-                  VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
-{
-       VALUE_PAIR *pair;
-       DICT_ATTR  *dict;
-       int attr;
-
-       instance = instance;
-       check_pairs = check_pairs; /* shut the compiler up */
-       reply_pairs = reply_pairs;
-
-       if (check->lvalue == 0) {
-               dict = dict_attrbyname((char *)check->strvalue);
-               if (dict == NULL) {
-                       return -1;
-               }
-               attr = dict->attr;
-       } else {
-               attr = check->lvalue;
-       }
-
-       /*
-        *      If there's no such attribute, then return MATCH,
-        *      else FAILURE.
-        */
-       pair = pairfind(request, attr);
-       if (pair == NULL) {
-               return 0;
-       }
-
-       return -1;
-}
-
-/*
- *     Compare the expiration date.
- */
-static int expirecmp(void *instance, REQUEST *req UNUSED,
-                    VALUE_PAIR *request, VALUE_PAIR *check,
-                    VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
-{
-       time_t now;
-
-       instance = instance;
-       request = request;      /* shut the compiler up */
-       check_pairs = check_pairs;
-       reply_pairs = reply_pairs;
-
-       /*
-        *  FIXME!  This should be request->timestamp!
-        */
-       now = time(NULL);
-
-       if (now <= (signed)check->lvalue) {
-               return 0;
-       }
-
-       return +1;
-}
-
-/*
- *     Compare the request packet type.
- */
-static int packetcmp(void *instance UNUSED, REQUEST *req,
-                    VALUE_PAIR *request UNUSED,
-                    VALUE_PAIR *check,
-                    VALUE_PAIR *check_pairs UNUSED,
-                    VALUE_PAIR **reply_pairs UNUSED)
-{
-       if (req->packet->code == check->lvalue) {
-               return 0;
-       }
-
-       return 1;
-}
-
-/*
- *     Compare the response packet type.
- */
-static int responsecmp(void *instance UNUSED,
-                      REQUEST *req,
-                      VALUE_PAIR *request UNUSED,
-                      VALUE_PAIR *check,
-                      VALUE_PAIR *check_pairs UNUSED,
-                      VALUE_PAIR **reply_pairs UNUSED)
-{
-       if (req->reply->code == check->lvalue) {
-               return 0;
-       }
-
-       return 1;
-}
-
-/*
- *     Register server-builtin special attributes.
- */
-void pair_builtincompare_init(void)
-{
-       paircompare_register(PW_NAS_PORT, -1, portcmp, NULL);
-       paircompare_register(PW_PREFIX, PW_USER_NAME, presufcmp, NULL);
-       paircompare_register(PW_SUFFIX, PW_USER_NAME, presufcmp, NULL);
-       paircompare_register(PW_CONNECT_RATE, PW_CONNECT_INFO, connectcmp, NULL);
-       paircompare_register(PW_CURRENT_TIME, 0, timecmp, NULL);
-       paircompare_register(PW_NO_SUCH_ATTRIBUTE, 0, attrcmp, NULL);
-       paircompare_register(PW_EXPIRATION, 0, expirecmp, NULL);
-       paircompare_register(PW_PACKET_TYPE, 0, packetcmp, NULL);
-       paircompare_register(PW_RESPONSE_PACKET_TYPE, 0, responsecmp, NULL);
-}
-
-void paircompare_builtin_free(void)
-{
-       struct cmp *c, *next;
-       
-       for (c = cmp; c != NULL; c = next) {
-               next = c->next;
-               free(c);
-       }
-}
-
-
 
 /*
  *     Move pairs, replacing/over-writing them, and doing xlat.
@@ -788,11 +529,11 @@ void pairxlatmove(REQUEST *req, VALUE_PAIR **to, VALUE_PAIR **from)
                 */
                if (i->flags.do_xlat) {
                        int rcode;
-                       char buffer[sizeof(i->strvalue)];
+                       char buffer[sizeof(i->vp_strvalue)];
 
                        i->flags.do_xlat = 0;
                        rcode = radius_xlat(buffer, sizeof(buffer),
-                                           i->strvalue,
+                                           i->vp_strvalue,
                                            req, NULL);
 
                        /*
@@ -810,9 +551,9 @@ void pairxlatmove(REQUEST *req, VALUE_PAIR **to, VALUE_PAIR **from)
                         */
                case T_OP_SUB:          /* -= */
                        if (found) {
-                               if (!i->strvalue[0] ||
-                                   (strcmp((char *)found->strvalue,
-                                           (char *)i->strvalue) == 0)){
+                               if (!i->vp_strvalue[0] ||
+                                   (strcmp((char *)found->vp_strvalue,
+                                           (char *)i->vp_strvalue) == 0)){
                                        pairdelete(to, found->attribute);
 
                                        /*
index fde2f37..dffbe91 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Alan DeKok <aland@ox.org>
  * Copyright 2000  Chris Parker <cparker@starnetusa.com>
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
-#include "radiusd.h"
+#include <freeradius-devel/radiusd.h>
 
 /*
  *     Display the revision number for this program
@@ -49,7 +50,7 @@ void NEVER_RETURNS version(void)
 #endif
        printf("\n");
 #endif
-       printf("Copyright (C) 2000-2006 The FreeRADIUS server project.\n");
+       printf("Copyright (C) 2000-2003 The FreeRADIUS server project.\n");
        printf("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n");
        printf("PARTICULAR PURPOSE.\n");
        printf("You may redistribute copies of FreeRADIUS under the terms of the\n");
index 7a11c41..25e76e9 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
 
-static const char rcsid[] =
-"$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include       "autoconf.h"
-#include       "libradius.h"
+#include       <freeradius-devel/autoconf.h>
 
 #include       <stdio.h>
 #include       <stdlib.h>
 #include       <string.h>
 #include       <ctype.h>
 
-#include       "radiusd.h"
+#include       <freeradius-devel/radiusd.h>
 
-#include       "rad_assert.h"
+#include       <freeradius-devel/rad_assert.h>
 
 typedef struct xlat_t {
        char            module[MAX_STRING_LEN];
@@ -50,17 +49,17 @@ static rbtree_t *xlat_root = NULL;
 /*
  *     Define all xlat's in the structure.
  */
-static const char *internal_xlat[] = {"check",
-                                     "request",
-                                     "reply",
-                                     "proxy-request",
-                                     "proxy-reply",
-                                     NULL};
+static const char * const internal_xlat[] = {"check",
+                                            "request",
+                                            "reply",
+                                            "proxy-request",
+                                            "proxy-reply",
+                                            NULL};
 
 #if REQUEST_MAX_REGEX > 8
 #error Please fix the following line
 #endif
-static int xlat_inst[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };        /* up to 8 for regex */
+static const int xlat_inst[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };  /* up to 8 for regex */
 
 
 /*
@@ -72,25 +71,28 @@ static int valuepair2str(char * out,int outlen,VALUE_PAIR * pair,
        char buffer[MAX_STRING_LEN * 4];
 
        if (pair != NULL) {
-               vp_prints_value(buffer, sizeof(buffer), pair, 0);
+               vp_prints_value(buffer, sizeof(buffer), pair, -1);
                return func(out, outlen, buffer);
        }
 
        switch (type) {
        case PW_TYPE_STRING :
-               strNcpy(out,"_",outlen);
+               strlcpy(out,"_",outlen);
                break;
        case PW_TYPE_INTEGER :
-               strNcpy(out,"0",outlen);
+               strlcpy(out,"0",outlen);
                break;
        case PW_TYPE_IPADDR :
-               strNcpy(out,"?.?.?.?",outlen);
+               strlcpy(out,"?.?.?.?",outlen);
+               break;
+       case PW_TYPE_IPV6ADDR :
+               strlcpy(out,":?:",outlen);
                break;
        case PW_TYPE_DATE :
-               strNcpy(out,"0",outlen);
+               strlcpy(out,"0",outlen);
                break;
        default :
-               strNcpy(out,"unknown_type",outlen);
+               strlcpy(out,"unknown_type",outlen);
        }
        return strlen(out);
 }
@@ -149,14 +151,55 @@ static int xlat_packet(void *instance, REQUEST *request,
                if (!p) return 0;
                if (strlen(fmt) > sizeof(buffer)) return 0;
 
-               strNcpy(buffer, fmt, p - fmt + 1);
+               strlcpy(buffer, fmt, p - fmt + 1);
+
+               da = dict_attrbyname(buffer);
+               if (!da) return 0;
+
+               /*
+                *      %{Attribute-Name[#]} returns the count of
+                *      attributes of that name in the list.
+                */
+               if ((p[1] == '#') && (p[2] == ']')) {
+                       count = 0;
+
+                       for (vp = pairfind(vps, da->attr);
+                            vp != NULL;
+                            vp = pairfind(vp->next, da->attr)) {
+                               count++;
+                       }
+                       snprintf(out, outlen, "%d", count);
+                       return strlen(out);
+               }
 
+               /*
+                *      %{Attribute-Name[*]} returns ALL of the
+                *      the attributes, separated by a newline.
+                */             
+               if ((p[1] == '*') && (p[2] == ']')) {
+                       int total = 0;
+
+                       for (vp = pairfind(vps, da->attr);
+                            vp != NULL;
+                            vp = pairfind(vp->next, da->attr)) {
+                               count = valuepair2str(out, outlen - 1, vp, da->type, func);
+                               rad_assert(count <= outlen);
+                               total += count + 1;
+                               outlen -= (count + 1);
+                               out += count;
+                               
+                               *(out++) = '\n';
+
+                               if (outlen == 0) break;
+                       }
+
+                       return total;
+               }
+               
                count = atoi(p + 1);
 
                /*
-                *      Check the format of the index before looking
-                *      the attribute up in the dictionary, because
-                *      it's a cheap check.
+                *      Skip the numbers.
                 */
                p += 1 + strspn(p + 1, "0123456789");
                if (*p != ']') {
@@ -165,10 +208,6 @@ static int xlat_packet(void *instance, REQUEST *request,
                        return 0;
                }
 
-               da = dict_attrbyname(buffer);
-               if (!da) return 0;
-
-
                /*
                 *      Find the N'th value.
                 */
@@ -193,9 +232,14 @@ static int xlat_packet(void *instance, REQUEST *request,
                 *      Some "magic" handlers, which are never in VP's, but
                 *      which are in the packet.
                 *
-                *      FIXME: Add SRC/DST IP address!
+                *      FIXME: We should really do this in a more
+                *      intelligent way...
                 */
                if (packet) {
+                       VALUE_PAIR localvp;
+
+                       localvp.vp_strvalue[0] = 0;
+
                        switch (da->attr) {
                        case PW_PACKET_TYPE:
                        {
@@ -210,10 +254,87 @@ static int xlat_packet(void *instance, REQUEST *request,
                                return strlen(out);
                        }
                        break;
+
+                       case PW_CLIENT_IP_ADDRESS: /* the same as below */
+                       case PW_PACKET_SRC_IP_ADDRESS:
+                               if (packet->src_ipaddr.af != AF_INET) {
+                                       return 0;
+                               }
+                               localvp.attribute = da->attr;
+                               localvp.lvalue = packet->src_ipaddr.ipaddr.ip4addr.s_addr;
+                               break;
+                       
+                       case PW_PACKET_DST_IP_ADDRESS:
+                               if (packet->dst_ipaddr.af != AF_INET) {
+                                       return 0;
+                               }
+                               localvp.attribute = da->attr;
+                               localvp.lvalue = packet->dst_ipaddr.ipaddr.ip4addr.s_addr;
+                               break;
+                       
+                       case PW_PACKET_SRC_PORT:
+                               localvp.attribute = da->attr;
+                               localvp.lvalue = packet->src_port;
+                               break;
+                       
+                       case PW_PACKET_DST_PORT:
+                               localvp.attribute = da->attr;
+                               localvp.lvalue = packet->dst_port;
+                               break;
+
+                       case PW_PACKET_AUTHENTICATION_VECTOR:
+                               localvp.attribute = da->attr;
+                               memcpy(localvp.vp_strvalue, packet->vector,
+                                      sizeof(packet->vector));
+                               localvp.length = sizeof(packet->vector);
+                               break;
+
+                               /*
+                                *      Authorization, accounting, etc.
+                                */
+                       case PW_REQUEST_PROCESSING_STAGE:
+                               if (request->component) {
+                                       strlcpy(out, request->component, outlen);
+                               } else {
+                                       strlcpy(out, "server_core", outlen);
+                               }
+                               return strlen(out);
+                       
+                       case PW_PACKET_SRC_IPV6_ADDRESS:
+                               if (packet->src_ipaddr.af != AF_INET6) {
+                                       return 0;
+                               }
+                               localvp.attribute = da->attr;
+                               memcpy(localvp.vp_strvalue,
+                                      &packet->src_ipaddr.ipaddr.ip6addr,
+                                      sizeof(packet->src_ipaddr.ipaddr.ip6addr));
+                               break;
+                       
+                       case PW_PACKET_DST_IPV6_ADDRESS:
+                               if (packet->dst_ipaddr.af != AF_INET6) {
+                                       return 0;
+                               }
+                               localvp.attribute = da->attr;
+                               memcpy(localvp.vp_strvalue,
+                                      &packet->dst_ipaddr.ipaddr.ip6addr,
+                                      sizeof(packet->dst_ipaddr.ipaddr.ip6addr));
+                               break;
+                       
+                       case PW_SERVER_IDENTITY:
+                               if (!request->listener || !request->listener->identity) return 0;
+
+                               snprintf(out, outlen, "%s", request->listener->identity);
+                               return strlen(out);
+                               break;
                        
                        default:
+                               return 0; /* not found */
                                break;
                        }
+
+                       localvp.type = da->type;
+                       return valuepair2str(out, outlen, &localvp,
+                                            da->type, func);
                }
 
                /*
@@ -247,7 +368,7 @@ static int xlat_regex(void *instance, REQUEST *request,
        fmt = fmt;              /* -Wunused */
        func = func;            /* -Wunused FIXME: do escaping? */
        
-       regex = request_data_get(request, request,
+       regex = request_data_reference(request, request,
                                 REQUEST_DATA_REGEX | *(int *)instance);
        if (!regex) return 0;
 
@@ -255,8 +376,7 @@ static int xlat_regex(void *instance, REQUEST *request,
         *      Copy UP TO "freespace" bytes, including
         *      a zero byte.
         */
-       strNcpy(out, regex, outlen);
-       free(regex); /* was strdup'd */
+       strlcpy(out, regex, outlen);
        return strlen(out);
 }
 #endif                         /* HAVE_REGEX_H */
@@ -279,20 +399,27 @@ static int xlat_cmp(const void *a, const void *b)
 /*
  *     find the appropriate registered xlat function.
  */
-static xlat_t *xlat_find(const char *module)
+static const xlat_t *xlat_find(const char *module)
 {
-       char *p;
        xlat_t my_xlat;
 
-       strNcpy(my_xlat.module, module, sizeof(my_xlat.module));
-
        /*
-        *      We get passed the WHOLE string, and all we want here
-        *      is the first piece.
+        *      Look for dictionary attributes first.
         */
-       p = strchr(my_xlat.module, ':');
-       if (p) *p = '\0';
+       if ((dict_attrbyname(module) != NULL) ||
+           (strchr(module, '[') != NULL)) {
+               static const xlat_t dict_xlat = {
+                       "request",
+                       7,
+                       &xlat_inst[1],
+                       xlat_packet,
+                       TRUE
+               };
+
+               return &dict_xlat;
+       }
 
+       strlcpy(my_xlat.module, module, sizeof(my_xlat.module));
        my_xlat.length = strlen(my_xlat.module);
 
        return rbtree_finddata(xlat_root, &my_xlat);
@@ -358,7 +485,7 @@ int xlat_register(const char *module, RAD_XLAT_FUNC func, void *instance)
        /*
         *      If it already exists, replace the instance.
         */
-       strNcpy(my_xlat.module, module, sizeof(my_xlat.module));
+       strlcpy(my_xlat.module, module, sizeof(my_xlat.module));
        my_xlat.length = strlen(my_xlat.module);
        c = rbtree_finddata(xlat_root, &my_xlat);
        if (c) {
@@ -379,7 +506,7 @@ int xlat_register(const char *module, RAD_XLAT_FUNC func, void *instance)
        memset(c, 0, sizeof(*c));
 
        c->do_xlat = func;
-       strNcpy(c->module, module, sizeof(c->module));
+       strlcpy(c->module, module, sizeof(c->module));
        c->length = strlen(c->module);
        c->instance = instance;
 
@@ -401,7 +528,9 @@ void xlat_unregister(const char *module, RAD_XLAT_FUNC func)
 
        func = func;            /* -Wunused */
 
-       strNcpy(my_xlat.module, module, sizeof(my_xlat.module));
+       if (!module) return;
+
+       strlcpy(my_xlat.module, module, sizeof(my_xlat.module));
        my_xlat.length = strlen(my_xlat.module);
 
        node = rbtree_find(xlat_root, &my_xlat);
@@ -410,7 +539,6 @@ void xlat_unregister(const char *module, RAD_XLAT_FUNC func)
        rbtree_delete(xlat_root, node);
 }
 
-
 /*
  *     De-register all xlat functions,
  *     used mainly for debugging.
@@ -428,17 +556,19 @@ static void decode_attribute(const char **from, char **to, int freespace,
                             int *open, REQUEST *request,
                             RADIUS_ESCAPE_STRING func)
 {
-       char attrname[4096];
+       int     do_length = 0;
+       char    xlat_name[128];
+       char    *xlat_string = NULL; /* can be large */
+       int     free_xlat_string = FALSE;
        const char *p;
        char *q, *pa;
-       int stop=0, found=0, retlen=0;
+       int found=0, retlen=0;
        int openbraces = *open;
-       xlat_t *c;
-       size_t namelen = sizeof(attrname);
+       const xlat_t *c;
 
        p = *from;
        q = *to;
-       pa = &attrname[0];
+       pa = &xlat_name[0];
 
        *q = '\0';
 
@@ -449,19 +579,91 @@ static void decode_attribute(const char **from, char **to, int freespace,
        p++;
        openbraces++;
 
+       if (*p == '#') {
+               p++;
+               do_length = 1;
+       }
+
        /*
-        *  Copy over the rest of the string.
+        *      First, copy the xlat key name to one buffer
         */
-       while ((*p) && (!stop) && (namelen > 1)) {
-               switch(*p) {
+       while (*p && (*p != '}') && (*p != ':')) {
+               *pa++ = *p++;
+
+               if (pa >= (xlat_name + sizeof(xlat_name) - 1)) {
                        /*
-                        *  Allow braces inside things, too.
+                        *      Skip to the end of the input
                         */
+                       p += strlen(p);
+                       DEBUG("xlat: Module name is too long in string %%%s",
+                             *from);
+                       goto done;
+               }
+       }
+       *pa = '\0';
+
+       if (!*p) {
+               DEBUG("xlat: Invalid syntax in %s", *from);
+
+               /*
+                *      %{name} is a simple attribute reference,
+                *      or regex reference.
+                */
+       } else if (*p == '}') {
+               openbraces--;
+               rad_assert(openbraces == *open);
+
+               p++;
+               xlat_string = xlat_name;
+               goto do_xlat;
+
+       } else if (p[1] == '-') { /* handle ':- */
+               p += 2;
+               xlat_string = xlat_name;
+               goto do_xlat;
+               
+       } else {      /* module name, followed by per-module string */
+               int stop = 0;
+               int delimitbrace = *open;
+
+               rad_assert(*p == ':');
+               p++;                    /* skip the ':' */
+
+               /*
+                *  If there's a brace immediately following the colon,
+                *  then we've chosen to delimite the per-module string,
+                *  so keep track of that.
+                */
+               if (*p == '{') {
+                       delimitbrace = openbraces;
+                       openbraces++;
+                       p++;
+               }
+               
+               xlat_string = rad_malloc(strlen(p) + 1); /* always returns */
+               free_xlat_string = TRUE;
+               pa = xlat_string;
+               
+               /*
+                *  Copy over the rest of the string, which is per-module
+                *  data.
+                */
+               while (*p && !stop) {
+                       switch(*p) {
+                               /*
+                                *      What the heck is this supposed
+                                *      to be doing?
+                                */
                        case '\\':
                                p++; /* skip it */
                                *pa++ = *p++;
                                break;
 
+                               /*
+                                *      This is pretty hokey...  we
+                                *      should use the functions in
+                                *      util.c
+                                */
                        case '{':
                                openbraces++;
                                *pa++ = *p++;
@@ -469,73 +671,53 @@ static void decode_attribute(const char **from, char **to, int freespace,
 
                        case '}':
                                openbraces--;
-                               if (openbraces == *open) {
+                               if (openbraces == delimitbrace) {
                                        p++;
                                        stop=1;
                                } else {
                                        *pa++ = *p++;
                                }
                                break;
-
-                               /*
-                                *  Attr-Name1:-Attr-Name2
-                                *
-                                *  Use Attr-Name1, and if not found,
-                                *  use Attr-Name2.
-                                */
-                       case ':':
-                               if (p[1] == '-') {
-                                       p += 2;
-                                       stop = 1;
-                                       break;
-                               }
-                               /* else FALL-THROUGH */
-
+                               
                        default:
                                *pa++ = *p++;
                                break;
+                       }
                }
-               namelen--;
-       }
-       *pa = '\0';
 
-       /*
-        *      Look up almost everything in the new tree of xlat
-        *      functions.  this makes it a little quicker...
-        */
-       if ((c = xlat_find(attrname)) != NULL) {
-               if (!c->internal) DEBUG("radius_xlat: Running registered xlat function of module %s for string \'%s\'",
-                                       c->module, attrname+ c->length + 1);
-               retlen = c->do_xlat(c->instance, request, attrname+(c->length+1), q, freespace, func);
-               /* If retlen is 0, treat it as not found */
-               if (retlen == 0) {
-                       found = 0;
-               } else {
-                       found = 1;
-                       q += retlen;
-               }
+               *pa = '\0';
 
                /*
-                *      Not in the default xlat database.  Must be
-                *      a bare attribute number.
+                *      Now check to see if we're at the end of the string
+                *      we were sent.  If we're not, check for :-
                 */
-       } else if ((retlen = xlat_packet(&xlat_inst[1], request, attrname,
-                                        q, freespace, func)) > 0) {
-               found = 1;
-               q += retlen;
-
+               if (openbraces == delimitbrace) {
+                       if (p[0] == ':' && p[1] == '-') {
+                               p += 2;
+                       }
+               }
+               
                /*
-                *      Look up the name, in order to get the correct
-                *      debug message.
+                *      Look up almost everything in the new tree of xlat
+                *      functions.  This makes it a little quicker...
                 */
+       do_xlat:
+               if ((c = xlat_find(xlat_name)) != NULL) {
+                       if (!c->internal) DEBUG("radius_xlat: Running registered xlat function of module %s for string \'%s\'",
+                                               c->module, xlat_string);
+                       retlen = c->do_xlat(c->instance, request, xlat_string,
+                                           q, freespace, func);
+                       /* If retlen is 0, treat it as not found */
+                       if (retlen > 0) found = 1;
 #ifndef NDEBUG
-       } else if (dict_attrbyname(attrname) == NULL) {
-               /*
-                *      No attribute by that name, return an error.
-                */
-               DEBUG2("WARNING: Attempt to use unknown xlat function, or non-existent attribute in string %%{%s}", attrname);
+               } else {
+                       /*
+                        *      No attribute by that name, return an error.
+                        */
+                       DEBUG2("WARNING: Unknown module \"%s\" in string expansion \"%%%s\"", xlat_name, *from);
 #endif
-       } /* else the attribute is known, but not in the request */
+               }
+       }
 
        /*
         * Skip to last '}' if attr is found
@@ -543,6 +725,13 @@ static void decode_attribute(const char **from, char **to, int freespace,
         * useless if we found what we need
         */
        if (found) {
+               if (do_length) {
+                       snprintf(q, freespace, "%d", retlen);
+                       retlen = strlen(q);
+               }
+
+               q += retlen;
+
                while((*p != '\0') && (openbraces > *open)) {
                        /*
                         *      Handle escapes outside of the loop.
@@ -572,6 +761,9 @@ static void decode_attribute(const char **from, char **to, int freespace,
                        p++;    /* skip the character */
                }
        }
+       
+       done:
+       if (free_xlat_string) free(xlat_string);
 
        *open = openbraces;
        *from = p;
@@ -633,7 +825,7 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                func = xlat_copy;
        }
 
-       q = out;
+               q = out;
        p = fmt;
        while (*p) {
                /* Calculate freespace in output */
@@ -720,7 +912,7 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                                TM = localtime_r(&request->timestamp, &s_TM);
                                len = strftime(tmpdt, sizeof(tmpdt), "%d", TM);
                                if (len > 0) {
-                                       strNcpy(q, tmpdt, freespace);
+                                       strlcpy(q, tmpdt, freespace);
                                        q += strlen(q);
                                }
                                p++;
@@ -736,7 +928,7 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                        case 'l': /* request timestamp */
                                snprintf(tmpdt, sizeof(tmpdt), "%lu",
                                         (unsigned long) request->timestamp);
-                               strNcpy(q,tmpdt,freespace);
+                               strlcpy(q,tmpdt,freespace);
                                q += strlen(q);
                                p++;
                                break;
@@ -744,7 +936,7 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                                TM = localtime_r(&request->timestamp, &s_TM);
                                len = strftime(tmpdt, sizeof(tmpdt), "%m", TM);
                                if (len > 0) {
-                                       strNcpy(q, tmpdt, freespace);
+                                       strlcpy(q, tmpdt, freespace);
                                        q += strlen(q);
                                }
                                p++;
@@ -765,7 +957,7 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                                CTIME_R(&request->timestamp, tmpdt, sizeof(tmpdt));
                                nl = strchr(tmpdt, '\n');
                                if (nl) *nl = '\0';
-                               strNcpy(q, tmpdt, freespace);
+                               strlcpy(q, tmpdt, freespace);
                                q += strlen(q);
                                p++;
                                break;
@@ -774,12 +966,12 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                                p++;
                                break;
                        case 'A': /* radacct_dir */
-                               strNcpy(q,radacct_dir,freespace-1);
+                               strlcpy(q,radacct_dir,freespace);
                                q += strlen(q);
                                p++;
                                break;
                        case 'C': /* ClientName */
-                               strNcpy(q,client_name(request->packet->src_ipaddr),freespace-1);
+                               strlcpy(q,client_name_old(&request->packet->src_ipaddr),freespace);
                                q += strlen(q);
                                p++;
                                break;
@@ -787,7 +979,7 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                                TM = localtime_r(&request->timestamp, &s_TM);
                                len = strftime(tmpdt, sizeof(tmpdt), "%Y%m%d", TM);
                                if (len > 0) {
-                                       strNcpy(q, tmpdt, freespace);
+                                       strlcpy(q, tmpdt, freespace);
                                        q += strlen(q);
                                }
                                p++;
@@ -796,13 +988,13 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                                TM = localtime_r(&request->timestamp, &s_TM);
                                len = strftime(tmpdt, sizeof(tmpdt), "%H", TM);
                                if (len > 0) {
-                                       strNcpy(q, tmpdt, freespace);
+                                       strlcpy(q, tmpdt, freespace);
                                        q += strlen(q);
                                }
                                p++;
                                break;
                        case 'L': /* radlog_dir */
-                               strNcpy(q,radlog_dir,freespace-1);
+                               strlcpy(q,radlog_dir,freespace);
                                q += strlen(q);
                                p++;
                                break;
@@ -811,7 +1003,7 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                                p++;
                                break;
                        case 'R': /* radius_dir */
-                               strNcpy(q,radius_dir,freespace-1);
+                               strlcpy(q,radius_dir,freespace);
                                q += strlen(q);
                                p++;
                                break;
@@ -819,7 +1011,7 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                                TM = localtime_r(&request->timestamp, &s_TM);
                                len = strftime(tmpdt, sizeof(tmpdt), "%Y-%m-%d %H:%M:%S", TM);
                                if (len > 0) {
-                                       strNcpy(q, tmpdt, freespace);
+                                       strlcpy(q, tmpdt, freespace);
                                        q += strlen(q);
                                }
                                p++;
@@ -828,7 +1020,7 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                                TM = localtime_r(&request->timestamp, &s_TM);
                                len = strftime(tmpdt, sizeof(tmpdt), "%Y-%m-%d-%H.%M.%S.000000", TM);
                                if (len > 0) {
-                                       strNcpy(q, tmpdt, freespace);
+                                       strlcpy(q, tmpdt, freespace);
                                        q += strlen(q);
                                }
                                p++;
@@ -839,9 +1031,9 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                                break;
                        case 'V': /* Request-Authenticator */
                                if (request->packet->verified)
-                                       strNcpy(q,"Verified",freespace-1);
+                                       strlcpy(q,"Verified",freespace);
                                else
-                                       strNcpy(q,"None",freespace-1);
+                                       strlcpy(q,"None",freespace);
                                q += strlen(q);
                                p++;
                                break;
@@ -849,7 +1041,7 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                                TM = localtime_r(&request->timestamp, &s_TM);
                                len = strftime(tmpdt, sizeof(tmpdt), "%Y", TM);
                                if (len > 0) {
-                                       strNcpy(q, tmpdt, freespace);
+                                       strlcpy(q, tmpdt, freespace);
                                        q += strlen(q);
                                }
                                p++;
@@ -857,7 +1049,7 @@ int radius_xlat(char *out, int outlen, const char *fmt,
                        case 'Z': /* Full request pairs except password */
                                tmp = request->packet->vps;
                                while (tmp && (freespace > 3)) {
-                                       if (tmp->attribute != PW_PASSWORD) {
+                                       if (tmp->attribute != PW_USER_PASSWORD) {
                                                *q++ = '\t';
                                                len = vp_prints(q, freespace - 2, tmp);
                                                q += len;
index 6b3ac7c..691ca40 100644 (file)
@@ -38,7 +38,7 @@ reconfig:
                 if grep AC_CONFIG_HEADERS configure.in >/dev/null; then\
                        $(AUTOHEADER); \
                 fi; \
-               ) || exit $$?; \
+               )  || exit $$?; \
        done
 
 common:
index 46e1375..ed51a71 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
-#include "radiusd.h"
-#include "modules.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 /*
  *  Room for at least 16 attributes.
  */
 #define  BUFFERLEN  4096
 
-static const char rcsid[] = "$Id$";
-
 typedef struct rlm_acct_unique_list_t {
        DICT_ATTR                     *dattr;
        struct rlm_acct_unique_list_t *next;
@@ -45,7 +46,7 @@ typedef struct rlm_acct_unique_t {
        rlm_acct_unique_list_t *head;
 } rlm_acct_unique_t;
 
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
   { "key",  PW_TYPE_STRING_PTR, offsetof(rlm_acct_unique_t,key), NULL,  NULL },
   { NULL, -1, 0, NULL, NULL }    /* end the list */
 };
@@ -75,14 +76,21 @@ static int unique_parse_key(rlm_acct_unique_t *inst, char *key)
        char *ptr, *prev, *keyptr;
        DICT_ATTR *a;
 
-       keyptr = key;
-       ptr = key;
        prev = key;
+       keyptr = ptr = key;
 
        /* Let's remove spaces in the string */
-       rad_rmspace(key);
+       while (*keyptr) {
+               if (isspace((int) *keyptr)) {
+                       keyptr++;
+               } else {
+                       *(ptr++) = *(keyptr++);
+               }
+       }
+       *ptr = '\0';
 
-       ptr = key;
+
+       keyptr = ptr = key;
        while(ptr) {
                switch(*ptr) {
                case ',':
@@ -121,7 +129,6 @@ static int unique_detach(void *instance)
        rlm_acct_unique_t *inst = instance;
        rlm_acct_unique_list_t *this, *next;
 
-       free(inst->key);
        for (this = inst->head; this != NULL; this = next) {
                next = this->next;
                free(this);
@@ -234,10 +241,11 @@ static int add_unique_id(void *instance, REQUEST *request)
 
 /* globally exported name */
 module_t rlm_acct_unique = {
+       RLM_MODULE_INIT,
        "Acct-Unique-Session-Id",
        0,                              /* type: reserved */
-       NULL,                           /* initialization */
        unique_instantiate,             /* instantiation */
+       unique_detach,          /* detach */
        {
                NULL,                   /* authentication */
                add_unique_id,  /* authorization */
@@ -248,6 +256,4 @@ module_t rlm_acct_unique = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       unique_detach,          /* detach */
-       NULL,                           /* destroy */
 };
diff --git a/src/modules/rlm_acctlog/Makefile.in b/src/modules/rlm_acctlog/Makefile.in
new file mode 100644 (file)
index 0000000..a39c006
--- /dev/null
@@ -0,0 +1,11 @@
+TARGET      = @targetname@
+SRCS        = rlm_acctlog.c
+RLM_CFLAGS  = @acctlog_cflags@
+RLM_LIBS    = @acctlog_ldflags@
+
+include ../rules.mak
+
+$(LT_OBJS): $(HEADERS)
+
+install-example:
+       touch .
similarity index 53%
rename from src/modules/rlm_eap/types/rlm_eap_md5/configure
rename to src/modules/rlm_acctlog/configure
index 39dfd93..904ed0f 100755 (executable)
@@ -1,9 +1,10 @@
 #! /bin/sh
-# From configure.in Revision: 1.1 .
+# From configure.in 0.1.
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59.
+# Generated by GNU Autoconf 2.60.
 #
-# Copyright (C) 2003 Free Software Foundation, Inc.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 # This configure script is free software; the Free Software Foundation
 # gives unlimited permission to copy, distribute and modify it.
 ## --------------------- ##
@@ -17,11 +18,35 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
   # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
   # is contrary to our usage.  Disable this feature.
   alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
-  set -o posix
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
 fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
 DUALCASE=1; export DUALCASE # for MKS sh
 
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
 # Support unset when possible.
 if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
   as_unset=unset
@@ -30,8 +55,43 @@ else
 fi
 
 
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
 # Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
 PS1='$ '
 PS2='> '
 PS4='+ '
@@ -45,18 +105,19 @@ do
   if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
     eval $as_var=C; export $as_var
   else
-    $as_unset $as_var
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
   fi
 done
 
 # Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
   as_expr=expr
 else
   as_expr=false
 fi
 
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
   as_basename=basename
 else
   as_basename=false
@@ -64,157 +125,386 @@ fi
 
 
 # Name of the executable.
-as_me=`$as_basename "$0" ||
+as_me=`$as_basename -- "$0" ||
 $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
         X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)$' \| \
-        .     : '\(.\)' 2>/dev/null ||
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
 echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
-         /^X\/\(\/\/\)$/{ s//\1/; q; }
-         /^X\/\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
 
+# CDPATH.
+$as_unset CDPATH
 
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
 
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
+if test "x$CONFIG_SHELL" = x; then
+  if (eval ":") 2>/dev/null; then
+  as_have_required=yes
+else
+  as_have_required=no
 fi
 
+  if test $as_have_required = yes &&    (eval ":
+(as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
 
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
-  # Find who we are.  Look in the path if we contain no path at all
-  # relative or not.
-  case $0 in
-    *[\\/]* ) as_myself=$0 ;;
-    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
 
-       ;;
-  esac
-  # We did not find ourselves, most probably we were run as `sh COMMAND'
-  # in which case we are not to be found in the path.
-  if test "x$as_myself" = x; then
-    as_myself=$0
-  fi
-  if test ! -f "$as_myself"; then
-    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
-   { (exit 1); exit 1; }; }
-  fi
-  case $CONFIG_SHELL in
-  '')
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=\$LINENO
+  as_lineno_2=\$LINENO
+  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+  :
+else
+  as_candidate_shells=
     as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
 do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
-  for as_base in sh bash ksh sh5; do
-        case $as_dir in
+  case $as_dir in
         /*)
-          if ("$as_dir/$as_base" -c '
+          for as_base in sh bash ksh sh5; do
+            as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+          done;;
+       esac
+done
+IFS=$as_save_IFS
+
+
+      for as_shell in $as_candidate_shells $SHELL; do
+        # Try only shells that exist, to save several forks.
+        if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+               { ("$as_shell") 2> /dev/null <<\_ASEOF
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+:
+_ASEOF
+}; then
+  CONFIG_SHELL=$as_shell
+              as_have_required=yes
+              if { "$as_shell" 2> /dev/null <<\_ASEOF
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+:
+(as_func_return () {
+  (exit $1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
   as_lineno_1=$LINENO
   as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
   test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
-            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
-            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
-            CONFIG_SHELL=$as_dir/$as_base
-            export CONFIG_SHELL
-            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
-          fi;;
-        esac
-       done
-done
-;;
-  esac
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+  break
+fi
+
+fi
+
+      done
+
+      if test "x$CONFIG_SHELL" != x; then
+  for as_var in BASH_ENV ENV
+        do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+        done
+        export CONFIG_SHELL
+        exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+    if test $as_have_required = no; then
+  echo This script requires a shell more modern than all the
+      echo shells that I found on your system.  Please install a
+      echo modern shell, or manually run the script under such a
+      echo shell if you do have one.
+      { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+  echo No shell found that supports shell functions.
+  echo Please tell autoconf@gnu.org about your system,
+  echo including any error possibly output before this
+  echo message
+}
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
 
   # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
   # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line before each line; the second 'sed' does the real
-  # work.  The second script uses 'N' to pair each line-number line
-  # with the numbered line, and appends trailing '-' during
-  # substitution so that $LINENO is not a special case at line end.
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
   # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
-  sed '=' <$as_myself |
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
     sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
       N
-      s,$,-,
-      : loop
-      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
       t loop
-      s,-$,,
-      s,^['$as_cr_digits']*\n,,
+      s/-\n.*//
     ' >$as_me.lineno &&
-  chmod +x $as_me.lineno ||
+  chmod +x "$as_me.lineno" ||
     { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
    { (exit 1); exit 1; }; }
 
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensible to this).
-  . ./$as_me.lineno
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
   # Exit status is that of the last command.
   exit
 }
 
 
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
-  *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T='     ' ;;
-  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
-  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
 esac
 
-if expr a : '\(a\)' >/dev/null 2>&1; then
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
   as_expr=expr
 else
   as_expr=false
 fi
 
 rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
 echo >conf$$.file
 if ln -s conf$$.file conf$$ 2>/dev/null; then
-  # We could just check for DJGPP; but this test a) works b) is more generic
-  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
-  if test -f conf$$.exe; then
-    # Don't use ln at all; we don't have any links
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
     as_ln_s='cp -p'
-  else
-    as_ln_s='ln -s'
-  fi
 elif ln conf$$.file conf$$ 2>/dev/null; then
   as_ln_s=ln
 else
   as_ln_s='cp -p'
 fi
-rm -f conf$$ conf$$.exe conf$$.file
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
 
 if mkdir -p . 2>/dev/null; then
   as_mkdir_p=:
@@ -223,7 +513,19 @@ else
   as_mkdir_p=false
 fi
 
-as_executable_p="test -f"
+# Find out whether ``test -x'' works.  Don't use a zero-byte file, as
+# systems may use methods other than mode bits to determine executability.
+cat >conf$$.file <<_ASEOF
+#! /bin/sh
+exit 0
+_ASEOF
+chmod +x conf$$.file
+if test -x conf$$.file >/dev/null 2>&1; then
+  as_executable_p="test -x"
+else
+  as_executable_p=:
+fi
+rm -f conf$$.file
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -232,39 +534,27 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
 as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
 
 
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS="  $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
 
+exec 7<&0 </dev/null 6>&1
 
 # Name of the host.
 # hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
 # so uname gets run too.
 ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
 
-exec 6>&1
-
 #
 # Initializations.
 #
 ac_default_prefix=/usr/local
+ac_clean_files=
 ac_config_libobj_dir=.
+LIBOBJS=
 cross_compiling=no
 subdirs=
 MFLAGS=
 MAKEFLAGS=
 SHELL=${CONFIG_SHELL-/bin/sh}
 
-# Maximum number of lines to put in a shell here document.
-# This variable seems obsolete.  It should probably be removed, and
-# only ac_max_sed_lines should be used.
-: ${ac_max_here_lines=38}
-
 # Identity of this package.
 PACKAGE_NAME=
 PACKAGE_TARNAME=
@@ -272,7 +562,7 @@ PACKAGE_VERSION=
 PACKAGE_STRING=
 PACKAGE_BUGREPORT=
 
-ac_unique_file="rlm_eap_md5.c"
+ac_unique_file="rlm_acctlog.c"
 # Factoring default headers for most tests.
 ac_includes_default="\
 #include <stdio.h>
@@ -301,17 +591,76 @@ ac_includes_default="\
 #endif
 #if HAVE_INTTYPES_H
 # include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-#  include <stdint.h>
-# endif
+#endif
+#if HAVE_STDINT_H
+# include <stdint.h>
 #endif
 #if HAVE_UNISTD_H
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP eap_md5_cflags eap_md5_ldflags targetname LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL
+PATH_SEPARATOR
+PACKAGE_NAME
+PACKAGE_TARNAME
+PACKAGE_VERSION
+PACKAGE_STRING
+PACKAGE_BUGREPORT
+exec_prefix
+prefix
+program_transform_name
+bindir
+sbindir
+libexecdir
+datarootdir
+datadir
+sysconfdir
+sharedstatedir
+localstatedir
+includedir
+oldincludedir
+docdir
+infodir
+htmldir
+dvidir
+pdfdir
+psdir
+libdir
+localedir
+mandir
+DEFS
+ECHO_C
+ECHO_N
+ECHO_T
+LIBS
+build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+ac_ct_CC
+EXEEXT
+OBJEXT
+CPP
+GREP
+EGREP
+acctlog_cflags
+acctlog_ldflags
+targetname
+LIBOBJS
+LTLIBOBJS'
 ac_subst_files=''
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+CPPFLAGS
+CPP'
+
 
 # Initialize some variables set by options.
 ac_init_help=
@@ -338,34 +687,48 @@ x_libraries=NONE
 # and all the variables that are supposed to be based on exec_prefix
 # by default will actually change.
 # Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
 bindir='${exec_prefix}/bin'
 sbindir='${exec_prefix}/sbin'
 libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
-libdir='${exec_prefix}/lib'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
-infodir='${prefix}/info'
-mandir='${prefix}/man'
+docdir='${datarootdir}/doc/${PACKAGE}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
 
 ac_prev=
+ac_dashdash=
 for ac_option
 do
   # If the previous option needs an argument, assign it.
   if test -n "$ac_prev"; then
-    eval "$ac_prev=\$ac_option"
+    eval $ac_prev=\$ac_option
     ac_prev=
     continue
   fi
 
-  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+  case $ac_option in
+  *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)   ac_optarg=yes ;;
+  esac
 
   # Accept the important Cygnus configure options, so we can diagnose typos.
 
-  case $ac_option in
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
 
   -bindir | --bindir | --bindi | --bind | --bin | --bi)
     ac_prev=bindir ;;
@@ -387,12 +750,18 @@ do
   --config-cache | -C)
     cache_file=config.cache ;;
 
-  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+  -datadir | --datadir | --datadi | --datad)
     ac_prev=datadir ;;
-  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
-  | --da=*)
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
     datadir=$ac_optarg ;;
 
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
   -disable-* | --disable-*)
     ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
     # Reject names that are not valid shell variable names.
@@ -400,7 +769,17 @@ do
       { echo "$as_me: error: invalid feature name: $ac_feature" >&2
    { (exit 1); exit 1; }; }
     ac_feature=`echo $ac_feature | sed 's/-/_/g'`
-    eval "enable_$ac_feature=no" ;;
+    eval enable_$ac_feature=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
 
   -enable-* | --enable-*)
     ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
@@ -409,11 +788,7 @@ do
       { echo "$as_me: error: invalid feature name: $ac_feature" >&2
    { (exit 1); exit 1; }; }
     ac_feature=`echo $ac_feature | sed 's/-/_/g'`
-    case $ac_option in
-      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
-      *) ac_optarg=yes ;;
-    esac
-    eval "enable_$ac_feature='$ac_optarg'" ;;
+    eval enable_$ac_feature=\$ac_optarg ;;
 
   -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
   | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
@@ -440,6 +815,12 @@ do
   -host=* | --host=* | --hos=* | --ho=*)
     host_alias=$ac_optarg ;;
 
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
   -includedir | --includedir | --includedi | --included | --include \
   | --includ | --inclu | --incl | --inc)
     ac_prev=includedir ;;
@@ -464,13 +845,16 @@ do
   | --libexe=* | --libex=* | --libe=*)
     libexecdir=$ac_optarg ;;
 
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
   -localstatedir | --localstatedir | --localstatedi | --localstated \
-  | --localstate | --localstat | --localsta | --localst \
-  | --locals | --local | --loca | --loc | --lo)
+  | --localstate | --localstat | --localsta | --localst | --locals)
     ac_prev=localstatedir ;;
   -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
-  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
-  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
     localstatedir=$ac_optarg ;;
 
   -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
@@ -535,6 +919,16 @@ do
   | --progr-tra=* | --program-tr=* | --program-t=*)
     program_transform_name=$ac_optarg ;;
 
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
   -q | -quiet | --quiet | --quie | --qui | --qu | --q \
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
@@ -591,11 +985,7 @@ do
       { echo "$as_me: error: invalid package name: $ac_package" >&2
    { (exit 1); exit 1; }; }
     ac_package=`echo $ac_package| sed 's/-/_/g'`
-    case $ac_option in
-      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
-      *) ac_optarg=yes ;;
-    esac
-    eval "with_$ac_package='$ac_optarg'" ;;
+    eval with_$ac_package=\$ac_optarg ;;
 
   -without-* | --without-*)
     ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
@@ -604,7 +994,7 @@ do
       { echo "$as_me: error: invalid package name: $ac_package" >&2
    { (exit 1); exit 1; }; }
     ac_package=`echo $ac_package | sed 's/-/_/g'`
-    eval "with_$ac_package=no" ;;
+    eval with_$ac_package=no ;;
 
   --x)
     # Obsolete; use --with-x.
@@ -635,8 +1025,7 @@ Try \`$0 --help' for more information." >&2
     expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
       { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
    { (exit 1); exit 1; }; }
-    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
-    eval "$ac_envvar='$ac_optarg'"
+    eval $ac_envvar=\$ac_optarg
     export $ac_envvar ;;
 
   *)
@@ -656,27 +1045,19 @@ if test -n "$ac_prev"; then
    { (exit 1); exit 1; }; }
 fi
 
-# Be sure to have absolute paths.
-for ac_var in exec_prefix prefix
+# Be sure to have absolute directory names.
+for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
+               datadir sysconfdir sharedstatedir localstatedir includedir \
+               oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+               libdir localedir mandir
 do
-  eval ac_val=$`echo $ac_var`
+  eval ac_val=\$$ac_var
   case $ac_val in
-    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
-    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
-   { (exit 1); exit 1; }; };;
-  esac
-done
-
-# Be sure to have absolute paths.
-for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
-             localstatedir libdir includedir oldincludedir infodir mandir
-do
-  eval ac_val=$`echo $ac_var`
-  case $ac_val in
-    [\\/$]* | ?:[\\/]* ) ;;
-    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
-   { (exit 1); exit 1; }; };;
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
   esac
+  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; }
 done
 
 # There might be people who depend on the old broken behavior: `$host'
@@ -703,74 +1084,76 @@ test -n "$host_alias" && ac_tool_prefix=$host_alias-
 test "$silent" = yes && exec 6>/dev/null
 
 
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  { echo "$as_me: error: Working directory cannot be determined" >&2
+   { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  { echo "$as_me: error: pwd does not report name of working directory" >&2
+   { (exit 1); exit 1; }; }
+
+
 # Find the source files, if location was not specified.
 if test -z "$srcdir"; then
   ac_srcdir_defaulted=yes
-  # Try the directory containing this script, then its parent.
-  ac_confdir=`(dirname "$0") 2>/dev/null ||
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$0" ||
 $as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
         X"$0" : 'X\(//\)[^/]' \| \
         X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)' \| \
-        .     : '\(.\)' 2>/dev/null ||
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
 echo X"$0" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-         /^X\(\/\/\)$/{ s//\1/; q; }
-         /^X\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
   srcdir=$ac_confdir
-  if test ! -r $srcdir/$ac_unique_file; then
+  if test ! -r "$srcdir/$ac_unique_file"; then
     srcdir=..
   fi
 else
   ac_srcdir_defaulted=no
 fi
-if test ! -r $srcdir/$ac_unique_file; then
-  if test "$ac_srcdir_defaulted" = yes; then
-    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
    { (exit 1); exit 1; }; }
-  else
-    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
-   { (exit 1); exit 1; }; }
-  fi
 fi
-(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
-  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+       cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2
    { (exit 1); exit 1; }; }
-srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
-ac_env_build_alias_set=${build_alias+set}
-ac_env_build_alias_value=$build_alias
-ac_cv_env_build_alias_set=${build_alias+set}
-ac_cv_env_build_alias_value=$build_alias
-ac_env_host_alias_set=${host_alias+set}
-ac_env_host_alias_value=$host_alias
-ac_cv_env_host_alias_set=${host_alias+set}
-ac_cv_env_host_alias_value=$host_alias
-ac_env_target_alias_set=${target_alias+set}
-ac_env_target_alias_value=$target_alias
-ac_cv_env_target_alias_set=${target_alias+set}
-ac_cv_env_target_alias_value=$target_alias
-ac_env_CC_set=${CC+set}
-ac_env_CC_value=$CC
-ac_cv_env_CC_set=${CC+set}
-ac_cv_env_CC_value=$CC
-ac_env_CFLAGS_set=${CFLAGS+set}
-ac_env_CFLAGS_value=$CFLAGS
-ac_cv_env_CFLAGS_set=${CFLAGS+set}
-ac_cv_env_CFLAGS_value=$CFLAGS
-ac_env_LDFLAGS_set=${LDFLAGS+set}
-ac_env_LDFLAGS_value=$LDFLAGS
-ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
-ac_cv_env_LDFLAGS_value=$LDFLAGS
-ac_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_env_CPPFLAGS_value=$CPPFLAGS
-ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_cv_env_CPPFLAGS_value=$CPPFLAGS
-ac_env_CPP_set=${CPP+set}
-ac_env_CPP_value=$CPP
-ac_cv_env_CPP_set=${CPP+set}
-ac_cv_env_CPP_value=$CPP
+       pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
 
 #
 # Report the --help message.
@@ -799,9 +1182,6 @@ Configuration:
   -n, --no-create         do not create output files
       --srcdir=DIR        find the sources in DIR [configure dir or \`..']
 
-_ACEOF
-
-  cat <<_ACEOF
 Installation directories:
   --prefix=PREFIX         install architecture-independent files in PREFIX
                          [$ac_default_prefix]
@@ -819,15 +1199,22 @@ Fine tuning of the installation directories:
   --bindir=DIR           user executables [EPREFIX/bin]
   --sbindir=DIR          system admin executables [EPREFIX/sbin]
   --libexecdir=DIR       program executables [EPREFIX/libexec]
-  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
   --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
   --libdir=DIR           object code libraries [EPREFIX/lib]
   --includedir=DIR       C header files [PREFIX/include]
   --oldincludedir=DIR    C header files for non-gcc [/usr/include]
-  --infodir=DIR          info documentation [PREFIX/info]
-  --mandir=DIR           man documentation [PREFIX/man]
+  --datarootdir=DIR      read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR          read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR          info documentation [DATAROOTDIR/info]
+  --localedir=DIR        locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR           man documentation [DATAROOTDIR/man]
+  --docdir=DIR           documentation root [DATAROOTDIR/doc/PACKAGE]
+  --htmldir=DIR          html documentation [DOCDIR]
+  --dvidir=DIR           dvi documentation [DOCDIR]
+  --pdfdir=DIR           pdf documentation [DOCDIR]
+  --psdir=DIR            ps documentation [DOCDIR]
 _ACEOF
 
   cat <<\_ACEOF
@@ -843,126 +1230,94 @@ Some influential environment variables:
   CFLAGS      C compiler flags
   LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
               nonstandard directory <lib dir>
-  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
-              headers in a nonstandard directory <include dir>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
   CPP         C preprocessor
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
 
 _ACEOF
+ac_status=$?
 fi
 
 if test "$ac_init_help" = "recursive"; then
   # If there are subdirs, report their specific --help.
-  ac_popdir=`pwd`
   for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
-    test -d $ac_dir || continue
+    test -d "$ac_dir" || continue
     ac_builddir=.
 
-if test "$ac_dir" != .; then
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
   ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A "../" for each directory in $ac_dir_suffix.
-  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
-  ac_dir_suffix= ac_top_builddir=
-fi
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
 
 case $srcdir in
-  .)  # No --srcdir option.  We are building in place.
+  .)  # We are building in place.
     ac_srcdir=.
-    if test -z "$ac_top_builddir"; then
-       ac_top_srcdir=.
-    else
-       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
-    fi ;;
-  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
     ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir ;;
-  *) # Relative path.
-    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
-  case "$ac_dir" in
-  .) ac_abs_builddir=`pwd`;;
-  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
-  *) ac_abs_builddir=`pwd`/"$ac_dir";;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
-  case ${ac_top_builddir}. in
-  .) ac_abs_top_builddir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
-  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
-  case $ac_srcdir in
-  .) ac_abs_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
-  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
-  case $ac_top_srcdir in
-  .) ac_abs_top_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
-  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
-  esac;;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
 esac
-
-    cd $ac_dir
-    # Check for guested configure; otherwise get Cygnus style configure.
-    if test -f $ac_srcdir/configure.gnu; then
-      echo
-      $SHELL $ac_srcdir/configure.gnu  --help=recursive
-    elif test -f $ac_srcdir/configure; then
-      echo
-      $SHELL $ac_srcdir/configure  --help=recursive
-    elif test -f $ac_srcdir/configure.ac ||
-          test -f $ac_srcdir/configure.in; then
-      echo
-      $ac_configure --help
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
-    fi
-    cd $ac_popdir
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
   done
 fi
 
-test -n "$ac_init_help" && exit 0
+test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
+configure
+generated by GNU Autoconf 2.60
 
-Copyright (C) 2003 Free Software Foundation, Inc.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 _ACEOF
-  exit 0
+  exit
 fi
-exec 5>config.log
-cat >&5 <<_ACEOF
+cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
 It was created by $as_me, which was
-generated by GNU Autoconf 2.59.  Invocation command line was
+generated by GNU Autoconf 2.60.  Invocation command line was
 
   $ $0 $@
 
 _ACEOF
+exec 5>>config.log
 {
 cat <<_ASUNAME
 ## --------- ##
@@ -981,7 +1336,7 @@ uname -v = `(uname -v) 2>/dev/null || echo unknown`
 /bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
 /usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
 /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
-hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
 /bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
 /usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
 /bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
@@ -995,6 +1350,7 @@ do
   test -z "$as_dir" && as_dir=.
   echo "PATH: $as_dir"
 done
+IFS=$as_save_IFS
 
 } >&5
 
@@ -1016,7 +1372,6 @@ _ACEOF
 ac_configure_args=
 ac_configure_args0=
 ac_configure_args1=
-ac_sep=
 ac_must_keep_next=false
 for ac_pass in 1 2
 do
@@ -1027,7 +1382,7 @@ do
     -q | -quiet | --quiet | --quie | --qui | --qu | --q \
     | -silent | --silent | --silen | --sile | --sil)
       continue ;;
-    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+    *\'*)
       ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
     esac
     case $ac_pass in
@@ -1049,9 +1404,7 @@ do
          -* ) ac_must_keep_next=true ;;
        esac
       fi
-      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
-      # Get rid of the leading space.
-      ac_sep=" "
+      ac_configure_args="$ac_configure_args '$ac_arg'"
       ;;
     esac
   done
@@ -1062,8 +1415,8 @@ $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_
 # When interrupted or exit'd, cleanup temporary files, and complete
 # config.log.  We remove comments because anyway the quotes in there
 # would cause problems or look ugly.
-# WARNING: Be sure not to use single quotes in there, as some shells,
-# such as our DU 5.0 friend, will then `close' the trap.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
 trap 'exit_status=$?
   # Save into config.log some information that might help in debugging.
   {
@@ -1076,20 +1429,34 @@ trap 'exit_status=$?
 _ASBOX
     echo
     # The following way of writing the cache mishandles newlines in values,
-{
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
   (set) 2>&1 |
-    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
-    *ac_space=\ *)
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
       sed -n \
-       "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
-         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
-      ;;
+       "s/'\''/'\''\\\\'\'''\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
     *)
-      sed -n \
-       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
       ;;
-    esac;
-}
+    esac |
+    sort
+)
     echo
 
     cat <<\_ASBOX
@@ -1100,22 +1467,28 @@ _ASBOX
     echo
     for ac_var in $ac_subst_vars
     do
-      eval ac_val=$`echo $ac_var`
-      echo "$ac_var='"'"'$ac_val'"'"'"
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      echo "$ac_var='\''$ac_val'\''"
     done | sort
     echo
 
     if test -n "$ac_subst_files"; then
       cat <<\_ASBOX
-## ------------- ##
-## Output files. ##
-## ------------- ##
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
 _ASBOX
       echo
       for ac_var in $ac_subst_files
       do
-       eval ac_val=$`echo $ac_var`
-       echo "$ac_var='"'"'$ac_val'"'"'"
+       eval ac_val=\$$ac_var
+       case $ac_val in
+       *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+       esac
+       echo "$ac_var='\''$ac_val'\''"
       done | sort
       echo
     fi
@@ -1127,26 +1500,24 @@ _ASBOX
 ## ----------- ##
 _ASBOX
       echo
-      sed "/^$/d" confdefs.h | sort
+      cat confdefs.h
       echo
     fi
     test "$ac_signal" != 0 &&
       echo "$as_me: caught signal $ac_signal"
     echo "$as_me: exit $exit_status"
   } >&5
-  rm -f core *.core &&
-  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
     exit $exit_status
-     ' 0
+' 0
 for ac_signal in 1 2 13 15; do
   trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
 done
 ac_signal=0
 
 # confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo >confdefs.h
+rm -f -r conftest* confdefs.h
 
 # Predefined preprocessor variables.
 
@@ -1177,14 +1548,17 @@ _ACEOF
 
 # Let the site file select an alternate cache file if it wants to.
 # Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
-  if test "x$prefix" != xNONE; then
-    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
-  else
-    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
-  fi
+if test -n "$CONFIG_SITE"; then
+  set x "$CONFIG_SITE"
+elif test "x$prefix" != xNONE; then
+  set x "$prefix/share/config.site" "$prefix/etc/config.site"
+else
+  set x "$ac_default_prefix/share/config.site" \
+       "$ac_default_prefix/etc/config.site"
 fi
-for ac_site_file in $CONFIG_SITE; do
+shift
+for ac_site_file
+do
   if test -r "$ac_site_file"; then
     { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
 echo "$as_me: loading site script $ac_site_file" >&6;}
@@ -1200,8 +1574,8 @@ if test -r "$cache_file"; then
     { echo "$as_me:$LINENO: loading cache $cache_file" >&5
 echo "$as_me: loading cache $cache_file" >&6;}
     case $cache_file in
-      [\\/]* | ?:[\\/]* ) . $cache_file;;
-      *)                      . ./$cache_file;;
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
     esac
   fi
 else
@@ -1213,12 +1587,11 @@ fi
 # Check that the precious variables saved in the cache have kept the same
 # value.
 ac_cache_corrupted=false
-for ac_var in `(set) 2>&1 |
-              sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+for ac_var in $ac_precious_vars; do
   eval ac_old_set=\$ac_cv_env_${ac_var}_set
   eval ac_new_set=\$ac_env_${ac_var}_set
-  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
-  eval ac_new_val="\$ac_env_${ac_var}_value"
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
   case $ac_old_set,$ac_new_set in
     set,)
       { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
@@ -1243,8 +1616,7 @@ echo "$as_me:   current value: $ac_new_val" >&2;}
   # Pass precious variables to config.status.
   if test "$ac_new_set" = set; then
     case $ac_new_val in
-    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
-      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
     *) ac_arg=$ac_var=$ac_new_val ;;
     esac
     case " $ac_configure_args " in
@@ -1261,12 +1633,6 @@ echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start ov
    { (exit 1); exit 1; }; }
 fi
 
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
 
 
 
@@ -1283,15 +1649,18 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
 
 
-if test x$with_rlm_eap_md5 != xno; then
+if test x$with_rlm_acctlog != xno; then
 
-       ## We may need more complex checking here.  Assume for now that
-       ## everyone has it.
        ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -1300,8 +1669,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
 set dummy ${ac_tool_prefix}gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
 if test "${ac_cv_prog_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -1314,32 +1683,34 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
+IFS=$as_save_IFS
 
 fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
 fi
 
+
 fi
 if test -z "$ac_cv_prog_CC"; then
   ac_ct_CC=$CC
   # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -1352,36 +1723,51 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_ac_ct_CC="gcc"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
+IFS=$as_save_IFS
 
 fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
 fi
 
-  CC=$ac_ct_CC
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
 else
   CC="$ac_cv_prog_CC"
 fi
 
 if test -z "$CC"; then
-  if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
 set dummy ${ac_tool_prefix}cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
 if test "${ac_cv_prog_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -1394,74 +1780,34 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
+IFS=$as_save_IFS
 
 fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_CC"; then
-  ac_ct_CC=$CC
-  # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
+  { echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
 fi
 
-  CC=$ac_ct_CC
-else
-  CC="$ac_cv_prog_CC"
-fi
 
+  fi
 fi
 if test -z "$CC"; then
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
 if test "${ac_cv_prog_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -1475,7 +1821,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
        continue
@@ -1486,6 +1832,7 @@ do
   fi
 done
 done
+IFS=$as_save_IFS
 
 if test $ac_prog_rejected = yes; then
   # We found a bogon in the path, so make sure we never use it.
@@ -1503,22 +1850,23 @@ fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
 fi
 
+
 fi
 if test -z "$CC"; then
   if test -n "$ac_tool_prefix"; then
-  for ac_prog in cl
+  for ac_prog in cl.exe
   do
     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
 if test "${ac_cv_prog_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -1531,36 +1879,38 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
+IFS=$as_save_IFS
 
 fi
 fi
 CC=$ac_cv_prog_CC
 if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6; }
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
 fi
 
+
     test -n "$CC" && break
   done
 fi
 if test -z "$CC"; then
   ac_ct_CC=$CC
-  for ac_prog in cl
+  for ac_prog in cl.exe
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
 if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -1573,29 +1923,45 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
   for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
     echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
 done
 done
+IFS=$as_save_IFS
 
 fi
 fi
 ac_ct_CC=$ac_cv_prog_ac_ct_CC
 if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6; }
 else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
 fi
 
+
   test -n "$ac_ct_CC" && break
 done
 
-  CC=$ac_ct_CC
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet.  If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
 fi
 
 fi
@@ -1608,21 +1974,35 @@ See \`config.log' for more details." >&2;}
    { (exit 1); exit 1; }; }
 
 # Provide some information about the compiler.
-echo "$as_me:$LINENO:" \
-     "checking for C compiler version" >&5
+echo "$as_me:$LINENO: checking for C compiler version" >&5
 ac_compiler=`set X $ac_compile; echo $2`
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
-  (eval $ac_compiler --version </dev/null >&5) 2>&5
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
-  (eval $ac_compiler -v </dev/null >&5) 2>&5
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
-  (eval $ac_compiler -V </dev/null >&5) 2>&5
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }
@@ -1647,46 +2027,70 @@ ac_clean_files="$ac_clean_files a.out a.exe b.out"
 # Try to create an executable without -o first, disregard a.out.
 # It will help us diagnose broken compilers, and finding out an intuition
 # of exeext.
-echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
-echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6; }
 ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
-  (eval $ac_link_default) 2>&5
+#
+# List of possible output files, starting from the most likely.
+# The algorithm is not robust to junk in `.', hence go to wildcards (a.*)
+# only as a last resort.  b.out is created by i960 compilers.
+ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out'
+#
+# The IRIX 6 linker writes into existing files which may not be
+# executable, retaining their permissions.  Remove them first so a
+# subsequent execution test works.
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link_default") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; then
-  # Find the output, starting from the most likely.  This scheme is
-# not robust to junk in `.', hence go to wildcards (a.*) only as a last
-# resort.
-
-# Be careful to initialize this variable, since it used to be cached.
-# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
-ac_cv_exeext=
-# b.out is created by i960 compilers.
-for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files
 do
   test -f "$ac_file" || continue
   case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
-       ;;
-    conftest.$ac_ext )
-       # This is the source file.
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj )
        ;;
     [ab].out )
        # We found the default executable, but exeext='' is most
        # certainly right.
        break;;
     *.* )
-       ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-       # FIXME: I believe we export ac_cv_exeext for Libtool,
-       # but it would be cool to find out if it's true.  Does anybody
-       # maintain Libtool? --akim.
-       export ac_cv_exeext
+        if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+       then :; else
+          ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       fi
+       # We set ac_cv_exeext here because the later test for it is not
+       # safe: cross compilers may not add the suffix if given an `-o'
+       # argument, so we may need to know it at that point already.
+       # Even if this section looks crufty: it has the advantage of
+       # actually working.
        break;;
     * )
        break;;
   esac
 done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
@@ -1699,19 +2103,23 @@ See \`config.log' for more details." >&2;}
 fi
 
 ac_exeext=$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6; }
 
-# Check the compiler produces executables we can run.  If not, either
+# Check that the compiler produces executables we can run.  If not, either
 # the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether the C compiler works" >&5
-echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6; }
 # FIXME: These cross compiler hacks should be removed for Autoconf 3.0
 # If not cross compiling, check that we can run a simple program.
 if test "$cross_compiling" != yes; then
   if { ac_try='./$ac_file'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -1730,22 +2138,27 @@ See \`config.log' for more details." >&2;}
     fi
   fi
 fi
-echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
 
 rm -f a.out a.exe conftest$ac_cv_exeext b.out
 ac_clean_files=$ac_clean_files_save
-# Check the compiler produces executables we can run.  If not, either
+# Check that the compiler produces executables we can run.  If not, either
 # the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
-echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
-echo "$as_me:$LINENO: result: $cross_compiling" >&5
-echo "${ECHO_T}$cross_compiling" >&6
-
-echo "$as_me:$LINENO: checking for suffix of executables" >&5
-echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>&5
+{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6; }
+
+{ echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; then
@@ -1756,9 +2169,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
 for ac_file in conftest.exe conftest conftest.*; do
   test -f "$ac_file" || continue
   case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;;
     *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-         export ac_cv_exeext
          break;;
     * ) break;;
   esac
@@ -1772,14 +2184,14 @@ See \`config.log' for more details." >&2;}
 fi
 
 rm -f conftest$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
-echo "${ECHO_T}$ac_cv_exeext" >&6
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6; }
 
 rm -f conftest.$ac_ext
 EXEEXT=$ac_cv_exeext
 ac_exeext=$EXEEXT
-echo "$as_me:$LINENO: checking for suffix of object files" >&5
-echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; }
 if test "${ac_cv_objext+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -1799,14 +2211,20 @@ main ()
 }
 _ACEOF
 rm -f conftest.o conftest.obj
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>&5
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; then
-  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
   case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;;
     *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
        break;;
   esac
@@ -1824,12 +2242,12 @@ fi
 
 rm -f conftest.$ac_cv_objext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
-echo "${ECHO_T}$ac_cv_objext" >&6
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6; }
 OBJEXT=$ac_cv_objext
 ac_objext=$OBJEXT
-echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6; }
 if test "${ac_cv_c_compiler_gnu+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -1852,24 +2270,36 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -1878,24 +2308,139 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-ac_compiler_gnu=no
+       ac_compiler_gnu=no
 fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 ac_cv_c_compiler_gnu=$ac_compiler_gnu
 
 fi
-echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6; }
 GCC=`test $ac_compiler_gnu = yes && echo yes`
 ac_test_CFLAGS=${CFLAGS+set}
 ac_save_CFLAGS=$CFLAGS
-CFLAGS="-g"
-echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+{ echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6; }
 if test "${ac_cv_prog_cc_g+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  cat >conftest.$ac_ext <<_ACEOF
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
@@ -1911,24 +2456,36 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -1937,12 +2494,20 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-ac_cv_prog_cc_g=no
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
 fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6; }
 if test "$ac_test_CFLAGS" = set; then
   CFLAGS=$ac_save_CFLAGS
 elif test $ac_cv_prog_cc_g = yes; then
@@ -1958,12 +2523,12 @@ else
     CFLAGS=
   fi
 fi
-echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
-echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_stdc+set}" = set; then
+{ echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+echo $ECHO_N "checking for $CC option to accept ISO C89... $ECHO_C" >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  ac_cv_prog_cc_stdc=no
+  ac_cv_prog_cc_c89=no
 ac_save_CC=$CC
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
@@ -1997,12 +2562,17 @@ static char *f (char * (*g) (char **, int), char **p, ...)
 /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
    function prototypes and stuff, but not '\xHH' hex character constants.
    These don't provoke an error unfortunately, instead are silently treated
-   as 'x'.  The following induces an error, until -std1 is added to get
+   as 'x'.  The following induces an error, until -std is added to get
    proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
    array size at least.  It's necessary to write '\x00'==0 to get something
-   that's true only with -std1.  */
+   that's true only with -std.  */
 int osf4_cc_array ['\x00' == 0 ? 1 : -1];
 
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
 int test (int i, double x);
 struct s1 {int (*f) (int a);};
 struct s2 {int (*f) (double a);};
@@ -2017,239 +2587,107 @@ return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
   return 0;
 }
 _ACEOF
-# Don't try gcc -ansi; that turns off useful extensions and
-# breaks some systems' header files.
-# AIX                  -qlanglvl=ansi
-# Ultrix and OSF/1     -std1
-# HP-UX 10.20 and later        -Ae
-# HP-UX older versions -Aa -D_HPUX_SOURCE
-# SVR4                 -Xc -D__EXTENSIONS__
-for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
 do
   CC="$ac_save_CC $ac_arg"
   rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_prog_cc_stdc=$ac_arg
-break
+  ac_cv_prog_cc_c89=$ac_arg
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
+
 fi
-rm -f conftest.err conftest.$ac_objext
+
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
 done
-rm -f conftest.$ac_ext conftest.$ac_objext
+rm -f conftest.$ac_ext
 CC=$ac_save_CC
 
 fi
-
-case "x$ac_cv_prog_cc_stdc" in
-  x|xno)
-    echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6 ;;
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6; } ;;
+  xno)
+    { echo "$as_me:$LINENO: result: unsupported" >&5
+echo "${ECHO_T}unsupported" >&6; } ;;
   *)
-    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
-    CC="$CC $ac_cv_prog_cc_stdc" ;;
+    CC="$CC $ac_cv_prog_cc_c89"
+    { echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_c89" >&6; } ;;
 esac
 
-# Some people use a C++ compiler to compile C.  Since we use `exit',
-# in C++ we need to declare it.  In case someone uses the same compiler
-# for both compiling C and C++ we need to have the C++ compiler decide
-# the declaration of exit, since it's the most demanding environment.
-cat >conftest.$ac_ext <<_ACEOF
-#ifndef __cplusplus
-  choke me
-#endif
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  for ac_declaration in \
-   '' \
-   'extern "C" void std::exit (int) throw (); using std::exit;' \
-   'extern "C" void std::exit (int); using std::exit;' \
-   'extern "C" void exit (int) throw ();' \
-   'extern "C" void exit (int);' \
-   'void exit (int);'
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+       ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
 do
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_declaration
-#include <stdlib.h>
-int
-main ()
-{
-exit (42);
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-continue
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_declaration
-int
-main ()
-{
-exit (42);
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-rm -f conftest*
-if test -n "$ac_declaration"; then
-  echo '#ifdef __cplusplus' >>confdefs.h
-  echo $ac_declaration      >>confdefs.h
-  echo '#endif'             >>confdefs.h
-fi
-
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
-echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
-  CPP=
-fi
-if test -z "$CPP"; then
-  if test "${ac_cv_prog_CPP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-      # Double quotes because CPP needs to be expanded
-    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
-    do
-      ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -2263,8 +2701,13 @@ cat >>conftest.$ac_ext <<_ACEOF
 #endif
                     Syntax error
 _ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
@@ -2289,9 +2732,10 @@ sed 's/^/| /' conftest.$ac_ext >&5
   # Broken: fails on valid input.
 continue
 fi
+
 rm -f conftest.err conftest.$ac_ext
 
-  # OK, works on sane cases.  Now check whether non-existent headers
+  # OK, works on sane cases.  Now check whether nonexistent headers
   # can be detected and how.
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
@@ -2301,8 +2745,13 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 #include <ac_nonexistent.h>
 _ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
@@ -2329,6 +2778,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
 ac_preproc_ok=:
 break
 fi
+
 rm -f conftest.err conftest.$ac_ext
 
 done
@@ -2346,8 +2796,8 @@ fi
 else
   ac_cv_prog_CPP=$CPP
 fi
-echo "$as_me:$LINENO: result: $CPP" >&5
-echo "${ECHO_T}$CPP" >&6
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6; }
 ac_preproc_ok=false
 for ac_c_preproc_warn_flag in '' yes
 do
@@ -2370,8 +2820,13 @@ cat >>conftest.$ac_ext <<_ACEOF
 #endif
                     Syntax error
 _ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
@@ -2396,9 +2851,10 @@ sed 's/^/| /' conftest.$ac_ext >&5
   # Broken: fails on valid input.
 continue
 fi
+
 rm -f conftest.err conftest.$ac_ext
 
-  # OK, works on sane cases.  Now check whether non-existent headers
+  # OK, works on sane cases.  Now check whether nonexistent headers
   # can be detected and how.
   cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
@@ -2408,8 +2864,13 @@ cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 #include <ac_nonexistent.h>
 _ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
@@ -2436,6 +2897,7 @@ sed 's/^/| /' conftest.$ac_ext >&5
 ac_preproc_ok=:
 break
 fi
+
 rm -f conftest.err conftest.$ac_ext
 
 done
@@ -2458,23 +2920,172 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
-echo "$as_me:$LINENO: checking for egrep" >&5
-echo $ECHO_N "checking for egrep... $ECHO_C" >&6
-if test "${ac_cv_prog_egrep+set}" = set; then
+
+
+{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
-    then ac_cv_prog_egrep='grep -E'
-    else ac_cv_prog_egrep='egrep'
+  # Extract the first word of "grep ggrep" to use in msg output
+if test -z "$GREP"; then
+set dummy grep ggrep; ac_prog_name=$2
+if test "${ac_cv_path_GREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_GREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in grep ggrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_GREP" && $as_executable_p "$ac_path_GREP"; } || continue
+    # Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
     fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_GREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
 fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
-echo "${ECHO_T}$ac_cv_prog_egrep" >&6
- EGREP=$ac_cv_prog_egrep
 
+GREP="$ac_cv_path_GREP"
+if test -z "$GREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
 
-echo "$as_me:$LINENO: checking for ANSI C header files" >&5
-echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+echo "${ECHO_T}$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     # Extract the first word of "egrep" to use in msg output
+if test -z "$EGREP"; then
+set dummy egrep; ac_prog_name=$2
+if test "${ac_cv_path_EGREP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_path_EGREP_found=false
+# Loop through the user's path and test for each of PROGNAME-LIST
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in egrep; do
+  for ac_exec_ext in '' $ac_executable_extensions; do
+    ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+    { test -f "$ac_path_EGREP" && $as_executable_p "$ac_path_EGREP"; } || continue
+    # Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+
+    $ac_path_EGREP_found && break 3
+  done
+done
+
+done
+IFS=$as_save_IFS
+
+
+fi
+
+EGREP="$ac_cv_path_EGREP"
+if test -z "$EGREP"; then
+  { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+
+   fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+echo "${ECHO_T}$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; }
 if test "${ac_cv_header_stdc+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
@@ -2498,24 +3109,36 @@ main ()
 }
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -2524,9 +3147,10 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-ac_cv_header_stdc=no
+       ac_cv_header_stdc=no
 fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
@@ -2582,6 +3206,7 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 #include <ctype.h>
+#include <stdlib.h>
 #if ((' ' & 0x0FF) == 0x020)
 # define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
 # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
@@ -2601,18 +3226,27 @@ main ()
   for (i = 0; i < 256; i++)
     if (XOR (islower (i), ISLOWER (i))
        || toupper (i) != TOUPPER (i))
-      exit(2);
-  exit (0);
+      return 2;
+  return 0;
 }
 _ACEOF
 rm -f conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>&5
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -2625,12 +3259,14 @@ sed 's/^/| /' conftest.$ac_ext >&5
 ( exit $ac_status )
 ac_cv_header_stdc=no
 fi
-rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
 fi
+
+
 fi
 fi
-echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
-echo "${ECHO_T}$ac_cv_header_stdc" >&6
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6; }
 if test $ac_cv_header_stdc = yes; then
 
 cat >>confdefs.h <<\_ACEOF
@@ -2653,9 +3289,9 @@ for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
                  inttypes.h stdint.h unistd.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
+echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   cat >conftest.$ac_ext <<_ACEOF
@@ -2669,24 +3305,36 @@ $ac_includes_default
 #include <$ac_header>
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -2695,12 +3343,14 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-eval "$as_ac_Header=no"
+       eval "$as_ac_Header=no"
 fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+ac_res=`eval echo '${'$as_ac_Header'}'`
+              { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
 if test `eval echo '${'$as_ac_Header'}'` = yes; then
   cat >>confdefs.h <<_ACEOF
 #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
@@ -2711,22 +3361,18 @@ fi
 done
 
 
-
-for ac_header in malloc.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
-  echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
+if test "${ac_cv_header_stdio_h+set}" = set; then
+  { echo "$as_me:$LINENO: checking for stdio.h" >&5
+echo $ECHO_N "checking for stdio.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdio_h+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdio_h" >&5
+echo "${ECHO_T}$ac_cv_header_stdio_h" >&6; }
 else
   # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
+{ echo "$as_me:$LINENO: checking stdio.h usability" >&5
+echo $ECHO_N "checking stdio.h usability... $ECHO_C" >&6; }
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
@@ -2734,27 +3380,39 @@ cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
 $ac_includes_default
-#include <$ac_header>
+#include <stdio.h>
 _ACEOF
 rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+        { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; } &&
         { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
@@ -2763,25 +3421,31 @@ else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-ac_header_compiler=no
+       ac_header_compiler=no
 fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
 
 # Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
+{ echo "$as_me:$LINENO: checking stdio.h presence" >&5
+echo $ECHO_N "checking stdio.h presence... $ECHO_C" >&6; }
 cat >conftest.$ac_ext <<_ACEOF
 /* confdefs.h.  */
 _ACEOF
 cat confdefs.h >>conftest.$ac_ext
 cat >>conftest.$ac_ext <<_ACEOF
 /* end confdefs.h.  */
-#include <$ac_header>
+#include <stdio.h>
 _ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
   ac_status=$?
   grep -v '^ *+' conftest.er1 >conftest.err
   rm -f conftest.er1
@@ -2805,79 +3469,72 @@ sed 's/^/| /' conftest.$ac_ext >&5
 
   ac_header_preproc=no
 fi
+
 rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
 
 # So?  What about this header?
 case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
   yes:no: )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdio.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: stdio.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdio.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: stdio.h: proceeding with the compiler's result" >&2;}
     ac_header_preproc=yes
     ;;
   no:yes:* )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
-    (
-      cat <<\_ASBOX
-## ------------------------------------------ ##
-## Report this to the AC_PACKAGE_NAME lists.  ##
-## ------------------------------------------ ##
-_ASBOX
-    ) |
-      sed "s/^/$as_me: WARNING:     /" >&2
+    { echo "$as_me:$LINENO: WARNING: stdio.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: stdio.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdio.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: stdio.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdio.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: stdio.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdio.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: stdio.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdio.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: stdio.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: stdio.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: stdio.h: in the future, the compiler will take precedence" >&2;}
+
     ;;
 esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
+{ echo "$as_me:$LINENO: checking for stdio.h" >&5
+echo $ECHO_N "checking for stdio.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_stdio_h+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
-  eval "$as_ac_Header=\$ac_header_preproc"
+  ac_cv_header_stdio_h=$ac_header_preproc
 fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+{ echo "$as_me:$LINENO: result: $ac_cv_header_stdio_h" >&5
+echo "${ECHO_T}$ac_cv_header_stdio_h" >&6; }
 
 fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+if test $ac_cv_header_stdio_h = yes; then
+   slog_cflags="$acctlog_cflags -I/usr/include"
+else
+   fail=$fail" stdio.h"
 
 fi
 
-done
 
 
-       targetname=rlm_eap_md5     # keep this!  Don't change!
+       targetname=rlm_acctlog
 else
-       targetname=            # keep this!  Don't change!
-       echo \*\*\* module rlm_eap_md5 is disabled.  # keep this!  Don't change!
+       targetname=
+       echo \*\*\* module rlm_acctlog is disabled.
 fi
 
 if test x"$fail" != x""; then
        if test x"${enable_strict_dependencies}" = x"yes"; then
-               { { echo "$as_me:$LINENO: error: set --without-rlm_eap_md5 to disable it explicitly." >&5
-echo "$as_me: error: set --without-rlm_eap_md5 to disable it explicitly." >&2;}
+               { { echo "$as_me:$LINENO: error: set --without-rlm_acctlog to disable it explicitly." >&5
+echo "$as_me: error: set --without-rlm_acctlog to disable it explicitly." >&2;}
    { (exit 1); exit 1; }; }
        else
-               { echo "$as_me:$LINENO: WARNING: silently not building rlm_eap_md5." >&5
-echo "$as_me: WARNING: silently not building rlm_eap_md5." >&2;}
-               { echo "$as_me:$LINENO: WARNING: FAILURE: rlm_eap_md5 requires: $fail." >&5
-echo "$as_me: WARNING: FAILURE: rlm_eap_md5 requires: $fail." >&2;};
+               { echo "$as_me:$LINENO: WARNING: silently not building rlm_acctlog." >&5
+echo "$as_me: WARNING: silently not building rlm_acctlog." >&2;}
+               { echo "$as_me:$LINENO: WARNING: FAILURE: rlm_acctlog requires: $fail." >&5
+echo "$as_me: WARNING: FAILURE: rlm_acctlog requires: $fail." >&2;};
                targetname=""
        fi
 fi
@@ -2886,8 +3543,10 @@ fi
 
 
 
-  # keep this!  Don't change!
-          ac_config_files="$ac_config_files Makefile"
+
+
+ac_config_files="$ac_config_files Makefile"
+
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
 # tests run on this system so they can be shared between configure
@@ -2906,39 +3565,58 @@ _ACEOF
 
 # The following way of writing the cache mishandles newlines in values,
 # but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
+# So, we kill variables containing newlines.
 # Ultrix sh set writes to stderr and can't be redirected directly,
 # and sets the high bit in the cache file unless we assign to the vars.
-{
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5
+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+
   (set) 2>&1 |
-    case `(ac_space=' '; set | grep ac_space) 2>&1` in
-    *ac_space=\ *)
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
       # `set' does not quote correctly, so add quotes (double-quote
       # substitution turns \\\\ into \\, and sed turns \\ into \).
       sed -n \
        "s/'/'\\\\''/g;
          s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
-      ;;
+      ;; #(
     *)
       # `set' quotes correctly as required by POSIX, so do not add quotes.
-      sed -n \
-       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
       ;;
-    esac;
-} |
+    esac |
+    sort
+) |
   sed '
+     /^ac_cv_env_/b end
      t clear
-     : clear
+     :clear
      s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
      t end
-     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
-     : end' >>confcache
-if diff $cache_file confcache >/dev/null 2>&1; then :; else
-  if test -w $cache_file; then
-    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { echo "$as_me:$LINENO: updating cache $cache_file" >&5
+echo "$as_me: updating cache $cache_file" >&6;}
     cat confcache >$cache_file
   else
-    echo "not updating unwritable cache $cache_file"
+    { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+echo "$as_me: not updating unwritable cache $cache_file" >&6;}
   fi
 fi
 rm -f confcache
@@ -2947,63 +3625,48 @@ test "x$prefix" = xNONE && prefix=$ac_default_prefix
 # Let make expand exec_prefix.
 test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
 
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
-# trailing colons and then remove the whole line if VPATH becomes empty
-# (actually we leave an empty line to preserve line numbers).
-if test "x$srcdir" = x.; then
-  ac_vpsub='/^[         ]*VPATH[        ]*=/{
-s/:*\$(srcdir):*/:/;
-s/:*\${srcdir}:*/:/;
-s/:*@srcdir@:*/:/;
-s/^\([^=]*=[    ]*\):*/\1/;
-s/:*$//;
-s/^[^=]*=[      ]*$//;
-}'
-fi
-
 # Transform confdefs.h into DEFS.
 # Protect against shell expansion while executing Makefile rules.
 # Protect against Makefile macro expansion.
 #
 # If the first sed substitution is executed (which looks for macros that
-# take arguments), then we branch to the quote section.  Otherwise,
+# take arguments), then branch to the quote section.  Otherwise,
 # look for a macro that doesn't take arguments.
-cat >confdef2opt.sed <<\_ACEOF
+ac_script='
 t clear
-: clear
-s,^[    ]*#[    ]*define[       ][      ]*\([^  (][^    (]*([^)]*)\)[   ]*\(.*\),-D\1=\2,g
+:clear
+s/^[    ]*#[    ]*define[       ][      ]*\([^  (][^    (]*([^)]*)\)[   ]*\(.*\)/-D\1=\2/g
 t quote
-s,^[    ]*#[    ]*define[       ][      ]*\([^  ][^     ]*\)[   ]*\(.*\),-D\1=\2,g
+s/^[    ]*#[    ]*define[       ][      ]*\([^  ][^     ]*\)[   ]*\(.*\)/-D\1=\2/g
 t quote
-d
-: quote
-s,[     `~#$^&*(){}\\|;'"<>?],\\&,g
-s,\[,\\&,g
-s,\],\\&,g
-s,\$,$$,g
-p
-_ACEOF
-# We use echo to avoid assuming a particular line-breaking character.
-# The extra dot is to prevent the shell from consuming trailing
-# line-breaks from the sub-command output.  A line-break within
-# single-quotes doesn't work because, if this script is created in a
-# platform that uses two characters for line-breaks (e.g., DOS), tr
-# would break.
-ac_LF_and_DOT=`echo; echo .`
-DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
-rm -f confdef2opt.sed
+b any
+:quote
+s/[     `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+       g
+       s/^\n//
+       s/\n/ /g
+       p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
 
 
 ac_libobjs=
 ac_ltlibobjs=
 for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
   # 1. Remove the extension, and $U if already installed.
-  ac_i=`echo "$ac_i" |
-        sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
-  # 2. Add them.
-  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
-  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
 done
 LIBOBJS=$ac_libobjs
 
@@ -3041,11 +3704,35 @@ if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
   # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
   # is contrary to our usage.  Disable this feature.
   alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
-  set -o posix
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
 fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
 DUALCASE=1; export DUALCASE # for MKS sh
 
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  echo "#! /bin/sh" >conf$$.sh
+  echo  "exit 0"   >>conf$$.sh
+  chmod +x conf$$.sh
+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+    PATH_SEPARATOR=';'
+  else
+    PATH_SEPARATOR=:
+  fi
+  rm -f conf$$.sh
+fi
+
 # Support unset when possible.
 if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
   as_unset=unset
@@ -3054,8 +3741,43 @@ else
 fi
 
 
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+as_nl='
+'
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
 # Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
 PS1='$ '
 PS2='> '
 PS4='+ '
@@ -3069,18 +3791,19 @@ do
   if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
     eval $as_var=C; export $as_var
   else
-    $as_unset $as_var
+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
   fi
 done
 
 # Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
   as_expr=expr
 else
   as_expr=false
 fi
 
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
   as_basename=basename
 else
   as_basename=false
 
 
 # Name of the executable.
-as_me=`$as_basename "$0" ||
+as_me=`$as_basename -- "$0" ||
 $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
         X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)$' \| \
-        .     : '\(.\)' 2>/dev/null ||
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
 echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
-         /^X\/\(\/\/\)$/{ s//\1/; q; }
-         /^X\/\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
 
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
+# CDPATH.
+$as_unset CDPATH
 
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
-fi
 
 
   as_lineno_1=$LINENO
   as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
   test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
-  # Find who we are.  Look in the path if we contain no path at all
-  # relative or not.
-  case $0 in
-    *[\\/]* ) as_myself=$0 ;;
-    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
-       ;;
-  esac
-  # We did not find ourselves, most probably we were run as `sh COMMAND'
-  # in which case we are not to be found in the path.
-  if test "x$as_myself" = x; then
-    as_myself=$0
-  fi
-  if test ! -f "$as_myself"; then
-    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
-echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
-   { (exit 1); exit 1; }; }
-  fi
-  case $CONFIG_SHELL in
-  '')
-    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for as_base in sh bash ksh sh5; do
-        case $as_dir in
-        /*)
-          if ("$as_dir/$as_base" -c '
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
-            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
-            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
-            CONFIG_SHELL=$as_dir/$as_base
-            export CONFIG_SHELL
-            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
-          fi;;
-        esac
-       done
-done
-;;
-  esac
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
 
   # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
   # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line before each line; the second 'sed' does the real
-  # work.  The second script uses 'N' to pair each line-number line
-  # with the numbered line, and appends trailing '-' during
-  # substitution so that $LINENO is not a special case at line end.
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
   # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
-  sed '=' <$as_myself |
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
     sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
       N
-      s,$,-,
-      : loop
-      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
       t loop
-      s,-$,,
-      s,^['$as_cr_digits']*\n,,
+      s/-\n.*//
     ' >$as_me.lineno &&
-  chmod +x $as_me.lineno ||
-    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
-echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+  chmod +x "$as_me.lineno" ||
+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
    { (exit 1); exit 1; }; }
 
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensible to this).
-  . ./$as_me.lineno
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
   # Exit status is that of the last command.
   exit
 }
 
 
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
-  *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T='     ' ;;
-  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
-  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
 esac
 
-if expr a : '\(a\)' >/dev/null 2>&1; then
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
   as_expr=expr
 else
   as_expr=false
 fi
 
 rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir
+fi
 echo >conf$$.file
 if ln -s conf$$.file conf$$ 2>/dev/null; then
-  # We could just check for DJGPP; but this test a) works b) is more generic
-  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
-  if test -f conf$$.exe; then
-    # Don't use ln at all; we don't have any links
+  as_ln_s='ln -s'
+  # ... but there are two gotchas:
+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+  # In both cases, we have to default to `cp -p'.
+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
     as_ln_s='cp -p'
-  else
-    as_ln_s='ln -s'
-  fi
 elif ln conf$$.file conf$$ 2>/dev/null; then
   as_ln_s=ln
 else
   as_ln_s='cp -p'
 fi
-rm -f conf$$ conf$$.exe conf$$.file
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
 
 if mkdir -p . 2>/dev/null; then
   as_mkdir_p=:
@@ -3249,7 +3933,19 @@ else
   as_mkdir_p=false
 fi
 
-as_executable_p="test -f"
+# Find out whether ``test -x'' works.  Don't use a zero-byte file, as
+# systems may use methods other than mode bits to determine executability.
+cat >conf$$.file <<_ASEOF
+#! /bin/sh
+exit 0
+_ASEOF
+chmod +x conf$$.file
+if test -x conf$$.file >/dev/null 2>&1; then
+  as_executable_p="test -x"
+else
+  as_executable_p=:
+fi
+rm -f conf$$.file
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -3258,31 +3954,14 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
 as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
 
 
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS="  $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
 exec 6>&1
 
-# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# Save the log message, to keep $[0] and so on meaningful, and to
 # report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling.  Logging --version etc. is OK.
-exec 5>>config.log
-{
-  echo
-  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
-} >&5
-cat >&5 <<_CSEOF
-
+# values after options handling.
+ac_log="
 This file was extended by $as_me, which was
-generated by GNU Autoconf 2.59.  Invocation command line was
+generated by GNU Autoconf 2.60.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -3290,30 +3969,18 @@ generated by GNU Autoconf 2.59.  Invocation command line was
   CONFIG_COMMANDS = $CONFIG_COMMANDS
   $ $0 $@
 
-_CSEOF
-echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
-echo >&5
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
 _ACEOF
 
+cat >>$CONFIG_STATUS <<_ACEOF
 # Files that config.status was made for.
-if test -n "$ac_config_files"; then
-  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_headers"; then
-  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
-fi
+config_files="$ac_config_files"
 
-if test -n "$ac_config_links"; then
-  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_commands"; then
-  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
-fi
+_ACEOF
 
 cat >>$CONFIG_STATUS <<\_ACEOF
-
 ac_cs_usage="\
 \`$as_me' instantiates files from templates according to the
 current configuration.
@@ -3332,18 +3999,20 @@ Configuration files:
 $config_files
 
 Report bugs to <bug-autoconf@gnu.org>."
-_ACEOF
 
+_ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
 config.status
-configured by $0, generated by GNU Autoconf 2.59,
-  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+configured by $0, generated by GNU Autoconf 2.60,
+  with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
-Copyright (C) 2003 Free Software Foundation, Inc.
+Copyright (C) 2006 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
-srcdir=$srcdir
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
 _ACEOF
 
 cat >>$CONFIG_STATUS <<\_ACEOF
@@ -3354,60 +4023,42 @@ while test $# != 0
 do
   case $1 in
   --*=*)
-    ac_option=`expr "x$1" : 'x\([^=]*\)='`
-    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
     ac_shift=:
     ;;
-  -*)
+  *)
     ac_option=$1
     ac_optarg=$2
     ac_shift=shift
     ;;
-  *) # This is not an option, so the user has probably given explicit
-     # arguments.
-     ac_option=$1
-     ac_need_defaults=false;;
   esac
 
   case $ac_option in
   # Handling of the options.
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
   -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
     ac_cs_recheck=: ;;
-  --version | --vers* | -V )
-    echo "$ac_cs_version"; exit 0 ;;
-  --he | --h)
-    # Conflict between --help and --header
-    { { echo "$as_me:$LINENO: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&2;}
-   { (exit 1); exit 1; }; };;
-  --help | --hel | -h )
-    echo "$ac_cs_usage"; exit 0 ;;
-  --debug | --d* | -d )
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
     debug=: ;;
   --file | --fil | --fi | --f )
     $ac_shift
     CONFIG_FILES="$CONFIG_FILES $ac_optarg"
     ac_need_defaults=false;;
-  --header | --heade | --head | --hea )
-    $ac_shift
-    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
-    ac_need_defaults=false;;
+  --he | --h |  --help | --hel | -h )
+    echo "$ac_cs_usage"; exit ;;
   -q | -quiet | --quiet | --quie | --qui | --qu | --q \
   | -silent | --silent | --silen | --sile | --sil | --si | --s)
     ac_cs_silent=: ;;
 
   # This is an error.
-  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2;}
+  -*) { echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
    { (exit 1); exit 1; }; } ;;
 
-  *) ac_config_targets="$ac_config_targets $1" ;;
+  *) ac_config_targets="$ac_config_targets $1"
+     ac_need_defaults=false ;;
 
   esac
   shift
@@ -3423,28 +4074,42 @@ fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 if \$ac_cs_recheck; then
-  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
-  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+  CONFIG_SHELL=$SHELL
+  export CONFIG_SHELL
+  exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
 fi
 
 _ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  echo "$ac_log"
+} >&5
 
-
-
-
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+_ACEOF
 
 cat >>$CONFIG_STATUS <<\_ACEOF
+
+# Handling of arguments.
 for ac_config_target in $ac_config_targets
 do
-  case "$ac_config_target" in
-  # Handling of arguments.
-  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+  case $ac_config_target in
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+
   *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
 echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
    { (exit 1); exit 1; }; };;
   esac
 done
 
+
 # If the user did not use the arguments to specify the items to instantiate,
 # then the envvar interface is used.  Set only those that are not.
 # We use the long form for the default assignment because of an extremely
@@ -3454,294 +4119,362 @@ if $ac_need_defaults; then
 fi
 
 # Have a temporary directory for convenience.  Make it in the build tree
-# simply because there is no reason to put it here, and in addition,
+# simply because there is no reason against having it here, and in addition,
 # creating and moving files from /tmp can sometimes cause problems.
-# Create a temporary directory, and hook for its removal unless debugging.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
 $debug ||
 {
-  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
   trap '{ (exit 1); exit 1; }' 1 2 13 15
 }
-
 # Create a (secure) tmp directory for tmp files.
 
 {
-  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
   test -n "$tmp" && test -d "$tmp"
 }  ||
 {
-  tmp=./confstat$$-$RANDOM
-  (umask 077 && mkdir $tmp)
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
 } ||
 {
    echo "$me: cannot create a temporary directory in ." >&2
    { (exit 1); exit 1; }
 }
 
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-
 #
-# CONFIG_FILES section.
+# Set up the sed scripts for CONFIG_FILES section.
 #
 
 # No need to generate the scripts if there are no CONFIG_FILES.
 # This happens for instance when ./config.status config.h
-if test -n "\$CONFIG_FILES"; then
-  # Protect against being on the right side of a sed subst in config.status.
-  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
-   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
-s,@SHELL@,$SHELL,;t t
-s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
-s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
-s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
-s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
-s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
-s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
-s,@exec_prefix@,$exec_prefix,;t t
-s,@prefix@,$prefix,;t t
-s,@program_transform_name@,$program_transform_name,;t t
-s,@bindir@,$bindir,;t t
-s,@sbindir@,$sbindir,;t t
-s,@libexecdir@,$libexecdir,;t t
-s,@datadir@,$datadir,;t t
-s,@sysconfdir@,$sysconfdir,;t t
-s,@sharedstatedir@,$sharedstatedir,;t t
-s,@localstatedir@,$localstatedir,;t t
-s,@libdir@,$libdir,;t t
-s,@includedir@,$includedir,;t t
-s,@oldincludedir@,$oldincludedir,;t t
-s,@infodir@,$infodir,;t t
-s,@mandir@,$mandir,;t t
-s,@build_alias@,$build_alias,;t t
-s,@host_alias@,$host_alias,;t t
-s,@target_alias@,$target_alias,;t t
-s,@DEFS@,$DEFS,;t t
-s,@ECHO_C@,$ECHO_C,;t t
-s,@ECHO_N@,$ECHO_N,;t t
-s,@ECHO_T@,$ECHO_T,;t t
-s,@LIBS@,$LIBS,;t t
-s,@CC@,$CC,;t t
-s,@CFLAGS@,$CFLAGS,;t t
-s,@LDFLAGS@,$LDFLAGS,;t t
-s,@CPPFLAGS@,$CPPFLAGS,;t t
-s,@ac_ct_CC@,$ac_ct_CC,;t t
-s,@EXEEXT@,$EXEEXT,;t t
-s,@OBJEXT@,$OBJEXT,;t t
-s,@CPP@,$CPP,;t t
-s,@EGREP@,$EGREP,;t t
-s,@eap_md5_cflags@,$eap_md5_cflags,;t t
-s,@eap_md5_ldflags@,$eap_md5_ldflags,;t t
-s,@targetname@,$targetname,;t t
-s,@LIBOBJS@,$LIBOBJS,;t t
-s,@LTLIBOBJS@,$LTLIBOBJS,;t t
-CEOF
-
-_ACEOF
-
-  cat >>$CONFIG_STATUS <<\_ACEOF
-  # Split the substitutions into bite-sized pieces for seds with
-  # small command number limits, like on Digital OSF/1 and HP-UX.
-  ac_max_sed_lines=48
-  ac_sed_frag=1 # Number of current file.
-  ac_beg=1 # First line for current file.
-  ac_end=$ac_max_sed_lines # Line after last line for current file.
-  ac_more_lines=:
-  ac_sed_cmds=
-  while $ac_more_lines; do
-    if test $ac_beg -gt 1; then
-      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
-    else
-      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
-    fi
-    if test ! -s $tmp/subs.frag; then
-      ac_more_lines=false
-    else
-      # The purpose of the label and of the branching condition is to
-      # speed up the sed processing (if there are no `@' at all, there
-      # is no need to browse any of the substitutions).
-      # These are the two extra sed commands mentioned above.
-      (echo ':t
-  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
-      if test -z "$ac_sed_cmds"; then
-       ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
-      else
-       ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
-      fi
-      ac_sed_frag=`expr $ac_sed_frag + 1`
-      ac_beg=$ac_end
-      ac_end=`expr $ac_end + $ac_max_sed_lines`
-    fi
-  done
-  if test -z "$ac_sed_cmds"; then
-    ac_sed_cmds=cat
+if test -n "$CONFIG_FILES"; then
+
+_ACEOF
+
+
+
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  cat >conf$$subs.sed <<_ACEOF
+SHELL!$SHELL$ac_delim
+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim
+PACKAGE_NAME!$PACKAGE_NAME$ac_delim
+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim
+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim
+PACKAGE_STRING!$PACKAGE_STRING$ac_delim
+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim
+exec_prefix!$exec_prefix$ac_delim
+prefix!$prefix$ac_delim
+program_transform_name!$program_transform_name$ac_delim
+bindir!$bindir$ac_delim
+sbindir!$sbindir$ac_delim
+libexecdir!$libexecdir$ac_delim
+datarootdir!$datarootdir$ac_delim
+datadir!$datadir$ac_delim
+sysconfdir!$sysconfdir$ac_delim
+sharedstatedir!$sharedstatedir$ac_delim
+localstatedir!$localstatedir$ac_delim
+includedir!$includedir$ac_delim
+oldincludedir!$oldincludedir$ac_delim
+docdir!$docdir$ac_delim
+infodir!$infodir$ac_delim
+htmldir!$htmldir$ac_delim
+dvidir!$dvidir$ac_delim
+pdfdir!$pdfdir$ac_delim
+psdir!$psdir$ac_delim
+libdir!$libdir$ac_delim
+localedir!$localedir$ac_delim
+mandir!$mandir$ac_delim
+DEFS!$DEFS$ac_delim
+ECHO_C!$ECHO_C$ac_delim
+ECHO_N!$ECHO_N$ac_delim
+ECHO_T!$ECHO_T$ac_delim
+LIBS!$LIBS$ac_delim
+build_alias!$build_alias$ac_delim
+host_alias!$host_alias$ac_delim
+target_alias!$target_alias$ac_delim
+CC!$CC$ac_delim
+CFLAGS!$CFLAGS$ac_delim
+LDFLAGS!$LDFLAGS$ac_delim
+CPPFLAGS!$CPPFLAGS$ac_delim
+ac_ct_CC!$ac_ct_CC$ac_delim
+EXEEXT!$EXEEXT$ac_delim
+OBJEXT!$OBJEXT$ac_delim
+CPP!$CPP$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
+acctlog_cflags!$acctlog_cflags$ac_delim
+acctlog_ldflags!$acctlog_ldflags$ac_delim
+targetname!$targetname$ac_delim
+LIBOBJS!$LIBOBJS$ac_delim
+LTLIBOBJS!$LTLIBOBJS$ac_delim
+_ACEOF
+
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 52; then
+    break
+  elif $ac_last_try; then
+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
   fi
-fi # test -n "$CONFIG_FILES"
+done
+
+ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`
+if test -n "$ac_eof"; then
+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`
+  ac_eof=`expr $ac_eof + 1`
+fi
 
+cat >>$CONFIG_STATUS <<_ACEOF
+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end
+_ACEOF
+sed '
+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g
+s/^/s,@/; s/!/@,|#_!!_#|/
+:n
+t n
+s/'"$ac_delim"'$/,g/; t
+s/$/\\/; p
+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n
+' >>$CONFIG_STATUS <conf$$subs.sed
+rm -f conf$$subs.sed
+cat >>$CONFIG_STATUS <<_ACEOF
+:end
+s/|#_!!_#|//g
+CEOF$ac_eof
 _ACEOF
+
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[    ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[      ]*$//
+}'
+fi
+
 cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
-  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
-  case $ac_file in
-  - | *:- | *:-:* ) # input from stdin
-       cat >$tmp/stdin
-       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
-       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
-  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
-       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
-  * )   ac_file_in=$ac_file.in ;;
+fi # test -n "$CONFIG_FILES"
+
+
+for ac_tag in  :F $CONFIG_FILES
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5
+echo "$as_me: error: Invalid tag $ac_tag." >&2;}
+   { (exit 1); exit 1; }; };;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+        # (if the path is not absolute).  The absolute path cannot be DOS-style,
+        # because $ac_f cannot contain `:'.
+        test -f "$ac_f" ||
+          case $ac_f in
+          [\\/$]*) false;;
+          *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+          esac ||
+          { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+   { (exit 1); exit 1; }; };;
+      esac
+      ac_file_inputs="$ac_file_inputs $ac_f"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input="Generated from "`IFS=:
+         echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    fi
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin";;
+    esac
+    ;;
   esac
 
-  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
-  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+  ac_dir=`$as_dirname -- "$ac_file" ||
 $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
         X"$ac_file" : 'X\(//\)[^/]' \| \
         X"$ac_file" : 'X\(//\)$' \| \
-        X"$ac_file" : 'X\(/\)' \| \
-        .     : '\(.\)' 2>/dev/null ||
+        X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
 echo X"$ac_file" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-         /^X\(\/\/\)$/{ s//\1/; q; }
-         /^X\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-  { if $as_mkdir_p; then
-    mkdir -p "$ac_dir"
-  else
-    as_dir="$ac_dir"
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  { as_dir="$ac_dir"
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
     as_dirs=
-    while test ! -d "$as_dir"; do
-      as_dirs="$as_dir $as_dirs"
-      as_dir=`(dirname "$as_dir") 2>/dev/null ||
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
 $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
         X"$as_dir" : 'X\(//\)[^/]' \| \
         X"$as_dir" : 'X\(//\)$' \| \
-        X"$as_dir" : 'X\(/\)' \| \
-        .     : '\(.\)' 2>/dev/null ||
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
 echo X"$as_dir" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-         /^X\(\/\/\)$/{ s//\1/; q; }
-         /^X\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
     done
-    test ! -n "$as_dirs" || mkdir $as_dirs
-  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
-echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+echo "$as_me: error: cannot create directory $as_dir" >&2;}
    { (exit 1); exit 1; }; }; }
-
   ac_builddir=.
 
-if test "$ac_dir" != .; then
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
   ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A "../" for each directory in $ac_dir_suffix.
-  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
-  ac_dir_suffix= ac_top_builddir=
-fi
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
 
 case $srcdir in
-  .)  # No --srcdir option.  We are building in place.
+  .)  # We are building in place.
     ac_srcdir=.
-    if test -z "$ac_top_builddir"; then
-       ac_top_srcdir=.
-    else
-       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
-    fi ;;
-  [\\/]* | ?:[\\/]* )  # Absolute path.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
     ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir ;;
-  *) # Relative path.
-    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_builddir$srcdir ;;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
 esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
 
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
-  case "$ac_dir" in
-  .) ac_abs_builddir=`pwd`;;
-  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
-  *) ac_abs_builddir=`pwd`/"$ac_dir";;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
-  case ${ac_top_builddir}. in
-  .) ac_abs_top_builddir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
-  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
-  case $ac_srcdir in
-  .) ac_abs_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
-  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
-  case $ac_top_srcdir in
-  .) ac_abs_top_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
-  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
-  esac;;
-esac
 
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
 
+_ACEOF
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
-  # Let's still pretend it is `configure' which instantiates (i.e., don't
-  # use $as_me), people would be surprised to read:
-  #    /* config.h.  Generated by config.status.  */
-  if test x"$ac_file" = x-; then
-    configure_input=
-  else
-    configure_input="$ac_file.  "
-  fi
-  configure_input=$configure_input"Generated from `echo $ac_file_in |
-                                    sed 's,.*/,,'` by configure."
-
-  # First look for the input files in the build tree, otherwise in the
-  # src tree.
-  ac_file_inputs=`IFS=:
-    for f in $ac_file_in; do
-      case $f in
-      -) echo $tmp/stdin ;;
-      [\\/$]*)
-        # Absolute (can't be DOS-style, as IFS=:)
-        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
-   { (exit 1); exit 1; }; }
-        echo "$f";;
-      *) # Relative
-        if test -f "$f"; then
-          # Build tree
-          echo "$f"
-        elif test -f "$srcdir/$f"; then
-          # Source tree
-          echo "$srcdir/$f"
-        else
-          # /dev/null tree
-          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
-   { (exit 1); exit 1; }; }
-        fi;;
-      esac
-    done` || { (exit 1); exit 1; }
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+case `sed -n '/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+' $ac_file_inputs` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+    s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
 _ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
 $extrasub
@@ -3749,28 +4482,39 @@ _ACEOF
 cat >>$CONFIG_STATUS <<\_ACEOF
 :t
 /@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s,@configure_input@,$configure_input,;t t
-s,@srcdir@,$ac_srcdir,;t t
-s,@abs_srcdir@,$ac_abs_srcdir,;t t
-s,@top_srcdir@,$ac_top_srcdir,;t t
-s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
-s,@builddir@,$ac_builddir,;t t
-s,@abs_builddir@,$ac_abs_builddir,;t t
-s,@top_builddir@,$ac_top_builddir,;t t
-s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
-" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
-  rm -f $tmp/stdin
-  if test x"$ac_file" != x-; then
-    mv $tmp/out $ac_file
-  else
-    cat $tmp/out
-    rm -f $tmp/out
-  fi
+s&@configure_input@&$configure_input&;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[         ]*datarootdir[  ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out"; rm -f "$tmp/out";;
+  *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
+  esac
+ ;;
 
-done
-_ACEOF
 
-cat >>$CONFIG_STATUS <<\_ACEOF
+
+  esac
+
+done # for ac_tag
+
 
 { (exit 0); exit 0; }
 _ACEOF
@@ -3798,4 +4542,4 @@ if test "$no_create" != yes; then
   # would make configure fail if this is the last instruction.
   $ac_cs_success || { (exit 1); exit 1; }
 fi
-  # keep this!  Don't change!
+
diff --git a/src/modules/rlm_acctlog/configure.in b/src/modules/rlm_acctlog/configure.in
new file mode 100644 (file)
index 0000000..7b182cd
--- /dev/null
@@ -0,0 +1,39 @@
+AC_PREREQ([2.53])
+AC_INIT(rlm_acctlog.c)
+AC_REVISION(0.1)
+AC_DEFUN(modname,[rlm_acctlog]) 
+
+if test x$with_[]modname != xno; then
+
+       AC_PROG_CC
+       AC_PROG_CPP
+
+       AC_CHECK_HEADER(stdio.h,
+               [ slog_cflags="$acctlog_cflags -I/usr/include" ],
+               [ fail=$fail" stdio.h" ]
+       )
+
+       targetname=modname     
+else
+       targetname=            
+       echo \*\*\* module modname is disabled.  
+fi
+
+dnl  Don't change this section.
+if test x"$fail" != x""; then
+       if test x"${enable_strict_dependencies}" = x"yes"; then
+               AC_MSG_ERROR([set --without-]modname[ to disable it explicitly.])
+       else
+               AC_MSG_WARN([silently not building ]modname[.])
+               AC_MSG_WARN([FAILURE: ]modname[ requires: $fail.]); 
+               targetname=""
+       fi
+fi
+
+
+AC_SUBST(acctlog_cflags)  
+AC_SUBST(acctlog_ldflags)
+
+
+AC_SUBST(targetname) 
+AC_OUTPUT(Makefile) 
diff --git a/src/modules/rlm_acctlog/rlm_acctlog.c b/src/modules/rlm_acctlog/rlm_acctlog.c
new file mode 100644 (file)
index 0000000..137e666
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ *      rlm_acctlog.c
+ *
+ *   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 2006 Suntel Communications - www.suntel.com.tr
+ *   Copyright 2006 The FreeRADIUS server project
+ *
+ *   Tuyan Ozipek
+ *   Peter Nixon
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/conffile.h>
+
+typedef struct rlm_acctlog_t {
+    char        *acctstart;
+    char        *acctstop;
+       char            *acctupdate;
+    char        *accton;
+       char            *acctoff;
+
+} rlm_acctlog_t;
+
+static const CONF_PARSER module_config[] = {
+    { "acctlog_update",  PW_TYPE_STRING_PTR, offsetof(rlm_acctlog_t, acctupdate), NULL,  ""},
+    { "acctlog_start",  PW_TYPE_STRING_PTR, offsetof(rlm_acctlog_t, acctstart), NULL,  ""},
+    { "acctlog_stop",  PW_TYPE_STRING_PTR, offsetof(rlm_acctlog_t, acctstop), NULL,  ""},
+    { "acctlog_on",  PW_TYPE_STRING_PTR, offsetof(rlm_acctlog_t, accton), NULL,  ""},
+    { "acctlog_off",  PW_TYPE_STRING_PTR, offsetof(rlm_acctlog_t, acctoff), NULL,  ""},
+    { NULL, -1, 0, NULL, NULL }     /* end the list */
+};
+
+
+static int acctlog_detach(void *instance)
+{   
+    rlm_acctlog_t *inst = instance;
+       
+       
+    free(inst);
+    return 0;
+}
+
+static int acctlog_instantiate(CONF_SECTION *conf, void **instance)
+{
+       rlm_acctlog_t *inst;
+
+    inst = rad_malloc(sizeof(*inst));
+    memset(inst, 0, sizeof(*inst));
+
+       if (cf_section_parse(conf, inst, module_config) < 0) {
+               acctlog_detach(inst);
+               return -1;
+       }
+
+       *instance = inst;
+
+    return 0;
+
+}
+
+static int do_acctlog_acct(void *instance, REQUEST *request)
+{
+       rlm_acctlog_t *inst;
+       VALUE_PAIR *pair;
+
+       char    logstr[MAX_STRING_LEN];
+       int     acctstatustype = 0;
+
+
+       inst = (rlm_acctlog_t*) instance;
+
+    if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) != NULL) {
+        acctstatustype = pair->lvalue;
+    } else {
+        radius_xlat(logstr, sizeof(logstr), "packet has no accounting status type. [user '%{User-Name}', nas '%{NAS-IP-Address}']", request, NULL);
+        radlog(L_ERR, "rlm_acctlog (%s)", logstr);
+        return RLM_MODULE_INVALID;
+    }
+
+       switch (acctstatustype) {
+               case PW_STATUS_START:
+                       radius_xlat(logstr, sizeof(logstr), inst->acctstart, request, NULL);
+               break;
+               case PW_STATUS_STOP:
+                       radius_xlat(logstr, sizeof(logstr), inst->acctstop, request, NULL);
+               break;
+               case PW_STATUS_ALIVE:
+                       radius_xlat(logstr, sizeof(logstr), inst->acctupdate, request, NULL);
+               break;
+               case PW_STATUS_ACCOUNTING_ON:
+                       radius_xlat(logstr, sizeof(logstr), inst->accton, request, NULL);
+               break;
+               case PW_STATUS_ACCOUNTING_OFF:
+                       radius_xlat(logstr, sizeof(logstr), inst->acctoff, request, NULL);
+               break;
+               
+       }
+
+       if (strlen(logstr))
+               radlog(L_ACCT,"%s", logstr);
+
+       return RLM_MODULE_OK;
+}
+
+/*
+ *  Externally visible module definition.
+ */
+module_t rlm_acctlog = {
+    RLM_MODULE_INIT,
+    "acctlog",
+    RLM_TYPE_THREAD_SAFE,       /* type */
+    acctlog_instantiate,        /* instantiation */
+    acctlog_detach,         /* detach */
+    {
+        NULL, /* authentication */
+        NULL, /* authorization */
+        NULL, /* preaccounting */
+        do_acctlog_acct, /* accounting */
+        NULL,       /* checksimul */
+        NULL,     /* pre-proxy */
+        NULL, /* post-proxy */
+        NULL  /* post-auth */
+    },
+};
+
index ddc6648..27363e4 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
-
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 /*
  *     The instance data for rlm_always is the list of fake values we are
@@ -51,7 +50,7 @@ typedef struct rlm_always_t {
  *     to the strdup'd string into 'config.string'.  This gets around
  *     buffer over-flows.
  */
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
   { "rcode",      PW_TYPE_STRING_PTR, offsetof(rlm_always_t,rcode_str),
     NULL, "fail" },
   { "simulcount", PW_TYPE_INTEGER,    offsetof(rlm_always_t,simulcount),
@@ -115,8 +114,6 @@ static int always_instantiate(CONF_SECTION *conf, void **instance)
         *      Convert the rcode string to an int, and get rid of it
         */
        data->rcode = str2rcode(data->rcode_str);
-       free(data->rcode_str);
-       data->rcode_str = NULL;
        if (data->rcode == -1) {
                free(data);
                return -1;
@@ -161,10 +158,11 @@ static int always_detach(void *instance)
 }
 
 module_t rlm_always = {
+       RLM_MODULE_INIT,
        "always",
        RLM_TYPE_THREAD_SAFE,           /* type */
-       NULL,                           /* initialization */
        always_instantiate,             /* instantiation */
+       always_detach,                  /* detach */
        {
                always_return,          /* authentication */
                always_return,          /* authorization */
@@ -175,6 +173,4 @@ module_t rlm_always = {
                always_return,          /* post-proxy */
                always_return           /* post-auth */
        },
-       always_detach,                  /* detach */
-       NULL,                           /* destroy */
 };
index 9caefb8..408f599 100644 (file)
  *
  *   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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright (C) 2001 The FreeRADIUS server project
+ * Copyright (C) 2001,2006 The FreeRADIUS server project
  * Copyright (C) 2001 Chris Parker <cparker@starnetusa.net>
  */
 
-#include       "autoconf.h"
-#include       "libradius.h"
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include       <freeradius-devel/autoconf.h>
 
 #include       <sys/stat.h>
 
 #include       <fcntl.h>
 #include        <limits.h>
 
-#ifdef HAVE_REGEX_H
-#  include      <regex.h>
-#endif
-
-#include       "radiusd.h"
-#include       "modules.h"
-
-static const char rcsid[] = "$Id$";
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/rad_assert.h>
+#include       <freeradius-devel/modules.h>
 
+/*
+ *     Define a structure with the module configuration, so it can
+ *     be used as the instance handle.
+ */
 struct attr_filter_instance {
-        /* autz */
         char *attrsfile;
+       char *key;
         PAIR_LIST *attrs;
 };
 
-static int check_pair(VALUE_PAIR *check_item, VALUE_PAIR *reply_item,
-                      int comp, int *pa, int *fa) {
-#ifdef HAVE_REGEX_H
-       regex_t         reg;
-#endif
-       switch(check_item->operator) {
-
-               case T_OP_SET:            /* nothing to do for set */
-                   break;
-               case T_OP_EQ:
-                    default:
-                       radlog(L_ERR, "Invalid operator for item %s: "
-                       "reverting to '=='", check_item->name);
-
-               case T_OP_CMP_TRUE:       /* comp always == 0 */
-               case T_OP_CMP_FALSE:      /* comp always == 1 */
-               case T_OP_CMP_EQ:
-                   if (comp == 0) {
-                       ++*(pa);
-                   } else {
-                       ++*(fa);
-                   }
-                   break;
-
-               case T_OP_NE:
-                   if (comp != 0) {
-                       ++*(pa);
-                   } else {
-                       ++*(fa);
-                   }
-                   break;
-
-               case T_OP_LT:
-                   if (comp < 0) {
-                       ++*(pa);
-                   } else {
-                       ++*(fa);
-                   }
-                   break;
+static const CONF_PARSER module_config[] = {
+       { "attrsfile",     PW_TYPE_FILENAME,
+         offsetof(struct attr_filter_instance,attrsfile), NULL, "${raddbdir}/attrs" },
+       { "key",     PW_TYPE_STRING_PTR,
+         offsetof(struct attr_filter_instance,key), NULL, "%{Realm}" },
+       { NULL, -1, 0, NULL, NULL }
+};
 
-               case T_OP_GT:
-                   if (comp > 0) {
-                       ++*(pa);
-                   } else {
-                       ++*(fa);
-                   }
-                   break;
+static void check_pair(VALUE_PAIR *check_item, VALUE_PAIR *reply_item,
+                      int *pass, int *fail)
+{
+       int compare;
 
-               case T_OP_LE:
-                   if (comp <= 0) {
-                       ++*(pa);
-                   } else {
-                       ++*(fa);
-                   }
-                   break;
+       if (check_item->operator == T_OP_SET) return;
 
-               case T_OP_GE:
-                   if (comp >= 0) {
-                       ++*(pa);
-                   } else {
-                       ++*(fa);
-                   }
-                   break;
-#ifdef HAVE_REGEX_H
-               case T_OP_REG_EQ:
-                   regcomp(&reg, (char *)check_item->strvalue, 0);
-                   comp = regexec(&reg, (char *)reply_item->strvalue,
-                                     0, NULL, 0);
-                   regfree(&reg);
-                   if (comp == 0) {
-                       ++*(pa);
-                   } else {
-                       ++*(fa);
-                   }
-                   break;
-
-               case T_OP_REG_NE:
-                   regcomp(&reg, (char *)check_item->strvalue, 0);
-                   comp = regexec(&reg, (char *)reply_item->strvalue,
-                                     0, NULL, 0);
-                   regfree(&reg);
-                   if (comp != 0) {
-                       ++*(pa);
-                   } else {
-                       ++*(fa);
-                   }
-                   break;
-#endif
+       compare = paircmp(check_item, reply_item);
+       if (compare == 1) {
+               ++*(pass);
+       } else {
+               ++*(fail);
        }
-        return 0;
+
+       return;
 }
 
 /*
@@ -146,40 +80,23 @@ static int check_pair(VALUE_PAIR *check_item, VALUE_PAIR *reply_item,
  */
 static int mypairappend(VALUE_PAIR *item, VALUE_PAIR **to)
 {
-  VALUE_PAIR *tmp;
-  tmp = paircreate(item->attribute, item->type);
-  if (!tmp) {
-       radlog(L_ERR|L_CONS, "no memory");
-       return -1;
-  }
-
-  /*
-   *   Copy EVERYTHING.
-   */
-  memcpy(tmp, item, sizeof(*tmp));
-  tmp->next = NULL;
-  pairadd(to, tmp);
-  return 0;
-}
-
-/*
- *     See if a VALUE_PAIR list contains Fall-Through = Yes
- */
-static int fallthrough(VALUE_PAIR *vp)
-{
        VALUE_PAIR *tmp;
+       tmp = paircreate(item->attribute, item->type);
+       if (!tmp) {
+               radlog(L_ERR|L_CONS, "no memory");
+               return -1;
+       }
+       
+       /*
+        *      Copy EVERYTHING.
+        */
+       memcpy(tmp, item, sizeof(*tmp));
+       tmp->next = NULL;
+       *to = tmp;
 
-       tmp = pairfind(vp, PW_FALL_THROUGH);
-
-       return tmp ? tmp->lvalue : 0;
+       return 0;
 }
 
-static CONF_PARSER module_config[] = {
-       { "attrsfile",     PW_TYPE_STRING_PTR,
-         offsetof(struct attr_filter_instance,attrsfile), NULL, "${raddbdir}/attrs" },
-       { NULL, -1, 0, NULL, NULL }
-};
-
 static int getattrsfile(const char *filename, PAIR_LIST **pair_list)
 {
        int rcode;
@@ -227,6 +144,19 @@ static int getattrsfile(const char *filename, PAIR_LIST **pair_list)
        return 0;
 }
 
+
+/*
+ *     Clean up.
+ */
+static int attr_filter_detach(void *instance)
+{
+       struct attr_filter_instance *inst = instance;
+       pairlist_free(&inst->attrs);
+       free(inst);
+       return 0;
+}
+
+
 /*
  *     (Re-)read the "attrs" file into memory.
  */
@@ -242,581 +172,203 @@ static int attr_filter_instantiate(CONF_SECTION *conf, void **instance)
        memset(inst, 0, sizeof(*inst));
 
        if (cf_section_parse(conf, inst, module_config) < 0) {
-               free(inst);
+               attr_filter_detach(inst);
                return -1;
        }
 
        rcode = getattrsfile(inst->attrsfile, &inst->attrs);
         if (rcode != 0) {
                radlog(L_ERR|L_CONS, "Errors reading %s", inst->attrsfile);
-               free(inst->attrsfile);
-               free(inst);
+               attr_filter_detach(inst);
                return -1;
        }
-       radlog(L_ERR|L_CONS, " rlm_attr_filter: Authorize method will be"\
-                             " deprecated.");
        *instance = inst;
        return 0;
 }
 
-static int attr_filter_authorize(void *instance, REQUEST *request)
+
+/*
+ *     Common attr_filter checks
+ */
+static int attr_filter_common(void *instance, REQUEST *request,
+                             VALUE_PAIR **input)
 {
        struct attr_filter_instance *inst = instance;
-       VALUE_PAIR      *request_pairs;
-       VALUE_PAIR      **reply_items;
-       VALUE_PAIR      *reply_item;
-       VALUE_PAIR      *reply_tmp = NULL;
-       VALUE_PAIR      *check_item;
-       PAIR_LIST       *pl;
-       int             found = 0;
-       int             compare;
-       int             pass, fail;
-       VALUE_PAIR      *realmpair;
-       REALM           *realm;
-       char            *realmname;
-
-       /*
-        *      It's not a proxy reply, so return NOOP
-        */
-
-       if( request->proxy == NULL ) {
-               return( RLM_MODULE_NOOP );
-       }
+       VALUE_PAIR      *vp;
+       VALUE_PAIR      *output = NULL;
+       VALUE_PAIR      **output_tail;
+       VALUE_PAIR      *check_item;
+       PAIR_LIST       *pl;
+       int             found = 0;
+       int             pass, fail = 0;
+       char            *keyname = NULL;
+       char            buffer[256];
 
-       request_pairs = request->packet->vps;
-       reply_items = &request->reply->vps;
+       if (!inst->key) {
+               VALUE_PAIR      *namepair;
 
-       /*
-        *      Get the realm.  Can't use request->config_items as
-        *      that gets freed by rad_authenticate....  use the one
-        *      set in the original request vps
-        */
-       realmpair = pairfind(request_pairs, PW_REALM);
-       if(!realmpair) {
-               /*    Can't find a realm, so no filtering of attributes
-                *    or should we use a DEFAULT entry?
-                *    For now, just return NOTFOUND. (maybe NOOP?)
-                */
-               return RLM_MODULE_NOTFOUND;
+               namepair = pairfind(request->packet->vps, PW_REALM);
+               if (!namepair) {
+                       return (RLM_MODULE_NOOP);
+               }
+               keyname = namepair->vp_strvalue;
+       } else {
+               int len;
+
+               len = radius_xlat(buffer, sizeof(buffer), inst->key,
+                                 request, NULL);
+               if (!len) {
+                       return RLM_MODULE_NOOP;
+               }
+               keyname = buffer;
        }
 
-       realmname = (char *) realmpair->strvalue;
-       realm = realm_find(realmname, FALSE);
+       output_tail = &output;
 
        /*
-        *      Find the attr_filter profile entry for the realm.
+        *      Find the attr_filter profile entry for the entry.
         */
-       for(pl = inst->attrs; pl; pl = pl->next) {
+       for (pl = inst->attrs; pl; pl = pl->next) {
+               int fall_through = 0;
 
                /*
                 *  If the current entry is NOT a default,
                 *  AND the realm does NOT match the current entry,
                 *  then skip to the next entry.
                 */
-               if ( (strcmp(pl->name, "DEFAULT") != 0) &&
-                    (strcmp(realmname, pl->name) != 0) )  {
+               if ((strcmp(pl->name, "DEFAULT") != 0) &&
+                   (strcmp(keyname, pl->name) != 0))  {
                    continue;
                }
 
                DEBUG2(" attr_filter: Matched entry %s at line %d", pl->name,
-                                                                   pl->lineno);
+                      pl->lineno);
                found = 1;
 
-               check_item = pl->check;
-
-               while( check_item != NULL ) {
-
-                   /*
-                    *      If it is a SET operator, add the attribute to
-                    *      the reply list without checking reply_items.
-                    *
-                    */
-
-                   if( check_item->operator == T_OP_SET ) {
-                       if (mypairappend(check_item, &reply_tmp) < 0) {
-                               return RLM_MODULE_FAIL;
+               for (check_item = pl->check;
+                    check_item != NULL;
+                    check_item = check_item->next) {
+                       if (check_item->attribute == PW_FALL_THROUGH) {
+                               fall_through = 1;
+                               continue;
                        }
-                   }
-                   check_item = check_item->next;
 
+                       /*
+                        *    If it is a SET operator, add the attribute to
+                        *    the output list without checking it.
+                        */
+                       if (check_item->operator == T_OP_SET ) {
+                               if (mypairappend(check_item, output_tail) < 0) {
+                                       pairfree(&output);
+                                       return RLM_MODULE_FAIL;
+                               }
+                               output_tail = &((*output_tail)->next);
+                       }
                }
 
-                /*
-                 * Iterate through the reply items, comparing each reply item
-                * to every rule, then moving it to the reply_tmp list
-                * only if it matches all rules for that attribute.
-                * IE, Idle-Timeout is moved only if it matches all rules that
-                 * describe an Idle-Timeout.
-                 */
-
-               for(reply_item = *reply_items;
-                   reply_item != NULL;
-                   reply_item = reply_item->next ) {
-
-                   /* reset the pass,fail vars for each reply item */
-                   pass = fail = 0;
-
-                   /* reset the check_item pointer to beginning of the list */
-                   check_item = pl->check;
-
-                   while( check_item != NULL ) {
-
-                       if(reply_item->attribute == check_item->attribute) {
-
-                           compare = simplepaircmp(request, reply_item,
-                                                   check_item);
-                           check_pair(check_item, reply_item, compare,
-                                      &pass, &fail);
+               /*
+                *      Iterate through the input items, comparing
+                *      each item to every rule, then moving it to the
+                *      output list only if it matches all rules
+                *      for that attribute.  IE, Idle-Timeout is moved
+                *      only if it matches all rules that describe an
+                *      Idle-Timeout.
+                */
+               for (vp = *input; vp != NULL; vp = vp->next ) {
+                       /* reset the pass,fail vars for each reply item */
+                       pass = fail = 0;
+                       
+                       /*
+                        *      reset the check_item pointer to
+                        *      beginning of the list
+                        */
+                       for (check_item = pl->check;
+                            check_item != NULL;
+                            check_item = check_item->next) {
+                               /*
+                                *      Vendor-Specific is special, and
+                                *      matches any VSA if the comparison
+                                *      is always true.
+                                */
+                               if ((check_item->attribute == PW_VENDOR_SPECIFIC) &&
+                                   (VENDOR(vp->attribute) != 0) &&
+                                   (check_item->operator == T_OP_CMP_TRUE)) {
+                                       pass++;
+                                       continue;
+                               }
+
+                               if (vp->attribute == check_item->attribute) {
+                                       check_pair(check_item, vp,
+                                                  &pass, &fail);
+                               }
                        }
-
-                       check_item = check_item->next;
-
-                   }
-
-                   /* only move attribute if it passed all rules */
-                   if (fail == 0 && pass > 0) {
-                       if (mypairappend( reply_item, &reply_tmp) < 0) {
-                               return RLM_MODULE_FAIL;
+                       
+                       /* only move attribute if it passed all rules */
+                       if (fail == 0 && pass > 0) {
+                               if (mypairappend(vp, output_tail) < 0) {
+                                       pairfree(&output);
+                                       return RLM_MODULE_FAIL;
+                               }
+                               output_tail = &((*output_tail)->next);
                        }
-                   }
-
                }
-
+               
                /* If we shouldn't fall through, break */
-               if(!fallthrough(pl->check))
-                   break;
+               if (!fall_through)
+                       break;
        }
 
-       pairfree(&request->reply->vps);
-       request->reply->vps = reply_tmp;
-
        /*
-        *      See if we succeeded.  If we didn't find the realm,
-        *      then exit from the module.
+        *      No entry matched.  We didn't do anything.
         */
-       if (!found)
-               return RLM_MODULE_OK;
+       if (!found) {
+               rad_assert(output == NULL);
+               return RLM_MODULE_NOOP;
+       }
 
-       /*
-        *      Remove server internal parameters.
-        */
-       pairdelete(reply_items, PW_FALL_THROUGH);
+       pairfree(input);
+       *input = output;
 
        return RLM_MODULE_UPDATED;
 }
 
 static int attr_filter_accounting(void *instance, REQUEST *request)
 {
-       struct attr_filter_instance *inst = instance;
-       VALUE_PAIR      *request_pairs;
-       VALUE_PAIR      *send_item;
-       VALUE_PAIR      *send_tmp = NULL;
-       VALUE_PAIR      *check_item;
-       PAIR_LIST       *pl;
-       int             found = 0;
-       int             compare;
-       int             pass, fail;
-       VALUE_PAIR      *realmpair;
-       REALM           *realm;
-       char            *realmname;
-       /*
-        * Accounting is similar to pre-proxy.
-        * Here we are concerned with what we are going to forward to
-        * the remote server as opposed to concerns with what we will send
-        * to the NAS based on a proxy reply to an auth request.
-        */
-
-       if (request->packet->code != PW_ACCOUNTING_REQUEST) {
-               return (RLM_MODULE_NOOP);
-       }
-
-       request_pairs = request->packet->vps;
-
-       /* Get the realm from the original request vps. */
-       realmpair = pairfind(request_pairs, PW_REALM);
-
-       if (!realmpair) {
-               /* If there is no realm...NOOP */
-               return (RLM_MODULE_NOOP);
-       }
-
-       realmname = (char *) realmpair->strvalue;
-       realm = realm_find (realmname, FALSE);
-
-       /*
-        * Find the attr_filter profile entry for the realm
-        */
-       for (pl = inst->attrs; pl; pl = pl->next) {
-
-               /*
-                * If the current entry is NOT a default,
-                * AND the realm does not match the current entry,
-                * then skip to the next entry.
-                */
-               if ( (strcmp(pl->name, "DEFAULT") != 0) &&
-                    (strcasecmp(realmname, pl->name) != 0) ) {
-                   continue;
-               }
-
-               DEBUG2(" attr_filter: Matched entry %s at line %d", pl->name,
-                                                                   pl->lineno);
-               found = 1;
-
-               check_item = pl->check;
-
-               while (check_item != NULL) {
-
-                   /*
-                    * If it is a SET operator, add the attribute to
-                    * the send list w/out checking.
-                    */
-
-                   if (check_item->operator == T_OP_SET) {
-                       if (mypairappend(check_item, &send_tmp) < 0) {
-                               return RLM_MODULE_FAIL;
-                       }
-                   }
-                   check_item = check_item->next;
-               }
-               /*
-                * Iterate through the request_pairs (items sent from NAS).
-                * Compare each pair to every rule for this realm/DEFAULT.
-                * Move an item to send_tmp if it matches all rules for
-                * attribute in question.
-                */
-               for (send_item = request_pairs; send_item != NULL;
-                    send_item = send_item->next ) {
-
-                   /* reset the pass/fail vars for each packet->vp. */
-                   pass = fail = 0;
-
-                   /* reset the check_item pointer to beginning of the list */
-                   check_item = pl->check;
-
-                   while (check_item != NULL) {
-                       if (send_item->attribute == check_item->attribute) {
-
-                           compare = simplepaircmp(request, send_item,
-                                                   check_item);
-                           check_pair(check_item, send_item, compare,
-                                      &pass, &fail);
-                       }
-
-                       check_item = check_item->next;
-                   }
-                   /* only send if attribute passed all rules */
-                   if (fail == 0 && pass > 0) {
-                       if (mypairappend (send_item, &send_tmp) < 0) {
-                               return RLM_MODULE_FAIL;
-                       }
-                   }
-               }
-               if (!fallthrough(pl->check))
-                   break;
-       }
-       pairfree (&request->packet->vps);
-       request->packet->vps = send_tmp;
-
-       /*
-        * See if we succeeded. If we didn't find the realm,
-        * then exit from the module.
-        */
-       if (!found)
-               return RLM_MODULE_OK;
-
-       /*
-        * Remove server internal paramters.
-        */
-       pairdelete(&send_tmp, PW_FALL_THROUGH);
-
-       return RLM_MODULE_UPDATED;
+       return attr_filter_common(instance, request, &request->packet->vps);
 }
 
-static int attr_filter_preproxy (void *instance, REQUEST *request)
+static int attr_filter_preproxy(void *instance, REQUEST *request)
 {
-       struct attr_filter_instance *inst = instance;
-       VALUE_PAIR      *request_pairs;
-       VALUE_PAIR      *send_item;
-       VALUE_PAIR      *send_tmp = NULL;
-       VALUE_PAIR      *check_item;
-       PAIR_LIST       *pl;
-       int             found = 0;
-       int             compare;
-       int             pass, fail;
-       VALUE_PAIR      *realmpair;
-       REALM           *realm;
-       char            *realmname;
-
-       /*
-        * Pre-proxy we are
-         * concerned with what we are going to forward to
-        * to the remote server as opposed to we will do with
-        * with the remote servers' repsonse pairs. Consequently,
-        * we deal with modifications to the request->packet->vps;
-        */
-       request_pairs = request->proxy->vps;
-       if (request->packet->code != PW_AUTHENTICATION_REQUEST) {
-               return (RLM_MODULE_NOOP);
-       }
-       realmpair = pairfind(request_pairs, PW_REALM);
-       if (!realmpair) {
-               return (RLM_MODULE_NOOP);
-       }
-
-       realmname = (char *)realmpair->strvalue;
-       realm = realm_find(realmname, FALSE);
-
-       for (pl = inst->attrs; pl; pl = pl->next) {
-               if ( (strcmp(pl->name, "DEFAULT") != 0) &&
-                    (strcasecmp(realmname, pl->name) != 0) ) {
-                   continue;
-               }
-
-               DEBUG2(" attr_filter: Matched entry %s at line %d", pl->name,
-                                                                   pl->lineno);
-               found = 1;
-
-               check_item = pl->check;
-
-               while (check_item != NULL) {
-
-                   /*
-                    * Append all SET operator attributes with no check.
-                    */
-                   if (check_item->operator == T_OP_SET) {
-                       if (mypairappend(check_item, &send_tmp) < 0) {
-                               return RLM_MODULE_FAIL;
-                       }
-                   }
-                   check_item = check_item->next;
-               }
-               /*
-                * Iterate through the request_pairs (items sent from NAS).
-                * Compare each pair to every rule for this realm/DEFAULT.
-                * Move an item to send_tmp if it matches all rules for
-                * attribute in question.
-                */
-               for (send_item = request_pairs;
-                    send_item != NULL;
-                   send_item = send_item->next ) {
-
-                   /* reset the pass/fail vars for each packet->vp. */
-                   pass = fail = 0;
-
-                   /* reset the check_item to the beginning */
-                   check_item = pl->check;
-
-                   /*
-                    * compare each packet->vp to the entire list of
-                    * check_items for this realm.
-                    */
-                   while (check_item != NULL) {
-                       if (send_item->attribute == check_item->attribute) {
-
-                           compare = simplepaircmp(request, send_item,
-                                                   check_item);
-                           check_pair(check_item, send_item, compare,
-                                      &pass, &fail);
-
-                       }
-
-                       check_item = check_item->next;
-                   }
-
-                   /* only send if attribute passed all rules */
-                   if (fail == 0 && pass > 0) {
-                       if (mypairappend (send_item, &send_tmp) < 0) {
-                               return RLM_MODULE_FAIL;
-                       }
-                   }
-               }
-               if (!fallthrough(pl->check))
-                   break;
-       }
-       pairfree (&request->proxy->vps);
-       request->proxy->vps = send_tmp;
-
-       if (!found)
-               return RLM_MODULE_OK;
-       pairdelete(&send_tmp, PW_FALL_THROUGH);
-       return RLM_MODULE_UPDATED;
+       return attr_filter_common(instance, request, &request->proxy->vps);
 }
 
 static int attr_filter_postproxy(void *instance, REQUEST *request)
 {
-       struct attr_filter_instance *inst = instance;
-       VALUE_PAIR      *request_pairs;
-       VALUE_PAIR      **reply_items;
-       VALUE_PAIR      *reply_item;
-       VALUE_PAIR      *reply_tmp = NULL;
-       VALUE_PAIR      *check_item;
-       PAIR_LIST       *pl;
-       int             found = 0;
-       int             compare;
-       int             pass, fail = 0;
-       VALUE_PAIR      *realmpair;
-       REALM           *realm;
-       char            *realmname;
-       /*
-        *      It's not a proxy reply, so return NOOP
-        */
-
-       if( request->proxy == NULL ) {
-               return( RLM_MODULE_NOOP );
-       }
-
-       request_pairs = request->packet->vps;
-       reply_items = &request->proxy_reply->vps;
-
-       /*
-        * Get the realm.  Can't use request->config_items as
-        * that gets freed by rad_authenticate....  use the one
-        * set in the original request vps
-        */
-       realmpair = pairfind(request_pairs, PW_REALM);
-       if(!realmpair) {
-               /*    Can't find a realm, so no filtering of attributes
-                *    or should we use a DEFAULT entry?
-                *    For now, just return NOTFOUND. (maybe NOOP?)
-                */
-               return RLM_MODULE_NOTFOUND;
-       }
-
-       realmname = (char *) realmpair->strvalue;
-
-       realm = realm_find(realmname, FALSE);
-
-       /*
-        *      Find the attr_filter profile entry for the realm.
-        */
-       for(pl = inst->attrs; pl; pl = pl->next) {
-
-               /*
-                *  If the current entry is NOT a default,
-                *  AND the realm does NOT match the current entry,
-                *  then skip to the next entry.
-                */
-               if ( (strcmp(pl->name, "DEFAULT") != 0) &&
-                    (strcmp(realmname, pl->name) != 0) )  {
-                   continue;
-               }
-
-               DEBUG2(" attr_filter: Matched entry %s at line %d", pl->name,
-                                                                   pl->lineno);
-               found = 1;
-
-               check_item = pl->check;
-
-               while( check_item != NULL ) {
-
-                   /*
-                    *    If it is a SET operator, add the attribute to
-                    *    the reply list without checking reply_items.
-                    */
-
-                   if( check_item->operator == T_OP_SET ) {
-                       if (mypairappend(check_item, &reply_tmp) < 0) {
-                               return RLM_MODULE_FAIL;
-                       }
-                   }
-                   check_item = check_item->next;
-
-               }
-
-               /*
-                * Iterate through the reply items,
-                * comparing each reply item to every rule,
-                * then moving it to the reply_tmp list only if it matches all
-                * rules for that attribute.
-                * IE, Idle-Timeout is moved only if it matches
-                * all rules that describe an Idle-Timeout.
-                */
-
-               for( reply_item = *reply_items; reply_item != NULL;
-                    reply_item = reply_item->next ) {
-
-                   /* reset the pass,fail vars for each reply item */
-                   pass = fail = 0;
-
-                   /* reset the check_item pointer to beginning of the list */
-                   check_item = pl->check;
-
-                   while( check_item != NULL ) {
-
-                       if(reply_item->attribute == check_item->attribute) {
-
-                           compare = simplepaircmp(request, reply_item,
-                                                   check_item);
-                           check_pair(check_item, reply_item, compare,
-                                      &pass, &fail);
-                       }
-
-                       check_item = check_item->next;
-
-                   }
-
-                   /* only move attribute if it passed all rules */
-                   if (fail == 0 && pass > 0) {
-                       if (mypairappend( reply_item, &reply_tmp) < 0) {
-                               return RLM_MODULE_FAIL;
-                       }
-                   }
-
-               }
-
-               /* If we shouldn't fall through, break */
-               if(!fallthrough(pl->check))
-                   break;
-       }
-
-       pairfree(&request->proxy_reply->vps);
-       request->proxy_reply->vps = reply_tmp;
-
-       /*
-        * See if we succeeded.  If we didn't find the realm,
-        * then exit from the module.
-        */
-       if (!found)
-               return RLM_MODULE_OK;
-
-       /*
-        *      Remove server internal parameters.
-        */
-       pairdelete(reply_items, PW_FALL_THROUGH);
-
-       return RLM_MODULE_UPDATED;
+       return attr_filter_common(instance, request, &request->proxy_reply->vps);
 }
 
-/*
- *     Clean up.
- */
-static int attr_filter_detach(void *instance)
+static int attr_filter_postauth(void *instance, REQUEST *request)
 {
-       struct attr_filter_instance *inst = instance;
-       pairlist_free(&inst->attrs);
-       free(inst->attrsfile);
-       free(inst);
-       return 0;
+       return attr_filter_common(instance, request, &request->reply->vps);
 }
 
 
 /* globally exported name */
 module_t rlm_attr_filter = {
+       RLM_MODULE_INIT,
        "attr_filter",
        0,                              /* type: reserved */
-       NULL,                           /* initialization */
        attr_filter_instantiate,        /* instantiation */
+       attr_filter_detach,             /* detach */
        {
                NULL,                   /* authentication */
-               attr_filter_authorize,  /* authorization */
+               NULL,                   /* authorization */
                NULL,                   /* preaccounting */
                attr_filter_accounting, /* accounting */
                NULL,                   /* checksimul */
                attr_filter_preproxy,   /* pre-proxy */
                attr_filter_postproxy,  /* post-proxy */
-               NULL                    /* post-auth */
+               attr_filter_postauth    /* post-auth */
        },
-       attr_filter_detach,             /* detach */
-       NULL                            /* destroy */
 };
 
index 7f67892..6c6222b 100644 (file)
@@ -4,6 +4,10 @@
 
 TARGET      = @targetname@
 SRCS        = rlm_attr_rewrite.c
+HEADERS     =
+RLM_CFLAGS  = @attr_rewrite_cflags@
+RLM_LIBS    = @attr_rewrite_ldflags@
+RLM_INSTALL =
 
 include ../rules.mak
 
index db1e7d5..5b7dfdf 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.1.10.1 .
+# From configure.in Revision: 1.3 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -273,7 +273,7 @@ PACKAGE_STRING=
 PACKAGE_BUGREPORT=
 
 ac_unique_file="rlm_attr_rewrite.c"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS targetname LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP attr_rewrite_cflags attr_rewrite_ldflags targetname LIBOBJS LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -714,6 +714,26 @@ ac_env_target_alias_set=${target_alias+set}
 ac_env_target_alias_value=$target_alias
 ac_cv_env_target_alias_set=${target_alias+set}
 ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
 
 #
 # Report the --help message.
@@ -781,6 +801,18 @@ if test -n "$ac_init_help"; then
 
   cat <<\_ACEOF
 
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
 _ACEOF
 fi
 
@@ -869,7 +901,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1221,6 +1253,1164 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 if test x$with_rlm_attr_rewrite != xno; then
 
+       ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+       ;;
+    conftest.$ac_ext )
+       # This is the source file.
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+       ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       # FIXME: I believe we export ac_cv_exeext for Libtool,
+       # but it would be cool to find out if it's true.  Does anybody
+       # maintain Libtool? --akim.
+       export ac_cv_exeext
+       break;;
+    * )
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         export ac_cv_exeext
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std1 is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std1.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX                  -qlanglvl=ansi
+# Ultrix and OSF/1     -std1
+# HP-UX 10.20 and later        -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4                 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+       ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
 
        targetname=rlm_attr_rewrite
 else
@@ -1228,6 +2418,24 @@ else
        echo \*\*\* module rlm_attr_rewrite is disabled.
 fi
 
+if test x"$fail" != x""; then
+       if test x"${enable_strict_dependencies}" = x"yes"; then
+               { { echo "$as_me:$LINENO: error: set --without-rlm_attr_rewrite to disable it explicitly." >&5
+echo "$as_me: error: set --without-rlm_attr_rewrite to disable it explicitly." >&2;}
+   { (exit 1); exit 1; }; }
+       else
+               { echo "$as_me:$LINENO: WARNING: silently not building rlm_attr_rewrite." >&5
+echo "$as_me: WARNING: silently not building rlm_attr_rewrite." >&2;}
+               { echo "$as_me:$LINENO: WARNING: FAILURE: rlm_attr_rewrite requires: $fail." >&5
+echo "$as_me: WARNING: FAILURE: rlm_attr_rewrite requires: $fail." >&2;};
+               targetname=""
+       fi
+fi
+
+
+
+
+
 
           ac_config_files="$ac_config_files Makefile"
 cat >confcache <<\_ACEOF
@@ -1864,6 +3072,16 @@ s,@ECHO_C@,$ECHO_C,;t t
 s,@ECHO_N@,$ECHO_N,;t t
 s,@ECHO_T@,$ECHO_T,;t t
 s,@LIBS@,$LIBS,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@CPP@,$CPP,;t t
+s,@attr_rewrite_cflags@,$attr_rewrite_cflags,;t t
+s,@attr_rewrite_ldflags@,$attr_rewrite_ldflags,;t t
 s,@targetname@,$targetname,;t t
 s,@LIBOBJS@,$LIBOBJS,;t t
 s,@LTLIBOBJS@,$LTLIBOBJS,;t t
@@ -2029,11 +3247,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -2072,6 +3285,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 9900215..21c048a 100644 (file)
@@ -1,11 +1,12 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_attr_rewrite.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_attr_rewrite])
 
 if test x$with_[]modname != xno; then
 
-       dnl  This module doesn't need any autoconf test which is not already
-       dnl  in top-level configure.
+       AC_PROG_CC
+       AC_PROG_CPP
 
        targetname=modname
 else
@@ -13,5 +14,20 @@ else
        echo \*\*\* module modname is disabled.
 fi
 
+dnl  Don't change this section.
+if test x"$fail" != x""; then
+       if test x"${enable_strict_dependencies}" = x"yes"; then
+               AC_MSG_ERROR([set --without-]modname[ to disable it explicitly.])
+       else
+               AC_MSG_WARN([silently not building ]modname[.])
+               AC_MSG_WARN([FAILURE: ]modname[ requires: $fail.]); 
+               targetname=""
+       fi
+fi
+
+
+AC_SUBST(attr_rewrite_cflags)
+AC_SUBST(attr_rewrite_ldflags)
+
 AC_SUBST(targetname)
 AC_OUTPUT(Makefile)
index ca06e50..e22ab58 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2002  The FreeRADIUS server project
+ * Copyright 2002,2006  The FreeRADIUS server project
  * Copyright 2002  Kostas Kalevras <kkalev@noc.ntua.gr>
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -30,9 +33,8 @@
 #      include <regex.h>
 #endif
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 #define RLM_REGEX_INPACKET 0
 #define RLM_REGEX_INCONFIG 1
@@ -40,8 +42,6 @@
 #define RLM_REGEX_INPROXY 3
 #define RLM_REGEX_INPROXYREPLY 4
 
-static const char rcsid[] = "$Id$";
-
 typedef struct rlm_attr_rewrite_t {
        char *attribute;        /* The attribute to search for */
        int  attr_num;          /* The attribute number */
@@ -58,7 +58,6 @@ typedef struct rlm_attr_rewrite_t {
        char *name;             /* The module name */
 } rlm_attr_rewrite_t;
 
-
 static const CONF_PARSER module_config[] = {
   { "attribute", PW_TYPE_STRING_PTR, offsetof(rlm_attr_rewrite_t,attribute), NULL, NULL },
   { "searchfor", PW_TYPE_STRING_PTR, offsetof(rlm_attr_rewrite_t,search), NULL, NULL },
@@ -71,12 +70,11 @@ static const CONF_PARSER module_config[] = {
   { NULL, -1, 0, NULL, NULL }
 };
 
-
 static int attr_rewrite_instantiate(CONF_SECTION *conf, void **instance)
 {
        rlm_attr_rewrite_t *data;
        DICT_ATTR *dattr;
-       char *instance_name = NULL;
+       const char *instance_name = NULL;
 
        /*
         *      Set up a storage area for instance data
@@ -182,7 +180,7 @@ static int do_attr_rewrite(void *instance, REQUEST *request)
        int replace_len = 0;
 
        if ((attr_vp = pairfind(request->config_items, PW_REWRITE_RULE)) != NULL){
-               if (data->name == NULL || strcmp(data->name,attr_vp->strvalue))
+               if (data->name == NULL || strcmp(data->name,attr_vp->vp_strvalue))
                        return RLM_MODULE_NOOP;
        }
 
@@ -237,7 +235,7 @@ static int do_attr_rewrite(void *instance, REQUEST *request)
                        case RLM_REGEX_INPACKET:
                                if (data->attr_num == PW_USER_NAME)
                                        attr_vp = request->username;
-                               else if (data->attr_num == PW_PASSWORD)
+                               else if (data->attr_num == PW_USER_PASSWORD)
                                        attr_vp = request->password;
                                else
                                        tmp = request->packet->vps;
@@ -271,7 +269,7 @@ do_again:
                        DEBUG2("rlm_attr_rewrite: Could not find value pair for attribute %s",data->attribute);
                        return ret;
                }
-               if (attr_vp->strvalue == NULL || attr_vp->length == 0){
+               if (attr_vp->vp_strvalue == NULL || attr_vp->length == 0){
                        DEBUG2("rlm_attr_rewrite: Attribute %s string value NULL or of zero length",data->attribute);
                        return ret;
                }
@@ -289,8 +287,16 @@ do_again:
                        DEBUG2("rlm_attr_rewrite: regcomp() returned error: %s",err_msg);
                        return ret;
                }
+               
+               if ((attr_vp->type == PW_TYPE_IPADDR) &&
+                   (attr_vp->vp_strvalue[0] == '\0')) {
+                 inet_ntop(AF_INET, &(attr_vp->lvalue),
+                           attr_vp->vp_strvalue,
+                           sizeof(attr_vp->vp_strvalue));
+               }
+
                ptr = new_str;
-               ptr2 = attr_vp->strvalue;
+               ptr2 = attr_vp->vp_strvalue;
                counter = 0;
 
                for ( i = 0 ;i < (unsigned)data->num_matches; i++) {
@@ -298,7 +304,7 @@ do_again:
                        if (err == REG_NOMATCH) {
                                if (i == 0) {
                                        DEBUG2("rlm_attr_rewrite: No match found for attribute %s with value '%s'",
-                                                       data->attribute, attr_vp->strvalue);
+                                                       data->attribute, attr_vp->vp_strvalue);
                                        regfree(&preg);
                                        goto to_do_again;
                                } else
@@ -307,7 +313,7 @@ do_again:
                        if (err != 0) {
                                regfree(&preg);
                                radlog(L_ERR, "rlm_attr_rewrite: match failure for attribute %s with value '%s'",
-                                               data->attribute, attr_vp->strvalue);
+                                               data->attribute, attr_vp->vp_strvalue);
                                return ret;
                        }
                        if (pmatch[0].rm_so == -1)
@@ -320,11 +326,11 @@ do_again:
                        if (counter >= MAX_STRING_LEN) {
                                regfree(&preg);
                                DEBUG2("rlm_attr_rewrite: Replacement out of limits for attribute %s with value '%s'",
-                                               data->attribute, attr_vp->strvalue);
+                                               data->attribute, attr_vp->vp_strvalue);
                                return ret;
                        }
 
-                       strncpy(ptr, ptr2,len);
+                       strlcpy(ptr, ptr2,len);
                        ptr += len;
                        ptr2 += pmatch[0].rm_eo;
 
@@ -334,10 +340,10 @@ do_again:
                                 */
                                for(j = 0; j <= REQUEST_MAX_REGEX; j++){
                                        char *p;
-                                       char buffer[sizeof(attr_vp->strvalue)];
+                                       char buffer[sizeof(attr_vp->vp_strvalue)];
 
                                        /*
-                                        * Stolen from src/main/valuepair.c, paircmp()
+                                        * Stolen from src/main/valuepair.c, paircompare()
                                         */
 
                                        /*
@@ -353,7 +359,7 @@ do_again:
                                                break;
                                        }
                                        memcpy(buffer,
-                                              attr_vp->strvalue + pmatch[j].rm_so,
+                                              attr_vp->vp_strvalue + pmatch[j].rm_so,
                                               pmatch[j].rm_eo - pmatch[j].rm_so);
                                        buffer[pmatch[j].rm_eo - pmatch[j].rm_so] = '\0';
                                        p = strdup(buffer);
@@ -375,11 +381,11 @@ do_again:
                        if (counter >= MAX_STRING_LEN) {
                                regfree(&preg);
                                DEBUG2("rlm_attr_rewrite: Replacement out of limits for attribute %s with value '%s'",
-                                               data->attribute, attr_vp->strvalue);
+                                               data->attribute, attr_vp->vp_strvalue);
                                return ret;
                        }
                        if (replace_len){
-                               strncpy(ptr, replace_STR, replace_len);
+                               strlcpy(ptr, replace_STR, replace_len);
                                ptr += replace_len;
                        }
                }
@@ -388,13 +394,13 @@ do_again:
                counter += len;
                if (counter >= MAX_STRING_LEN){
                        DEBUG2("rlm_attr_rewrite: Replacement out of limits for attribute %s with value '%s'",
-                                       data->attribute, attr_vp->strvalue);
+                                       data->attribute, attr_vp->vp_strvalue);
                        return ret;
                }
-               strncpy(ptr, ptr2, len);
+               strlcpy(ptr, ptr2, len);
 
                DEBUG2("rlm_attr_rewrite: Changed value for attribute %s from '%s' to '%s'",
-                               data->attribute, attr_vp->strvalue, new_str);
+                               data->attribute, attr_vp->vp_strvalue, new_str);
                if (pairparsevalue(attr_vp, new_str) == NULL) {
                        DEBUG2("rlm_attr_rewrite: Could not write value '%s' into attribute %s: %s", new_str, data->attribute, librad_errstr);
                        return ret;
@@ -413,7 +419,6 @@ to_do_again:
        return ret;
 }
 
-
 static int attr_rewrite_accounting(void *instance, REQUEST *request)
 {
        return do_attr_rewrite(instance, request);
@@ -423,15 +428,18 @@ static int attr_rewrite_authorize(void *instance, REQUEST *request)
 {
        return do_attr_rewrite(instance, request);
 }
+
 static int attr_rewrite_authenticate(void *instance, REQUEST *request)
 {
        return do_attr_rewrite(instance, request);
 }
+
 static int attr_rewrite_preacct(void *instance, REQUEST *request)
 {
        return do_attr_rewrite(instance, request);
 }
-static int attr_rewrite_ismul(void *instance, REQUEST *request)
+
+static int attr_rewrite_checksimul(void *instance, REQUEST *request)
 {
        return do_attr_rewrite(instance, request);
 }
@@ -455,12 +463,6 @@ static int attr_rewrite_detach(void *instance)
 {
        rlm_attr_rewrite_t *data = (rlm_attr_rewrite_t *) instance;
 
-       if (data->attribute)
-               free(data->attribute);
-       if (data->search)
-               free(data->search);
-       if (data->replace)
-               free(data->replace);
        if (data->name)
                free(data->name);
 
@@ -478,20 +480,19 @@ static int attr_rewrite_detach(void *instance)
  *     is single-threaded.
  */
 module_t rlm_attr_rewrite = {
+       RLM_MODULE_INIT,
        "attr_rewrite",
        RLM_TYPE_THREAD_UNSAFE,         /* type */
-       NULL,                           /* initialization */
        attr_rewrite_instantiate,               /* instantiation */
+       attr_rewrite_detach,                    /* detach */
        {
                attr_rewrite_authenticate,      /* authentication */
                attr_rewrite_authorize,         /* authorization */
                attr_rewrite_preacct,           /* preaccounting */
                attr_rewrite_accounting,        /* accounting */
-               attr_rewrite_ismul,             /* checksimul */
+               attr_rewrite_checksimul,        /* checksimul */
                attr_rewrite_preproxy,          /* pre-proxy */
                attr_rewrite_postproxy,         /* post-proxy */
                attr_rewrite_postauth           /* post-auth */
        },
-       attr_rewrite_detach,                    /* detach */
-       NULL,                           /* destroy */
 };
diff --git a/src/modules/rlm_caching/Makefile.in b/src/modules/rlm_caching/Makefile.in
new file mode 100644 (file)
index 0000000..ff82a91
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# $Id$
+#
+
+TARGET      = @targetname@
+SRCS        = rlm_caching.c
+HEADERS     =
+RLM_CFLAGS  = @caching_cflags@
+RLM_LIBS    = @caching_ldflags@
+RLM_INSTALL =
+
+include ../rules.mak
+
+$(LT_OBJS): $(HEADERS)
diff --git a/src/modules/rlm_caching/rlm_caching.c b/src/modules/rlm_caching/rlm_caching.c
new file mode 100644 (file)
index 0000000..5a56e33
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+ * rlm_caching.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,2006  The FreeRADIUS server project
+ * Copyright 2001  Alan DeKok <aland@ox.org>
+ * Copyright 2001-3  Kostas Kalevras <kkalev@noc.ntua.gr>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include "config.h"
+#include <freeradius-devel/autoconf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/conffile.h>
+
+#include <gdbm.h>
+#include <time.h>
+
+#ifdef NEEDS_GDBM_SYNC
+#      define GDBM_SYNCOPT GDBM_SYNC
+#else
+#      define GDBM_SYNCOPT 0
+#endif
+
+#ifdef GDBM_NOLOCK
+#define GDBM_COUNTER_OPTS (GDBM_SYNCOPT | GDBM_NOLOCK)
+#else
+#define GDBM_COUNTER_OPTS (GDBM_SYNCOPT)
+#endif
+
+#ifndef HAVE_GDBM_FDESC
+#define gdbm_fdesc(foo) (-1)
+#endif
+
+#define UNIQUEID_MAX_LEN 32
+
+/*
+ *     Define a structure for our module configuration.
+ *
+ *     These variables do not need to be in a structure, but it's
+ *     a lot cleaner to do so, and a pointer to the structure can
+ *     be used as the instance handle.
+ */
+typedef struct rlm_caching_t {
+       char *filename;         /* name of the database file */
+       char *key;              /* An xlated string to use as key for the records */
+       char *post_auth;        /* If set and we find a cached entry, set Post-Auth to this value */    
+       char *cache_ttl_str;    /* The string represantation of the TTL */
+       int cache_ttl;          /* The cache TTL */
+       int hit_ratio;          /* Show cache hit ratio every so many queries */
+       int cache_rejects;      /* Do we also cache rejects? */
+       int cache_size;         /* The cache size to pass to GDBM */
+       uint32_t cache_queries; /* The number of cache requests */
+       uint32_t cache_hits;    /* The number of cache hits */
+       GDBM_FILE gdbm;         /* The gdbm file handle */
+#ifdef HAVE_PTHREAD_H
+       pthread_mutex_t mutex;  /* A mutex to lock the gdbm file for only one reader/writer */
+#endif
+} rlm_caching_t;
+
+#define MAX_RECORD_LEN 750
+#define MAX_AUTH_TYPE 32
+
+#define show_hit_ratio \
+       if (data->hit_ratio && (data->cache_queries % data->hit_ratio) == 0) \
+               radlog(L_INFO, "rlm_caching: Cache Queries: %7d, Cache Hits: %7d, Hit Ratio: %.2f%%", \
+                       data->cache_queries,data->cache_hits,hit_ratio)
+
+typedef struct rlm_caching_data {
+       time_t creation;
+       char data[MAX_RECORD_LEN];
+       char auth_type[MAX_AUTH_TYPE];
+       int len;
+} rlm_caching_data;
+
+#ifndef HAVE_PTHREAD_H
+/*
+ *     This is a lot simpler than putting ifdef's around
+ *     every use of the pthread functions.
+ */
+#define pthread_mutex_lock(a)
+#define pthread_mutex_unlock(a)
+#define pthread_mutex_init(a,b)
+#define pthread_mutex_destroy(a)
+#endif
+
+/*
+ *     A mapping of configuration file names to internal variables.
+ *
+ *     Note that the string is dynamically allocated, so it MUST
+ *     be freed.  When the configuration file parse re-reads the string,
+ *     it free's the old one, and strdup's the new one, placing the pointer
+ *     to the strdup'd string into 'config.string'.  This gets around
+ *     buffer over-flows.
+ */
+static const CONF_PARSER module_config[] = {
+  { "filename", PW_TYPE_STRING_PTR, offsetof(rlm_caching_t,filename), NULL, NULL },
+  { "key", PW_TYPE_STRING_PTR, offsetof(rlm_caching_t,key), NULL, "%{Acct-Unique-Session-Id}" },
+  { "post-auth", PW_TYPE_STRING_PTR, offsetof(rlm_caching_t,post_auth), NULL,  NULL },
+  { "cache-ttl", PW_TYPE_STRING_PTR, offsetof(rlm_caching_t,cache_ttl_str), NULL, "1d" },
+  { "cache-size", PW_TYPE_INTEGER, offsetof(rlm_caching_t,cache_size), NULL, "1000" },
+  { "hit-ratio", PW_TYPE_INTEGER, offsetof(rlm_caching_t,hit_ratio), NULL, "0" },
+  { "cache-rejects", PW_TYPE_BOOLEAN, offsetof(rlm_caching_t,cache_rejects), NULL, "yes" },
+  { NULL, -1, 0, NULL, NULL }
+};
+
+static int caching_detach(void *instance);
+
+static int find_ttl(char *ttl)
+{
+       unsigned len = 0;
+       char last = 's';
+
+       if (isdigit((int) ttl[0])){
+               len = strlen(ttl);
+               if (len == 0)
+                       return -1;
+               last = ttl[len - 1];
+               if (!isalpha((int) last))
+                       last = 's';
+               len = atoi(ttl);
+               DEBUG("rlm_caching::find_ttl: num=%d, last=%c",len,last);
+       }
+       switch (last){
+               case 's':
+               default:
+                       break;
+               case 'm':
+                       len *= 60;
+                       break;
+               case 'h':
+                       len *= 3600;
+                       break;
+               case 'd':
+                       len *= 86400;
+                       break;
+               case 'w':
+                       len *= 604800;
+                       break;
+       }
+
+       DEBUG("rlm_caching::find_ttl: Returning '%d'",len);
+
+       return len;
+}
+
+/*
+ *     Do any per-module initialization that is separate to each
+ *     configured instance of the module.  e.g. set up connections
+ *     to external databases, read configuration files, set up
+ *     dictionary entries, etc.
+ *
+ *     If configuration information is given in the config section
+ *     that must be referenced in later calls, store a handle to it
+ *     in *instance otherwise put a null pointer there.
+ */
+static int caching_instantiate(CONF_SECTION *conf, void **instance)
+{
+       rlm_caching_t *data;
+       int cache_size;
+
+       /*
+        *      Set up a storage area for instance data
+        */
+       data = rad_malloc(sizeof(*data));
+       if (!data) {
+               radlog(L_ERR, "rlm_caching: rad_malloc() failed.");
+               return -1;
+       }
+       memset(data, 0, sizeof(*data));
+
+       /*
+        *      If the configuration parameters can't be parsed, then
+        *      fail.
+        */
+       if (cf_section_parse(conf, data, module_config) < 0) {
+               free(data);
+               return -1;
+       }
+       cache_size = data->cache_size;
+
+       /*
+        *      Discover the attribute number of the key.
+        */
+       if (data->key == NULL) {
+               radlog(L_ERR, "rlm_caching: 'key' must be set.");
+               caching_detach(data);
+               return -1;
+       }
+       if (data->cache_ttl_str == NULL) {
+               radlog(L_ERR, "rlm_caching: 'cache-ttl' must be set.");
+               caching_detach(data);
+               return -1;
+       }
+       else {
+               data->cache_ttl = find_ttl(data->cache_ttl_str);
+               if (data->cache_ttl == 0) {
+                       radlog(L_ERR, "rlm_caching: 'cache-ttl' is invalid.");
+                       caching_detach(data);
+                       return -1;
+               }
+       }
+
+       if (data->filename == NULL) {
+               radlog(L_ERR, "rlm_caching: 'filename' must be set.");
+               caching_detach(data);
+               return -1;
+       }
+       data->gdbm = gdbm_open(data->filename, sizeof(int),
+                       GDBM_WRCREAT | GDBM_COUNTER_OPTS, 0600, NULL);
+       if (data->gdbm == NULL) {
+               radlog(L_ERR, "rlm_caching: Failed to open file %s: %s",
+                               data->filename, strerror(errno));
+               caching_detach(data);
+               return -1;
+       }
+       if (gdbm_setopt(data->gdbm, GDBM_CACHESIZE, &cache_size, sizeof(int)) == -1)
+               radlog(L_ERR, "rlm_caching: Failed to set cache size");
+
+       /*
+        * Init the mutex
+        */
+       pthread_mutex_init(&data->mutex, NULL);
+
+       *instance = data;
+
+       return 0;
+}
+
+/*
+ *     Cache the reply items and the Auth-Type
+ */
+static int caching_postauth(void *instance, REQUEST *request)
+{
+       rlm_caching_t *data = (rlm_caching_t *)instance;
+       char key[MAX_STRING_LEN];
+       datum key_datum;
+       datum data_datum;
+       VALUE_PAIR *reply_vp;
+       VALUE_PAIR *auth_type;
+       rlm_caching_data cache_data;
+       int count = 0;
+       int ret = 0;    
+       int size = 0;
+       int rcode = 0;
+
+       if (pairfind(request->packet->vps, PW_CACHE_NO_CACHING) != NULL){
+               DEBUG("rlm_caching: Cache-No-Caching is set. Returning NOOP");
+               return RLM_MODULE_NOOP;
+       }
+       if ((auth_type = pairfind(request->config_items, PW_AUTH_TYPE)) != NULL){
+               DEBUG("rlm_caching: Found Auth-Type, value: '%s'",auth_type->vp_strvalue);
+               if (strcmp(auth_type->vp_strvalue,"Reject") == 0 && data->cache_rejects == 0){
+                       DEBUG("rlm_caching: No caching of Rejects. Returning NOOP");
+                       return RLM_MODULE_NOOP;
+               }
+               if (strlen(auth_type->vp_strvalue) > MAX_AUTH_TYPE - 1){
+                       DEBUG("rlm_caching: Auth-Type value too large");
+                       return RLM_MODULE_NOOP;
+               }
+       }
+       else{
+               DEBUG("rlm_caching: No Auth-Type found. Returning NOOP");
+               return RLM_MODULE_NOOP;
+       }
+
+       reply_vp = request->reply->vps;
+
+       if (reply_vp == NULL) {
+               DEBUG("rlm_caching: The Request does not contain any reply attributes");
+               return RLM_MODULE_NOOP;
+       }
+       if (!radius_xlat(key,sizeof(key), data->key, request, NULL)){
+               radlog(L_ERR, "rlm_caching: xlat on key '%s' failed.",data->key);
+               return RLM_MODULE_FAIL;
+       }
+
+       memset(&cache_data,0,sizeof(rlm_caching_data));
+
+       cache_data.creation = time(NULL);
+       strcpy(cache_data.auth_type,auth_type->vp_strvalue);
+
+       size = MAX_RECORD_LEN;
+
+       while(reply_vp) {
+               if (size <= 1){
+                       DEBUG("rlm_caching: Not enough space.");
+                       return RLM_MODULE_NOOP;
+               }
+               ret = vp_prints(cache_data.data + count,size,reply_vp);
+               if (ret == 0) {
+                       DEBUG("rlm_caching: Record is too large, will not store it.");
+                       return RLM_MODULE_NOOP;
+               }
+               count += (ret + 1);
+               size -= (ret + 1);
+               DEBUG("rlm_caching: VP=%s,VALUE=%s,length=%d,cache record length=%d, space left=%d",
+                       reply_vp->name,reply_vp->vp_strvalue,ret,count,size);
+               reply_vp = reply_vp->next;
+       }
+       cache_data.len = count;
+
+       DEBUG("rlm_caching: Storing cache for Key='%s'",key);
+       data_datum.dptr = (rlm_caching_data *) &cache_data;
+       data_datum.dsize = sizeof(rlm_caching_data);
+
+       key_datum.dptr = (char *) key;
+       key_datum.dsize = strlen(key);
+
+       pthread_mutex_lock(&data->mutex);
+       rcode = gdbm_store(data->gdbm, key_datum, data_datum, GDBM_REPLACE);
+       pthread_mutex_unlock(&data->mutex);
+       if (rcode < 0) {
+               radlog(L_ERR, "rlm_caching: Failed storing data to %s: %s",
+                               data->filename, gdbm_strerror(gdbm_errno));
+               return RLM_MODULE_FAIL;
+       }
+       DEBUG("rlm_caching: New value stored successfully.");
+
+       return RLM_MODULE_OK;
+}
+
+/*
+ *     Find the named user in this modules database.  Create the set
+ *     of attribute-value pairs to check and reply with for this user
+ *     from the database. The authentication code only needs to check
+ *     the password, the rest is done here.
+ */
+static int caching_authorize(void *instance, REQUEST *request)
+{
+       rlm_caching_t *data = (rlm_caching_t *) instance;
+       char key[MAX_STRING_LEN];
+       datum key_datum;
+       datum data_datum;
+       rlm_caching_data cache_data;
+       VALUE_PAIR *reply_item;
+       VALUE_PAIR *item;
+       char *tmp;
+       int len = 0;
+       int delete_cache = 0;
+       float hit_ratio = 0.0;
+
+       /* quiet the compiler */
+       instance = instance;
+       request = request;
+
+       if (pairfind(request->packet->vps, PW_CACHE_NO_CACHING) != NULL){
+               DEBUG("rlm_caching: Cache-No-Caching is set. Returning NOOP");
+               return RLM_MODULE_NOOP;
+       }
+       if (pairfind(request->packet->vps, PW_CACHE_DELETE_CACHE) != NULL){
+               DEBUG("rlm_caching: Found Cache-Delete-Cache. Will delete record if found");
+               delete_cache = 1;
+       }
+
+       if (!radius_xlat(key,sizeof(key), data->key, request, NULL)){
+               radlog(L_ERR, "rlm_caching: xlat on key '%s' failed.",data->key);
+               return RLM_MODULE_FAIL;
+       }
+
+       key_datum.dptr = key;
+       key_datum.dsize = strlen(key);
+
+
+       DEBUG("rlm_caching: Searching the database for key '%s'",key);
+       pthread_mutex_lock(&data->mutex);
+       data_datum = gdbm_fetch(data->gdbm, key_datum);
+       pthread_mutex_unlock(&data->mutex);
+       data->cache_queries++;
+       if (data_datum.dptr != NULL){
+               DEBUG("rlm_caching: Key Found.");
+               data->cache_hits++;
+               hit_ratio = (float)data->cache_hits / data->cache_queries;
+               hit_ratio *= 100.0;
+               memcpy(&cache_data, data_datum.dptr, sizeof(rlm_caching_data));
+               free(data_datum.dptr);
+
+               if (delete_cache == 0 && cache_data.creation + data->cache_ttl <= time(NULL)){
+                       DEBUG("rlm_caching: Cache entry has expired");
+                       DEBUG("rlm_caching: Cache Queries: %7d, Cache Hits: %7d, Hit Ratio: %.2f%%",
+                       data->cache_queries,data->cache_hits,hit_ratio);
+                       show_hit_ratio;
+                       delete_cache = 1;
+               }
+               if (delete_cache){
+                       DEBUG("rlm_caching: Deleting record");
+                       
+                       pthread_mutex_lock(&data->mutex);
+                       gdbm_delete(data->gdbm, key_datum);
+                       pthread_mutex_unlock(&data->mutex);
+
+                       return RLM_MODULE_NOOP;
+               }
+               tmp = cache_data.data;
+               if (tmp){
+                       pairfree(&request->reply->vps);
+                       while(tmp && len < cache_data.len){
+                               reply_item = NULL;
+                               if (userparse(tmp, &reply_item) > 0 && reply_item != NULL)
+                                       pairadd(&request->reply->vps, reply_item);
+                               len += (strlen(tmp) + 1);
+                               DEBUG("rlm_caching: VP='%s',VALUE='%s',lenth='%d',cache record length='%d'",
+                               reply_item->name,reply_item->vp_strvalue,reply_item->length,len);
+                               tmp = cache_data.data + len;
+                       }
+               }
+               else{
+                       DEBUG("rlm_caching: No reply items found. Returning NOOP");
+                       return RLM_MODULE_NOOP;
+               }               
+               if (cache_data.auth_type){
+                       DEBUG("rlm_caching: Adding Auth-Type '%s'",cache_data.auth_type);
+
+                       if ((item = pairfind(request->config_items, PW_AUTH_TYPE)) == NULL){
+                               item = pairmake("Auth-Type", cache_data.auth_type, T_OP_SET);
+                               pairadd(&request->config_items, item);
+                       }
+                       else{
+                               strcmp(item->vp_strvalue, cache_data.auth_type);
+                               item->length = strlen(cache_data.auth_type);
+                       }
+               }
+               if (data->post_auth){
+                       DEBUG("rlm_caching: Adding Post-Auth-Type '%s'",data->post_auth);
+
+                       if ((item = pairfind(request->config_items, PW_POST_AUTH_TYPE)) == NULL){
+                               item = pairmake("Post-Auth-Type", data->post_auth, T_OP_SET);
+                               pairadd(&request->config_items, item);
+                       }
+                       else{
+                               strcmp(item->vp_strvalue, data->post_auth);
+                               item->length = strlen(data->post_auth);
+                       }
+               }
+               item = pairmake("Cache-No-Caching", "YES", T_OP_EQ);
+               pairadd(&request->packet->vps, item);
+
+               DEBUG("rlm_caching: Cache Queries: %7d, Cache Hits: %7d, Hit Ratio: %.2f%%",
+                       data->cache_queries,data->cache_hits,hit_ratio);
+               show_hit_ratio;
+
+               return RLM_MODULE_OK;
+       }
+       else{
+               DEBUG("rlm_caching: Could not find the requested key in the database.");
+               DEBUG("rlm_caching: Cache Queries: %7d, Cache Hits: %7d, Hit Ratio: %.2f%%",
+                       data->cache_queries,data->cache_hits,hit_ratio);
+               show_hit_ratio;
+       }
+
+       return RLM_MODULE_NOOP;
+}
+
+static int caching_detach(void *instance)
+{
+       rlm_caching_t *data = (rlm_caching_t *) instance;
+
+       if (data->gdbm)
+               gdbm_close(data->gdbm);
+       pthread_mutex_destroy(&data->mutex);
+
+       free(instance);
+       return 0;
+}
+
+/*
+ *     The module name should be the only globally exported symbol.
+ *     That is, everything else should be 'static'.
+ *
+ *     If the module needs to temporarily modify it's instantiation
+ *     data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
+ *     The server will then take care of ensuring that the module
+ *     is single-threaded.
+ */
+module_t rlm_caching = {
+       RLM_MODULE_INIT,
+       "Caching",
+       RLM_TYPE_THREAD_SAFE,           /* type */
+       caching_instantiate,            /* instantiation */
+       caching_detach,                 /* detach */
+       {
+               NULL,                   /* authentication */
+               caching_authorize,      /* authorization */
+               NULL,                   /* preaccounting */
+               NULL,                   /* accounting */
+               NULL,                   /* checksimul */
+               NULL,                   /* pre-proxy */
+               NULL,                   /* post-proxy */
+               caching_postauth        /* post-auth */
+       },
+};
index 44ea3b5..434d1c8 100644 (file)
@@ -15,9 +15,9 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2001  The FreeRADIUS server project
+ * Copyright 2001,2006  The FreeRADIUS server project
  * Copyright 2001  Kostas Kalevras <kkalev@noc.ntua.gr>
  *
  * Nov 03 2001, Kostas Kalevras <kkalev@noc.ntua.gr>
  * - Added module messages when rejecting user
  */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
-
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 static int chap_authorize(void *instance, REQUEST *request)
 {
@@ -45,8 +44,7 @@ static int chap_authorize(void *instance, REQUEST *request)
        instance = instance;
        request = request;
 
-       if (!request->password ||
-           request->password->attribute != PW_CHAP_PASSWORD) {
+       if (!pairfind(request->packet->vps, PW_CHAP_PASSWORD)) {
                return RLM_MODULE_NOOP;
        }
 
@@ -70,8 +68,8 @@ static int chap_authorize(void *instance, REQUEST *request)
  */
 static int chap_authenticate(void *instance, REQUEST *request)
 {
-       VALUE_PAIR *passwd_item;
-       char pass_str[MAX_STRING_LEN];
+       VALUE_PAIR *passwd_item, *chap;
+       uint8_t pass_str[MAX_STRING_LEN];
        VALUE_PAIR *module_fmsg_vp;
        char module_fmsg[MAX_STRING_LEN];
 
@@ -84,18 +82,19 @@ static int chap_authenticate(void *instance, REQUEST *request)
                return RLM_MODULE_INVALID;
        }
 
-       if (!request->password) {
+       chap = pairfind(request->packet->vps, PW_CHAP_PASSWORD);
+       if (!chap) {
                radlog(L_AUTH, "rlm_chap: Attribute \"CHAP-Password\" is required for authentication.");
                return RLM_MODULE_INVALID;
        }
 
-       if (request->password->attribute != PW_CHAP_PASSWORD) {
-               radlog(L_AUTH, "rlm_chap: Attribute \"CHAP-Password\" is required for authentication. Cannot use \"%s\".", request->password->name);
+       if (chap->length == 0) {
+               radlog(L_ERR, "rlm_chap: empty password supplied");
                return RLM_MODULE_INVALID;
        }
 
-       if (request->password->length == 0) {
-               radlog(L_ERR, "rlm_chap: empty password supplied");
+       if (chap->length != CHAP_VALUE_LENGTH + 1) {
+               radlog(L_ERR, "rlm_chap: password supplied has wrong length");
                return RLM_MODULE_INVALID;
        }
 
@@ -103,30 +102,37 @@ static int chap_authenticate(void *instance, REQUEST *request)
         *      Don't print out the CHAP password here.  It's binary crap.
         */
        DEBUG("  rlm_chap: login attempt by \"%s\" with CHAP password",
-               request->username->strvalue);
-
-       if ((passwd_item = pairfind(request->config_items, PW_PASSWORD)) == NULL){
-               DEBUG("  rlm_chap: Could not find clear text password for user %s",request->username->strvalue);
-               snprintf(module_fmsg,sizeof(module_fmsg),"rlm_chap: Clear text password not available");
-               module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ);
+               request->username->vp_strvalue);
+
+       if ((passwd_item = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD)) == NULL){
+         DEBUG("  rlm_chap: Cleartext-Password is required for authentication");
+               snprintf(module_fmsg, sizeof(module_fmsg),
+                        "rlm_chap: Clear text password not available");
+               module_fmsg_vp = pairmake("Module-Failure-Message",
+                                         module_fmsg, T_OP_EQ);
                pairadd(&request->packet->vps, module_fmsg_vp);
                return RLM_MODULE_INVALID;
        }
 
        DEBUG("  rlm_chap: Using clear text password \"%s\" for user %s authentication.",
-             passwd_item->strvalue, request->username->strvalue);
+             passwd_item->vp_strvalue, request->username->vp_strvalue);
 
-       rad_chap_encode(request->packet,pass_str,request->password->strvalue[0],passwd_item);
+       rad_chap_encode(request->packet,pass_str,
+                       chap->vp_octets[0],passwd_item);
 
-       if (memcmp(pass_str+1,request->password->strvalue+1,CHAP_VALUE_LENGTH) != 0){
+       if (memcmp(pass_str + 1, chap->vp_octets + 1,
+                  CHAP_VALUE_LENGTH) != 0){
                DEBUG("  rlm_chap: Password check failed");
-               snprintf(module_fmsg,sizeof(module_fmsg),"rlm_chap: Wrong user password");
-               module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ);
+               snprintf(module_fmsg, sizeof(module_fmsg),
+                        "rlm_chap: Wrong user password");
+               module_fmsg_vp = pairmake("Module-Failure-Message",
+                                         module_fmsg, T_OP_EQ);
                pairadd(&request->packet->vps, module_fmsg_vp);
                return RLM_MODULE_REJECT;
        }
 
-       DEBUG("  rlm_chap: chap user %s authenticated succesfully",request->username->strvalue);
+       DEBUG("  rlm_chap: chap user %s authenticated succesfully",
+             request->username->vp_strvalue);
 
        return RLM_MODULE_OK;
 }
@@ -141,10 +147,11 @@ static int chap_authenticate(void *instance, REQUEST *request)
  *     is single-threaded.
  */
 module_t rlm_chap = {
+        RLM_MODULE_INIT,
        "CHAP",
        0,                              /* type */
-       NULL,                           /* initialization */
        NULL,                           /* instantiation */
+       NULL,                           /* detach */
        {
                chap_authenticate,      /* authentication */
                chap_authorize,         /* authorization */
@@ -155,6 +162,4 @@ module_t rlm_chap = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       NULL,                           /* detach */
-       NULL,                           /* destroy */
 };
index e5cf75d..c022199 100644 (file)
@@ -4,6 +4,10 @@
 
 TARGET      = @targetname@
 SRCS        = rlm_checkval.c
+HEADERS     =
+RLM_CFLAGS  = @checkval_cflags@
+RLM_LIBS    = @checkval_ldflags@
+RLM_INSTALL =
 
 include ../rules.mak
 
index ba7ed70..81980e0 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.2.6.1 .
+# From configure.in Revision: 1.4 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -273,7 +273,7 @@ PACKAGE_STRING=
 PACKAGE_BUGREPORT=
 
 ac_unique_file="rlm_checkval.c"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS targetname LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP checkval_cflags checkval_ldflags targetname LIBOBJS LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -714,6 +714,26 @@ ac_env_target_alias_set=${target_alias+set}
 ac_env_target_alias_value=$target_alias
 ac_cv_env_target_alias_set=${target_alias+set}
 ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
 
 #
 # Report the --help message.
@@ -781,6 +801,18 @@ if test -n "$ac_init_help"; then
 
   cat <<\_ACEOF
 
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
 _ACEOF
 fi
 
@@ -869,7 +901,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1221,6 +1253,1164 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 if test x$with_rlm_checkval != xno; then
 
+       ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+       ;;
+    conftest.$ac_ext )
+       # This is the source file.
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+       ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       # FIXME: I believe we export ac_cv_exeext for Libtool,
+       # but it would be cool to find out if it's true.  Does anybody
+       # maintain Libtool? --akim.
+       export ac_cv_exeext
+       break;;
+    * )
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         export ac_cv_exeext
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std1 is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std1.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX                  -qlanglvl=ansi
+# Ultrix and OSF/1     -std1
+# HP-UX 10.20 and later        -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4                 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+       ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
 
        targetname=rlm_checkval
 else
@@ -1228,6 +2418,24 @@ else
        echo \*\*\* module rlm_checkval is disabled.
 fi
 
+if test x"$fail" != x""; then
+       if test x"${enable_strict_dependencies}" = x"yes"; then
+               { { echo "$as_me:$LINENO: error: set --without-rlm_checkval to disable it explicitly." >&5
+echo "$as_me: error: set --without-rlm_checkval to disable it explicitly." >&2;}
+   { (exit 1); exit 1; }; }
+       else
+               { echo "$as_me:$LINENO: WARNING: silently not building rlm_checkval." >&5
+echo "$as_me: WARNING: silently not building rlm_checkval." >&2;}
+               { echo "$as_me:$LINENO: WARNING: FAILURE: rlm_checkval requires: $fail." >&5
+echo "$as_me: WARNING: FAILURE: rlm_checkval requires: $fail." >&2;};
+               targetname=""
+       fi
+fi
+
+
+
+
+
 
           ac_config_files="$ac_config_files Makefile"
 cat >confcache <<\_ACEOF
@@ -1864,6 +3072,16 @@ s,@ECHO_C@,$ECHO_C,;t t
 s,@ECHO_N@,$ECHO_N,;t t
 s,@ECHO_T@,$ECHO_T,;t t
 s,@LIBS@,$LIBS,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@CPP@,$CPP,;t t
+s,@checkval_cflags@,$checkval_cflags,;t t
+s,@checkval_ldflags@,$checkval_ldflags,;t t
 s,@targetname@,$targetname,;t t
 s,@LIBOBJS@,$LIBOBJS,;t t
 s,@LTLIBOBJS@,$LTLIBOBJS,;t t
@@ -2029,11 +3247,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -2072,6 +3285,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index f334371..37aea46 100644 (file)
@@ -1,11 +1,12 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_checkval.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_checkval])
 
 if test x$with_[]modname != xno; then
 
-       dnl  This module doesn't need any autoconf test which is not already
-       dnl  in top-level configure.
+       AC_PROG_CC
+       AC_PROG_CPP
 
        targetname=modname
 else
@@ -13,5 +14,20 @@ else
        echo \*\*\* module modname is disabled.
 fi
 
+dnl  Don't change this section.
+if test x"$fail" != x""; then
+       if test x"${enable_strict_dependencies}" = x"yes"; then
+               AC_MSG_ERROR([set --without-]modname[ to disable it explicitly.])
+       else
+               AC_MSG_WARN([silently not building ]modname[.])
+               AC_MSG_WARN([FAILURE: ]modname[ requires: $fail.]); 
+               targetname=""
+       fi
+fi
+
+
+AC_SUBST(checkval_cflags)
+AC_SUBST(checkval_ldflags)
+
 AC_SUBST(targetname)
 AC_OUTPUT(Makefile)
index aac33ec..04059a5 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2003  The FreeRADIUS server project
+ * Copyright 2003,2006  The FreeRADIUS server project
  * Copyright 2003  Kostas Kalevras <kkalev@noc.ntua.gr>
  */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 #ifdef HAVE_REGEX_H
 #      include <regex.h>
 #endif
@@ -67,7 +68,7 @@ typedef struct rlm_checkval_t {
  *     to the strdup'd string into 'config.string'.  This gets around
  *     buffer over-flows.
  */
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
   { "item-name",  PW_TYPE_STRING_PTR, offsetof(rlm_checkval_t,item_name), NULL,  NULL},
   { "check-name",  PW_TYPE_STRING_PTR, offsetof(rlm_checkval_t,check_name), NULL,  NULL},
   { "data-type",    PW_TYPE_STRING_PTR, offsetof(rlm_checkval_t,data_type),NULL, "integer"},
@@ -80,13 +81,6 @@ static int checkval_detach(void *instance)
 {
        rlm_checkval_t *data = (rlm_checkval_t *) instance;
 
-       if (data->item_name)
-               free((char *)data->item_name);
-       if (data->check_name)
-               free((char *)data->check_name);
-       if (data->data_type)
-               free((char *)data->data_type);
-
        free(instance);
        return 0;
 }
@@ -227,7 +221,7 @@ static int do_checkval(void *instance, REQUEST *request)
                        ret = RLM_MODULE_NOTFOUND;
        }
        if (item_vp)
-               DEBUG2("rlm_checkval: Item Name: %s, Value: %s",data->item_name, item_vp->strvalue);
+               DEBUG2("rlm_checkval: Item Name: %s, Value: %s",data->item_name, item_vp->vp_strvalue);
        tmp = request->config_items;
        do{
                if (!(chk_vp = pairfind(tmp, data->chk_attr))){
@@ -239,7 +233,7 @@ static int do_checkval(void *instance, REQUEST *request)
                }
                if (!item_vp)
                        break;
-               DEBUG2("rlm_checkval: Value Name: %s, Value: %s",data->check_name, chk_vp->strvalue);
+               DEBUG2("rlm_checkval: Value Name: %s, Value: %s",data->check_name, chk_vp->vp_strvalue);
 
                /*
                * Check if item != check
@@ -250,8 +244,8 @@ static int do_checkval(void *instance, REQUEST *request)
                        if (item_vp->length != chk_vp->length)
                                ret = RLM_MODULE_REJECT;
                        else{
-                               if (!memcmp(item_vp->strvalue,
-                                           chk_vp->strvalue,
+                               if (!memcmp(item_vp->vp_strvalue,
+                                           chk_vp->vp_strvalue,
                                            (size_t) chk_vp->length))
                                        ret = RLM_MODULE_OK;
                                else
@@ -273,13 +267,13 @@ static int do_checkval(void *instance, REQUEST *request)
                        char err_msg[MAX_STRING_LEN];
 
                        DEBUG("rlm_checkval: Doing regex");
-                       err = regcomp(&reg, (char *)chk_vp->strvalue, REG_EXTENDED|REG_NOSUB);
+                       err = regcomp(&reg, (char *)chk_vp->vp_strvalue, REG_EXTENDED|REG_NOSUB);
                        if (err){
                                regerror(err, &reg,err_msg, MAX_STRING_LEN);
                                DEBUG("rlm_checkval: regcomp() returned error: %s", err_msg);
                                return RLM_MODULE_FAIL;
                        }
-                       if (regexec(&reg, (char *)item_vp->strvalue,0, NULL, 0) == 0)
+                       if (regexec(&reg, (char *)item_vp->vp_strvalue,0, NULL, 0) == 0)
                                ret = RLM_MODULE_OK;
                        else
                                ret = RLM_MODULE_REJECT;
@@ -337,10 +331,11 @@ static int checkval_accounting(void *instance, REQUEST *request)
  *     is single-threaded.
  */
 module_t rlm_checkval = {
+        RLM_MODULE_INIT,
        "checkval",
        0,              /* type */
-       NULL,                           /* initialization */
        checkval_instantiate,           /* instantiation */
+       checkval_detach,                /* detach */
        {
                NULL,                   /* authentication */
                checkval_authorize,     /* authorization */
@@ -351,6 +346,4 @@ module_t rlm_checkval = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       checkval_detach,                /* detach */
-       NULL,                           /* destroy */
 };
diff --git a/src/modules/rlm_copy_packet/Makefile b/src/modules/rlm_copy_packet/Makefile
new file mode 100644 (file)
index 0000000..2b182ac
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile
+#
+# Version:     $Id$
+#
+
+TARGET         = rlm_copy_packet
+SRCS           = rlm_copy_packet.c
+
+include ../rules.mak
diff --git a/src/modules/rlm_copy_packet/README b/src/modules/rlm_copy_packet/README
new file mode 100644 (file)
index 0000000..e2fe1bb
--- /dev/null
@@ -0,0 +1,26 @@
+  This module initializes the Access-Accept packet by copying all of
+the attributes from the Access-Request to the Access-Accept.
+
+  It should be listed in the "authorize" section of "radiusd.conf",
+probably after "preprocess", but before any other module.
+
+
+       authorize {
+               ...
+
+               copy_packet
+
+               ...
+       }
+
+  It currently takes no configuration, so the sub-section of the
+"modules" section should look like:
+
+       modules {
+               ...
+
+               copy_packet {
+               }
+
+               ...
+       }
diff --git a/src/modules/rlm_copy_packet/rlm_copy_packet.c b/src/modules/rlm_copy_packet/rlm_copy_packet.c
new file mode 100644 (file)
index 0000000..72f0baa
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * rlm_copy_packet.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 2004,2006  The FreeRADIUS server project
+ * Copyright 2004  Alan DeKok <aland@cladju.com>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/conffile.h>
+
+/*
+ *     Define a structure for our module configuration.
+ *
+ *     It doesn't take any configuration right now...
+ */
+typedef struct rlm_packet_t {
+       char            *string;
+} rlm_packet_t;
+
+
+/*
+ *     A mapping of configuration file names to internal variables.
+ *
+ *     Note that the string is dynamically allocated, so it MUST
+ *     be freed.  When the configuration file parse re-reads the string,
+ *     it free's the old one, and strdup's the new one, placing the pointer
+ *     to the strdup'd string into 'config.string'.  This gets around
+ *     buffer over-flows.
+ */
+static const CONF_PARSER module_config[] = {
+  { "string",  PW_TYPE_STRING_PTR, offsetof(rlm_packet_t,string), NULL,  NULL},
+
+  { NULL, -1, 0, NULL, NULL }          /* end the list */
+};
+
+
+static int packet_detach(void *instance)
+{
+       rlm_packet_t    *inst = instance;
+
+       free(instance);
+       return 0;
+}
+
+
+/*
+ *     Do any per-module initialization that is separate to each
+ *     configured instance of the module.  e.g. set up connections
+ *     to external databases, read configuration files, set up
+ *     dictionary entries, etc.
+ *
+ *     If configuration information is given in the config section
+ *     that must be referenced in later calls, store a handle to it
+ *     in *instance otherwise put a null pointer there.
+ */
+static int packet_instantiate(CONF_SECTION *conf, void **instance)
+{
+       rlm_packet_t *inst;
+
+       /*
+        *      Set up a storage area for instance data
+        */
+       inst = rad_malloc(sizeof(*inst));
+       if (!inst) {
+               return -1;
+       }
+       memset(inst, 0, sizeof(*inst));
+
+       /*
+        *      If the configuration parameters can't be parsed, then
+        *      fail.
+        */
+       if (cf_section_parse(conf, inst, module_config) < 0) {
+               packet_detach(inst);
+               return -1;
+       }
+
+       *instance = inst;
+
+       return 0;
+}
+
+
+/*
+ *     Initialize the reply with the request.
+ */
+static int packet_authorize(void *instance, REQUEST *request)
+{
+       VALUE_PAIR      *vps;
+
+       instance = instance;    /* -Wunused */
+
+       vps = paircopy(request->packet->vps);
+       pairadd(&(request->reply->vps), vps);
+       return RLM_MODULE_UPDATED;
+}
+
+
+/*
+ *     The module name should be the only globally exported symbol.
+ *     That is, everything else should be 'static'.
+ *
+ *     If the module needs to temporarily modify it's instantiation
+ *     data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
+ *     The server will then take care of ensuring that the module
+ *     is single-threaded.
+ */
+module_t rlm_copy_packet = {
+        RLM_MODULE_INIT,
+       "copy_packet",
+       RLM_TYPE_THREAD_SAFE,           /* type */
+       packet_instantiate,             /* instantiation */
+       packet_detach,                  /* detach */
+       {
+               NULL,                   /* authentication */
+               packet_authorize,       /* authorization */
+               NULL,                   /* preaccounting */
+               NULL,                   /* accounting */
+               NULL,                   /* checksimul */
+               NULL,                   /* pre-proxy */
+               NULL,                   /* post-proxy */
+               NULL                    /* post-auth */
+       },
+};
diff --git a/src/modules/rlm_counter/acconfig.h b/src/modules/rlm_counter/acconfig.h
deleted file mode 100644 (file)
index 376f75b..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/* do we need GDBM_SYNC */
-#undef NEED_GDBM_SYNC
-
-/* do we have gdbm_fdesc */
-#undef HAVE_GDBM_FDESC
index 072ac27..32fad9e 100644 (file)
@@ -1,7 +1,22 @@
-/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* do we have gdbm_fdesc */
+#undef HAVE_GDBM_FDESC
 
 /* do we need GDBM_SYNC */
 #undef NEED_GDBM_SYNC
 
-/* do we have gdbm_fdesc */
-#undef HAVE_GDBM_FDESC
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
index 2c05d8a..c988de6 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.9 .
+# From configure.in Revision: 1.11 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -901,7 +901,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1821,8 +1821,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1880,8 +1879,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1997,8 +1995,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2052,8 +2049,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2098,8 +2094,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2143,8 +2138,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2457,8 +2451,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2481,8 +2474,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" = "x"; then
@@ -2511,8 +2504,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2590,8 +2582,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2614,8 +2605,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" != "x"; then
@@ -2667,8 +2658,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2691,8 +2681,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" = "x"; then
@@ -2721,8 +2711,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2827,8 +2816,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2851,8 +2839,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" != "x"; then
@@ -2907,7 +2895,8 @@ _ACEOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
   $EGREP "found-gdbm-sync" >/dev/null 2>&1; then
 
-                       cat >>confdefs.h <<\_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
 #define NEED_GDBM_SYNC yes
 _ACEOF
 
@@ -2992,8 +2981,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3020,8 +3008,9 @@ echo "${ECHO_T}$ac_cv_func_gdbm_fdesc" >&6
 
        if test "x$ac_cv_func_gdbm_fdesc" = "xyes";
        then
-               cat >>confdefs.h <<\_ACEOF
-#define HAVE_GDBM_FDESC 1
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GDBM_FDESC
 _ACEOF
 
        fi
@@ -3841,11 +3830,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3884,6 +3868,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 4783219..a81bff9 100644 (file)
@@ -1,3 +1,4 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_counter.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_counter])
@@ -7,8 +8,8 @@ if test x$with_[]modname != xno; then
        AC_PROG_CC
        AC_PROG_CPP
 
-       AC_SMART_CHECK_INCLUDE(gdbm.h)
-       AC_SMART_CHECK_LIB(gdbm, gdbm_open)
+       FR_SMART_CHECK_INCLUDE(gdbm.h)
+       FR_SMART_CHECK_LIB(gdbm, gdbm_open)
        if test "x$ac_cv_lib_gdbm_gdbm_open" != "xyes"; then
                fail="$fail libgdbm"
        fi
@@ -23,7 +24,7 @@ if test x$with_[]modname != xno; then
        not found.  this version must use sync by default.
 #endif
                        ], [
-                       AC_DEFINE(NEED_GDBM_SYNC, yes) 
+                       AC_DEFINE(NEED_GDBM_SYNC, yes, [do we need GDBM_SYNC]
                        AC_MSG_RESULT(needs it.)
                        ], [
                        AC_MSG_RESULT(SYNCs by default.)
@@ -36,7 +37,7 @@ if test x$with_[]modname != xno; then
        AC_CHECK_FUNC(gdbm_fdesc)
        if test "x$ac_cv_func_gdbm_fdesc" = "xyes";
        then
-               AC_DEFINE(HAVE_GDBM_FDESC)
+               AC_DEFINE(HAVE_GDBM_FDESC, [], [do we have gdbm_fdesc])
        fi
        LIBS=$old_LIBS
 
index ccaf8ed..b50649c 100755 (executable)
@@ -9,13 +9,28 @@ use Getopt::Long;
 
 my $user = '';
 my $divisor = 1;
+my $reset = 0;
 my $match = '.*';
+my $help = 0;
 
 #
 #  This should be fixed...
 #
 $filename = '';
 
+sub show_help {
+    print "Usage: $0 --file=<counter filename> [--reset=<seconds>] [--match=<regexp>]\n";
+    print "[--user=<username>] [--help] [--hours|--minutes|--seconds]\n\n";
+    print "--user=<username>", "\t\t", "Information for specific user\n";
+    print "--file=<filename>", "\t\t", "Counter db filename\n";
+    print "--match=<regexp>", "\t\t", "Information for matching users\n";
+    print "--reset=<number>", "\t\t", "Reset counter to <number>.\n";
+    print "\t\t\t\t", "If divisor is set use it, else <number> means seconds\n";
+    print "--help", "\t\t\t\t", "Show this help screen\n";
+    print "--(hours|minutes|seconds)", "\t", "Specify information divisor\n";
+    exit 0;
+}
+
 #
 #  Print out only one user,
 #
@@ -24,27 +39,37 @@ $filename = '';
 GetOptions ('user=s'  => \$user,
            'match=s' => \$match,
            'file=s'  => \$filename,
+            'reset=i' => \$reset,
+            'help'    => \$help,
            'hours'   => sub { $divisor = 3600 },
            'minutes' => sub { $divisor = 60 },
            'seconds' => sub { $divisor = 1 } );
 
-#
-#  For now, this must be specified by hand.
-#
-if ($filename eq '') {
-    die "You MUST specify the DB filename via: --file = <filename>\n";
-}
+show_help if ($help || $filename eq '');
 
 #
 #  Open the file.
 #
-my $db = tie(%hash, 'GDBM_File', $filename, O_RDONLY, 0666) or die "Cannot open$filename: $!\n";
+if ($reset){
+    my $db = tie(%hash, 'GDBM_File', $filename, O_RDWR, 0666) or die "Cannot open $filename: $!\n";
+}else{
+    my $db = tie(%hash, 'GDBM_File', $filename, O_RDONLY, 0666) or die "Cannot open $filename: $!\n";
+}
 
 #
 #  If given one name, give the seconds
 #
 if ($user ne '') {
-    print $user, "\t\t", int ( unpack('L',$hash{$user}) / $divisor), "\n";
+    if (defined($hash{$user})){
+        print $user, "\t\t", int ( unpack('L',$hash{$user}) / $divisor), "\n";
+       if ($reset){
+            my $uniqueid = (unpack('L A32',$hash{$user}))[1];
+            $hash{$user} = pack('L A32',$reset * $divisor,$uniqueid);
+            print $user, "\t\t", "Counter reset to ", $reset * $divisor, "\n";
+        }
+    }else{
+        print $user, "\t\t", "Not found\n"; 
+    }
 
     undef $db;
     untie %hash;
@@ -69,6 +94,11 @@ foreach $key (sort keys %hash) {
     #
     #  Print out the names...
     print $key, "\t\t", int ( unpack('L',$hash{$key}) / $divisor), "\n";
+    if ($reset){
+        my $uniqueid = (unpack('L A32',$hash{$key}))[1];
+        $hash{$key} = pack('L A32',$reset * $divisor,$uniqueid);
+        print $key, "\t\t", "Counter reset to ", $reset * $divisor, "\n";
+    }
 }
 undef $db;
 untie %hash;
index 7480475..2a523b6 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2001  The FreeRADIUS server project
+ * Copyright 2001,2006  The FreeRADIUS server project
  * Copyright 2001  Alan DeKok <aland@ox.org>
  * Copyright 2001-3  Kostas Kalevras <kkalev@noc.ntua.gr>
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include "config.h"
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 #include <gdbm.h>
-#include <time.h>
 
 #ifdef NEEDS_GDBM_SYNC
 #      define GDBM_SYNCOPT GDBM_SYNC
@@ -56,8 +56,6 @@
 
 #define UNIQUEID_MAX_LEN 32
 
-static const char rcsid[] = "$Id$";
-
 /*
  *     Define a structure for our module configuration.
  *
@@ -72,12 +70,14 @@ typedef struct rlm_counter_t {
        char *count_attribute;  /* Acct-Session-Time */
        char *counter_name;     /* Daily-Session-Time */
        char *check_name;       /* Daily-Max-Session */
+       char *reply_name;       /* Session-Timeout */
        char *service_type;     /* Service-Type to search for */
        int cache_size;
        int service_val;
        int key_attr;
        int count_attr;
        int check_attr;
+       int reply_attr;
        time_t reset_time;      /* The time of the next reset. */
        time_t last_reset;      /* The time of the last reset. */
        int dict_attr;          /* attribute number for the counter. */
@@ -112,13 +112,14 @@ typedef struct rad_counter {
  *     to the strdup'd string into 'config.string'.  This gets around
  *     buffer over-flows.
  */
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
   { "filename", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,filename), NULL, NULL },
   { "key", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,key_name), NULL, NULL },
   { "reset", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,reset), NULL,  NULL },
   { "count-attribute", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,count_attribute), NULL, NULL },
   { "counter-name", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,counter_name), NULL,  NULL },
   { "check-name", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,check_name), NULL, NULL },
+  { "reply-name", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,reply_name), NULL, NULL },
   { "allowed-servicetype", PW_TYPE_STRING_PTR, offsetof(rlm_counter_t,service_type),NULL, NULL },
   { "cache-size", PW_TYPE_INTEGER, offsetof(rlm_counter_t,cache_size), NULL, "1000" },
   { NULL, -1, 0, NULL, NULL }
@@ -153,7 +154,7 @@ static int counter_cmp(void *instance,
                return RLM_MODULE_NOOP;
        }
 
-       key_datum.dptr = key_vp->strvalue;
+       key_datum.dptr = key_vp->vp_strvalue;
        key_datum.dsize = key_vp->length;
 
        count_datum = gdbm_fetch(data->gdbm, key_datum);
@@ -241,21 +242,21 @@ static int reset_db(rlm_counter_t *data)
 
 static int find_next_reset(rlm_counter_t *data, time_t timeval)
 {
-       int ret=0;
-       unsigned int num=1;
-       char last = 0;
+       int ret = 0;
+       size_t len;
+       unsigned int num = 1;
+       char last = '\0';
        struct tm *tm, s_tm;
        char sCurrentTime[40], sNextTime[40];
 
        tm = localtime_r(&timeval, &s_tm);
-       strftime(sCurrentTime, sizeof(sCurrentTime),"%Y-%m-%d %H:%M:%S",tm);
+       len = strftime(sCurrentTime, sizeof(sCurrentTime), "%Y-%m-%d %H:%M:%S", tm);
+       if (len == 0) *sCurrentTime = '\0';
        tm->tm_sec = tm->tm_min = 0;
 
        if (data->reset == NULL)
                return -1;
        if (isdigit((int) data->reset[0])){
-               unsigned int len=0;
-
                len = strlen(data->reset);
                if (len == 0)
                        return -1;
@@ -297,9 +298,11 @@ static int find_next_reset(rlm_counter_t *data, time_t timeval)
                        data->reset);
                return -1;
        }
-       strftime(sNextTime, sizeof(sNextTime),"%Y-%m-%d %H:%M:%S",tm);
-       DEBUG2("rlm_counter: Current Time: %d [%s], Next reset %d [%s]",
-               (int)timeval,sCurrentTime,(int)data->reset_time,sNextTime);
+
+       len = strftime(sNextTime, sizeof(sNextTime), "%Y-%m-%d %H:%M:%S", tm);
+       if (len == 0) *sNextTime = '\0';
+       DEBUG2("rlm_counter: Current Time: %li [%s], Next reset %li [%s]",
+               timeval, sCurrentTime, data->reset_time, sNextTime);
 
        return ret;
 }
@@ -384,6 +387,27 @@ static int counter_instantiate(CONF_SECTION *conf, void **instance)
        data->count_attr = dattr->attr;
 
        /*
+        * Discover the attribute number of the reply attribute.
+        */
+       if (data->reply_name != NULL) {
+               dattr = dict_attrbyname(data->reply_name);
+               if (dattr == NULL) {
+                       radlog(L_ERR, "rlm_counter: No such attribute %s",
+                                       data->reply_name);
+                       counter_detach(data);
+                       return -1;
+               }
+               if (dattr->type != PW_TYPE_INTEGER) {
+                       radlog(L_ERR, "rlm_counter: Reply attribute %s is not of type integer",
+                               data->reply_name);
+                       counter_detach(data);
+                       return -1;
+               }
+               data->reply_attr = dattr->attr;
+       }
+       
+
+       /*
         *  Create a new attribute for the counter.
         */
        if (data->counter_name == NULL) {
@@ -564,7 +588,7 @@ static int counter_accounting(void *instance, REQUEST *request)
        }
        uniqueid_vp = pairfind(request->packet->vps, PW_ACCT_UNIQUE_SESSION_ID);
        if (uniqueid_vp != NULL)
-               DEBUG("rlm_counter: Packet Unique ID = '%s'",uniqueid_vp->strvalue);
+               DEBUG("rlm_counter: Packet Unique ID = '%s'",uniqueid_vp->vp_strvalue);
 
        /*
         *      Before doing anything else, see if we have to reset
@@ -629,10 +653,10 @@ static int counter_accounting(void *instance, REQUEST *request)
                return RLM_MODULE_NOOP;
        }
 
-       key_datum.dptr = key_vp->strvalue;
+       key_datum.dptr = key_vp->vp_strvalue;
        key_datum.dsize = key_vp->length;
 
-       DEBUG("rlm_counter: Searching the database for key '%s'",key_vp->strvalue);
+       DEBUG("rlm_counter: Searching the database for key '%s'",key_vp->vp_strvalue);
        pthread_mutex_lock(&data->mutex);
        count_datum = gdbm_fetch(data->gdbm, key_datum);
        pthread_mutex_unlock(&data->mutex);
@@ -640,7 +664,8 @@ static int counter_accounting(void *instance, REQUEST *request)
                DEBUG("rlm_counter: Could not find the requested key in the database.");
                counter.user_counter = 0;
                if (uniqueid_vp != NULL)
-                       strncpy(counter.uniqueid,uniqueid_vp->strvalue,UNIQUEID_MAX_LEN - 1);
+                       strlcpy(counter.uniqueid,uniqueid_vp->vp_strvalue,
+                               sizeof(counter.uniqueid));
                else
                        memset((char *)counter.uniqueid,0,UNIQUEID_MAX_LEN);
        }
@@ -652,13 +677,14 @@ static int counter_accounting(void *instance, REQUEST *request)
                        DEBUG("rlm_counter: Counter Unique ID = '%s'",counter.uniqueid);
                if (uniqueid_vp != NULL){
                        if (counter.uniqueid != NULL &&
-                               strncmp(uniqueid_vp->strvalue,counter.uniqueid, UNIQUEID_MAX_LEN - 1) == 0){
+                               strncmp(uniqueid_vp->vp_strvalue,counter.uniqueid, UNIQUEID_MAX_LEN - 1) == 0){
                                DEBUG("rlm_counter: Unique IDs for user match. Droping the request.");
                                return RLM_MODULE_NOOP;
                        }
-                       strncpy(counter.uniqueid,uniqueid_vp->strvalue,UNIQUEID_MAX_LEN - 1);
+                       strlcpy(counter.uniqueid,uniqueid_vp->vp_strvalue,
+                               sizeof(counter.uniqueid));
                }
-               DEBUG("rlm_counter: User=%s, Counter=%d.",request->username->strvalue,counter.user_counter);
+               DEBUG("rlm_counter: User=%s, Counter=%d.",request->username->vp_strvalue,counter.user_counter);
        }
 
        if (data->count_attr == PW_ACCT_SESSION_TIME) {
@@ -690,7 +716,7 @@ static int counter_accounting(void *instance, REQUEST *request)
                counter.user_counter++;
        }
 
-       DEBUG("rlm_counter: User=%s, New Counter=%d.",request->username->strvalue,counter.user_counter);
+       DEBUG("rlm_counter: User=%s, New Counter=%d.",request->username->vp_strvalue,counter.user_counter);
        count_datum.dptr = (char *) &counter;
        count_datum.dsize = sizeof(rad_counter);
 
@@ -766,7 +792,7 @@ static int counter_authorize(void *instance, REQUEST *request)
                return ret;
        }
 
-       key_datum.dptr = key_vp->strvalue;
+       key_datum.dptr = key_vp->vp_strvalue;
        key_datum.dsize = key_vp->length;
 
 
@@ -776,7 +802,7 @@ static int counter_authorize(void *instance, REQUEST *request)
 
        counter.user_counter = 0;
 
-       DEBUG("rlm_counter: Searching the database for key '%s'",key_vp->strvalue);
+       DEBUG("rlm_counter: Searching the database for key '%s'",key_vp->vp_strvalue);
        pthread_mutex_lock(&data->mutex);
        count_datum = gdbm_fetch(data->gdbm, key_datum);
        pthread_mutex_unlock(&data->mutex);
@@ -817,9 +843,12 @@ static int counter_authorize(void *instance, REQUEST *request)
                        *       If we are near a reset then add the next
                        *       limit, so that the user will not need to
                        *       login again
+                       *       Before that set the return value to the time
+                       *       remaining to next reset
                        */
                        if (data->reset_time && (
                                res >= (data->reset_time - request->timestamp))) {
+                               res = data->reset_time - request->timestamp;
                                res += check_vp->lvalue;
                        }
 
@@ -835,14 +864,28 @@ static int counter_authorize(void *instance, REQUEST *request)
                                pairadd(&request->reply->vps, reply_item);
                        }
                }
+               else if (data->reply_attr) {
+                       if ((reply_item = pairfind(request->reply->vps, data->reply_attr)) != NULL) {
+                               if (reply_item->lvalue > res)
+                                       reply_item->lvalue = res;
+                       }
+                       else {
+                               if ((reply_item = paircreate(data->reply_attr, PW_TYPE_INTEGER)) == NULL) {
+                                       radlog(L_ERR|L_CONS, "no memory");
+                                       return RLM_MODULE_NOOP;
+                               }
+                               reply_item->lvalue = res;
+                               pairadd(&request->reply->vps, reply_item);
+                       }
+               }
 
                ret=RLM_MODULE_OK;
 
                DEBUG2("rlm_counter: (Check item - counter) is greater than zero");
                DEBUG2("rlm_counter: Authorized user %s, check_item=%d, counter=%d",
-                               key_vp->strvalue,check_vp->lvalue,counter.user_counter);
+                               key_vp->vp_strvalue,check_vp->lvalue,counter.user_counter);
                DEBUG2("rlm_counter: Sent Reply-Item for user %s, Type=Session-Timeout, value=%d",
-                               key_vp->strvalue,res);
+                               key_vp->vp_strvalue,res);
        }
        else{
                char module_fmsg[MAX_STRING_LEN];
@@ -862,7 +905,7 @@ static int counter_authorize(void *instance, REQUEST *request)
                ret=RLM_MODULE_REJECT;
 
                DEBUG2("rlm_counter: Rejected user %s, check_item=%d, counter=%d",
-                               key_vp->strvalue,check_vp->lvalue,counter.user_counter);
+                               key_vp->vp_strvalue,check_vp->lvalue,counter.user_counter);
        }
 
        return ret;
@@ -875,13 +918,6 @@ static int counter_detach(void *instance)
        paircompare_unregister(data->dict_attr, counter_cmp);
        if (data->gdbm)
                gdbm_close(data->gdbm);
-       free(data->filename);
-       free(data->reset);
-       free(data->key_name);
-       free(data->count_attribute);
-       free(data->counter_name);
-       free(data->check_name);
-       free(data->service_type);
        pthread_mutex_destroy(&data->mutex);
 
        free(instance);
@@ -898,10 +934,11 @@ static int counter_detach(void *instance)
  *     is single-threaded.
  */
 module_t rlm_counter = {
-       "Counter",
+        RLM_MODULE_INIT,
+       "counter",
        RLM_TYPE_THREAD_SAFE,           /* type */
-       NULL,                           /* initialization */
        counter_instantiate,            /* instantiation */
+       counter_detach,                 /* detach */
        {
                NULL,                   /* authentication */
                counter_authorize,      /* authorization */
@@ -912,6 +949,4 @@ module_t rlm_counter = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       counter_detach,                 /* detach */
-       NULL,                           /* destroy */
 };
index f36d8ef..58b18cf 100644 (file)
@@ -15,9 +15,9 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2002  The FreeRADIUS server project
+ * Copyright 2002,2006  The FreeRADIUS server project
  */
 
 /*
  *   (c) 2002 by SANDY (http://www.sandy.ru/) under GPL
  */
 
-#include       "autoconf.h"
-#include       "libradius.h"
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include       <freeradius-devel/autoconf.h>
 
 #include       <stdio.h>
 #include       <stdlib.h>
 #include       <string.h>
 #include       <ctype.h>
 
-#include       "radiusd.h"
-#include       "modules.h"
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/modules.h>
 
-#include        "md4.h"
-#include        "md5.h"
-#include        "sha1.h"
+#include        <freeradius-devel/md5.h>
 
 
 #define                SM_AUTHTYPE     ((11406<<16)|101)
@@ -132,14 +132,14 @@ static void calc_sha1_digest(char * buffer, const char * challenge, int challen,
 }
 
 
-static int cram_authenticate(void * instance, REQUEST *request)
+static int cram_authenticate(UNUSED void * instance, REQUEST *request)
 {
        VALUE_PAIR *authtype, *challenge, *response, *password;
        char buffer[64];
 
-       password = pairfind(request->config_items, PW_PASSWORD);
+       password = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);
        if(!password) {
-               radlog(L_AUTH, "rlm_cram: Password is not configured for user");
+               radlog(L_AUTH, "rlm_cram: Cleartext-Password is required for authentication.");
                return RLM_MODULE_INVALID;
        }
        authtype = pairfind(request->packet->vps, SM_AUTHTYPE);
@@ -163,32 +163,32 @@ static int cram_authenticate(void * instance, REQUEST *request)
                                radlog(L_AUTH, "rlm_cram: invalid MD5 challenge/response length");
                                return RLM_MODULE_INVALID;
                        }
-                       calc_md5_digest(buffer, challenge->strvalue, challenge->length, password->strvalue);
-                       if(!memcmp(buffer, response->strvalue, 16)) return RLM_MODULE_OK;
+                       calc_md5_digest(buffer, challenge->vp_strvalue, challenge->length, password->vp_strvalue);
+                       if(!memcmp(buffer, response->vp_strvalue, 16)) return RLM_MODULE_OK;
                        break;
                case 3:                         /*      APOP    */
                        if(challenge->length < 5 || response->length != 16) {
                                radlog(L_AUTH, "rlm_cram: invalid APOP challenge/response length");
                                return RLM_MODULE_INVALID;
                        }
-                       calc_apop_digest(buffer, challenge->strvalue, challenge->length, password->strvalue);
-                       if(!memcmp(buffer, response->strvalue, 16)) return RLM_MODULE_OK;
+                       calc_apop_digest(buffer, challenge->vp_strvalue, challenge->length, password->vp_strvalue);
+                       if(!memcmp(buffer, response->vp_strvalue, 16)) return RLM_MODULE_OK;
                        break;
                case 8:                         /*      CRAM-MD4        */
                        if(challenge->length < 5 || response->length != 16) {
                                radlog(L_AUTH, "rlm_cram: invalid MD4 challenge/response length");
                                return RLM_MODULE_INVALID;
                        }
-                       calc_md4_digest(buffer, challenge->strvalue, challenge->length, password->strvalue);
-                       if(!memcmp(buffer, response->strvalue, 16)) return RLM_MODULE_OK;
+                       calc_md4_digest(buffer, challenge->vp_strvalue, challenge->length, password->vp_strvalue);
+                       if(!memcmp(buffer, response->vp_strvalue, 16)) return RLM_MODULE_OK;
                        break;
                case 9:                         /*      CRAM-SHA1       */
                        if(challenge->length < 5 || response->length != 20) {
                                radlog(L_AUTH, "rlm_cram: invalid MD4 challenge/response length");
                                return RLM_MODULE_INVALID;
                        }
-                       calc_sha1_digest(buffer, challenge->strvalue, challenge->length, password->strvalue);
-                       if(!memcmp(buffer, response->strvalue, 20)) return RLM_MODULE_OK;
+                       calc_sha1_digest(buffer, challenge->vp_strvalue, challenge->length, password->vp_strvalue);
+                       if(!memcmp(buffer, response->vp_strvalue, 20)) return RLM_MODULE_OK;
                        break;
                default:
                        radlog(L_AUTH, "rlm_cram: unsupported Sandy-Mail-Authtype");
@@ -199,20 +199,19 @@ static int cram_authenticate(void * instance, REQUEST *request)
 }
 
 module_t rlm_cram = {
-  "CRAM",
-  RLM_TYPE_THREAD_SAFE,                                /* type */
-  NULL,                                /* initialize */
-  NULL,                /* instantiation */
-  {
-         cram_authenticate,    /* authenticate */
-         NULL,                 /* authorize */
-         NULL,                 /* pre-accounting */
-         NULL,                 /* accounting */
-         NULL,                 /* checksimul */
-         NULL,                 /* pre-proxy */
-         NULL,                 /* post-proxy */
-         NULL                  /* post-auth */
-  },
-  NULL,                                /* detach */
-  NULL,                                /* destroy */
+       RLM_MODULE_INIT,
+       "CRAM",
+       RLM_TYPE_THREAD_SAFE,           /* type */
+       NULL,                           /* instantiation */
+       NULL,                           /* detach */
+       {
+               cram_authenticate,      /* authenticate */
+               NULL,                   /* authorize */
+               NULL,                   /* pre-accounting */
+               NULL,                   /* accounting */
+               NULL,                   /* checksimul */
+               NULL,                   /* pre-proxy */
+               NULL,                   /* post-proxy */
+               NULL                    /* post-auth */
+       },
 };
index 2d1554d..3cbf230 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.12 .
+# From configure.in Revision: 1.13 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -907,7 +907,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1827,8 +1827,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1886,8 +1885,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2003,8 +2001,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2058,8 +2055,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2104,8 +2100,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2149,8 +2144,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2504,8 +2498,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2528,8 +2521,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" = "x"; then
@@ -2558,8 +2551,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2637,8 +2629,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2661,8 +2652,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" != "x"; then
@@ -2717,8 +2708,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2741,8 +2731,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" = "x"; then
@@ -2771,8 +2761,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2850,8 +2839,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2874,8 +2862,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" != "x"; then
@@ -2931,8 +2919,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2955,8 +2942,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" = "x"; then
@@ -2985,8 +2972,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3064,8 +3050,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3088,8 +3073,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" != "x"; then
@@ -3136,8 +3121,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3201,8 +3185,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3225,8 +3208,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" = "x"; then
@@ -3255,8 +3238,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3361,8 +3343,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3385,8 +3366,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" != "x"; then
@@ -3439,8 +3420,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3463,8 +3443,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" = "x"; then
@@ -3493,8 +3473,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3599,8 +3578,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3623,8 +3601,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" != "x"; then
@@ -3677,8 +3655,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3701,8 +3678,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" = "x"; then
@@ -3731,8 +3708,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3837,8 +3813,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3861,8 +3836,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" != "x"; then
@@ -4727,11 +4702,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -4770,6 +4740,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 1aa5340..08eb109 100644 (file)
@@ -1,3 +1,4 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_dbm.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_dbm])
@@ -40,16 +41,16 @@ if test x$with_[]modname != xno; then
        )
 
        smart_try_dir=$rlm_dbm_include_dir
-       AC_SMART_CHECK_INCLUDE(ndbm.h)
+       FR_SMART_CHECK_INCLUDE(ndbm.h)
        if test "x$ac_cv_header_ndbm_h" = "xyes"; then
           SMART_CFLAGS="${SMART_CFLAGS} -DHAVE_NDBM_H"
        else
-               AC_SMART_CHECK_INCLUDE(gdbm/ndbm.h)
+               FR_SMART_CHECK_INCLUDE(gdbm/ndbm.h)
                if test "x$ac_cv_header_gdbm_ndbm_h" = "xyes"; then
                        SMART_CFLAGS="${SMART_CFLAGS} -DHAVE_GDBM_NDBM_H"
                else
                        ac_cv_header_gdbm_ndbm_h="bad autoconf assumption"
-                       AC_SMART_CHECK_INCLUDE(gdbm-ndbm.h)
+                       FR_SMART_CHECK_INCLUDE(gdbm-ndbm.h)
                        if test "x$ac_cv_header_gdbmmndbm_h" = "xyes"; then
                                SMART_CFLAGS="${SMART_CFLAGS} -DHAVE_GDBMNDBM_H"
                        else
@@ -62,13 +63,13 @@ if test x$with_[]modname != xno; then
                AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)])
        if test "x$ac_cv_lib_default_dbm_open" != "xyes"; then
                smart_try_dir=$rlm_dbm_lib_dir
-               AC_SMART_CHECK_LIB(ndbm, dbm_open)
+               FR_SMART_CHECK_LIB(ndbm, dbm_open)
                if test "x$ac_cv_lib_ndbm_dbm_open" != "xyes"; then
                        dnl GNU DBM < 1.8.1
-                       AC_SMART_CHECK_LIB(gdbm, dbm_open)
+                       FR_SMART_CHECK_LIB(gdbm, dbm_open)
                        if test "x$ac_cv_lib_gdbm_dbm_open" != "xyes"; then
                                dnl GNU DBM >= 1.8.1
-                               AC_SMART_CHECK_LIB(gdbm_compat, dbm_open)
+                               FR_SMART_CHECK_LIB(gdbm_compat, dbm_open)
                                if test "x$ac_cv_lib_gdbm_compat_dbm_open" != "xyes"; then
                                        fail="$fail (libndbm or libgdbm or libgdbm_compat)"
                                fi
index 9ee2859..850670f 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2001 Koulik Andrei, Sandy Service
+ * Copyright 2006 The FreeRADIUS server project
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
 #include <string.h>
 #include <stdlib.h>
 
 
 #include <fcntl.h>
 
-#include "libradius.h"
-#include "radiusd.h"
-#include "modules.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 #ifdef SANDY_MOD
 #      include "sandymod.h"
 #endif
 
-static const char rcsid[] = "$Id$";
-
 #define MYDBM  DBM
 #define get_user_content dbm_fetch
 
@@ -72,7 +75,7 @@ typedef struct user_entry {
 } SM_USER_ENTRY;
 
 
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
         { "usersfile",     PW_TYPE_STRING_PTR,offsetof(struct rlm_dbm_t,userfile),
                NULL, "/etc/uf" },
         { NULL, -1, 0, NULL, NULL }
@@ -199,7 +202,7 @@ static int sm_parse_user(DBM *pdb, const char * username, VALUE_PAIR const* requ
                DEBUG2("parse buffer: <<%s>>\n",beg);
 
                retcod = userparse(beg,&vp);
-               if ( retcod == T_INVALID ) librad_perror("parse error ");
+               if ( retcod == T_OP_INVALID ) librad_perror("parse error ");
 
                switch ( retcod ) {
                        case T_COMMA: break; /* continue parse the current list */
@@ -207,7 +210,7 @@ static int sm_parse_user(DBM *pdb, const char * username, VALUE_PAIR const* requ
                                        if ( parse_state == SMP_PATTERN ) { /* pattern line found */
                                                DEBUG2("process pattern");
                                                /* check pattern against request */
-                                               if ( paircmp(NULL, request, vp, reply ) == 0 ) {
+                                               if ( paircompare(NULL, request, vp, reply ) == 0 ) {
                                                        DEBUG2("rlm_dbm: Pattern matched, look for request");
                                                        pairmove(&tmp_config, &vp);
                                                        pairfree(&vp);
@@ -225,9 +228,9 @@ static int sm_parse_user(DBM *pdb, const char * username, VALUE_PAIR const* requ
                                                join_attr = vp;
                                                while( (join_attr = pairfind(join_attr,SM_JOIN_ATTR) ) != NULL ) {
                                                        DEBUG2("rlm_dbm: Proccess nested record: username %s",
-                                                               (char *)join_attr->strvalue);
+                                                               (char *)join_attr->vp_strvalue);
                                                        /* res =  RLM_MODULE_NOTFOUND; */
-                                                       res =  sm_parse_user(pdb, (char *)join_attr->strvalue, request, &tmp_config,
+                                                       res =  sm_parse_user(pdb, (char *)join_attr->vp_strvalue, request, &tmp_config,
                                                                        &nu_reply, ulist);
                                                        DEBUG("rlm_dbm: recived: %d\n",res);
                                                        switch ( res ) {
@@ -324,7 +327,7 @@ static int rlm_dbm_authorize(void *instance, REQUEST *request)
          *      Grab the canonical user name.
          */
         namepair = request->username;
-        name = namepair ? (char *) namepair->strvalue : "NONE";
+        name = namepair ? (char *) namepair->vp_strvalue : "NONE";
 
        DEBUG2("rlm_dbm: try open database file: %s\n",inst -> userfile);
 
@@ -360,7 +363,6 @@ static int rlm_dbm_authorize(void *instance, REQUEST *request)
 static int rlm_dbm_detach(void *instance)
 {
        struct rlm_dbm_t *inst = instance;
-       free(inst -> userfile);
        free(inst);
        return 0;
 }
@@ -368,10 +370,11 @@ static int rlm_dbm_detach(void *instance)
 
 /* globally exported name */
 module_t rlm_dbm = {
+       RLM_MODULE_INIT,
         "dbm",
         0,                              /* type: reserved */
-        NULL,                           /* initialization */
         rlm_dbm_instantiate,            /* instantiation */
+        rlm_dbm_detach,                 /* detach */
         {
                 NULL,                   /* authentication */
                 rlm_dbm_authorize,      /* authorization */
@@ -382,6 +385,4 @@ module_t rlm_dbm = {
                 NULL,                  /* post-proxy */
                 NULL                   /* post-auth */
        },
-        rlm_dbm_detach,                 /* detach */
-       NULL                            /* destroy */
 };
index ca02ee1..3d3bfb1 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2001 Koulik Andrei, Sandy Service
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/autoconf.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -69,7 +69,11 @@ static void dump_record(datum key,datum data)
        putchar('\n');
 }
 
+#ifdef __GNUC__
+static void __attribute__((noreturn)) usage(void)
+#else
 static void usage(void)
+#endif
 {
        fprintf(stderr, "Usage: %s: [-f file] [-w] [-i number] [-l number] [-v]\n\n",progname);
 
index 5053db4..a3ddcc4 100644 (file)
@@ -15,7 +15,7 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2001 Koulik Andrei, Sandy Service
  */
@@ -24,7 +24,7 @@
 char sccsid[] =
 "$Id$ sandy module project\n Copyright 2001 Sandy Service\nCopyright 2001 Koulik Andrei";
 
-#include "autoconf.h"
+#include <freeradius-devel/autoconf.h>
 #include <fcntl.h>
 
 #include <stdlib.h>
@@ -45,11 +45,11 @@ char sccsid[] =
 #include <ctype.h>
 #include <string.h>
 
-#include "conf.h"
-#include "radpaths.h"
-#include "missing.h"
+#include <freeradius-devel/radiusd.h>
 
-#include "radiusd.h"
+#include <freeradius-devel/conf.h>
+#include <freeradius-devel/radpaths.h>
+#include <freeradius-devel/missing.h>
 
 #define        MAX_BUFF_SIZE   1024
 
index 2aa3820..e7b4805 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
-static const char rcsid[] = "$Id$";
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include       "autoconf.h"
-#include       "libradius.h"
+#include       <freeradius-devel/autoconf.h>
 
 #include       <sys/stat.h>
 #include       <sys/select.h>
@@ -33,8 +33,10 @@ static const char rcsid[] = "$Id$";
 #include       <ctype.h>
 #include       <fcntl.h>
 
-#include       "radiusd.h"
-#include       "modules.h"
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/modules.h>
+#include       <freeradius-devel/rad_assert.h>
+
 #define        DIRLEN  8192
 
 static const char *packet_codes[] = {
@@ -66,21 +68,31 @@ struct detail_instance {
        /* last made directory */
        char *last_made_directory;
 
+       /* timestamp & stuff */
+       char *header;
+
        /* if we want file locking */
        int locking;
 
+       /* log src/dst information */
+       int log_srcdst;
+
        lrad_hash_table_t *ht;
 };
 
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
        { "detailfile",    PW_TYPE_STRING_PTR,
          offsetof(struct detail_instance,detailfile), NULL, "%A/%{Client-IP-Address}/detail" },
+       { "header",    PW_TYPE_STRING_PTR,
+         offsetof(struct detail_instance,header), NULL, "%t" },
        { "detailperm",    PW_TYPE_INTEGER,
          offsetof(struct detail_instance,detailperm), NULL, "0600" },
        { "dirperm",       PW_TYPE_INTEGER,
          offsetof(struct detail_instance,dirperm),    NULL, "0755" },
        { "locking",       PW_TYPE_BOOLEAN,
          offsetof(struct detail_instance,locking),    NULL, "no" },
+       { "log_packet_header",       PW_TYPE_BOOLEAN,
+         offsetof(struct detail_instance,log_srcdst),    NULL, "no" },
        { NULL, -1, 0, NULL, NULL }
 };
 
@@ -91,10 +103,7 @@ static CONF_PARSER module_config[] = {
 static int detail_detach(void *instance)
 {
         struct detail_instance *inst = instance;
-       free((char *) inst->detailfile);
-
        free((char*) inst->last_made_directory);
-
        if (inst->ht) lrad_hash_table_free(inst->ht);
 
         free(inst);
@@ -102,21 +111,15 @@ static int detail_detach(void *instance)
 }
 
 
-/*
- *     Hash callback functions.  Copied from src/lib/dict.c
- */
-static uint32_t dict_attr_value_hash(const void *data)
+static uint32_t detail_hash(const void *data)
 {
-       return lrad_hash(&((const DICT_ATTR *)data)->attr,
-                        sizeof(((const DICT_ATTR *)data)->attr));
+       const DICT_ATTR *da = data;
+       return lrad_hash(&(da->attr), sizeof(da->attr));
 }
 
-static int dict_attr_value_cmp(const void *one, const void *two)
+static int detail_cmp(const void *a, const void *b)
 {
-       const DICT_ATTR *a = one;
-       const DICT_ATTR *b = two;
-
-       return a->attr - b->attr;
+       return ((const DICT_ATTR *)a)->attr - ((const DICT_ATTR *)b)->attr;
 }
 
 
@@ -148,8 +151,7 @@ static int detail_instantiate(CONF_SECTION *conf, void **instance)
        if (cs) {
                CONF_ITEM       *ci;
 
-               inst->ht = lrad_hash_table_create(dict_attr_value_hash,
-                                                 dict_attr_value_cmp,
+               inst->ht = lrad_hash_table_create(detail_hash, detail_cmp,
                                                  NULL);
 
                for (ci = cf_item_find_next(cs, NULL);
@@ -169,6 +171,12 @@ static int detail_instantiate(CONF_SECTION *conf, void **instance)
                                continue;
                        }
 
+                       /*
+                        *      For better distribution we should really
+                        *      hash the attribute number or name.  But
+                        *      since the suppression list will usually
+                        *      be small, it doesn't matter.
+                        */
                        if (!lrad_hash_table_insert(inst->ht, da)) {
                                radlog(L_ERR, "rlm_detail: Failed trying to remember %s", attr);
                                detail_detach(inst);
@@ -190,6 +198,7 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
 {
        int             outfd;
        FILE            *outfp;
+       char            timestamp[256];
        char            buffer[DIRLEN];
        char            *p;
        struct stat     st;
@@ -198,7 +207,7 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
        struct timeval  tv;
        REALM           *proxy_realm;
        char            proxy_buffer[16];
-       VALUE_PAIR      *pair;
+       VALUE_PAIR      *pair = packet->vps;
 
        struct detail_instance *inst = instance;
 
@@ -244,15 +253,7 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
                 */
                if ((inst->last_made_directory == NULL) ||
                    (strcmp(inst->last_made_directory, buffer) != 0)) {
-
-                       /*
-                        *      Free any previously cached name.
-                        */
-                       if (inst->last_made_directory != NULL) {
-                               free((char *) inst->last_made_directory);
-                               inst->last_made_directory = NULL;
-                       }
-
+                       free((char *) inst->last_made_directory);
                        inst->last_made_directory = strdup(buffer);
                }
 
@@ -271,25 +272,24 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
                *p = '/';
        } /* else there was no directory delimiter. */
 
-       /*
-        *      Open & create the file, with the given permissions.
-        */
-       if ((outfd = open(buffer, O_WRONLY | O_APPEND | O_CREAT,
-                         inst->detailperm)) < 0) {
-               radlog(L_ERR, "rlm_detail: Couldn't open file %s: %s",
-                      buffer, strerror(errno));
-               return RLM_MODULE_FAIL;
-       }
-
-       /*
-        *      If we're not using locking, we'll just pass straight though
-        *      the while loop.
-        *      If we fail to aquire the filelock in 80 tries (approximately
-        *      two seconds) we bail out.
-        */
        locked = 0;
        lock_count = 0;
        do {
+               /*
+                *      Open & create the file, with the given
+                *      permissions.
+                */
+               if ((outfd = open(buffer, O_WRONLY | O_APPEND | O_CREAT,
+                                 inst->detailperm)) < 0) {
+                       radlog(L_ERR, "rlm_detail: Couldn't open file %s: %s",
+                              buffer, strerror(errno));
+                       return RLM_MODULE_FAIL;
+               }
+
+               /*
+                *      If we fail to aquire the filelock in 80 tries
+                *      (approximately two seconds) we bail out.
+                */
                if (inst->locking) {
                        lseek(outfd, 0L, SEEK_SET);
                        if (rad_lockfd_nonblock(outfd, 0) < 0) {
@@ -298,15 +298,36 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
                                tv.tv_usec = 25000;
                                select(0, NULL, NULL, NULL, &tv);
                                lock_count++;
-                       } else {
-                               DEBUG("rlm_detail: Acquired filelock, tried %d time(s)",
-                                     lock_count + 1);
-                               locked = 1;
+                               continue;
+                       }
+
+                       /*
+                        *      The file might have been deleted by
+                        *      radrelay while we tried to acquire
+                        *      the lock (race condition)
+                        */
+                       if (fstat(outfd, &st) != 0) {
+                               radlog(L_ERR, "rlm_detail: Couldn't stat file %s: %s",
+                                      buffer, strerror(errno));
+                               close(outfd);
+                               return RLM_MODULE_FAIL;
+                       }
+                       if (st.st_nlink == 0) {
+                               DEBUG("rlm_detail: File %s removed by another program, retrying",
+                                     buffer);
+                               close(outfd);
+                               lock_count = 0;
+                               continue;
                        }
+
+                       DEBUG("rlm_detail: Acquired filelock, tried %d time(s)",
+                             lock_count + 1);
+                       locked = 1;
                }
-       } while (!locked && inst->locking && lock_count < 80);
+       } while (inst->locking && !locked && lock_count < 80);
 
-       if (!locked && inst->locking && lock_count >= 80) {
+       if (inst->locking && !locked) {
+               close(outfd);
                radlog(L_ERR, "rlm_detail: Failed to aquire filelock for %s, giving up",
                       buffer);
                return RLM_MODULE_FAIL;
@@ -324,12 +345,19 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
                        rad_unlockfd(outfd, 0);
                        DEBUG("rlm_detail: Released filelock");
                }
-               close(outfd);
+               close(outfd);   /* automatically releases the lock */
 
                return RLM_MODULE_FAIL;
        }
 
        /*
+        *      Post a timestamp
+        */
+       fseek(outfp, 0L, SEEK_END);
+       radius_xlat(timestamp, sizeof(timestamp), inst->header, request, NULL);
+       fprintf(outfp, "%s\n", timestamp);
+
+       /*
         *      Write the information to the file.
         */
        if (!compat) {
@@ -339,28 +367,78 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
                 */
                if ((packet->code > 0) &&
                    (packet->code <= PW_ACCESS_CHALLENGE)) {
-                       fprintf(outfp, "Packet-Type = %s\n",
+                       fprintf(outfp, "\tPacket-Type = %s\n",
                                packet_codes[packet->code]);
                } else {
-                       fprintf(outfp, "Packet-Type = %d\n", packet->code);
+                       fprintf(outfp, "\tPacket-Type = %d\n", packet->code);
                }
        }
 
-       /*
-        *      Post a timestamp
-        */
-       fseek(outfp, 0L, SEEK_END);
-       fputs(CTIME_R(&request->timestamp, buffer, DIRLEN), outfp);
+       if (inst->log_srcdst) {
+               VALUE_PAIR src_vp, dst_vp;
+
+               src_vp.name[0] = dst_vp.name[0] = '\0'; /* for vp_prints() */
+               src_vp.operator = dst_vp.operator = T_OP_EQ;
+
+               switch (packet->src_ipaddr.af) {
+               case AF_INET:
+                       src_vp.type = PW_TYPE_IPADDR;
+                       src_vp.attribute = PW_PACKET_SRC_IP_ADDRESS;
+                       src_vp.lvalue = packet->src_ipaddr.ipaddr.ip4addr.s_addr;
+                       dst_vp.type = PW_TYPE_IPADDR;
+                       dst_vp.attribute = PW_PACKET_DST_IP_ADDRESS;
+                       dst_vp.lvalue = packet->dst_ipaddr.ipaddr.ip4addr.s_addr;
+                       break;
+               case AF_INET6:
+                       src_vp.type = PW_TYPE_IPV6ADDR; 
+                       src_vp.attribute = PW_PACKET_SRC_IPV6_ADDRESS;
+                       memcpy(src_vp.vp_strvalue,
+                              &packet->src_ipaddr.ipaddr.ip6addr,
+                              sizeof(packet->src_ipaddr.ipaddr.ip6addr));
+                       dst_vp.type = PW_TYPE_IPV6ADDR; 
+                       dst_vp.attribute = PW_PACKET_DST_IPV6_ADDRESS;
+                       memcpy(dst_vp.vp_strvalue,
+                              &packet->dst_ipaddr.ipaddr.ip6addr,
+                              sizeof(packet->dst_ipaddr.ipaddr.ip6addr));
+                       break;
+               default:
+                       break;
+               }
+
+               fputs("\t", outfp);
+               vp_print(outfp, &src_vp);
+               fputs("\n", outfp);
+               fputs("\t", outfp);
+               vp_print(outfp, &dst_vp);
+               fputs("\n", outfp);
+
+               src_vp.attribute = PW_PACKET_SRC_PORT;
+               src_vp.type = PW_TYPE_INTEGER;
+               src_vp.lvalue = packet->src_port;
+               dst_vp.attribute = PW_PACKET_DST_PORT;
+               dst_vp.type = PW_TYPE_INTEGER;
+               dst_vp.lvalue = packet->dst_port;
+
+               fputs("\t", outfp);
+               vp_print(outfp, &src_vp);
+               fputs("\n", outfp);
+               fputs("\t", outfp);
+               vp_print(outfp, &dst_vp);
+               fputs("\n", outfp);
+       }
 
        /* Write each attribute/value to the log file */
-       for (pair = packet->vps; pair != NULL; pair = pair->next) {
+       for (; pair != NULL; pair = pair->next) {
+               DICT_ATTR da;
+               da.attr = pair->attribute;
+
                if (inst->ht &&
-                   lrad_hash_table_finddata(inst->ht, pair)) continue;
+                   lrad_hash_table_finddata(inst->ht, &da)) continue;
 
                /*
                 *      Don't print passwords in old format...
                 */
-               if (compat && (pair->attribute == PW_PASSWORD)) continue;
+               if (compat && (pair->attribute == PW_USER_PASSWORD)) continue;
 
                /*
                 *      Print all of the attributes.
@@ -376,10 +454,15 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
        if (compat) {
                if ((pair = pairfind(request->config_items,
                                     PW_PROXY_TO_REALM)) != NULL) {
-                       proxy_realm = realm_find(pair->strvalue, TRUE);
+                       proxy_realm = realm_find(pair->vp_strvalue, TRUE);
                        if (proxy_realm) {
                                memset((char *) proxy_buffer, 0, 16);
-                               ip_ntoa(proxy_buffer, proxy_realm->acct_ipaddr);
+
+                               rad_assert(proxy_realm->acct_ipaddr.af == AF_INET);
+
+                               inet_ntop(proxy_realm->acct_ipaddr.af,
+                                         &proxy_realm->acct_ipaddr.ipaddr,
+                                         proxy_buffer, sizeof(proxy_buffer));
                                fprintf(outfp, "\tFreeradius-Proxied-To = %s\n",
                                        proxy_buffer);
                                DEBUG("rlm_detail: Freeradius-Proxied-To set to %s",
@@ -468,10 +551,11 @@ static int detail_post_proxy(void *instance, REQUEST *request)
 
 /* globally exported name */
 module_t rlm_detail = {
+       RLM_MODULE_INIT,
        "detail",
        RLM_TYPE_THREAD_UNSAFE,        /* type: reserved */
-       NULL,                           /* initialization */
        detail_instantiate,             /* instantiation */
+       detail_detach,                  /* detach */
        {
                NULL,                   /* authentication */
                detail_authorize,       /* authorization */
@@ -482,7 +566,5 @@ module_t rlm_detail = {
                detail_post_proxy,      /* post-proxy */
                detail_postauth         /* post-auth */
        },
-       detail_detach,                  /* detach */
-       NULL                            /* destroy */
 };
 
index 8e85159..2ddb321 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2002  The FreeRADIUS server project
+ * Copyright 2002,2006  The FreeRADIUS server project
  * Copyright 2002  Alan DeKok <aland@ox.org>
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
-
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 static int digest_authorize(void *instance, REQUEST *request)
 {
@@ -103,10 +103,10 @@ static int digest_authenticate(void *instance, REQUEST *request)
                        return RLM_MODULE_INVALID;
                }
        } else {
-               passwd = pairfind(request->config_items, PW_PASSWORD);
+               passwd = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);
        }
        if (!passwd) {
-               radlog(L_AUTH, "rlm_digest: Configuration item \"User-Password\" or Digest-HA1 is required for authentication.");
+               radlog(L_AUTH, "rlm_digest: Cleartext-Password or Digest-HA1 is required for authentication.");
                return RLM_MODULE_INVALID;
        }
 
@@ -126,7 +126,7 @@ static int digest_authenticate(void *instance, REQUEST *request)
        while (vp) {
                int length = vp->length;
                int attrlen;
-               uint8_t *p = &vp->strvalue[0];
+               uint8_t *p = &vp->vp_octets[0];
                VALUE_PAIR *sub;
 
                /*
@@ -170,8 +170,8 @@ static int digest_authenticate(void *instance, REQUEST *request)
                        if (!sub) {
                                return RLM_MODULE_FAIL; /* out of memory */
                        }
-                       memcpy(&sub->strvalue[0], &p[2], attrlen - 2);
-                       sub->strvalue[attrlen - 2] = '\0';
+                       memcpy(&sub->vp_octets[0], &p[2], attrlen - 2);
+                       sub->vp_octets[attrlen - 2] = '\0';
                        sub->length = attrlen - 2;
 
                        if (debug_flag) {
@@ -217,7 +217,7 @@ static int digest_authenticate(void *instance, REQUEST *request)
                DEBUG("ERROR: No Digest-User-Name: Cannot perform Digest authentication");
                return RLM_MODULE_INVALID;
        }
-       memcpy(&a1[0], &vp->strvalue[0], vp->length);
+       memcpy(&a1[0], &vp->vp_octets[0], vp->length);
        a1_len = vp->length;
 
        a1[a1_len] = ':';
@@ -228,14 +228,14 @@ static int digest_authenticate(void *instance, REQUEST *request)
                DEBUG("ERROR: No Digest-Realm: Cannot perform Digest authentication");
                return RLM_MODULE_INVALID;
        }
-       memcpy(&a1[a1_len], &vp->strvalue[0], vp->length);
+       memcpy(&a1[a1_len], &vp->vp_octets[0], vp->length);
        a1_len += vp->length;
 
        a1[a1_len] = ':';
        a1_len++;
 
-       if (passwd->attribute == PW_USER_PASSWORD) {
-               memcpy(&a1[a1_len], &passwd->strvalue[0], passwd->length);
+       if (passwd->attribute == PW_CLEARTEXT_PASSWORD) {
+               memcpy(&a1[a1_len], &passwd->vp_octets[0], passwd->length);
                a1_len += passwd->length;
                a1[a1_len] = '\0';
                DEBUG2("A1 = %s", a1);
@@ -251,29 +251,29 @@ static int digest_authenticate(void *instance, REQUEST *request)
         */
        algo = pairfind(request->packet->vps, PW_DIGEST_ALGORITHM);
        if ((algo == NULL) || 
-           (strcasecmp(algo->strvalue, "MD5") == 0)) {
+           (strcasecmp(algo->vp_strvalue, "MD5") == 0)) {
                /*
                 *      Set A1 to Digest-HA1 if no User-Password found
                 */
                if (passwd->attribute == PW_DIGEST_HA1) {
-                       if (lrad_hex2bin(passwd->strvalue, &a1[0], 16) != 16) {
+                       if (lrad_hex2bin(passwd->vp_strvalue, &a1[0], 16) != 16) {
                                DEBUG2("rlm_digest: Invalid text in Digest-HA1");
                                return RLM_MODULE_INVALID;
                        }
                }
 
-       } else if (strcasecmp(algo->strvalue, "MD5-sess") == 0) {
+       } else if (strcasecmp(algo->vp_strvalue, "MD5-sess") == 0) {
                /*
                 *      K1 = H(A1) : Digest-Nonce ... : H(A2)
                 *
                 *      If we find Digest-HA1, we assume it contains
                 *      H(A1).
                 */
-               if (passwd->attribute == PW_USER_PASSWORD) {
+               if (passwd->attribute == PW_CLEARTEXT_PASSWORD) {
                        librad_md5_calc(hash, &a1[0], a1_len);
                        lrad_bin2hex(hash, &a1[0], 16);
                } else {        /* MUST be Digest-HA1 */
-                       memcpy(&a1[0], passwd->strvalue, 32);
+                       memcpy(&a1[0], passwd->vp_strvalue, 32);
                }
                a1_len = 32;
 
@@ -287,7 +287,7 @@ static int digest_authenticate(void *instance, REQUEST *request)
                        DEBUG("ERROR: Received Digest-Nonce hex string with invalid length: Cannot perform Digest authentication");
                        return RLM_MODULE_INVALID;
                }
-               memcpy(&a1[a1_len], &nonce->strvalue[0], nonce->length);
+               memcpy(&a1[a1_len], &nonce->vp_octets[0], nonce->length);
                a1_len += nonce->length;
 
                a1[a1_len] = ':';
@@ -306,16 +306,16 @@ static int digest_authenticate(void *instance, REQUEST *request)
                        DEBUG("ERROR: Received Digest-CNonce hex string with invalid length: Cannot perform Digest authentication");
                        return RLM_MODULE_INVALID;
                }
-               memcpy(&a1[a1_len], &vp->strvalue[0], vp->length);
+               memcpy(&a1[a1_len], &vp->vp_octets[0], vp->length);
                a1_len += vp->length;
 
        } else if ((algo != NULL) &&
-                  (strcasecmp(algo->strvalue, "MD5") != 0)) {
+                  (strcasecmp(algo->vp_strvalue, "MD5") != 0)) {
                /*
                 *      We check for "MD5-sess" and "MD5".
                 *      Anything else is an error.
                 */
-               DEBUG("ERROR: Unknown Digest-Algorithm \"%s\": Cannot perform Digest authentication", vp->strvalue);
+               DEBUG("ERROR: Unknown Digest-Algorithm \"%s\": Cannot perform Digest authentication", vp->vp_strvalue);
                return RLM_MODULE_INVALID;
        }
 
@@ -327,7 +327,7 @@ static int digest_authenticate(void *instance, REQUEST *request)
                DEBUG("ERROR: No Digest-Method: Cannot perform Digest authentication");
                return RLM_MODULE_INVALID;
        }
-       memcpy(&a2[0], &vp->strvalue[0], vp->length);
+       memcpy(&a2[0], &vp->vp_octets[0], vp->length);
        a2_len = vp->length;
 
        a2[a2_len] = ':';
@@ -338,7 +338,7 @@ static int digest_authenticate(void *instance, REQUEST *request)
                DEBUG("ERROR: No Digest-URI: Cannot perform Digest authentication");
                return RLM_MODULE_INVALID;
        }
-       memcpy(&a2[a2_len], &vp->strvalue[0], vp->length);
+       memcpy(&a2[a2_len], &vp->vp_octets[0], vp->length);
        a2_len += vp->length;
 
        /*
@@ -346,7 +346,7 @@ static int digest_authenticate(void *instance, REQUEST *request)
         */
        qop = pairfind(request->packet->vps, PW_DIGEST_QOP);
        if ((qop != NULL) &&
-           (strcasecmp(qop->strvalue, "auth-int") == 0)) {
+           (strcasecmp(qop->vp_strvalue, "auth-int") == 0)) {
                VALUE_PAIR *body;
 
                /*
@@ -369,12 +369,12 @@ static int digest_authenticate(void *instance, REQUEST *request)
                        return RLM_MODULE_INVALID;
                }
 
-               memcpy(a2 + a2_len, body->strvalue, body->length);
+               memcpy(a2 + a2_len, body->vp_octets, body->length);
                a2_len += body->length;
 
        } else if ((qop != NULL) &&
-                  (strcasecmp(qop->strvalue, "auth") != 0)) {
-               DEBUG("ERROR: Unknown Digest-QOP \"%s\": Cannot perform Digest authentication", qop->strvalue);
+                  (strcasecmp(qop->vp_strvalue, "auth") != 0)) {
+               DEBUG("ERROR: Unknown Digest-QOP \"%s\": Cannot perform Digest authentication", qop->vp_strvalue);
                return RLM_MODULE_INVALID;
        }
 
@@ -387,9 +387,9 @@ static int digest_authenticate(void *instance, REQUEST *request)
         *     or if we found a User-Password.
         */
        if (((algo != NULL) && 
-            (strcasecmp(algo->strvalue, "MD5-Sess") == 0)) ||
-           (passwd->attribute == PW_USER_PASSWORD)) {
-         a1[a1_len] = '\0';
+            (strcasecmp(algo->vp_strvalue, "MD5-Sess") == 0)) ||
+           (passwd->attribute == PW_CLEARTEXT_PASSWORD)) {
+               a1[a1_len] = '\0';
                librad_md5_calc(&hash[0], &a1[0], a1_len);
        } else {
                memcpy(&hash[0], &a1[0], a1_len);
@@ -410,7 +410,7 @@ static int digest_authenticate(void *instance, REQUEST *request)
        kd[kd_len] = ':';
        kd_len++;
 
-       memcpy(&kd[kd_len], nonce->strvalue, nonce->length);
+       memcpy(&kd[kd_len], nonce->vp_octets, nonce->length);
        kd_len += nonce->length;
 
        /*
@@ -434,7 +434,7 @@ static int digest_authenticate(void *instance, REQUEST *request)
                        DEBUG("ERROR: No Digest-Nonce-Count: Cannot perform Digest authentication");
                        return RLM_MODULE_INVALID;
                }
-               memcpy(&kd[kd_len], &vp->strvalue[0], vp->length);
+               memcpy(&kd[kd_len], &vp->vp_octets[0], vp->length);
                kd_len += vp->length;
 
                kd[kd_len] = ':';
@@ -445,13 +445,13 @@ static int digest_authenticate(void *instance, REQUEST *request)
                        DEBUG("ERROR: No Digest-CNonce: Cannot perform Digest authentication");
                        return RLM_MODULE_INVALID;
                }
-               memcpy(&kd[kd_len], &vp->strvalue[0], vp->length);
+               memcpy(&kd[kd_len], &vp->vp_octets[0], vp->length);
                kd_len += vp->length;
 
                kd[kd_len] = ':';
                kd_len++;
 
-               memcpy(&kd[kd_len], &qop->strvalue[0], qop->length);
+               memcpy(&kd[kd_len], &qop->vp_octets[0], qop->length);
                kd_len += qop->length;
        }
 
@@ -495,7 +495,7 @@ static int digest_authenticate(void *instance, REQUEST *request)
                return RLM_MODULE_INVALID;
        }
 
-       if (lrad_hex2bin(&vp->strvalue[0], &hash[0], vp->length >> 1) != (vp->length >> 1)) {
+       if (lrad_hex2bin(&vp->vp_octets[0], &hash[0], vp->length >> 1) != (vp->length >> 1)) {
                DEBUG2("rlm_digest: Invalid text in Digest-Response");
                return RLM_MODULE_INVALID;
        }
@@ -537,10 +537,11 @@ static int digest_authenticate(void *instance, REQUEST *request)
  *     is single-threaded.
  */
 module_t rlm_digest = {
-       "DIGEST",
+       RLM_MODULE_INIT,
+       "digest",
        0,                              /* type */
-       NULL,                           /* initialization */
        NULL,                           /* instantiation */
+       NULL,                           /* detach */
        {
                digest_authenticate,    /* authentication */
                digest_authorize,       /* authorization */
@@ -551,6 +552,4 @@ module_t rlm_digest = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       NULL,                           /* detach */
-       NULL,                           /* destroy */
 };
index 22508b9..5a5bf45 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.4 .
+# From configure.in Revision: 1.5 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -897,7 +897,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1820,8 +1820,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1879,8 +1878,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1996,8 +1994,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2051,8 +2048,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2097,8 +2093,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2142,8 +2137,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3074,11 +3068,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3117,6 +3106,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
@@ -3348,7 +3343,7 @@ echo "$as_me: error: $ac_sub_configure failed for $ac_dir" >&2;}
    { (exit 1); exit 1; }; }
     fi
 
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
index a8b9ba7..06a7cb2 100644 (file)
@@ -1,3 +1,4 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_eap.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_eap])
index 465d68e..0cdd32e 100644 (file)
@@ -15,9 +15,9 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000-2003  The FreeRADIUS server project
+ * Copyright 2000-2003,2006  The FreeRADIUS server project
  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
  * Copyright 2003  Alan DeKok <aland@freeradius.org>
  */
  *
  */
 
-#include "rlm_eap.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-static const char rcsid[] = "$Id$";
+#include "rlm_eap.h"
 
 static const char *eap_codes[] = {
   "",                          /* 0 is invalid */
@@ -539,7 +540,7 @@ int eap_compose(EAP_HANDLER *handler)
                 * This memory gets freed up when request is freed up
                 */
                eap_msg = paircreate(PW_EAP_MESSAGE, PW_TYPE_OCTETS);
-               memcpy(eap_msg->strvalue, ptr, len);
+               memcpy(eap_msg->vp_octets, ptr, len);
                eap_msg->length = len;
                pairadd(&(request->reply->vps), eap_msg);
                ptr += len;
@@ -556,7 +557,7 @@ int eap_compose(EAP_HANDLER *handler)
        vp = pairfind(request->reply->vps, PW_MESSAGE_AUTHENTICATOR);
        if (!vp) {
                vp = paircreate(PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);
-               memset(vp->strvalue, 0, AUTH_VECTOR_LEN);
+               memset(vp->vp_octets, 0, AUTH_VECTOR_LEN);
                vp->length = AUTH_VECTOR_LEN;
                pairadd(&(request->reply->vps), vp);
        }
@@ -644,8 +645,9 @@ int eap_start(rlm_eap_t *inst, REQUEST *request)
                 *      If it's a LOCAL realm, then we're not proxying
                 *      to it.
                 */
-               realm = realm_find(proxy->strvalue, 0);
-               if (realm && (realm->ipaddr == htonl(INADDR_NONE))) {
+               realm = realm_find(proxy->vp_strvalue, 0);
+               rad_assert(realm->ipaddr.af == AF_INET);
+               if (realm && (realm->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE))) {
                        proxy = NULL;
                }
        }
@@ -670,7 +672,7 @@ int eap_start(rlm_eap_t *inst, REQUEST *request)
                 */
                if (proxy) {
                do_proxy:
-                       DEBUG2("  rlm_eap: Request is supposed to be proxied to Realm %s.  Not doing EAP.", proxy->strvalue);
+                       DEBUG2("  rlm_eap: Request is supposed to be proxied to Realm %s.  Not doing EAP.", proxy->vp_strvalue);
                        return EAP_NOOP;
                }
                
@@ -722,7 +724,7 @@ int eap_start(rlm_eap_t *inst, REQUEST *request)
         */
        vp = paircreate(PW_EAP_TYPE, PW_TYPE_INTEGER);
        if (vp) {
-               vp->lvalue = eap_msg->strvalue[4];
+               vp->lvalue = eap_msg->vp_octets[4];
                pairadd(&(request->packet->vps), vp);
        }
 
@@ -744,13 +746,13 @@ int eap_start(rlm_eap_t *inst, REQUEST *request)
         *      We're allowed only a few codes.  Request, Response,
         *      Success, or Failure.
         */
-       if ((eap_msg->strvalue[0] == 0) ||
-           (eap_msg->strvalue[0] > PW_EAP_MAX_CODES)) {
+       if ((eap_msg->vp_octets[0] == 0) ||
+           (eap_msg->vp_octets[0] > PW_EAP_MAX_CODES)) {
                DEBUG2("  rlm_eap: Unknown EAP packet");
        } else {
                DEBUG2("  rlm_eap: EAP packet type %s id %d length %d",
-                      eap_codes[eap_msg->strvalue[0]],
-                      eap_msg->strvalue[1],
+                      eap_codes[eap_msg->vp_octets[0]],
+                      eap_msg->vp_octets[1],
                       eap_msg->length);
        }
 
@@ -760,8 +762,8 @@ int eap_start(rlm_eap_t *inst, REQUEST *request)
         *      sending success/fail packets to us, as it doesn't make
         *      sense.
         */
-       if ((eap_msg->strvalue[0] != PW_EAP_REQUEST) &&
-           (eap_msg->strvalue[0] != PW_EAP_RESPONSE)) {
+       if ((eap_msg->vp_octets[0] != PW_EAP_REQUEST) &&
+           (eap_msg->vp_octets[0] != PW_EAP_RESPONSE)) {
                DEBUG2("  rlm_eap: Ignoring EAP packet which we don't know how to handle.");
                return EAP_FAIL;
        }
@@ -774,11 +776,11 @@ int eap_start(rlm_eap_t *inst, REQUEST *request)
         *      EAP-Identity, Notification, and NAK are all handled
         *      internally, so they never have handlers.
         */
-       if ((eap_msg->strvalue[4] >= PW_EAP_MD5) &&
+       if ((eap_msg->vp_octets[4] >= PW_EAP_MD5) &&
            inst->ignore_unknown_eap_types &&
-           ((eap_msg->strvalue[4] == 0) ||
-            (eap_msg->strvalue[4] > PW_EAP_MAX_TYPES) ||
-            (inst->types[eap_msg->strvalue[4]] == NULL))) {
+           ((eap_msg->vp_octets[4] == 0) ||
+            (eap_msg->vp_octets[4] > PW_EAP_MAX_TYPES) ||
+            (inst->types[eap_msg->vp_octets[4]] == NULL))) {
                DEBUG2("  rlm_eap:  Ignoring Unknown EAP type");
                return EAP_NOOP;
        }
@@ -798,12 +800,12 @@ int eap_start(rlm_eap_t *inst, REQUEST *request)
         *      returns NOOP, and another module may choose to proxy
         *      the request.
         */
-       if ((eap_msg->strvalue[4] == PW_EAP_NAK) &&
+       if ((eap_msg->vp_octets[4] == PW_EAP_NAK) &&
            (eap_msg->length >= (EAP_HEADER_LEN + 2)) &&
            inst->ignore_unknown_eap_types &&
-           ((eap_msg->strvalue[5] == 0) ||
-            (eap_msg->strvalue[5] > PW_EAP_MAX_TYPES) ||
-            (inst->types[eap_msg->strvalue[5]] == NULL))) {
+           ((eap_msg->vp_octets[5] == 0) ||
+            (eap_msg->vp_octets[5] > PW_EAP_MAX_TYPES) ||
+            (inst->types[eap_msg->vp_octets[5]] == NULL))) {
                DEBUG2("  rlm_eap: Ignoring NAK with request for unknown EAP type");
                return EAP_NOOP;
        }
@@ -1046,7 +1048,7 @@ EAP_HANDLER *eap_handler(rlm_eap_t *inst, eap_packet_t **eap_packet_p,
                         *      request as the NAS is doing something
                         *      funny.
                        */
-                       if (strncmp(handler->identity, vp->strvalue,
+                       if (strncmp(handler->identity, vp->vp_strvalue,
                                   MAX_STRING_LEN) != 0) {
                                radlog(L_ERR, "rlm_eap: Identity does not match User-Name.  Authentication failed.");
                                free(*eap_packet_p);
@@ -1101,7 +1103,7 @@ EAP_HANDLER *eap_handler(rlm_eap_t *inst, eap_packet_t **eap_packet_p,
                         *      identity, the NAS is doing something
                         *      funny, so reject the request.
                        */
-                       if (strncmp(handler->identity, vp->strvalue,
+                       if (strncmp(handler->identity, vp->vp_strvalue,
                                   MAX_STRING_LEN) != 0) {
                                radlog(L_ERR, "rlm_eap: Identity does not match User-Name, setting from EAP Identity.");
                                free(*eap_packet_p);
index 2c0c8f9..8c5a476 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   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
  */
 #ifndef _EAP_H
 #define _EAP_H
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSIDH(eap_h, "$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #include <string.h>
 #include <stdlib.h>
 
-#include "radiusd.h"
-#include "modules.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
-#include "rad_assert.h"
+#include <freeradius-devel/rad_assert.h>
 
 #include "eap_types.h"
 
@@ -102,7 +106,7 @@ typedef enum operation_t {
 typedef struct _eap_handler {
        struct _eap_handler *prev, *next;
        uint8_t         state[EAP_STATE_LEN];
-       uint32_t        src_ipaddr;
+       lrad_ipaddr_t   src_ipaddr;
        unsigned int    eap_id;
        unsigned int    eap_type;
 
index 7f04e96..011d285 100644 (file)
@@ -12,7 +12,7 @@ SRCS          += cb.c eap_tls.c mppe_keys.c tls.c
 endif
 LT_OBJS                = $(SRCS:.c=.lo)
 INCLUDES       = eap_types.h eap_tls.h
-CFLAGS         += -DEAPLIB -I. -I.. -I$(top_builddir)/src/include $(OPENSSL_INCLUDE)
+CFLAGS         += -DEAPLIB -I. -I.. -I$(top_builddir)/src $(OPENSSL_INCLUDE)
 ifeq ($(USE_SHARED_LIBS),yes)
 LINK_MODE      = -export-dynamic
 else
index f4798b2..abf1444 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
+ * Copyright 2006  The FreeRADIUS server project
  */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include "eap_tls.h"
 
 #ifndef NO_OPENSSL
@@ -37,11 +42,11 @@ void cbtls_info(const SSL *s, int where, int ret)
        state = state ? state : "NULL";
 
        if (where & SSL_CB_LOOP) {
-               DEBUG2("%s: %s\n", str, state);
+               if (debug_flag) radlog(L_INFO, "%s: %s\n", str, state);
        } else if (where & SSL_CB_HANDSHAKE_START) {
-               DEBUG2("%s: %s\n", str, state);
+               if (debug_flag) radlog(L_INFO, "%s: %s\n", str, state);
        } else if (where & SSL_CB_HANDSHAKE_DONE) {
-               DEBUG2("%s: %s\n", str, state);
+               radlog(L_INFO, "%s: %s\n", str, state);
        } else if (where & SSL_CB_ALERT) {
                str=(where & SSL_CB_READ)?"read":"write";
                radlog(L_ERR,"TLS Alert %s:%s:%s\n", str,
@@ -103,7 +108,7 @@ RSA *cbtls_rsa(SSL *s UNUSED, int is_export UNUSED, int keylength)
        static RSA *rsa_tmp=NULL;
 
        if (rsa_tmp == NULL) {
-               DEBUG2("Generating temp (%d bit) RSA key...", keylength);
+               radlog(L_INFO, "Generating temp (%d bit) RSA key...", keylength);
                rsa_tmp=RSA_generate_key(keylength, RSA_F4, NULL, NULL);
        }
        return(rsa_tmp);
index e813485..84503c5 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2003  Michael Richardson <mcr@sandelman.ottawa.on.ca>
+ * Copyright 2006  The FreeRADIUS server project
  *
  */
 #ifndef _EAP_SIM_H
 #define _EAP_SIM_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(eap_sim_h, "$Id$")
+
 #include "eap_types.h"
 
 #define EAP_SIM_VERSION 0x0001
index 4450bb4..7a0ab48 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   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 "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 #include <assert.h>
 #include "eap_tls.h"
 
@@ -332,12 +336,11 @@ static eaptls_status_t eaptls_verify(EAP_HANDLER *handler)
            ((eap_ds->response->length == EAP_HEADER_LEN + 2) &&
             ((eaptls_packet->flags & 0xc0) == 0x00))) {
 
-               if (prev_eap_ds &&
-                   (prev_eap_ds->request->id == eap_ds->response->id)) {
+               if (prev_eap_ds->request->id == eap_ds->response->id) {
                        /*
                         *      Run the ACK handler directly from here.
                         */
-                       DEBUG2("rlm_eap_tls: Received EAP-TLS ACK message");
+                       radlog(L_INFO, "rlm_eap_tls: Received EAP-TLS ACK message");
                        return eaptls_ack_handler(handler);
                } else {
                        radlog(L_ERR, "rlm_eap_tls: Received Invalid EAP-TLS ACK message");
@@ -378,22 +381,22 @@ static eaptls_status_t eaptls_verify(EAP_HANDLER *handler)
                            (eaptls_prev == NULL) ||
                            !TLS_MORE_FRAGMENTS(eaptls_prev->flags)) {
 
-                               DEBUG2("rlm_eap_tls:  Received EAP-TLS First Fragment of the message");
+                               radlog(L_INFO, "rlm_eap_tls:  Received EAP-TLS First Fragment of the message");
                                return EAPTLS_FIRST_FRAGMENT;
                        } else {
 
-                               DEBUG2("rlm_eap_tls:  More Fragments with length included");
+                               radlog(L_INFO, "rlm_eap_tls:  More Fragments with length included");
                                return EAPTLS_MORE_FRAGMENTS_WITH_LENGTH;
                        }
                } else {
 
-                       DEBUG2("rlm_eap_tls:  Length Included");
+                       radlog(L_INFO, "rlm_eap_tls:  Length Included");
                        return EAPTLS_LENGTH_INCLUDED;
                }
        }
 
        if (TLS_MORE_FRAGMENTS(eaptls_packet->flags)) {
-               DEBUG2("rlm_eap_tls:  More fragments to follow");
+               radlog(L_INFO, "rlm_eap_tls:  More fragments to follow");
                return EAPTLS_MORE_FRAGMENTS;
        }
 
index 7103073..339ec4f 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   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
  */
 #ifndef _EAP_TLS_H
 #define _EAP_TLS_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(eap_tls_h, "$Id$")
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
index 8d787f7..b2aba57 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   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
  */
 #ifndef _EAP_TYPES_H
 #define _EAP_TYPES_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(eap_types_h, "$Id$")
+
 #if HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
@@ -36,8 +40,8 @@
 #include <string.h>
 #include <stdlib.h>
 
-#include "radiusd.h"
-#include "modules.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 #define PW_EAP_REQUEST         1
 #define PW_EAP_RESPONSE                2
@@ -48,8 +52,7 @@
 /* base for dictionary values */
 #define ATTRIBUTE_EAP_ID        1020
 #define ATTRIBUTE_EAP_CODE      1021
-#define ATTRIBUTE_EAP_MD5_PASSWORD 1022
-#define ATTRIBUTE_EAP_BASE      (5*256)
+#define ATTRIBUTE_EAP_BASE      1280
 
 #define PW_EAP_IDENTITY                1
 #define PW_EAP_NOTIFICATION    2
index 12418a5..d918f1a 100644 (file)
@@ -17,9 +17,9 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000-2003  The FreeRADIUS server project
+ * Copyright 2000-2003,2006  The FreeRADIUS server project
  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
  * Copyright 2003  Alan DeKok <aland@freeradius.org>
  * Copyright 2003  Michael Richardson <mcr@sandelman.ottawa.on.ca>
  *
  */
 
-#include "libradius.h"
-#include "eap_types.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
+#include "eap_types.h"
 
 static const char *eap_types[] = {
   "",
@@ -262,7 +265,7 @@ int eap_basic_compose(RADIUS_PACKET *packet, EAP_PACKET *reply)
                 * This memory gets freed up when packet is freed up
                 */
                eap_msg = paircreate(PW_EAP_MESSAGE, PW_TYPE_OCTETS);
-               memcpy(eap_msg->strvalue, ptr, len);
+               memcpy(eap_msg->vp_strvalue, ptr, len);
                eap_msg->length = len;
                pairadd(&(packet->vps), eap_msg);
                ptr += len;
@@ -279,7 +282,7 @@ int eap_basic_compose(RADIUS_PACKET *packet, EAP_PACKET *reply)
        vp = pairfind(packet->vps, PW_MESSAGE_AUTHENTICATOR);
        if (!vp) {
                vp = paircreate(PW_MESSAGE_AUTHENTICATOR, PW_TYPE_OCTETS);
-               memset(vp->strvalue, 0, AUTH_VECTOR_LEN);
+               memset(vp->vp_strvalue, 0, AUTH_VECTOR_LEN);
                vp->length = AUTH_VECTOR_LEN;
                pairadd(&(packet->vps), vp);
        }
@@ -386,7 +389,7 @@ void map_eap_types(RADIUS_PACKET *req)
                ep.type.type = eap_type;
                ep.type.length = vp->length;
                ep.type.data = malloc(vp->length);
-               memcpy(ep.type.data,vp->strvalue, vp->length);
+               memcpy(ep.type.data,vp->vp_octets, vp->length);
                eap_basic_compose(req, &ep);
        }
 }
@@ -427,7 +430,7 @@ eap_packet_t *eap_attribute(VALUE_PAIR *vps)
         *      Get the Actual length from the EAP packet
         *      First EAP-Message contains the EAP packet header
         */
-       memcpy(&len, first->strvalue + 2, sizeof(len));
+       memcpy(&len, first->vp_strvalue + 2, sizeof(len));
        len = ntohs(len);
 
        /*
@@ -475,7 +478,7 @@ eap_packet_t *eap_attribute(VALUE_PAIR *vps)
 
        /* RADIUS ensures order of attrs, so just concatenate all */
        for (vp = first; vp; vp = pairfind(vp->next, PW_EAP_MESSAGE)) {
-               memcpy(ptr, vp->strvalue, vp->length);
+               memcpy(ptr, vp->vp_strvalue, vp->length);
                ptr += vp->length;
        }
 
@@ -530,7 +533,6 @@ void unmap_eap_types(RADIUS_PACKET *rep)
                /* verify the length is big enough to hold type */
                if(len < 5)
                {
-                       free(e);
                        return;
                }
 
@@ -544,13 +546,12 @@ void unmap_eap_types(RADIUS_PACKET *rep)
                }
 
                eap1 = paircreate(type, PW_TYPE_OCTETS);
-               memcpy(eap1->strvalue, &e->data[1], len);
+               memcpy(eap1->vp_strvalue, &e->data[1], len);
                eap1->length = len;
                pairadd(&(rep->vps), eap1);
                break;
        }
 
-       free(e);
        return;
 }
 
index 18e65db..d0fe491 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2003  Michael Richardson <mcr@sandelman.ottawa.on.ca>
- * Copyright 2003  The FreeRADIUS server project
+ * Copyright 2003,2006  The FreeRADIUS server project
  *
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "eap_types.h"
 #include "eap_sim.h"
-#include "sha1.h"
+#include <freeradius-devel/sha1.h>
 
 void eapsim_calculate_keys(struct eapsim_keys *ek)
 {
index f36e6ea..2c1c589 100644 (file)
@@ -20,9 +20,9 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000-2003  The FreeRADIUS server project
+ * Copyright 2000-2003,2006  The FreeRADIUS server project
  * Copyright 2003  Michael Richardson <mcr@sandelman.ottawa.on.ca>
  */
 
  *
  */
 
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
 #include "eap_types.h"
 #include "eap_sim.h"
-#include "sha1.h"
-
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/sha1.h>
 
 /*
  * given a radius request with many attribues in the EAP-SIM range, build
@@ -225,13 +228,13 @@ int map_eapsim_basictypes(RADIUS_PACKET *r, EAP_PACKET *ep)
                        roundedlen = 20;
                        memset(&attr[2], 0, 18);
                        macspace = &attr[4];
-                       append = vp->strvalue;
+                       append = vp->vp_octets;
                        appendlen = vp->length;
                }
                else {
                        roundedlen = (vp->length + 2 + 3) & ~3;
                        memset(attr, 0, roundedlen);
-                       memcpy(&attr[2], vp->strvalue, vp->length);
+                       memcpy(&attr[2], vp->vp_strvalue, vp->length);
                }
                attr[0] = vp->attribute - ATTRIBUTE_EAP_SIM_BASE;
                attr[1] = roundedlen >> 2;
@@ -282,7 +285,7 @@ int map_eapsim_basictypes(RADIUS_PACKET *r, EAP_PACKET *ep)
 
                /* HMAC it! */
                lrad_hmac_sha1(buffer, hmaclen,
-                              vp->strvalue, vp->length,
+                              vp->vp_octets, vp->length,
                               sha1digest);
 
                /* done with the buffer, free it */
@@ -379,7 +382,7 @@ int unmap_eapsim_basictypes(RADIUS_PACKET *r,
                }
 
                newvp = paircreate(eapsim_attribute+ATTRIBUTE_EAP_SIM_BASE, PW_TYPE_OCTETS);
-               memcpy(newvp->strvalue, &attr[2], eapsim_len-2);
+               memcpy(newvp->vp_strvalue, &attr[2], eapsim_len-2);
                newvp->length = eapsim_len-2;
                pairadd(&(r->vps), newvp);
                newvp = NULL;
@@ -402,7 +405,7 @@ int unmap_eapsim_types(RADIUS_PACKET *r)
                return 0;
        }
 
-       return unmap_eapsim_basictypes(r, esvp->strvalue, esvp->length);
+       return unmap_eapsim_basictypes(r, esvp->vp_octets, esvp->length);
 }
 
 /*
@@ -489,7 +492,7 @@ eapsim_checkmac(VALUE_PAIR *rvps,
                       key, 16,
                       calcmac);
 
-       if(memcmp(&mac->strvalue[2], calcmac, 16) == 0) {
+       if(memcmp(&mac->vp_strvalue[2], calcmac, 16) == 0)      {
                ret = 1;
        } else {
                ret = 0;
@@ -642,8 +645,8 @@ main(int argc, char *argv[])
 
                        memset(calcmac, 0, sizeof(calcmac));
                        printf("Confirming MAC...");
-                       if(eapsim_checkmac(req2->vps, vpkey->strvalue,
-                                          vpextra->strvalue, vpextra->length,
+                       if(eapsim_checkmac(req2->vps, vpkey->vp_strvalue,
+                                          vpextra->vp_strvalue, vpextra->length,
                                           calcmac)) {
                                printf("succeed\n");
                        } else {
index 52abbae..1b5b73f 100644 (file)
@@ -23,7 +23,7 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * BSD notice:
  *
  *    from this software without specific prior written permission.
  *
  * Copyright 2003  Michael Richardson <mcr@sandelman.ottawa.on.ca>
+ * Copyright 2006  The FreeRADIUS server project
  *
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -61,7 +65,7 @@
 #include <inttypes.h>
 #endif
 
-#include "sha1.h"
+#include <freeradius-devel/sha1.h>
 
 /*
  * we do it in 8-bit chunks, because we have to keep the numbers
@@ -259,34 +263,3 @@ main(int argc, char *argv[])
        printf("\n");
 }
 #endif
-
-
-
-/*
- * $Log$
- * Revision 1.3.2.1.2.1  2006-05-19 14:19:15  nbk
- *     Don't use rad_assert in libeap, it's a server-only function.
- *
- * Revision 1.3.2.1  2005/08/24 14:37:52  nbk
- *     Fix compilation warnings with gcc 4.0
- *
- *     Patch from Steven Simon <simon.s@apple.com>
- *
- * Revision 1.3  2004/02/26 19:04:30  aland
- *     perl -i -npe "s/[ \t]+$//g" `find src -name "*.[ch]" -print`
- *
- *     Whitespace changes only, from a fresh checkout.
- *
- *     For bug # 13
- *
- * Revision 1.2  2003/11/06 15:37:24  aland
- *     Update includes to work a little better
- *
- * Revision 1.1  2003/10/29 02:49:19  mcr
- *     initial commit of eap-sim
- *
- *
- * Local Variables:
- * c-style: bsd
- * End:
- */
index 7bd321c..ef80fdc 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2002  Axis Communications AB
+ * Copyright 2006  The FreeRADIUS server project
  * Authors: Henrik Eriksson <henriken@axis.com> & Lars Viklund <larsv@axis.com>
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <openssl/hmac.h>
 #include "eap_tls.h"
 
@@ -28,7 +32,7 @@
  * Add value pair to reply
  */
 static void add_reply(VALUE_PAIR** vp,
-                     const char* name, const char* value, int len)
+                     const char* name, const uint8_t * value, int len)
 {
        VALUE_PAIR *reply_attr;
        reply_attr = pairmake(name, "", T_OP_EQ);
@@ -39,7 +43,7 @@ static void add_reply(VALUE_PAIR** vp,
                return;
        }
 
-       memcpy(reply_attr->strvalue, value, len);
+       memcpy(reply_attr->vp_octets, value, len);
        reply_attr->length = len;
        pairadd(vp, reply_attr);
 }
index cb7f578..e61d1bc 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   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 "eap_tls.h"
 
 /* record */
@@ -202,7 +207,7 @@ int tls_handshake_recv(tls_session_t *ssn)
                        return 0;
                }
        } else {
-               DEBUG2("rlm_eap_tls: Application Data");
+               radlog(L_INFO, "rlm_eap_tls: Application Data");
                /* Its clean application data, do whatever we want */
                record_init(&ssn->clean_out);
        }
index be3f7ac..231aea9 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000,2001  The FreeRADIUS server project
+ * Copyright 2000,2001,2006  The FreeRADIUS server project
  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
  */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <stdio.h>
 #include "rlm_eap.h"
 
-static const char rcsid[] = "$Id$";
-
 /*
  * Allocate a new EAP_PACKET
  */
@@ -197,7 +199,7 @@ int eaplist_add(rlm_eap_t *inst, EAP_HANDLER *handler)
        handler->timestamp = handler->request->timestamp;
        handler->status = 1;
 
-       memcpy(handler->state, state->strvalue, sizeof(handler->state));
+       memcpy(handler->state, state->vp_strvalue, sizeof(handler->state));
        handler->src_ipaddr = handler->request->packet->src_ipaddr;
        handler->eap_id = handler->eap_ds->request->id;
 
@@ -277,7 +279,7 @@ EAP_HANDLER *eaplist_find(rlm_eap_t *inst, REQUEST *request,
 
        myHandler.src_ipaddr = request->packet->src_ipaddr;
        myHandler.eap_id = eap_packet->id;
-       memcpy(myHandler.state, state->strvalue, sizeof(myHandler.state));
+       memcpy(myHandler.state, state->vp_strvalue, sizeof(myHandler.state));
 
        /*
         *      Playing with a data structure shared among threads
index f71e016..eb8423f 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
-static const char rcsid[] = "$Id$";
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -49,10 +51,10 @@ static const char rcsid[] = "$Id$";
 #      include <getopt.h>
 #endif
 
-#include "conf.h"
-#include "radpaths.h"
-#include "missing.h"
-#include "../../include/md5.h"
+#include <freeradius-devel/conf.h>
+#include <freeradius-devel/radpaths.h>
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/md5.h>
 
 #include "eap_types.h"
 #include "eap_sim.h"
@@ -170,12 +172,17 @@ static int send_packet(RADIUS_PACKET *req, RADIUS_PACKET **rep)
                         *      which we did NOT send a request to,
                         *      then complain.
                         */
-                       if (((*rep)->src_ipaddr != req->dst_ipaddr) ||
+                       if (((*rep)->src_ipaddr.af != req->dst_ipaddr.af) ||
+                           (memcmp(&(*rep)->src_ipaddr.ipaddr,
+                                   &req->dst_ipaddr.ipaddr,
+                                   ((req->dst_ipaddr.af == AF_INET ? /* AF_INET6? */
+                                     sizeof(req->dst_ipaddr.ipaddr.ip4addr) : /* FIXME: AF_INET6 */
+                                     sizeof(req->dst_ipaddr.ipaddr.ip6addr)))) != 0) ||
                            ((*rep)->src_port != req->dst_port)) {
-                               char src[64], dst[64];
+                               char src[128], dst[128];
 
-                               ip_ntoa(src, (*rep)->src_ipaddr);
-                               ip_ntoa(dst, req->dst_ipaddr);
+                               ip_ntoh(&(*rep)->src_ipaddr, src, sizeof(src));
+                               ip_ntoh(&req->dst_ipaddr, dst, sizeof(dst));
                                fprintf(stderr, "radclient: ERROR: Sent request to host %s port %d, got response from host %s port %d\n!",
                                        dst, req->dst_port,
                                        src, (*rep)->src_port);
@@ -199,7 +206,7 @@ static int send_packet(RADIUS_PACKET *req, RADIUS_PACKET **rep)
         *
         *      Hmm... we should really be using eapol_test, which does
         *      a lot more than radeapclient.
-        */
+                */
        if (rad_verify(*rep, req, secret) != 0) {
                librad_perror("rad_verify");
                exit(1);
@@ -276,7 +283,7 @@ static int process_eap_start(RADIUS_PACKET *req,
                return 0;
        }
 
-       versions = (uint16_t *)vp->strvalue;
+       versions = (uint16_t *)vp->vp_strvalue;
 
        /* verify that the attribute length is big enough for a length field */
        if(vp->length < 4)
@@ -354,7 +361,7 @@ static int process_eap_start(RADIUS_PACKET *req,
        /* insert selected version into response. */
        newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_SELECTED_VERSION,
                           PW_TYPE_OCTETS);
-       versions = (uint16_t *)newvp->strvalue;
+       versions = (uint16_t *)newvp->vp_strvalue;
        versions[0] = htons(selectedversion);
        newvp->length = 2;
        pairreplace(&(rep->vps), newvp);
@@ -371,15 +378,15 @@ static int process_eap_start(RADIUS_PACKET *req,
                 */
                newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_NONCE_MT,
                                   PW_TYPE_OCTETS);
-               newvp->strvalue[0]=0;
-               newvp->strvalue[1]=0;
+               newvp->vp_octets[0]=0;
+               newvp->vp_octets[1]=0;
                newvp->length = 18;  /* 16 bytes of nonce + padding */
 
                nonce[0]=lrad_rand();
                nonce[1]=lrad_rand();
                nonce[2]=lrad_rand();
                nonce[3]=lrad_rand();
-               memcpy(&newvp->strvalue[2], nonce, 16);
+               memcpy(&newvp->vp_octets[2], nonce, 16);
                pairreplace(&(rep->vps), newvp);
 
                /* also keep a copy of the nonce! */
@@ -400,16 +407,16 @@ static int process_eap_start(RADIUS_PACKET *req,
                }
                newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_IDENTITY,
                                   PW_TYPE_OCTETS);
-               idlen = strlen(vp->strvalue);
-               pidlen = (uint16_t *)newvp->strvalue;
+               idlen = strlen(vp->vp_strvalue);
+               pidlen = (uint16_t *)newvp->vp_strvalue;
                *pidlen = htons(idlen);
                newvp->length = idlen + 2;
 
-               memcpy(&newvp->strvalue[2], vp->strvalue, idlen);
+               memcpy(&newvp->vp_strvalue[2], vp->vp_strvalue, idlen);
                pairreplace(&(rep->vps), newvp);
 
                /* record it */
-               memcpy(eapsim_mk.identity, vp->strvalue, idlen);
+               memcpy(eapsim_mk.identity, vp->vp_strvalue, idlen);
                eapsim_mk.identitylen = idlen;
        }
 
@@ -438,7 +445,7 @@ static int process_eap_challenge(RADIUS_PACKET *req,
        /* look for the AT_MAC and the challenge data */
        mac   = pairfind(req->vps, ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_MAC);
        randvp= pairfind(req->vps, ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_RAND);
-       if(mac == NULL || randvp == NULL) {
+       if(mac == NULL || rand == NULL) {
                fprintf(stderr, "radeapclient: challenge message needs to contain RAND and MAC\n");
                return 0;
        }
@@ -451,9 +458,9 @@ static int process_eap_challenge(RADIUS_PACKET *req,
          VALUE_PAIR *randcfgvp[3];
          unsigned char *randcfg[3];
 
-         randcfg[0] = &randvp->strvalue[2];
-         randcfg[1] = &randvp->strvalue[2+EAPSIM_RAND_SIZE];
-         randcfg[2] = &randvp->strvalue[2+EAPSIM_RAND_SIZE*2];
+         randcfg[0] = &randvp->vp_strvalue[2];
+         randcfg[1] = &randvp->vp_strvalue[2+EAPSIM_RAND_SIZE];
+         randcfg[2] = &randvp->vp_strvalue[2+EAPSIM_RAND_SIZE*2];
 
          randcfgvp[0] = pairfind(rep->vps, ATTRIBUTE_EAP_SIM_RAND1);
          randcfgvp[1] = pairfind(rep->vps, ATTRIBUTE_EAP_SIM_RAND2);
@@ -466,9 +473,9 @@ static int process_eap_challenge(RADIUS_PACKET *req,
            return 0;
          }
 
-         if(memcmp(randcfg[0], randcfgvp[0]->strvalue, EAPSIM_RAND_SIZE)!=0 ||
-            memcmp(randcfg[1], randcfgvp[1]->strvalue, EAPSIM_RAND_SIZE)!=0 ||
-            memcmp(randcfg[2], randcfgvp[2]->strvalue, EAPSIM_RAND_SIZE)!=0) {
+         if(memcmp(randcfg[0], randcfgvp[0]->vp_strvalue, EAPSIM_RAND_SIZE)!=0 ||
+            memcmp(randcfg[1], randcfgvp[1]->vp_strvalue, EAPSIM_RAND_SIZE)!=0 ||
+            memcmp(randcfg[2], randcfgvp[2]->vp_strvalue, EAPSIM_RAND_SIZE)!=0) {
            int rnum,i,j;
 
            fprintf(stderr, "radeapclient: one of rand 1,2,3 didn't match\n");
@@ -493,7 +500,7 @@ static int process_eap_challenge(RADIUS_PACKET *req,
                }
                j++;
 
-               fprintf(stderr, "%02x", randcfgvp[rnum]->strvalue[i]);
+               fprintf(stderr, "%02x", randcfgvp[rnum]->vp_strvalue[i]);
              }
              fprintf(stderr, "\n");
            }
@@ -518,9 +525,9 @@ static int process_eap_challenge(RADIUS_PACKET *req,
                fprintf(stderr, "radeapclient: needs to have sres1, 2 and 3 set.\n");
                return 0;
        }
-       memcpy(eapsim_mk.sres[0], sres1->strvalue, sizeof(eapsim_mk.sres[0]));
-       memcpy(eapsim_mk.sres[1], sres2->strvalue, sizeof(eapsim_mk.sres[1]));
-       memcpy(eapsim_mk.sres[2], sres3->strvalue, sizeof(eapsim_mk.sres[2]));
+       memcpy(eapsim_mk.sres[0], sres1->vp_strvalue, sizeof(eapsim_mk.sres[0]));
+       memcpy(eapsim_mk.sres[1], sres2->vp_strvalue, sizeof(eapsim_mk.sres[1]));
+       memcpy(eapsim_mk.sres[2], sres3->vp_strvalue, sizeof(eapsim_mk.sres[2]));
 
        Kc1 = pairfind(rep->vps, ATTRIBUTE_EAP_SIM_KC1);
        Kc2 = pairfind(rep->vps, ATTRIBUTE_EAP_SIM_KC2);
@@ -532,9 +539,9 @@ static int process_eap_challenge(RADIUS_PACKET *req,
                fprintf(stderr, "radeapclient: needs to have Kc1, 2 and 3 set.\n");
                return 0;
        }
-       memcpy(eapsim_mk.Kc[0], Kc1->strvalue, sizeof(eapsim_mk.Kc[0]));
-       memcpy(eapsim_mk.Kc[1], Kc2->strvalue, sizeof(eapsim_mk.Kc[1]));
-       memcpy(eapsim_mk.Kc[2], Kc3->strvalue, sizeof(eapsim_mk.Kc[2]));
+       memcpy(eapsim_mk.Kc[0], Kc1->vp_strvalue, sizeof(eapsim_mk.Kc[0]));
+       memcpy(eapsim_mk.Kc[1], Kc2->vp_strvalue, sizeof(eapsim_mk.Kc[1]));
+       memcpy(eapsim_mk.Kc[2], Kc3->vp_strvalue, sizeof(eapsim_mk.Kc[2]));
 
        /* all set, calculate keys */
        eapsim_calculate_keys(&eapsim_mk);
@@ -579,14 +586,14 @@ static int process_eap_challenge(RADIUS_PACKET *req,
         */
        newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_MAC,
                           PW_TYPE_OCTETS);
-       memcpy(newvp->strvalue+EAPSIM_SRES_SIZE*0, sres1->strvalue, EAPSIM_SRES_SIZE);
-       memcpy(newvp->strvalue+EAPSIM_SRES_SIZE*1, sres2->strvalue, EAPSIM_SRES_SIZE);
-       memcpy(newvp->strvalue+EAPSIM_SRES_SIZE*2, sres3->strvalue, EAPSIM_SRES_SIZE);
+       memcpy(newvp->vp_strvalue+EAPSIM_SRES_SIZE*0, sres1->vp_strvalue, EAPSIM_SRES_SIZE);
+       memcpy(newvp->vp_strvalue+EAPSIM_SRES_SIZE*1, sres2->vp_strvalue, EAPSIM_SRES_SIZE);
+       memcpy(newvp->vp_strvalue+EAPSIM_SRES_SIZE*2, sres3->vp_strvalue, EAPSIM_SRES_SIZE);
        newvp->length = EAPSIM_SRES_SIZE*3;
        pairreplace(&(rep->vps), newvp);
 
        newvp = paircreate(ATTRIBUTE_EAP_SIM_KEY, PW_TYPE_OCTETS);
-       memcpy(newvp->strvalue,    eapsim_mk.K_aut, EAPSIM_AUTH_SIZE);
+       memcpy(newvp->vp_strvalue,    eapsim_mk.K_aut, EAPSIM_AUTH_SIZE);
        newvp->length = EAPSIM_AUTH_SIZE;
        pairreplace(&(rep->vps), newvp);
 
@@ -739,9 +746,9 @@ static int respond_eap_md5(RADIUS_PACKET *req,
        }
 
        /* got the details of the MD5 challenge */
-       valuesize = vp->strvalue[0];
-       value = &vp->strvalue[1];
-       name  = &vp->strvalue[valuesize+1];
+       valuesize = vp->vp_octets[0];
+       value = &vp->vp_octets[1];
+       name  = &vp->vp_octets[valuesize+1];
        namesize = vp->length - (valuesize + 1);
 
        /* sanitize items */
@@ -756,15 +763,15 @@ static int respond_eap_md5(RADIUS_PACKET *req,
         * buffer. We could also call rad_chap_encode, but it wants
         * a CHAP-Challenge, which we don't want to bother with.
         */
-       librad_MD5Init(&context);
-       librad_MD5Update(&context, &identifier, 1);
-       librad_MD5Update(&context, password, strlen(password));
-       librad_MD5Update(&context, value, valuesize);
-       librad_MD5Final(response, &context);
+       lrad_MD5Init(&context);
+       lrad_MD5Update(&context, &identifier, 1);
+       lrad_MD5Update(&context, password, strlen(password));
+       lrad_MD5Update(&context, value, valuesize);
+       lrad_MD5Final(response, &context);
 
        vp = paircreate(ATTRIBUTE_EAP_BASE+PW_EAP_MD5, PW_TYPE_OCTETS);
-       vp->strvalue[0]=16;
-       memcpy(&vp->strvalue[1], response, 16);
+       vp->vp_octets[0]=16;
+       memcpy(&vp->vp_strvalue[1], response, 16);
        vp->length = 17;
 
        pairreplace(&(rep->vps), vp);
@@ -788,16 +795,16 @@ static int sendrecv_eap(RADIUS_PACKET *rep)
        /*
         *      Keep a copy of the the User-Password attribute.
         */
-       if ((vp = pairfind(rep->vps, ATTRIBUTE_EAP_MD5_PASSWORD)) != NULL) {
-               strNcpy(password, (char *)vp->strvalue, sizeof(vp->strvalue));
+       if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD)) != NULL) {
+               strlcpy(password, (char *)vp->vp_strvalue, sizeof(vp->vp_strvalue));
 
-       } else  if ((vp = pairfind(rep->vps, PW_PASSWORD)) != NULL) {
-               strNcpy(password, (char *)vp->strvalue, sizeof(vp->strvalue));
+       } else  if ((vp = pairfind(rep->vps, PW_USER_PASSWORD)) != NULL) {
+               strlcpy(password, (char *)vp->vp_strvalue, sizeof(vp->vp_strvalue));
                /*
                 *      Otherwise keep a copy of the CHAP-Password attribute.
                 */
        } else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD)) != NULL) {
-               strNcpy(password, (char *)vp->strvalue, sizeof(vp->strvalue));
+               strlcpy(password, (char *)vp->vp_strvalue, sizeof(vp->vp_strvalue));
        } else {
                *password = '\0';
        }
@@ -833,10 +840,10 @@ static int sendrecv_eap(RADIUS_PACKET *rep)
                case PW_DIGEST_NONCE_COUNT:
                case PW_DIGEST_USER_NAME:
                        /* overlapping! */
-                       memmove(&vp->strvalue[2], &vp->strvalue[0], vp->length);
-                       vp->strvalue[0] = vp->attribute - PW_DIGEST_REALM + 1;
+                       memmove(&vp->vp_strvalue[2], &vp->vp_octets[0], vp->length);
+                       vp->vp_octets[0] = vp->attribute - PW_DIGEST_REALM + 1;
                        vp->length += 2;
-                       vp->strvalue[1] = vp->length;
+                       vp->vp_octets[1] = vp->length;
                        vp->attribute = PW_DIGEST_ATTRIBUTES;
                        break;
                }
@@ -856,15 +863,19 @@ static int sendrecv_eap(RADIUS_PACKET *rep)
                        sizeof(rep->vector));
 
        if (*password != '\0') {
-               if ((vp = pairfind(rep->vps, PW_PASSWORD)) != NULL) {
-                       strNcpy((char *)vp->strvalue, password, strlen(password) + 1);
+               if ((vp = pairfind(rep->vps, PW_CLEARTEXT_PASSWORD)) != NULL) {
+                       strlcpy((char *)vp->vp_strvalue, password, sizeof(vp->vp_strvalue));
+                       vp->length = strlen(password);
+
+               } else if ((vp = pairfind(rep->vps, PW_USER_PASSWORD)) != NULL) {
+                       strlcpy((char *)vp->vp_strvalue, password, sizeof(vp->vp_strvalue));
                        vp->length = strlen(password);
 
                } else if ((vp = pairfind(rep->vps, PW_CHAP_PASSWORD)) != NULL) {
-                       strNcpy((char *)vp->strvalue, password, strlen(password) + 1);
+                       strlcpy((char *)vp->vp_strvalue, password, sizeof(vp->vp_strvalue));
                        vp->length = strlen(password);
 
-                       rad_chap_encode(rep, (char *) vp->strvalue, rep->id, vp);
+                       rad_chap_encode(rep, (char *) vp->vp_strvalue, rep->id, vp);
                        vp->length = 17;
                }
        } /* there WAS a password */
@@ -1095,8 +1106,7 @@ int main(int argc, char **argv)
         *      Resolve hostname.
         */
        req->dst_port = port;
-       req->dst_ipaddr = ip_getaddr(argv[1]);
-       if (req->dst_ipaddr == INADDR_NONE) {
+       if (ip_hton(argv[1], AF_INET, &req->dst_ipaddr) < 0) {
                fprintf(stderr, "radclient: Failed to find IP address for host %s\n", argv[1]);
                exit(1);
        }
index 4f9a848..591361e 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000-2003  The FreeRADIUS server project
+ * Copyright 2000-2003,2006  The FreeRADIUS server project
  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
  * Copyright 2003  Alan DeKok <aland@freeradius.org>
  */
 
-#include "autoconf.h"
-#include "rlm_eap.h"
-#include "modules.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/autoconf.h>
+#include "rlm_eap.h"
+#include <freeradius-devel/modules.h>
 
 static const CONF_PARSER module_config[] = {
        { "default_eap_type", PW_TYPE_STRING_PTR,
@@ -62,7 +63,6 @@ static int eap_detach(void *instance)
 
        pthread_mutex_destroy(&(inst->session_mutex));
 
-       if (inst->default_eap_type_name) free(inst->default_eap_type_name);
        free(inst);
 
        return 0;
@@ -74,14 +74,38 @@ static int eap_detach(void *instance)
  */
 static int eap_handler_cmp(const void *a, const void *b)
 {
+       int rcode;
        const EAP_HANDLER *one = a;
        const EAP_HANDLER *two = b;
 
+
+       if (one->src_ipaddr.af < two->src_ipaddr.af) return -1;
+       if (one->src_ipaddr.af > two->src_ipaddr.af) return +1;
+
        if (one->eap_id < two->eap_id) return -1;
        if (one->eap_id > two->eap_id) return +1;
 
-       if (one->src_ipaddr < two->src_ipaddr) return -1;
-       if (one->src_ipaddr > two->src_ipaddr) return +1;
+       switch (one->src_ipaddr.af) {
+       case AF_INET:
+               rcode = memcmp(&one->src_ipaddr.ipaddr.ip4addr,
+                              &two->src_ipaddr.ipaddr.ip4addr,
+                              sizeof(one->src_ipaddr.ipaddr.ip4addr));
+               break;
+       case AF_INET6:
+               rcode = memcmp(&one->src_ipaddr.ipaddr.ip6addr,
+                              &two->src_ipaddr.ipaddr.ip6addr,
+                              sizeof(one->src_ipaddr.ipaddr.ip6addr));
+               break;
+       default:
+               return -1;      /* FIXME: die! */
+               break;
+       }
+       /*
+        *      We could optimize this away, but the compiler should
+        *      do that work for us, and this coding style helps us
+        *      remember what to do if we add more checks later.
+        */
+       if (rcode != 0) return rcode;
 
        return memcmp(one->state, two->state, sizeof(one->state));
 }
@@ -384,7 +408,7 @@ static int eap_authenticate(void *instance, REQUEST *request)
                 */
                vp = pairfind(request->reply->vps, PW_USER_NAME);
                if (!vp) {
-                       vp = pairmake("User-Name", request->username->strvalue,
+                       vp = pairmake("User-Name", request->username->vp_strvalue,
                                      T_OP_EQ);
                        rad_assert(vp != NULL);
                        pairadd(&(request->reply->vps), vp);
@@ -395,8 +419,8 @@ static int eap_authenticate(void *instance, REQUEST *request)
                 *      terminated string in Access-Accept.
                 */
                if ((inst->cisco_accounting_username_bug) &&
-                   (vp->length < (int) sizeof(vp->strvalue))) {
-                       vp->strvalue[vp->length] = '\0';
+                   (vp->length < (int) sizeof(vp->vp_strvalue))) {
+                       vp->vp_strvalue[vp->length] = '\0';
                        vp->length++;
                }
        }
@@ -543,7 +567,7 @@ static int eap_post_proxy(void *inst, REQUEST *request)
                         */
                        vp = pairfind(request->reply->vps, PW_USER_NAME);
                        if (!vp) {
-                               vp = pairmake("User-Name", request->username->strvalue,
+                               vp = pairmake("User-Name", request->username->vp_strvalue,
                                              T_OP_EQ);
                                rad_assert(vp != NULL);
                                pairadd(&(request->reply->vps), vp);
@@ -577,7 +601,7 @@ static int eap_post_proxy(void *inst, REQUEST *request)
                 *
                 *      The format is VERY specific!
                 */
-               if (strncasecmp(vp->strvalue, "leap:session-key=", 17) == 0) {
+               if (strncasecmp(vp->vp_strvalue, "leap:session-key=", 17) == 0) {
                        break;
                }
 
@@ -600,7 +624,7 @@ static int eap_post_proxy(void *inst, REQUEST *request)
         *      Decrypt the session key, using the proxy data.
         */
        i = 34;                 /* starts off with 34 octets */
-       len = rad_tunnel_pwdecode(vp->strvalue + 17, &i,
+       len = rad_tunnel_pwdecode(vp->vp_strvalue + 17, &i,
                                  request->proxysecret,
                                  request->proxy->vector);
 
@@ -611,7 +635,7 @@ static int eap_post_proxy(void *inst, REQUEST *request)
        /*
         *      Encrypt the session key again, using the request data.
         */
-       rad_tunnel_pwencode(vp->strvalue + 17, &len,
+       rad_tunnel_pwencode(vp->vp_strvalue + 17, &len,
                            request->secret,
                            request->packet->vector);
 
@@ -624,10 +648,11 @@ static int eap_post_proxy(void *inst, REQUEST *request)
  *     That is, everything else should be 'static'.
  */
 module_t rlm_eap = {
+       RLM_MODULE_INIT,
        "eap",
        RLM_TYPE_THREAD_SAFE,           /* type */
-       NULL,                           /* initialization */
        eap_instantiate,                /* instantiation */
+       eap_detach,                     /* detach */
        {
                eap_authenticate,       /* authentication */
                eap_authorize,          /* authorization */
@@ -638,6 +663,4 @@ module_t rlm_eap = {
                eap_post_proxy,         /* post-proxy */
                NULL                    /* post-auth */
        },
-       eap_detach,                     /* detach */
-       NULL,                           /* destroy */
 };
index 3d33c77..67ea755 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   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
  */
 #ifndef _RLM_EAP_H
 #define _RLM_EAP_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(rlm_eap_h, "$Id$")
+
 #include <ltdl.h>
 #include "eap.h"
 #include "eap_types.h"
index 3e165b5..13cc7ec 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
+ * Copyright 2006  The FreeRADIUS server project
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 #include "rlm_eap.h"
 
-static const char rcsid[] = "$Id$";
-
 /*
  *     Global key to generate & verify State
  *
@@ -146,8 +148,8 @@ VALUE_PAIR *generate_state(time_t timestamp)
                radlog(L_ERR, "rlm_eap: out of memory");
                return NULL;
        }
-       memcpy(state->strvalue, challenge, sizeof(challenge));
-       memcpy(state->strvalue + sizeof(challenge), hmac,
+       memcpy(state->vp_strvalue, challenge, sizeof(challenge));
+       memcpy(state->vp_strvalue + sizeof(challenge), hmac,
               EAP_USE_OF_HMAC);
 
        state->length = sizeof(challenge) + EAP_USE_OF_HMAC;
@@ -174,7 +176,7 @@ int verify_state(VALUE_PAIR *state, time_t timestamp)
         *      The first 16 octets of the State attribute constains
         *      the random challenge.
         */
-       memcpy(value, state->strvalue, EAP_CHALLENGE_LEN);
+       memcpy(value, state->vp_strvalue, EAP_CHALLENGE_LEN);
        memcpy(value + EAP_CHALLENGE_LEN, &timestamp, sizeof(timestamp));
 
        /* Generate hmac.  */
@@ -185,7 +187,7 @@ int verify_state(VALUE_PAIR *state, time_t timestamp)
         *      Compare the hmac we calculated to the one in the
         *      packet.
         */
-       return memcmp(hmac, state->strvalue + EAP_CHALLENGE_LEN,
+       return memcmp(hmac, state->vp_strvalue + EAP_CHALLENGE_LEN,
                      EAP_USE_OF_HMAC);
 }
 
index aff91fd..09879ff 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2003  The FreeRADIUS server project
+ * Copyright 2003,2006  The FreeRADIUS server project
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "eap.h"
 
-#include <rad_assert.h>
+#include <freeradius-devel/rad_assert.h>
 
 /*
  *     EAP-GTC is just ASCII data carried inside of the EAP session.
@@ -58,8 +61,6 @@ static int gtc_detach(void *arg)
 {
        rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) arg;
 
-       if (inst->challenge) free(inst->challenge);
-       if (inst->auth_type_name) free(inst->auth_type_name);
 
        free(inst);
 
@@ -155,7 +156,7 @@ static int gtc_authenticate(void *type_data, EAP_HANDLER *handler)
        rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) type_data;
 
        /*
-        *      Get the User-Password for this user.
+        *      Get the Cleartext-Password for this user.
         */
        rad_assert(handler->request != NULL);
        rad_assert(handler->stage == AUTHENTICATE);
@@ -191,9 +192,9 @@ static int gtc_authenticate(void *type_data, EAP_HANDLER *handler)
                /*
                 *      For now, do clear-text password authentication.
                 */
-               vp = pairfind(handler->request->config_items, PW_PASSWORD);
+               vp = pairfind(handler->request->config_items, PW_CLEARTEXT_PASSWORD);
                if (!vp) {
-                       DEBUG2("  rlm_eap_gtc: ERROR: Clear-test User-Password is required for authentication.");
+                       DEBUG2("  rlm_eap_gtc: ERROR: Cleartext-Password is required for authentication.");
                        eap_ds->request->code = PW_EAP_FAILURE;
                        return 0;
                }
@@ -205,7 +206,7 @@ static int gtc_authenticate(void *type_data, EAP_HANDLER *handler)
                }
 
                if (memcmp(eap_ds->response->type.data,
-                          vp->strvalue, vp->length) != 0) {
+                          vp->vp_strvalue, vp->length) != 0) {
                        DEBUG2("  rlm_eap_gtc: ERROR: Passwords are different");
                        eap_ds->request->code = PW_EAP_FAILURE;
                        return 0;
@@ -222,7 +223,7 @@ static int gtc_authenticate(void *type_data, EAP_HANDLER *handler)
                 *      If there was a User-Password in the request,
                 *      why the heck are they using EAP-GTC?
                 */
-               rad_assert(handler->request->password == NULL);
+               pairdelete(&handler->request->packet->vps, PW_USER_PASSWORD);
 
                vp = pairmake("User-Password", "", T_OP_EQ);
                if (!vp) {
@@ -230,8 +231,8 @@ static int gtc_authenticate(void *type_data, EAP_HANDLER *handler)
                        return 0;
                }
                vp->length = eap_ds->response->type.length;
-               memcpy(vp->strvalue, eap_ds->response->type.data, vp->length);
-               vp->strvalue[vp->length] = 0;
+               memcpy(vp->vp_strvalue, eap_ds->response->type.data, vp->length);
+               vp->vp_strvalue[vp->length] = 0;
 
                /*
                 *      Add the password to the request, and allow
index f3b624d..a85e0d1 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
  */
 
 /*
@@ -43,6 +44,9 @@
  *  The LEAP type (0x11) is *not* included in the type data...
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <stdio.h>
 #include <stdlib.h>
 #include "eap.h"
@@ -210,7 +214,7 @@ static int eapleap_ntpwdhash(unsigned char *ntpwdhash, VALUE_PAIR *password)
                         *  Yes, the *even* bytes have the values,
                         *  and the *odd* bytes are zero.
                         */
-                       unicode[(i << 1)] = password->strvalue[i];
+                       unicode[(i << 1)] = password->vp_strvalue[i];
                }
 
                /*
@@ -220,8 +224,8 @@ static int eapleap_ntpwdhash(unsigned char *ntpwdhash, VALUE_PAIR *password)
 
        } else {                /* MUST be NT-Password */
                if (password->length == 32) {
-                       password->length = lrad_hex2bin(password->strvalue,
-                                                       password->strvalue,
+                       password->length = lrad_hex2bin(password->vp_strvalue,
+                                                       password->vp_strvalue,
                                                        16);
                }
                if (password->length != 16) {
@@ -229,7 +233,7 @@ static int eapleap_ntpwdhash(unsigned char *ntpwdhash, VALUE_PAIR *password)
                        return 0;
                }
 
-               memcpy(ntpwdhash, password->strvalue, 16);
+               memcpy(ntpwdhash, password->vp_strvalue, 16);
        }
        return 1;
 }
@@ -318,7 +322,7 @@ LEAP_PACKET *eapleap_stage6(LEAP_PACKET *packet, REQUEST *request,
        /*
         *      Copy the name over, and ensure it's NUL terminated.
         */
-       memcpy(reply->name, user_name->strvalue, user_name->length);
+       memcpy(reply->name, user_name->vp_strvalue, user_name->length);
        reply->name[user_name->length] = '\0';
        reply->name_len = user_name->length;
 
@@ -367,12 +371,12 @@ LEAP_PACKET *eapleap_stage6(LEAP_PACKET *packet, REQUEST *request,
         */
        librad_md5_calc(ntpwdhash, buffer, 16 + 8 + 24 + 8 + 24);
 
-       memcpy(vp->strvalue + vp->length, ntpwdhash, 16);
-       memset(vp->strvalue + vp->length + 16, 0,
-              sizeof(vp->strvalue) - (vp->length + 16));
+       memcpy(vp->vp_strvalue + vp->length, ntpwdhash, 16);
+       memset(vp->vp_strvalue + vp->length + 16, 0,
+              sizeof(vp->vp_strvalue) - (vp->length + 16));
 
        i = 16;
-       rad_tunnel_pwencode(vp->strvalue + vp->length, &i,
+       rad_tunnel_pwencode(vp->vp_strvalue + vp->length, &i,
                            request->secret, request->packet->vector);
        vp->length += i;
        pairadd(reply_vps, vp);
@@ -428,7 +432,7 @@ LEAP_PACKET *eapleap_initiate(UNUSED EAP_DS *eap_ds, VALUE_PAIR *user_name)
        /*
         *      Copy the name over, and ensure it's NUL terminated.
         */
-       memcpy(reply->name, user_name->strvalue, user_name->length);
+       memcpy(reply->name, user_name->vp_strvalue, user_name->length);
        reply->name[user_name->length] = '\0';
        reply->name_len = user_name->length;
 
index c35202c..eb23f57 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef _EAP_LEAP_H
 #define _EAP_LEAP_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(eap_leap_h, "$Id$")
+
 #include "eap.h"
 
 #define PW_LEAP_CHALLENGE      1
index d492aba..6321706 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -36,7 +40,7 @@
  * len = header + type + leap_typedata
  * leap_typedata = value_size + value
  */
-static int leap_initiate(void *instance, EAP_HANDLER *handler)
+static int leap_initiate(UNUSED void *instance, EAP_HANDLER *handler)
 {
        leap_session_t  *session;
        LEAP_PACKET     *reply;
@@ -86,7 +90,7 @@ static int leap_initiate(void *instance, EAP_HANDLER *handler)
        return 1;
 }
 
-static int leap_authenticate(void *instance, EAP_HANDLER *handler)
+static int leap_authenticate(UNUSED void *instance, EAP_HANDLER *handler)
 {
        int             rcode;
        leap_session_t  *session;
@@ -108,16 +112,16 @@ static int leap_authenticate(void *instance, EAP_HANDLER *handler)
        if (!(packet = eapleap_extract(handler->eap_ds)))
                return 0;
 
-       username = (char *)handler->request->username->strvalue;
+       username = (char *)handler->request->username->vp_strvalue;
 
        /*
         *      The password is never sent over the wire.
         *      Always get the configured password, for each user.
         */
-       password = pairfind(handler->request->config_items, PW_PASSWORD);
+       password = pairfind(handler->request->config_items, PW_CLEARTEXT_PASSWORD);
        if (!password) password = pairfind(handler->request->config_items, PW_NT_PASSWORD);
        if (!password) {
-               radlog(L_INFO, "rlm_eap_leap: No User-Password or NT-Password configured for this user");
+               radlog(L_INFO, "rlm_eap_leap: No Cleartext-Password or NT-Password configured for this user");
                eapleap_free(&packet);
                return 0;
        }
@@ -130,7 +134,6 @@ static int leap_authenticate(void *instance, EAP_HANDLER *handler)
        case 4:                 /* Verify NtChallengeResponse */
                DEBUG2("  rlm_eap_leap: Stage 4");
                rcode = eapleap_stage4(packet, password, session);
-               eapleap_free(&packet);
                session->stage = 6;
 
                /*
@@ -139,6 +142,7 @@ static int leap_authenticate(void *instance, EAP_HANDLER *handler)
                 */
                if (!rcode) {
                        handler->eap_ds->request->code = PW_EAP_FAILURE;
+                       eapleap_free(&packet);
                        return 0;
                }
 
index b7ccc4d..ccee0fc 100644 (file)
@@ -5,6 +5,7 @@
    SMB authentication protocol
 
    Copyright (C) Andrew Tridgell 1998
+   Copyright 2006 The FreeRADIUS server project
 
    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
    should confirm it for yourself (and maybe let me know if you come
    up with a different answer to the one above)
 */
-#include "libradius.h"
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <string.h>
 #include <ctype.h>
 
@@ -1,11 +1,13 @@
 #
-# $Id$
+# Makefile
+#
+# Version:     $Id$
 #
 
-TARGET      = @targetname@
+TARGET      = rlm_eap_md5
 SRCS        = rlm_eap_md5.c eap_md5.c
 HEADERS     = eap_md5.h
-RLM_CFLAGS  = -I../.. -I../../libeap $(INCLTDL)
+RLM_CFLAGS  = $(INCLTDL) -I../.. -I../../libeap
 RLM_INSTALL =
 
 RLM_DIR=../../
diff --git a/src/modules/rlm_eap/types/rlm_eap_md5/configure.in b/src/modules/rlm_eap/types/rlm_eap_md5/configure.in
deleted file mode 100644 (file)
index a5c9e85..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-AC_INIT(rlm_eap_md5.c)
-AC_REVISION($Revision$)
-AC_DEFUN(modname,[rlm_eap_md5])
-
-if test x$with_[]modname != xno; then
-
-       ## We may need more complex checking here.  Assume for now that 
-       ## everyone has it.
-       AC_CHECK_HEADERS(malloc.h)
-
-       targetname=modname     # keep this!  Don't change!
-else
-       targetname=            # keep this!  Don't change!
-       echo \*\*\* module modname is disabled.  # keep this!  Don't change!
-fi
-
-dnl  Don't change this section.
-if test x"$fail" != x""; then
-       if test x"${enable_strict_dependencies}" = x"yes"; then
-               AC_MSG_ERROR([set --without-]modname[ to disable it explicitly.])
-       else
-               AC_MSG_WARN([silently not building ]modname[.])
-               AC_MSG_WARN([FAILURE: ]modname[ requires: $fail.]); 
-               targetname=""
-       fi
-fi
-
-AC_SUBST(eap_md5_cflags)
-AC_SUBST(eap_md5_ldflags)
-
-dnl AC_CONFIG_HEADER(config.h)
-
-AC_SUBST(targetname)  # keep this!  Don't change!
-AC_OUTPUT(Makefile)  # keep this!  Don't change!
index 2411d4b..09cc167 100644 (file)
@@ -15,9 +15,9 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000,2001  The FreeRADIUS server project
+ * Copyright 2000,2001,2006  The FreeRADIUS server project
  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
  */
 
@@ -35,6 +35,9 @@
  *
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <stdio.h>
 #include <stdlib.h>
 #include "eap.h"
@@ -184,7 +187,7 @@ int eapmd5_verify(MD5_PACKET *packet, VALUE_PAIR* password,
         */
        *ptr++ = packet->id;
        len++;
-       memcpy(ptr, password->strvalue, password->length);
+       memcpy(ptr, password->vp_strvalue, password->length);
        ptr += password->length;
        len += password->length;
 
@@ -222,7 +225,6 @@ int eapmd5_compose(EAP_DS *eap_ds, MD5_PACKET *reply)
                eap_ds->request->type.type = PW_EAP_MD5;
 
                rad_assert(reply->length > 0);
-               rad_assert(reply->value_size < 256);
 
                eap_ds->request->type.data = malloc(reply->length);
                if (eap_ds->request->type.data == NULL) {
index 698aab4..a7936eb 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef _EAP_MD5_H
 #define _EAP_MD5_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(eap_md5_h, "$Id$")
+
 #include "eap.h"
 
 #define PW_MD5_CHALLENGE       1
index 7abdb30..12b04bc 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000,2001  The FreeRADIUS server project
+ * Copyright 2000,2001,2006  The FreeRADIUS server project
  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "eap_md5.h"
 
-#include <rad_assert.h>
+#include <freeradius-devel/rad_assert.h>
 
 /*
  *     Initiate the EAP-MD5 session by sending a challenge to the peer.
@@ -104,21 +107,21 @@ static int md5_initiate(void *type_data, EAP_HANDLER *handler)
 /*
  *     Authenticate a previously sent challenge.
  */
-static int md5_authenticate(void *arg, EAP_HANDLER *handler)
+static int md5_authenticate(UNUSED void *arg, EAP_HANDLER *handler)
 {
        MD5_PACKET      *packet;
        MD5_PACKET      *reply;
        VALUE_PAIR      *password;
 
        /*
-        *      Get the User-Password for this user.
+        *      Get the Cleartext-Password for this user.
         */
        rad_assert(handler->request != NULL);
        rad_assert(handler->stage == AUTHENTICATE);
 
-       password = pairfind(handler->request->config_items, PW_PASSWORD);
+       password = pairfind(handler->request->config_items, PW_CLEARTEXT_PASSWORD);
        if (password == NULL) {
-               radlog(L_INFO, "rlm_eap_md5: User-Password is required for EAP-MD5 authentication");
+               radlog(L_INFO, "rlm_eap_md5: Cleartext-Password is required for EAP-MD5 authentication");
                return 0;
        }
 
@@ -133,7 +136,6 @@ static int md5_authenticate(void *arg, EAP_HANDLER *handler)
         */
        reply = eapmd5_alloc();
        if (!reply) {
-               eapmd5_free(&packet);
                return 0;
        }
        reply->id = handler->eap_ds->request->id;
@@ -146,7 +148,6 @@ static int md5_authenticate(void *arg, EAP_HANDLER *handler)
        if (eapmd5_verify(packet, password, handler->opaque)) {
                reply->code = PW_MD5_SUCCESS;
        } else {
-               DEBUG2("  rlm_eap_md5: Passwords do not match");
                reply->code = PW_MD5_FAILURE;
        }
 
@@ -1,11 +1,13 @@
 #
-# $Id$
+# Makefile
+#
+# Version:     $Id$
 #
 
-TARGET      = @targetname@
+TARGET      = rlm_eap_mschapv2
 SRCS        = rlm_eap_mschapv2.c
 HEADERS     = eap_mschapv2.h
-RLM_CFLAGS  = -I../.. -I../../libeap $(INCLTDL)
+RLM_CFLAGS  = $(INCLTDL) -I../.. -I../../libeap
 RLM_INSTALL =
 
 RLM_DIR=../../
diff --git a/src/modules/rlm_eap/types/rlm_eap_mschapv2/configure b/src/modules/rlm_eap/types/rlm_eap_mschapv2/configure
deleted file mode 100755 (executable)
index 64d267b..0000000
+++ /dev/null
@@ -1,3801 +0,0 @@
-#! /bin/sh
-# From configure.in Revision: 1.1 .
-# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59.
-#
-# Copyright (C) 2003 Free Software Foundation, Inc.
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-## --------------------- ##
-## M4sh Initialization.  ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
-  set -o posix
-fi
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
-  as_unset=unset
-else
-  as_unset=false
-fi
-
-
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
-  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
-  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
-  LC_TELEPHONE LC_TIME
-do
-  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
-    eval $as_var=C; export $as_var
-  else
-    $as_unset $as_var
-  fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
-  as_basename=basename
-else
-  as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
-        X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)$' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
-         /^X\/\(\/\/\)$/{ s//\1/; q; }
-         /^X\/\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-
-
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
-fi
-
-
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
-  # Find who we are.  Look in the path if we contain no path at all
-  # relative or not.
-  case $0 in
-    *[\\/]* ) as_myself=$0 ;;
-    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
-       ;;
-  esac
-  # We did not find ourselves, most probably we were run as `sh COMMAND'
-  # in which case we are not to be found in the path.
-  if test "x$as_myself" = x; then
-    as_myself=$0
-  fi
-  if test ! -f "$as_myself"; then
-    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
-   { (exit 1); exit 1; }; }
-  fi
-  case $CONFIG_SHELL in
-  '')
-    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for as_base in sh bash ksh sh5; do
-        case $as_dir in
-        /*)
-          if ("$as_dir/$as_base" -c '
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
-            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
-            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
-            CONFIG_SHELL=$as_dir/$as_base
-            export CONFIG_SHELL
-            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
-          fi;;
-        esac
-       done
-done
-;;
-  esac
-
-  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
-  # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line before each line; the second 'sed' does the real
-  # work.  The second script uses 'N' to pair each line-number line
-  # with the numbered line, and appends trailing '-' during
-  # substitution so that $LINENO is not a special case at line end.
-  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
-  sed '=' <$as_myself |
-    sed '
-      N
-      s,$,-,
-      : loop
-      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
-      t loop
-      s,-$,,
-      s,^['$as_cr_digits']*\n,,
-    ' >$as_me.lineno &&
-  chmod +x $as_me.lineno ||
-    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
-   { (exit 1); exit 1; }; }
-
-  # Don't try to exec as it changes $[0], causing all sort of problems
-  # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensible to this).
-  . ./$as_me.lineno
-  # Exit status is that of the last command.
-  exit
-}
-
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
-  *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T='     ' ;;
-  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
-  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
-  # We could just check for DJGPP; but this test a) works b) is more generic
-  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
-  if test -f conf$$.exe; then
-    # Don't use ln at all; we don't have any links
-    as_ln_s='cp -p'
-  else
-    as_ln_s='ln -s'
-  fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s=ln
-else
-  as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.file
-
-if mkdir -p . 2>/dev/null; then
-  as_mkdir_p=:
-else
-  test -d ./-p && rmdir ./-p
-  as_mkdir_p=false
-fi
-
-as_executable_p="test -f"
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS="  $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
-
-# Name of the host.
-# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
-# so uname gets run too.
-ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
-
-exec 6>&1
-
-#
-# Initializations.
-#
-ac_default_prefix=/usr/local
-ac_config_libobj_dir=.
-cross_compiling=no
-subdirs=
-MFLAGS=
-MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-# Maximum number of lines to put in a shell here document.
-# This variable seems obsolete.  It should probably be removed, and
-# only ac_max_sed_lines should be used.
-: ${ac_max_here_lines=38}
-
-# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-
-ac_unique_file="rlm_eap_mschapv2.c"
-# Factoring default headers for most tests.
-ac_includes_default="\
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#if HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-#if STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# if HAVE_STDLIB_H
-#  include <stdlib.h>
-# endif
-#endif
-#if HAVE_STRING_H
-# if !STDC_HEADERS && HAVE_MEMORY_H
-#  include <memory.h>
-# endif
-# include <string.h>
-#endif
-#if HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#else
-# if HAVE_STDINT_H
-#  include <stdint.h>
-# endif
-#endif
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif"
-
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP eap_mschapv2_cflags eap_mschapv2_ldflags targetname LIBOBJS LTLIBOBJS'
-ac_subst_files=''
-
-# Initialize some variables set by options.
-ac_init_help=
-ac_init_version=false
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-cache_file=/dev/null
-exec_prefix=NONE
-no_create=
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-verbose=
-x_includes=NONE
-x_libraries=NONE
-
-# Installation directory options.
-# These are left unexpanded so users can "make install exec_prefix=/foo"
-# and all the variables that are supposed to be based on exec_prefix
-# by default will actually change.
-# Use braces instead of parens because sh, perl, etc. also accept them.
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-libdir='${exec_prefix}/lib'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-infodir='${prefix}/info'
-mandir='${prefix}/man'
-
-ac_prev=
-for ac_option
-do
-  # If the previous option needs an argument, assign it.
-  if test -n "$ac_prev"; then
-    eval "$ac_prev=\$ac_option"
-    ac_prev=
-    continue
-  fi
-
-  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
-
-  # Accept the important Cygnus configure options, so we can diagnose typos.
-
-  case $ac_option in
-
-  -bindir | --bindir | --bindi | --bind | --bin | --bi)
-    ac_prev=bindir ;;
-  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
-    bindir=$ac_optarg ;;
-
-  -build | --build | --buil | --bui | --bu)
-    ac_prev=build_alias ;;
-  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
-    build_alias=$ac_optarg ;;
-
-  -cache-file | --cache-file | --cache-fil | --cache-fi \
-  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
-    ac_prev=cache_file ;;
-  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
-  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
-    cache_file=$ac_optarg ;;
-
-  --config-cache | -C)
-    cache_file=config.cache ;;
-
-  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
-    ac_prev=datadir ;;
-  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
-  | --da=*)
-    datadir=$ac_optarg ;;
-
-  -disable-* | --disable-*)
-    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
-   { (exit 1); exit 1; }; }
-    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
-    eval "enable_$ac_feature=no" ;;
-
-  -enable-* | --enable-*)
-    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
-   { (exit 1); exit 1; }; }
-    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
-    case $ac_option in
-      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
-      *) ac_optarg=yes ;;
-    esac
-    eval "enable_$ac_feature='$ac_optarg'" ;;
-
-  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
-  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
-  | --exec | --exe | --ex)
-    ac_prev=exec_prefix ;;
-  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
-  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
-  | --exec=* | --exe=* | --ex=*)
-    exec_prefix=$ac_optarg ;;
-
-  -gas | --gas | --ga | --g)
-    # Obsolete; use --with-gas.
-    with_gas=yes ;;
-
-  -help | --help | --hel | --he | -h)
-    ac_init_help=long ;;
-  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
-    ac_init_help=recursive ;;
-  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
-    ac_init_help=short ;;
-
-  -host | --host | --hos | --ho)
-    ac_prev=host_alias ;;
-  -host=* | --host=* | --hos=* | --ho=*)
-    host_alias=$ac_optarg ;;
-
-  -includedir | --includedir | --includedi | --included | --include \
-  | --includ | --inclu | --incl | --inc)
-    ac_prev=includedir ;;
-  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
-  | --includ=* | --inclu=* | --incl=* | --inc=*)
-    includedir=$ac_optarg ;;
-
-  -infodir | --infodir | --infodi | --infod | --info | --inf)
-    ac_prev=infodir ;;
-  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
-    infodir=$ac_optarg ;;
-
-  -libdir | --libdir | --libdi | --libd)
-    ac_prev=libdir ;;
-  -libdir=* | --libdir=* | --libdi=* | --libd=*)
-    libdir=$ac_optarg ;;
-
-  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
-  | --libexe | --libex | --libe)
-    ac_prev=libexecdir ;;
-  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
-  | --libexe=* | --libex=* | --libe=*)
-    libexecdir=$ac_optarg ;;
-
-  -localstatedir | --localstatedir | --localstatedi | --localstated \
-  | --localstate | --localstat | --localsta | --localst \
-  | --locals | --local | --loca | --loc | --lo)
-    ac_prev=localstatedir ;;
-  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
-  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
-  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
-    localstatedir=$ac_optarg ;;
-
-  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
-    ac_prev=mandir ;;
-  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
-    mandir=$ac_optarg ;;
-
-  -nfp | --nfp | --nf)
-    # Obsolete; use --without-fp.
-    with_fp=no ;;
-
-  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
-  | --no-cr | --no-c | -n)
-    no_create=yes ;;
-
-  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
-  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
-    no_recursion=yes ;;
-
-  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
-  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
-  | --oldin | --oldi | --old | --ol | --o)
-    ac_prev=oldincludedir ;;
-  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
-  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
-  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
-    oldincludedir=$ac_optarg ;;
-
-  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
-    ac_prev=prefix ;;
-  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
-    prefix=$ac_optarg ;;
-
-  -program-prefix | --program-prefix | --program-prefi | --program-pref \
-  | --program-pre | --program-pr | --program-p)
-    ac_prev=program_prefix ;;
-  -program-prefix=* | --program-prefix=* | --program-prefi=* \
-  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
-    program_prefix=$ac_optarg ;;
-
-  -program-suffix | --program-suffix | --program-suffi | --program-suff \
-  | --program-suf | --program-su | --program-s)
-    ac_prev=program_suffix ;;
-  -program-suffix=* | --program-suffix=* | --program-suffi=* \
-  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
-    program_suffix=$ac_optarg ;;
-
-  -program-transform-name | --program-transform-name \
-  | --program-transform-nam | --program-transform-na \
-  | --program-transform-n | --program-transform- \
-  | --program-transform | --program-transfor \
-  | --program-transfo | --program-transf \
-  | --program-trans | --program-tran \
-  | --progr-tra | --program-tr | --program-t)
-    ac_prev=program_transform_name ;;
-  -program-transform-name=* | --program-transform-name=* \
-  | --program-transform-nam=* | --program-transform-na=* \
-  | --program-transform-n=* | --program-transform-=* \
-  | --program-transform=* | --program-transfor=* \
-  | --program-transfo=* | --program-transf=* \
-  | --program-trans=* | --program-tran=* \
-  | --progr-tra=* | --program-tr=* | --program-t=*)
-    program_transform_name=$ac_optarg ;;
-
-  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-  | -silent | --silent | --silen | --sile | --sil)
-    silent=yes ;;
-
-  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
-    ac_prev=sbindir ;;
-  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
-  | --sbi=* | --sb=*)
-    sbindir=$ac_optarg ;;
-
-  -sharedstatedir | --sharedstatedir | --sharedstatedi \
-  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
-  | --sharedst | --shareds | --shared | --share | --shar \
-  | --sha | --sh)
-    ac_prev=sharedstatedir ;;
-  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
-  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
-  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
-  | --sha=* | --sh=*)
-    sharedstatedir=$ac_optarg ;;
-
-  -site | --site | --sit)
-    ac_prev=site ;;
-  -site=* | --site=* | --sit=*)
-    site=$ac_optarg ;;
-
-  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
-    ac_prev=srcdir ;;
-  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
-    srcdir=$ac_optarg ;;
-
-  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
-  | --syscon | --sysco | --sysc | --sys | --sy)
-    ac_prev=sysconfdir ;;
-  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
-  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
-    sysconfdir=$ac_optarg ;;
-
-  -target | --target | --targe | --targ | --tar | --ta | --t)
-    ac_prev=target_alias ;;
-  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
-    target_alias=$ac_optarg ;;
-
-  -v | -verbose | --verbose | --verbos | --verbo | --verb)
-    verbose=yes ;;
-
-  -version | --version | --versio | --versi | --vers | -V)
-    ac_init_version=: ;;
-
-  -with-* | --with-*)
-    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid package name: $ac_package" >&2
-   { (exit 1); exit 1; }; }
-    ac_package=`echo $ac_package| sed 's/-/_/g'`
-    case $ac_option in
-      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
-      *) ac_optarg=yes ;;
-    esac
-    eval "with_$ac_package='$ac_optarg'" ;;
-
-  -without-* | --without-*)
-    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid package name: $ac_package" >&2
-   { (exit 1); exit 1; }; }
-    ac_package=`echo $ac_package | sed 's/-/_/g'`
-    eval "with_$ac_package=no" ;;
-
-  --x)
-    # Obsolete; use --with-x.
-    with_x=yes ;;
-
-  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
-  | --x-incl | --x-inc | --x-in | --x-i)
-    ac_prev=x_includes ;;
-  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
-  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
-    x_includes=$ac_optarg ;;
-
-  -x-libraries | --x-libraries | --x-librarie | --x-librari \
-  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
-    ac_prev=x_libraries ;;
-  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
-  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
-    x_libraries=$ac_optarg ;;
-
-  -*) { echo "$as_me: error: unrecognized option: $ac_option
-Try \`$0 --help' for more information." >&2
-   { (exit 1); exit 1; }; }
-    ;;
-
-  *=*)
-    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
-   { (exit 1); exit 1; }; }
-    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
-    eval "$ac_envvar='$ac_optarg'"
-    export $ac_envvar ;;
-
-  *)
-    # FIXME: should be removed in autoconf 3.0.
-    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
-    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
-    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
-    ;;
-
-  esac
-done
-
-if test -n "$ac_prev"; then
-  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
-  { echo "$as_me: error: missing argument to $ac_option" >&2
-   { (exit 1); exit 1; }; }
-fi
-
-# Be sure to have absolute paths.
-for ac_var in exec_prefix prefix
-do
-  eval ac_val=$`echo $ac_var`
-  case $ac_val in
-    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
-    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
-   { (exit 1); exit 1; }; };;
-  esac
-done
-
-# Be sure to have absolute paths.
-for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
-             localstatedir libdir includedir oldincludedir infodir mandir
-do
-  eval ac_val=$`echo $ac_var`
-  case $ac_val in
-    [\\/$]* | ?:[\\/]* ) ;;
-    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
-   { (exit 1); exit 1; }; };;
-  esac
-done
-
-# There might be people who depend on the old broken behavior: `$host'
-# used to hold the argument of --host etc.
-# FIXME: To remove some day.
-build=$build_alias
-host=$host_alias
-target=$target_alias
-
-# FIXME: To remove some day.
-if test "x$host_alias" != x; then
-  if test "x$build_alias" = x; then
-    cross_compiling=maybe
-    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
-    If a cross compiler is detected then cross compile mode will be used." >&2
-  elif test "x$build_alias" != "x$host_alias"; then
-    cross_compiling=yes
-  fi
-fi
-
-ac_tool_prefix=
-test -n "$host_alias" && ac_tool_prefix=$host_alias-
-
-test "$silent" = yes && exec 6>/dev/null
-
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
-  ac_srcdir_defaulted=yes
-  # Try the directory containing this script, then its parent.
-  ac_confdir=`(dirname "$0") 2>/dev/null ||
-$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$0" : 'X\(//\)[^/]' \| \
-        X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X"$0" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-         /^X\(\/\/\)$/{ s//\1/; q; }
-         /^X\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-  srcdir=$ac_confdir
-  if test ! -r $srcdir/$ac_unique_file; then
-    srcdir=..
-  fi
-else
-  ac_srcdir_defaulted=no
-fi
-if test ! -r $srcdir/$ac_unique_file; then
-  if test "$ac_srcdir_defaulted" = yes; then
-    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
-   { (exit 1); exit 1; }; }
-  else
-    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
-   { (exit 1); exit 1; }; }
-  fi
-fi
-(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
-  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
-   { (exit 1); exit 1; }; }
-srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
-ac_env_build_alias_set=${build_alias+set}
-ac_env_build_alias_value=$build_alias
-ac_cv_env_build_alias_set=${build_alias+set}
-ac_cv_env_build_alias_value=$build_alias
-ac_env_host_alias_set=${host_alias+set}
-ac_env_host_alias_value=$host_alias
-ac_cv_env_host_alias_set=${host_alias+set}
-ac_cv_env_host_alias_value=$host_alias
-ac_env_target_alias_set=${target_alias+set}
-ac_env_target_alias_value=$target_alias
-ac_cv_env_target_alias_set=${target_alias+set}
-ac_cv_env_target_alias_value=$target_alias
-ac_env_CC_set=${CC+set}
-ac_env_CC_value=$CC
-ac_cv_env_CC_set=${CC+set}
-ac_cv_env_CC_value=$CC
-ac_env_CFLAGS_set=${CFLAGS+set}
-ac_env_CFLAGS_value=$CFLAGS
-ac_cv_env_CFLAGS_set=${CFLAGS+set}
-ac_cv_env_CFLAGS_value=$CFLAGS
-ac_env_LDFLAGS_set=${LDFLAGS+set}
-ac_env_LDFLAGS_value=$LDFLAGS
-ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
-ac_cv_env_LDFLAGS_value=$LDFLAGS
-ac_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_env_CPPFLAGS_value=$CPPFLAGS
-ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_cv_env_CPPFLAGS_value=$CPPFLAGS
-ac_env_CPP_set=${CPP+set}
-ac_env_CPP_value=$CPP
-ac_cv_env_CPP_set=${CPP+set}
-ac_cv_env_CPP_value=$CPP
-
-#
-# Report the --help message.
-#
-if test "$ac_init_help" = "long"; then
-  # Omit some internal or obsolete options to make the list less imposing.
-  # This message is too long to be a string in the A/UX 3.1 sh.
-  cat <<_ACEOF
-\`configure' configures this package to adapt to many kinds of systems.
-
-Usage: $0 [OPTION]... [VAR=VALUE]...
-
-To assign environment variables (e.g., CC, CFLAGS...), specify them as
-VAR=VALUE.  See below for descriptions of some of the useful variables.
-
-Defaults for the options are specified in brackets.
-
-Configuration:
-  -h, --help              display this help and exit
-      --help=short        display options specific to this package
-      --help=recursive    display the short help of all the included packages
-  -V, --version           display version information and exit
-  -q, --quiet, --silent   do not print \`checking...' messages
-      --cache-file=FILE   cache test results in FILE [disabled]
-  -C, --config-cache      alias for \`--cache-file=config.cache'
-  -n, --no-create         do not create output files
-      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
-
-_ACEOF
-
-  cat <<_ACEOF
-Installation directories:
-  --prefix=PREFIX         install architecture-independent files in PREFIX
-                         [$ac_default_prefix]
-  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
-                         [PREFIX]
-
-By default, \`make install' will install all the files in
-\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
-an installation prefix other than \`$ac_default_prefix' using \`--prefix',
-for instance \`--prefix=\$HOME'.
-
-For better control, use the options below.
-
-Fine tuning of the installation directories:
-  --bindir=DIR           user executables [EPREFIX/bin]
-  --sbindir=DIR          system admin executables [EPREFIX/sbin]
-  --libexecdir=DIR       program executables [EPREFIX/libexec]
-  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
-  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
-  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
-  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
-  --libdir=DIR           object code libraries [EPREFIX/lib]
-  --includedir=DIR       C header files [PREFIX/include]
-  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
-  --infodir=DIR          info documentation [PREFIX/info]
-  --mandir=DIR           man documentation [PREFIX/man]
-_ACEOF
-
-  cat <<\_ACEOF
-_ACEOF
-fi
-
-if test -n "$ac_init_help"; then
-
-  cat <<\_ACEOF
-
-Some influential environment variables:
-  CC          C compiler command
-  CFLAGS      C compiler flags
-  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
-              nonstandard directory <lib dir>
-  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
-              headers in a nonstandard directory <include dir>
-  CPP         C preprocessor
-
-Use these variables to override the choices made by `configure' or to help
-it to find libraries and programs with nonstandard names/locations.
-
-_ACEOF
-fi
-
-if test "$ac_init_help" = "recursive"; then
-  # If there are subdirs, report their specific --help.
-  ac_popdir=`pwd`
-  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
-    test -d $ac_dir || continue
-    ac_builddir=.
-
-if test "$ac_dir" != .; then
-  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A "../" for each directory in $ac_dir_suffix.
-  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
-  ac_dir_suffix= ac_top_builddir=
-fi
-
-case $srcdir in
-  .)  # No --srcdir option.  We are building in place.
-    ac_srcdir=.
-    if test -z "$ac_top_builddir"; then
-       ac_top_srcdir=.
-    else
-       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
-    fi ;;
-  [\\/]* | ?:[\\/]* )  # Absolute path.
-    ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir ;;
-  *) # Relative path.
-    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
-  case "$ac_dir" in
-  .) ac_abs_builddir=`pwd`;;
-  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
-  *) ac_abs_builddir=`pwd`/"$ac_dir";;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
-  case ${ac_top_builddir}. in
-  .) ac_abs_top_builddir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
-  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
-  case $ac_srcdir in
-  .) ac_abs_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
-  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
-  case $ac_top_srcdir in
-  .) ac_abs_top_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
-  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
-  esac;;
-esac
-
-    cd $ac_dir
-    # Check for guested configure; otherwise get Cygnus style configure.
-    if test -f $ac_srcdir/configure.gnu; then
-      echo
-      $SHELL $ac_srcdir/configure.gnu  --help=recursive
-    elif test -f $ac_srcdir/configure; then
-      echo
-      $SHELL $ac_srcdir/configure  --help=recursive
-    elif test -f $ac_srcdir/configure.ac ||
-          test -f $ac_srcdir/configure.in; then
-      echo
-      $ac_configure --help
-    else
-      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
-    fi
-    cd $ac_popdir
-  done
-fi
-
-test -n "$ac_init_help" && exit 0
-if $ac_init_version; then
-  cat <<\_ACEOF
-
-Copyright (C) 2003 Free Software Foundation, Inc.
-This configure script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it.
-_ACEOF
-  exit 0
-fi
-exec 5>config.log
-cat >&5 <<_ACEOF
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-
-It was created by $as_me, which was
-generated by GNU Autoconf 2.59.  Invocation command line was
-
-  $ $0 $@
-
-_ACEOF
-{
-cat <<_ASUNAME
-## --------- ##
-## Platform. ##
-## --------- ##
-
-hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
-/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
-
-/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
-/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
-hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
-/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
-/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
-/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
-
-_ASUNAME
-
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  echo "PATH: $as_dir"
-done
-
-} >&5
-
-cat >&5 <<_ACEOF
-
-
-## ----------- ##
-## Core tests. ##
-## ----------- ##
-
-_ACEOF
-
-
-# Keep a trace of the command line.
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Strip out --silent because we don't want to record it for future runs.
-# Also quote any args containing shell meta-characters.
-# Make two passes to allow for proper duplicate-argument suppression.
-ac_configure_args=
-ac_configure_args0=
-ac_configure_args1=
-ac_sep=
-ac_must_keep_next=false
-for ac_pass in 1 2
-do
-  for ac_arg
-  do
-    case $ac_arg in
-    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
-    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-    | -silent | --silent | --silen | --sile | --sil)
-      continue ;;
-    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
-      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
-    esac
-    case $ac_pass in
-    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
-    2)
-      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
-      if test $ac_must_keep_next = true; then
-       ac_must_keep_next=false # Got value, back to normal.
-      else
-       case $ac_arg in
-         *=* | --config-cache | -C | -disable-* | --disable-* \
-         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
-         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
-         | -with-* | --with-* | -without-* | --without-* | --x)
-           case "$ac_configure_args0 " in
-             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
-           esac
-           ;;
-         -* ) ac_must_keep_next=true ;;
-       esac
-      fi
-      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
-      # Get rid of the leading space.
-      ac_sep=" "
-      ;;
-    esac
-  done
-done
-$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
-$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
-
-# When interrupted or exit'd, cleanup temporary files, and complete
-# config.log.  We remove comments because anyway the quotes in there
-# would cause problems or look ugly.
-# WARNING: Be sure not to use single quotes in there, as some shells,
-# such as our DU 5.0 friend, will then `close' the trap.
-trap 'exit_status=$?
-  # Save into config.log some information that might help in debugging.
-  {
-    echo
-
-    cat <<\_ASBOX
-## ---------------- ##
-## Cache variables. ##
-## ---------------- ##
-_ASBOX
-    echo
-    # The following way of writing the cache mishandles newlines in values,
-{
-  (set) 2>&1 |
-    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
-    *ac_space=\ *)
-      sed -n \
-       "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
-         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
-      ;;
-    *)
-      sed -n \
-       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
-      ;;
-    esac;
-}
-    echo
-
-    cat <<\_ASBOX
-## ----------------- ##
-## Output variables. ##
-## ----------------- ##
-_ASBOX
-    echo
-    for ac_var in $ac_subst_vars
-    do
-      eval ac_val=$`echo $ac_var`
-      echo "$ac_var='"'"'$ac_val'"'"'"
-    done | sort
-    echo
-
-    if test -n "$ac_subst_files"; then
-      cat <<\_ASBOX
-## ------------- ##
-## Output files. ##
-## ------------- ##
-_ASBOX
-      echo
-      for ac_var in $ac_subst_files
-      do
-       eval ac_val=$`echo $ac_var`
-       echo "$ac_var='"'"'$ac_val'"'"'"
-      done | sort
-      echo
-    fi
-
-    if test -s confdefs.h; then
-      cat <<\_ASBOX
-## ----------- ##
-## confdefs.h. ##
-## ----------- ##
-_ASBOX
-      echo
-      sed "/^$/d" confdefs.h | sort
-      echo
-    fi
-    test "$ac_signal" != 0 &&
-      echo "$as_me: caught signal $ac_signal"
-    echo "$as_me: exit $exit_status"
-  } >&5
-  rm -f core *.core &&
-  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
-    exit $exit_status
-     ' 0
-for ac_signal in 1 2 13 15; do
-  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
-done
-ac_signal=0
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo >confdefs.h
-
-# Predefined preprocessor variables.
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
-
-
-# Let the site file select an alternate cache file if it wants to.
-# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
-  if test "x$prefix" != xNONE; then
-    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
-  else
-    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
-  fi
-fi
-for ac_site_file in $CONFIG_SITE; do
-  if test -r "$ac_site_file"; then
-    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
-echo "$as_me: loading site script $ac_site_file" >&6;}
-    sed 's/^/| /' "$ac_site_file" >&5
-    . "$ac_site_file"
-  fi
-done
-
-if test -r "$cache_file"; then
-  # Some versions of bash will fail to source /dev/null (special
-  # files actually), so we avoid doing that.
-  if test -f "$cache_file"; then
-    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
-echo "$as_me: loading cache $cache_file" >&6;}
-    case $cache_file in
-      [\\/]* | ?:[\\/]* ) . $cache_file;;
-      *)                      . ./$cache_file;;
-    esac
-  fi
-else
-  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
-echo "$as_me: creating cache $cache_file" >&6;}
-  >$cache_file
-fi
-
-# Check that the precious variables saved in the cache have kept the same
-# value.
-ac_cache_corrupted=false
-for ac_var in `(set) 2>&1 |
-              sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
-  eval ac_old_set=\$ac_cv_env_${ac_var}_set
-  eval ac_new_set=\$ac_env_${ac_var}_set
-  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
-  eval ac_new_val="\$ac_env_${ac_var}_value"
-  case $ac_old_set,$ac_new_set in
-    set,)
-      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
-      ac_cache_corrupted=: ;;
-    ,set)
-      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
-      ac_cache_corrupted=: ;;
-    ,);;
-    *)
-      if test "x$ac_old_val" != "x$ac_new_val"; then
-       { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
-echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
-       { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
-echo "$as_me:   former value:  $ac_old_val" >&2;}
-       { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
-echo "$as_me:   current value: $ac_new_val" >&2;}
-       ac_cache_corrupted=:
-      fi;;
-  esac
-  # Pass precious variables to config.status.
-  if test "$ac_new_set" = set; then
-    case $ac_new_val in
-    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
-      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
-    *) ac_arg=$ac_var=$ac_new_val ;;
-    esac
-    case " $ac_configure_args " in
-      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
-      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
-    esac
-  fi
-done
-if $ac_cache_corrupted; then
-  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
-echo "$as_me: error: changes in the environment can compromise the build" >&2;}
-  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
-echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-if test x$with_rlm_eap_mschapv2 != xno; then
-
-       ## We may need more complex checking here.  Assume for now that
-       ## everyone has it.
-       ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}gcc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_CC"; then
-  ac_ct_CC=$CC
-  # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="gcc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  CC=$ac_ct_CC
-else
-  CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
-  if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_CC"; then
-  ac_ct_CC=$CC
-  # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  CC=$ac_ct_CC
-else
-  CC="$ac_cv_prog_CC"
-fi
-
-fi
-if test -z "$CC"; then
-  # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-  ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
-       ac_prog_rejected=yes
-       continue
-     fi
-    ac_cv_prog_CC="cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-if test $ac_prog_rejected = yes; then
-  # We found a bogon in the path, so make sure we never use it.
-  set dummy $ac_cv_prog_CC
-  shift
-  if test $# != 0; then
-    # We chose a different compiler from the bogus one.
-    # However, it has the same basename, so the bogon will be chosen
-    # first if we set CC to just the basename; use the full file name.
-    shift
-    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
-  fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$CC"; then
-  if test -n "$ac_tool_prefix"; then
-  for ac_prog in cl
-  do
-    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-    test -n "$CC" && break
-  done
-fi
-if test -z "$CC"; then
-  ac_ct_CC=$CC
-  for ac_prog in cl
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  test -n "$ac_ct_CC" && break
-done
-
-  CC=$ac_ct_CC
-fi
-
-fi
-
-
-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-
-# Provide some information about the compiler.
-echo "$as_me:$LINENO:" \
-     "checking for C compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
-  (eval $ac_compiler --version </dev/null >&5) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
-  (eval $ac_compiler -v </dev/null >&5) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
-  (eval $ac_compiler -V </dev/null >&5) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.exe b.out"
-# Try to create an executable without -o first, disregard a.out.
-# It will help us diagnose broken compilers, and finding out an intuition
-# of exeext.
-echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
-echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
-ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
-  (eval $ac_link_default) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  # Find the output, starting from the most likely.  This scheme is
-# not robust to junk in `.', hence go to wildcards (a.*) only as a last
-# resort.
-
-# Be careful to initialize this variable, since it used to be cached.
-# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
-ac_cv_exeext=
-# b.out is created by i960 compilers.
-for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
-do
-  test -f "$ac_file" || continue
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
-       ;;
-    conftest.$ac_ext )
-       # This is the source file.
-       ;;
-    [ab].out )
-       # We found the default executable, but exeext='' is most
-       # certainly right.
-       break;;
-    *.* )
-       ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-       # FIXME: I believe we export ac_cv_exeext for Libtool,
-       # but it would be cool to find out if it's true.  Does anybody
-       # maintain Libtool? --akim.
-       export ac_cv_exeext
-       break;;
-    * )
-       break;;
-  esac
-done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
-See \`config.log' for more details." >&5
-echo "$as_me: error: C compiler cannot create executables
-See \`config.log' for more details." >&2;}
-   { (exit 77); exit 77; }; }
-fi
-
-ac_exeext=$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6
-
-# Check the compiler produces executables we can run.  If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether the C compiler works" >&5
-echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
-# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
-  if { ac_try='./$ac_file'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-    cross_compiling=no
-  else
-    if test "$cross_compiling" = maybe; then
-       cross_compiling=yes
-    else
-       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-    fi
-  fi
-fi
-echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
-
-rm -f a.out a.exe conftest$ac_cv_exeext b.out
-ac_clean_files=$ac_clean_files_save
-# Check the compiler produces executables we can run.  If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
-echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
-echo "$as_me:$LINENO: result: $cross_compiling" >&5
-echo "${ECHO_T}$cross_compiling" >&6
-
-echo "$as_me:$LINENO: checking for suffix of executables" >&5
-echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  # If both `conftest.exe' and `conftest' are `present' (well, observable)
-# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
-# work properly (i.e., refer to `conftest.exe'), while it won't with
-# `rm'.
-for ac_file in conftest.exe conftest conftest.*; do
-  test -f "$ac_file" || continue
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
-    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-         export ac_cv_exeext
-         break;;
-    * ) break;;
-  esac
-done
-else
-  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
-echo "${ECHO_T}$ac_cv_exeext" >&6
-
-rm -f conftest.$ac_ext
-EXEEXT=$ac_cv_exeext
-ac_exeext=$EXEEXT
-echo "$as_me:$LINENO: checking for suffix of object files" >&5
-echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
-if test "${ac_cv_objext+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.o conftest.obj
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
-    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
-       break;;
-  esac
-done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest.$ac_cv_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
-echo "${ECHO_T}$ac_cv_objext" >&6
-OBJEXT=$ac_cv_objext
-ac_objext=$OBJEXT
-echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-#ifndef __GNUC__
-       choke me
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_compiler_gnu=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_compiler_gnu=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
-fi
-echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
-GCC=`test $ac_compiler_gnu = yes && echo yes`
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-CFLAGS="-g"
-echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_g+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_prog_cc_g=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_prog_cc_g=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
-if test "$ac_test_CFLAGS" = set; then
-  CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
-  if test "$GCC" = yes; then
-    CFLAGS="-g -O2"
-  else
-    CFLAGS="-g"
-  fi
-else
-  if test "$GCC" = yes; then
-    CFLAGS="-O2"
-  else
-    CFLAGS=
-  fi
-fi
-echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
-echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_stdc+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_prog_cc_stdc=no
-ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
-     char **p;
-     int i;
-{
-  return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
-  char *s;
-  va_list v;
-  va_start (v,p);
-  s = g (p, va_arg (v,int));
-  va_end (v);
-  return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
-   function prototypes and stuff, but not '\xHH' hex character constants.
-   These don't provoke an error unfortunately, instead are silently treated
-   as 'x'.  The following induces an error, until -std1 is added to get
-   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
-   array size at least.  It's necessary to write '\x00'==0 to get something
-   that's true only with -std1.  */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
-
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
-  ;
-  return 0;
-}
-_ACEOF
-# Don't try gcc -ansi; that turns off useful extensions and
-# breaks some systems' header files.
-# AIX                  -qlanglvl=ansi
-# Ultrix and OSF/1     -std1
-# HP-UX 10.20 and later        -Ae
-# HP-UX older versions -Aa -D_HPUX_SOURCE
-# SVR4                 -Xc -D__EXTENSIONS__
-for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
-  CC="$ac_save_CC $ac_arg"
-  rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_prog_cc_stdc=$ac_arg
-break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext
-done
-rm -f conftest.$ac_ext conftest.$ac_objext
-CC=$ac_save_CC
-
-fi
-
-case "x$ac_cv_prog_cc_stdc" in
-  x|xno)
-    echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6 ;;
-  *)
-    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
-    CC="$CC $ac_cv_prog_cc_stdc" ;;
-esac
-
-# Some people use a C++ compiler to compile C.  Since we use `exit',
-# in C++ we need to declare it.  In case someone uses the same compiler
-# for both compiling C and C++ we need to have the C++ compiler decide
-# the declaration of exit, since it's the most demanding environment.
-cat >conftest.$ac_ext <<_ACEOF
-#ifndef __cplusplus
-  choke me
-#endif
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  for ac_declaration in \
-   '' \
-   'extern "C" void std::exit (int) throw (); using std::exit;' \
-   'extern "C" void std::exit (int); using std::exit;' \
-   'extern "C" void exit (int) throw ();' \
-   'extern "C" void exit (int);' \
-   'void exit (int);'
-do
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_declaration
-#include <stdlib.h>
-int
-main ()
-{
-exit (42);
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-continue
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_declaration
-int
-main ()
-{
-exit (42);
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-rm -f conftest*
-if test -n "$ac_declaration"; then
-  echo '#ifdef __cplusplus' >>confdefs.h
-  echo $ac_declaration      >>confdefs.h
-  echo '#endif'             >>confdefs.h
-fi
-
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
-echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
-  CPP=
-fi
-if test -z "$CPP"; then
-  if test "${ac_cv_prog_CPP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-      # Double quotes because CPP needs to be expanded
-    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
-    do
-      ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-                    Syntax error
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether non-existent headers
-  # can be detected and how.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  # Broken: success on invalid input.
-continue
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
-  break
-fi
-
-    done
-    ac_cv_prog_CPP=$CPP
-
-fi
-  CPP=$ac_cv_prog_CPP
-else
-  ac_cv_prog_CPP=$CPP
-fi
-echo "$as_me:$LINENO: result: $CPP" >&5
-echo "${ECHO_T}$CPP" >&6
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-                    Syntax error
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether non-existent headers
-  # can be detected and how.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  # Broken: success on invalid input.
-continue
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
-  :
-else
-  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&5
-echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-echo "$as_me:$LINENO: checking for egrep" >&5
-echo $ECHO_N "checking for egrep... $ECHO_C" >&6
-if test "${ac_cv_prog_egrep+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if echo a | (grep -E '(a|b)') >/dev/null 2>&1
-    then ac_cv_prog_egrep='grep -E'
-    else ac_cv_prog_egrep='egrep'
-    fi
-fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
-echo "${ECHO_T}$ac_cv_prog_egrep" >&6
- EGREP=$ac_cv_prog_egrep
-
-
-echo "$as_me:$LINENO: checking for ANSI C header files" >&5
-echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
-if test "${ac_cv_header_stdc+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_header_stdc=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_header_stdc=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
-  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "memchr" >/dev/null 2>&1; then
-  :
-else
-  ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
-  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  $EGREP "free" >/dev/null 2>&1; then
-  :
-else
-  ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
-  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
-  if test "$cross_compiling" = yes; then
-  :
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ctype.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
-                  (('a' <= (c) && (c) <= 'i') \
-                    || ('j' <= (c) && (c) <= 'r') \
-                    || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
-  int i;
-  for (i = 0; i < 256; i++)
-    if (XOR (islower (i), ISLOWER (i))
-       || toupper (i) != TOUPPER (i))
-      exit(2);
-  exit (0);
-}
-_ACEOF
-rm -f conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  :
-else
-  echo "$as_me: program exited with status $ac_status" >&5
-echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-( exit $ac_status )
-ac_cv_header_stdc=no
-fi
-rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-fi
-fi
-fi
-echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
-echo "${ECHO_T}$ac_cv_header_stdc" >&6
-if test $ac_cv_header_stdc = yes; then
-
-cat >>confdefs.h <<\_ACEOF
-#define STDC_HEADERS 1
-_ACEOF
-
-fi
-
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-
-
-
-
-
-
-
-
-
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
-                 inttypes.h stdint.h unistd.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  eval "$as_ac_Header=yes"
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-eval "$as_ac_Header=no"
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-
-for ac_header in malloc.h
-do
-as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
-  echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-else
-  # Is the header compilable?
-echo "$as_me:$LINENO: checking $ac_header usability" >&5
-echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_includes_default
-#include <$ac_header>
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_header_compiler=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_header_compiler=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
-echo "${ECHO_T}$ac_header_compiler" >&6
-
-# Is the header present?
-echo "$as_me:$LINENO: checking $ac_header presence" >&5
-echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <$ac_header>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  ac_header_preproc=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  ac_header_preproc=no
-fi
-rm -f conftest.err conftest.$ac_ext
-echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
-echo "${ECHO_T}$ac_header_preproc" >&6
-
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
-  yes:no: )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
-echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
-    ac_header_preproc=yes
-    ;;
-  no:yes:* )
-    { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
-echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
-echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
-echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
-echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
-echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
-    { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
-echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
-    (
-      cat <<\_ASBOX
-## ------------------------------------------ ##
-## Report this to the AC_PACKAGE_NAME lists.  ##
-## ------------------------------------------ ##
-_ASBOX
-    ) |
-      sed "s/^/$as_me: WARNING:     /" >&2
-    ;;
-esac
-echo "$as_me:$LINENO: checking for $ac_header" >&5
-echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
-if eval "test \"\${$as_ac_Header+set}\" = set"; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  eval "$as_ac_Header=\$ac_header_preproc"
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
-
-fi
-if test `eval echo '${'$as_ac_Header'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-       targetname=rlm_eap_mschapv2     # keep this!  Don't change!
-else
-       targetname=            # keep this!  Don't change!
-       echo \*\*\* module rlm_eap_mschapv2 is disabled.  # keep this!  Don't change!
-fi
-
-if test x"$fail" != x""; then
-       if test x"${enable_strict_dependencies}" = x"yes"; then
-               { { echo "$as_me:$LINENO: error: set --without-rlm_eap_mschapv2 to disable it explicitly." >&5
-echo "$as_me: error: set --without-rlm_eap_mschapv2 to disable it explicitly." >&2;}
-   { (exit 1); exit 1; }; }
-       else
-               { echo "$as_me:$LINENO: WARNING: silently not building rlm_eap_mschapv2." >&5
-echo "$as_me: WARNING: silently not building rlm_eap_mschapv2." >&2;}
-               { echo "$as_me:$LINENO: WARNING: FAILURE: rlm_eap_mschapv2 requires: $fail." >&5
-echo "$as_me: WARNING: FAILURE: rlm_eap_mschapv2 requires: $fail." >&2;};
-               targetname=""
-       fi
-fi
-
-
-
-
-
-  # keep this!  Don't change!
-          ac_config_files="$ac_config_files Makefile"
-cat >confcache <<\_ACEOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs, see configure's option --config-cache.
-# It is not useful on other systems.  If it contains results you don't
-# want to keep, you may remove or edit it.
-#
-# config.status only pays attention to the cache file if you give it
-# the --recheck option to rerun configure.
-#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
-# following values.
-
-_ACEOF
-
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-{
-  (set) 2>&1 |
-    case `(ac_space=' '; set | grep ac_space) 2>&1` in
-    *ac_space=\ *)
-      # `set' does not quote correctly, so add quotes (double-quote
-      # substitution turns \\\\ into \\, and sed turns \\ into \).
-      sed -n \
-       "s/'/'\\\\''/g;
-         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
-      ;;
-    *)
-      # `set' quotes correctly as required by POSIX, so do not add quotes.
-      sed -n \
-       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
-      ;;
-    esac;
-} |
-  sed '
-     t clear
-     : clear
-     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
-     t end
-     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
-     : end' >>confcache
-if diff $cache_file confcache >/dev/null 2>&1; then :; else
-  if test -w $cache_file; then
-    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
-    cat confcache >$cache_file
-  else
-    echo "not updating unwritable cache $cache_file"
-  fi
-fi
-rm -f confcache
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
-# trailing colons and then remove the whole line if VPATH becomes empty
-# (actually we leave an empty line to preserve line numbers).
-if test "x$srcdir" = x.; then
-  ac_vpsub='/^[         ]*VPATH[        ]*=/{
-s/:*\$(srcdir):*/:/;
-s/:*\${srcdir}:*/:/;
-s/:*@srcdir@:*/:/;
-s/^\([^=]*=[    ]*\):*/\1/;
-s/:*$//;
-s/^[^=]*=[      ]*$//;
-}'
-fi
-
-# Transform confdefs.h into DEFS.
-# Protect against shell expansion while executing Makefile rules.
-# Protect against Makefile macro expansion.
-#
-# If the first sed substitution is executed (which looks for macros that
-# take arguments), then we branch to the quote section.  Otherwise,
-# look for a macro that doesn't take arguments.
-cat >confdef2opt.sed <<\_ACEOF
-t clear
-: clear
-s,^[    ]*#[    ]*define[       ][      ]*\([^  (][^    (]*([^)]*)\)[   ]*\(.*\),-D\1=\2,g
-t quote
-s,^[    ]*#[    ]*define[       ][      ]*\([^  ][^     ]*\)[   ]*\(.*\),-D\1=\2,g
-t quote
-d
-: quote
-s,[     `~#$^&*(){}\\|;'"<>?],\\&,g
-s,\[,\\&,g
-s,\],\\&,g
-s,\$,$$,g
-p
-_ACEOF
-# We use echo to avoid assuming a particular line-breaking character.
-# The extra dot is to prevent the shell from consuming trailing
-# line-breaks from the sub-command output.  A line-break within
-# single-quotes doesn't work because, if this script is created in a
-# platform that uses two characters for line-breaks (e.g., DOS), tr
-# would break.
-ac_LF_and_DOT=`echo; echo .`
-DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
-rm -f confdef2opt.sed
-
-
-ac_libobjs=
-ac_ltlibobjs=
-for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
-  # 1. Remove the extension, and $U if already installed.
-  ac_i=`echo "$ac_i" |
-        sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
-  # 2. Add them.
-  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
-  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
-done
-LIBOBJS=$ac_libobjs
-
-LTLIBOBJS=$ac_ltlibobjs
-
-
-
-: ${CONFIG_STATUS=./config.status}
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
-echo "$as_me: creating $CONFIG_STATUS" >&6;}
-cat >$CONFIG_STATUS <<_ACEOF
-#! $SHELL
-# Generated by $as_me.
-# Run this file to recreate the current configuration.
-# Compiler output produced by configure, useful for debugging
-# configure, is in config.log if it exists.
-
-debug=false
-ac_cs_recheck=false
-ac_cs_silent=false
-SHELL=\${CONFIG_SHELL-$SHELL}
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-## --------------------- ##
-## M4sh Initialization.  ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
-  set -o posix
-fi
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
-  as_unset=unset
-else
-  as_unset=false
-fi
-
-
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
-  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
-  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
-  LC_TELEPHONE LC_TIME
-do
-  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
-    eval $as_var=C; export $as_var
-  else
-    $as_unset $as_var
-  fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
-  as_basename=basename
-else
-  as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
-        X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)$' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
-         /^X\/\(\/\/\)$/{ s//\1/; q; }
-         /^X\/\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-
-
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
-fi
-
-
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
-  # Find who we are.  Look in the path if we contain no path at all
-  # relative or not.
-  case $0 in
-    *[\\/]* ) as_myself=$0 ;;
-    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
-       ;;
-  esac
-  # We did not find ourselves, most probably we were run as `sh COMMAND'
-  # in which case we are not to be found in the path.
-  if test "x$as_myself" = x; then
-    as_myself=$0
-  fi
-  if test ! -f "$as_myself"; then
-    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
-echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
-   { (exit 1); exit 1; }; }
-  fi
-  case $CONFIG_SHELL in
-  '')
-    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for as_base in sh bash ksh sh5; do
-        case $as_dir in
-        /*)
-          if ("$as_dir/$as_base" -c '
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
-            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
-            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
-            CONFIG_SHELL=$as_dir/$as_base
-            export CONFIG_SHELL
-            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
-          fi;;
-        esac
-       done
-done
-;;
-  esac
-
-  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
-  # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line before each line; the second 'sed' does the real
-  # work.  The second script uses 'N' to pair each line-number line
-  # with the numbered line, and appends trailing '-' during
-  # substitution so that $LINENO is not a special case at line end.
-  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
-  sed '=' <$as_myself |
-    sed '
-      N
-      s,$,-,
-      : loop
-      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
-      t loop
-      s,-$,,
-      s,^['$as_cr_digits']*\n,,
-    ' >$as_me.lineno &&
-  chmod +x $as_me.lineno ||
-    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
-echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
-   { (exit 1); exit 1; }; }
-
-  # Don't try to exec as it changes $[0], causing all sort of problems
-  # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensible to this).
-  . ./$as_me.lineno
-  # Exit status is that of the last command.
-  exit
-}
-
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
-  *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T='     ' ;;
-  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
-  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
-  # We could just check for DJGPP; but this test a) works b) is more generic
-  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
-  if test -f conf$$.exe; then
-    # Don't use ln at all; we don't have any links
-    as_ln_s='cp -p'
-  else
-    as_ln_s='ln -s'
-  fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s=ln
-else
-  as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.file
-
-if mkdir -p . 2>/dev/null; then
-  as_mkdir_p=:
-else
-  test -d ./-p && rmdir ./-p
-  as_mkdir_p=false
-fi
-
-as_executable_p="test -f"
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS="  $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
-exec 6>&1
-
-# Open the log real soon, to keep \$[0] and so on meaningful, and to
-# report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling.  Logging --version etc. is OK.
-exec 5>>config.log
-{
-  echo
-  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
-} >&5
-cat >&5 <<_CSEOF
-
-This file was extended by $as_me, which was
-generated by GNU Autoconf 2.59.  Invocation command line was
-
-  CONFIG_FILES    = $CONFIG_FILES
-  CONFIG_HEADERS  = $CONFIG_HEADERS
-  CONFIG_LINKS    = $CONFIG_LINKS
-  CONFIG_COMMANDS = $CONFIG_COMMANDS
-  $ $0 $@
-
-_CSEOF
-echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
-echo >&5
-_ACEOF
-
-# Files that config.status was made for.
-if test -n "$ac_config_files"; then
-  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_headers"; then
-  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_links"; then
-  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_commands"; then
-  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
-fi
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-ac_cs_usage="\
-\`$as_me' instantiates files from templates according to the
-current configuration.
-
-Usage: $0 [OPTIONS] [FILE]...
-
-  -h, --help       print this help, then exit
-  -V, --version    print version number, then exit
-  -q, --quiet      do not print progress messages
-  -d, --debug      don't remove temporary files
-      --recheck    update $as_me by reconfiguring in the same conditions
-  --file=FILE[:TEMPLATE]
-                  instantiate the configuration file FILE
-
-Configuration files:
-$config_files
-
-Report bugs to <bug-autoconf@gnu.org>."
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-ac_cs_version="\\
-config.status
-configured by $0, generated by GNU Autoconf 2.59,
-  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
-
-Copyright (C) 2003 Free Software Foundation, Inc.
-This config.status script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it."
-srcdir=$srcdir
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-# If no file are specified by the user, then we need to provide default
-# value.  By we need to know if files were specified by the user.
-ac_need_defaults=:
-while test $# != 0
-do
-  case $1 in
-  --*=*)
-    ac_option=`expr "x$1" : 'x\([^=]*\)='`
-    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
-    ac_shift=:
-    ;;
-  -*)
-    ac_option=$1
-    ac_optarg=$2
-    ac_shift=shift
-    ;;
-  *) # This is not an option, so the user has probably given explicit
-     # arguments.
-     ac_option=$1
-     ac_need_defaults=false;;
-  esac
-
-  case $ac_option in
-  # Handling of the options.
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
-    ac_cs_recheck=: ;;
-  --version | --vers* | -V )
-    echo "$ac_cs_version"; exit 0 ;;
-  --he | --h)
-    # Conflict between --help and --header
-    { { echo "$as_me:$LINENO: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&2;}
-   { (exit 1); exit 1; }; };;
-  --help | --hel | -h )
-    echo "$ac_cs_usage"; exit 0 ;;
-  --debug | --d* | -d )
-    debug=: ;;
-  --file | --fil | --fi | --f )
-    $ac_shift
-    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
-    ac_need_defaults=false;;
-  --header | --heade | --head | --hea )
-    $ac_shift
-    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
-    ac_need_defaults=false;;
-  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-  | -silent | --silent | --silen | --sile | --sil | --si | --s)
-    ac_cs_silent=: ;;
-
-  # This is an error.
-  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2;}
-   { (exit 1); exit 1; }; } ;;
-
-  *) ac_config_targets="$ac_config_targets $1" ;;
-
-  esac
-  shift
-done
-
-ac_configure_extra_args=
-
-if $ac_cs_silent; then
-  exec 6>/dev/null
-  ac_configure_extra_args="$ac_configure_extra_args --silent"
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-if \$ac_cs_recheck; then
-  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
-  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
-fi
-
-_ACEOF
-
-
-
-
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_config_target in $ac_config_targets
-do
-  case "$ac_config_target" in
-  # Handling of arguments.
-  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
-  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
-echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
-   { (exit 1); exit 1; }; };;
-  esac
-done
-
-# If the user did not use the arguments to specify the items to instantiate,
-# then the envvar interface is used.  Set only those that are not.
-# We use the long form for the default assignment because of an extremely
-# bizarre bug on SunOS 4.1.3.
-if $ac_need_defaults; then
-  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
-fi
-
-# Have a temporary directory for convenience.  Make it in the build tree
-# simply because there is no reason to put it here, and in addition,
-# creating and moving files from /tmp can sometimes cause problems.
-# Create a temporary directory, and hook for its removal unless debugging.
-$debug ||
-{
-  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
-  trap '{ (exit 1); exit 1; }' 1 2 13 15
-}
-
-# Create a (secure) tmp directory for tmp files.
-
-{
-  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
-  test -n "$tmp" && test -d "$tmp"
-}  ||
-{
-  tmp=./confstat$$-$RANDOM
-  (umask 077 && mkdir $tmp)
-} ||
-{
-   echo "$me: cannot create a temporary directory in ." >&2
-   { (exit 1); exit 1; }
-}
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-
-#
-# CONFIG_FILES section.
-#
-
-# No need to generate the scripts if there are no CONFIG_FILES.
-# This happens for instance when ./config.status config.h
-if test -n "\$CONFIG_FILES"; then
-  # Protect against being on the right side of a sed subst in config.status.
-  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
-   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
-s,@SHELL@,$SHELL,;t t
-s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
-s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
-s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
-s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
-s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
-s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
-s,@exec_prefix@,$exec_prefix,;t t
-s,@prefix@,$prefix,;t t
-s,@program_transform_name@,$program_transform_name,;t t
-s,@bindir@,$bindir,;t t
-s,@sbindir@,$sbindir,;t t
-s,@libexecdir@,$libexecdir,;t t
-s,@datadir@,$datadir,;t t
-s,@sysconfdir@,$sysconfdir,;t t
-s,@sharedstatedir@,$sharedstatedir,;t t
-s,@localstatedir@,$localstatedir,;t t
-s,@libdir@,$libdir,;t t
-s,@includedir@,$includedir,;t t
-s,@oldincludedir@,$oldincludedir,;t t
-s,@infodir@,$infodir,;t t
-s,@mandir@,$mandir,;t t
-s,@build_alias@,$build_alias,;t t
-s,@host_alias@,$host_alias,;t t
-s,@target_alias@,$target_alias,;t t
-s,@DEFS@,$DEFS,;t t
-s,@ECHO_C@,$ECHO_C,;t t
-s,@ECHO_N@,$ECHO_N,;t t
-s,@ECHO_T@,$ECHO_T,;t t
-s,@LIBS@,$LIBS,;t t
-s,@CC@,$CC,;t t
-s,@CFLAGS@,$CFLAGS,;t t
-s,@LDFLAGS@,$LDFLAGS,;t t
-s,@CPPFLAGS@,$CPPFLAGS,;t t
-s,@ac_ct_CC@,$ac_ct_CC,;t t
-s,@EXEEXT@,$EXEEXT,;t t
-s,@OBJEXT@,$OBJEXT,;t t
-s,@CPP@,$CPP,;t t
-s,@EGREP@,$EGREP,;t t
-s,@eap_mschapv2_cflags@,$eap_mschapv2_cflags,;t t
-s,@eap_mschapv2_ldflags@,$eap_mschapv2_ldflags,;t t
-s,@targetname@,$targetname,;t t
-s,@LIBOBJS@,$LIBOBJS,;t t
-s,@LTLIBOBJS@,$LTLIBOBJS,;t t
-CEOF
-
-_ACEOF
-
-  cat >>$CONFIG_STATUS <<\_ACEOF
-  # Split the substitutions into bite-sized pieces for seds with
-  # small command number limits, like on Digital OSF/1 and HP-UX.
-  ac_max_sed_lines=48
-  ac_sed_frag=1 # Number of current file.
-  ac_beg=1 # First line for current file.
-  ac_end=$ac_max_sed_lines # Line after last line for current file.
-  ac_more_lines=:
-  ac_sed_cmds=
-  while $ac_more_lines; do
-    if test $ac_beg -gt 1; then
-      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
-    else
-      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
-    fi
-    if test ! -s $tmp/subs.frag; then
-      ac_more_lines=false
-    else
-      # The purpose of the label and of the branching condition is to
-      # speed up the sed processing (if there are no `@' at all, there
-      # is no need to browse any of the substitutions).
-      # These are the two extra sed commands mentioned above.
-      (echo ':t
-  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
-      if test -z "$ac_sed_cmds"; then
-       ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
-      else
-       ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
-      fi
-      ac_sed_frag=`expr $ac_sed_frag + 1`
-      ac_beg=$ac_end
-      ac_end=`expr $ac_end + $ac_max_sed_lines`
-    fi
-  done
-  if test -z "$ac_sed_cmds"; then
-    ac_sed_cmds=cat
-  fi
-fi # test -n "$CONFIG_FILES"
-
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
-  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
-  case $ac_file in
-  - | *:- | *:-:* ) # input from stdin
-       cat >$tmp/stdin
-       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
-       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
-  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
-       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
-  * )   ac_file_in=$ac_file.in ;;
-  esac
-
-  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
-  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$ac_file" : 'X\(//\)[^/]' \| \
-        X"$ac_file" : 'X\(//\)$' \| \
-        X"$ac_file" : 'X\(/\)' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X"$ac_file" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-         /^X\(\/\/\)$/{ s//\1/; q; }
-         /^X\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-  { if $as_mkdir_p; then
-    mkdir -p "$ac_dir"
-  else
-    as_dir="$ac_dir"
-    as_dirs=
-    while test ! -d "$as_dir"; do
-      as_dirs="$as_dir $as_dirs"
-      as_dir=`(dirname "$as_dir") 2>/dev/null ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$as_dir" : 'X\(//\)[^/]' \| \
-        X"$as_dir" : 'X\(//\)$' \| \
-        X"$as_dir" : 'X\(/\)' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X"$as_dir" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-         /^X\(\/\/\)$/{ s//\1/; q; }
-         /^X\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-    done
-    test ! -n "$as_dirs" || mkdir $as_dirs
-  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
-echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
-   { (exit 1); exit 1; }; }; }
-
-  ac_builddir=.
-
-if test "$ac_dir" != .; then
-  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A "../" for each directory in $ac_dir_suffix.
-  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
-  ac_dir_suffix= ac_top_builddir=
-fi
-
-case $srcdir in
-  .)  # No --srcdir option.  We are building in place.
-    ac_srcdir=.
-    if test -z "$ac_top_builddir"; then
-       ac_top_srcdir=.
-    else
-       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
-    fi ;;
-  [\\/]* | ?:[\\/]* )  # Absolute path.
-    ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir ;;
-  *) # Relative path.
-    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
-  case "$ac_dir" in
-  .) ac_abs_builddir=`pwd`;;
-  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
-  *) ac_abs_builddir=`pwd`/"$ac_dir";;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
-  case ${ac_top_builddir}. in
-  .) ac_abs_top_builddir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
-  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
-  case $ac_srcdir in
-  .) ac_abs_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
-  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
-  case $ac_top_srcdir in
-  .) ac_abs_top_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
-  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
-  esac;;
-esac
-
-
-
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
-  # Let's still pretend it is `configure' which instantiates (i.e., don't
-  # use $as_me), people would be surprised to read:
-  #    /* config.h.  Generated by config.status.  */
-  if test x"$ac_file" = x-; then
-    configure_input=
-  else
-    configure_input="$ac_file.  "
-  fi
-  configure_input=$configure_input"Generated from `echo $ac_file_in |
-                                    sed 's,.*/,,'` by configure."
-
-  # First look for the input files in the build tree, otherwise in the
-  # src tree.
-  ac_file_inputs=`IFS=:
-    for f in $ac_file_in; do
-      case $f in
-      -) echo $tmp/stdin ;;
-      [\\/$]*)
-        # Absolute (can't be DOS-style, as IFS=:)
-        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
-   { (exit 1); exit 1; }; }
-        echo "$f";;
-      *) # Relative
-        if test -f "$f"; then
-          # Build tree
-          echo "$f"
-        elif test -f "$srcdir/$f"; then
-          # Source tree
-          echo "$srcdir/$f"
-        else
-          # /dev/null tree
-          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
-   { (exit 1); exit 1; }; }
-        fi;;
-      esac
-    done` || { (exit 1); exit 1; }
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-  sed "$ac_vpsub
-$extrasub
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-:t
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s,@configure_input@,$configure_input,;t t
-s,@srcdir@,$ac_srcdir,;t t
-s,@abs_srcdir@,$ac_abs_srcdir,;t t
-s,@top_srcdir@,$ac_top_srcdir,;t t
-s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
-s,@builddir@,$ac_builddir,;t t
-s,@abs_builddir@,$ac_abs_builddir,;t t
-s,@top_builddir@,$ac_top_builddir,;t t
-s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
-" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
-  rm -f $tmp/stdin
-  if test x"$ac_file" != x-; then
-    mv $tmp/out $ac_file
-  else
-    cat $tmp/out
-    rm -f $tmp/out
-  fi
-
-done
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-{ (exit 0); exit 0; }
-_ACEOF
-chmod +x $CONFIG_STATUS
-ac_clean_files=$ac_clean_files_save
-
-
-# configure is writing to config.log, and then calls config.status.
-# config.status does its own redirection, appending to config.log.
-# Unfortunately, on DOS this fails, as config.log is still kept open
-# by configure, so config.status won't be able to write to it; its
-# output is simply discarded.  So we exec the FD to /dev/null,
-# effectively closing config.log, so it can be properly (re)opened and
-# appended to by config.status.  When coming back to configure, we
-# need to make the FD available again.
-if test "$no_create" != yes; then
-  ac_cs_success=:
-  ac_config_status_args=
-  test "$silent" = yes &&
-    ac_config_status_args="$ac_config_status_args --quiet"
-  exec 5>/dev/null
-  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
-  exec 5>>config.log
-  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
-  # would make configure fail if this is the last instruction.
-  $ac_cs_success || { (exit 1); exit 1; }
-fi
-  # keep this!  Don't change!
diff --git a/src/modules/rlm_eap/types/rlm_eap_mschapv2/configure.in b/src/modules/rlm_eap/types/rlm_eap_mschapv2/configure.in
deleted file mode 100644 (file)
index 5a84548..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-AC_INIT(rlm_eap_mschapv2.c)
-AC_REVISION($Revision$)
-AC_DEFUN(modname,[rlm_eap_mschapv2])
-
-if test x$with_[]modname != xno; then
-
-       ## We may need more complex checking here.  Assume for now that 
-       ## everyone has it.
-       AC_CHECK_HEADERS(malloc.h)
-
-       targetname=modname     # keep this!  Don't change!
-else
-       targetname=            # keep this!  Don't change!
-       echo \*\*\* module modname is disabled.  # keep this!  Don't change!
-fi
-
-dnl  Don't change this section.
-if test x"$fail" != x""; then
-       if test x"${enable_strict_dependencies}" = x"yes"; then
-               AC_MSG_ERROR([set --without-]modname[ to disable it explicitly.])
-       else
-               AC_MSG_WARN([silently not building ]modname[.])
-               AC_MSG_WARN([FAILURE: ]modname[ requires: $fail.]); 
-               targetname=""
-       fi
-fi
-
-AC_SUBST(eap_mschapv2_cflags)
-AC_SUBST(eap_mschapv2_ldflags)
-
-dnl AC_CONFIG_HEADER(config.h)
-
-AC_SUBST(targetname)  # keep this!  Don't change!
-AC_OUTPUT(Makefile)  # keep this!  Don't change!
index abf0606..a96fb7d 100644 (file)
@@ -1,8 +1,28 @@
 #ifndef _EAP_MSCHAPV2_H
 #define _EAP_MSCHAPV2_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(eap_mschapv2_h, "$Id$")
+
 #include "eap.h"
 
+/*
+ *     draft-kamath-pppext-eap-mschapv2-00.txt says:
+ *
+ *     Supplicant              FreeRADIUS
+ *                     <--     challenge
+ *     response        -->
+ *                     <--     success
+ *     success         -->
+ *
+ *     But what we often see is:
+ *
+ *     Supplicant              FreeRADIUS
+ *                     <--     challenge
+ *     response        -->
+ *                     <--     success
+ *     ack             -->
+ */
 #define PW_EAP_MSCHAPV2_ACK            0
 #define PW_EAP_MSCHAPV2_CHALLENGE      1
 #define PW_EAP_MSCHAPV2_RESPONSE       2
index 09cb3aa..511ed84 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2003  The FreeRADIUS server project
+ * Copyright 2003,2006  The FreeRADIUS server project
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 
 #include "eap_mschapv2.h"
 
-#include <rad_assert.h>
+#include <freeradius-devel/rad_assert.h>
 
 typedef struct rlm_eap_mschapv2_t {
         int with_ntdomain_hack;
@@ -137,7 +140,7 @@ static int eapmschapv2_compose(EAP_HANDLER *handler, VALUE_PAIR *reply)
                /*
                 *      Copy the Challenge, success, or error over.
                 */
-               memcpy(ptr, reply->strvalue, reply->length);
+               memcpy(ptr, reply->vp_strvalue, reply->length);
                memcpy((ptr + reply->length), handler->identity, strlen(handler->identity));
                break;
 
@@ -170,7 +173,7 @@ static int eapmschapv2_compose(EAP_HANDLER *handler, VALUE_PAIR *reply)
                eap_ds->request->type.data[1] = eap_ds->response->id;
                length = htons(length);
                memcpy((eap_ds->request->type.data + 2), &length, sizeof(uint16_t));
-               memcpy((eap_ds->request->type.data + 4), reply->strvalue + 1, 42);
+               memcpy((eap_ds->request->type.data + 4), reply->vp_strvalue + 1, 42);
                break;
 
        case PW_MSCHAP_ERROR:
@@ -227,7 +230,7 @@ static int mschapv2_initiate(void *type_data, EAP_HANDLER *handler)
         */
        challenge->length = MSCHAPV2_CHALLENGE_LEN;
        for (i = 0; i < MSCHAPV2_CHALLENGE_LEN; i++) {
-               challenge->strvalue[i] = lrad_rand();
+               challenge->vp_strvalue[i] = lrad_rand();
        }
        radlog(L_INFO, "rlm_eap_mschapv2: Issuing Challenge");
 
@@ -241,7 +244,7 @@ static int mschapv2_initiate(void *type_data, EAP_HANDLER *handler)
         *      We're at the stage where we're challenging the user.
         */
        data->code = PW_EAP_MSCHAPV2_CHALLENGE;
-       memcpy(data->challenge, challenge->strvalue, MSCHAPV2_CHALLENGE_LEN);
+       memcpy(data->challenge, challenge->vp_strvalue, MSCHAPV2_CHALLENGE_LEN);
 
        handler->opaque = data;
        handler->free_opaque = free;
@@ -359,9 +362,6 @@ static int mschapv2_authenticate(void *arg, EAP_HANDLER *handler)
        EAP_DS *eap_ds = handler->eap_ds;
        VALUE_PAIR *challenge, *response;
 
-       /*
-        *      Get the User-Password for this user.
-        */
        rad_assert(handler->request != NULL);
        rad_assert(handler->stage == AUTHENTICATE);
 
@@ -487,7 +487,7 @@ static int mschapv2_authenticate(void *arg, EAP_HANDLER *handler)
                return 0;
        }
        challenge->length = MSCHAPV2_CHALLENGE_LEN;
-       memcpy(challenge->strvalue, data->challenge, MSCHAPV2_CHALLENGE_LEN);
+       memcpy(challenge->vp_strvalue, data->challenge, MSCHAPV2_CHALLENGE_LEN);
 
        response = pairmake("MS-CHAP2-Response", "0x00", T_OP_EQ);
        if (!response) {
@@ -496,10 +496,10 @@ static int mschapv2_authenticate(void *arg, EAP_HANDLER *handler)
        }
 
        response->length = MSCHAPV2_RESPONSE_LEN;
-       memcpy(response->strvalue + 2, &eap_ds->response->type.data[5],
+       memcpy(response->vp_strvalue + 2, &eap_ds->response->type.data[5],
               MSCHAPV2_RESPONSE_LEN - 2);
-       response->strvalue[0] = eap_ds->response->type.data[1];
-       response->strvalue[1] = eap_ds->response->type.data[5 + MSCHAPV2_RESPONSE_LEN];
+       response->vp_strvalue[0] = eap_ds->response->type.data[1];
+       response->vp_strvalue[1] = eap_ds->response->type.data[5 + MSCHAPV2_RESPONSE_LEN];
 
        /*
         *      Add the pairs to the request, and call the 'mschap'
@@ -562,17 +562,17 @@ static int mschapv2_authenticate(void *arg, EAP_HANDLER *handler)
                if (inst->with_ntdomain_hack &&
                    ((challenge = pairfind(handler->request->packet->vps,
                                           PW_USER_NAME)) != NULL) &&
-                   ((username = strchr(challenge->strvalue, '\\')) != NULL)) {
+                   ((username = strchr(challenge->vp_strvalue, '\\')) != NULL)) {
                        /*
                         *      Wipe out the NT domain.
                         *
                         *      FIXME: Put it into MS-CHAP-Domain?
                         */
                        username++; /* skip the \\ */
-                       memmove(challenge->strvalue,
+                       memmove(challenge->vp_strvalue,
                                username,
                                strlen(username) + 1); /* include \0 */
-                       challenge->length = strlen(challenge->strvalue);
+                       challenge->length = strlen(challenge->vp_strvalue);
                }
 
                /*
index c4183ab..493d850 100644 (file)
@@ -1,15 +1,16 @@
-/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
-/*
+/* config.h.in.  Generated from configure.in by autoheader.  */
 
-acconfig.h - template used by autoheader to create config.h.in
-config.h.in - used by autoconf to create config.h
-config.h - created by autoconf; contains defines generated by autoconf
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
 
-*/
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
 
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
 
-/* Define if you have the <openssl/engine.h> header file.  */
-#undef HAVE_OPENSSL_ENGINE_H
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
 
-/* Define if you have the <openssl/err.h> header file.  */
-#undef HAVE_OPENSSL_ERR_H
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
index 128afcb..240f2e2 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.2.4.1 .
+# From configure.in Revision: 1.5 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -875,7 +875,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -2069,11 +2069,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -2112,6 +2107,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 4b18748..2f5a6a7 100644 (file)
@@ -4,6 +4,7 @@
 # Version:     $Id$
 #
 
+AC_PREREQ([2.53])
 AC_INIT(rlm_eap_peap.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_eap_peap])
index 264aa36..ab4b720 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
  */
 #ifndef _EAP_PEAP_H
 #define _EAP_PEAP_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(eap_peap_h, "$Id$")
+
 #include "eap_tls.h"
 
 typedef struct peap_tunnel_t {
index 82c9f31..6e2ba77 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  *   Copyright 2003 Alan DeKok <aland@freeradius.org>
+ *   Copyright 2006 The FreeRADIUS server project
  */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include "eap_peap.h"
 
 /*
@@ -166,12 +171,12 @@ static VALUE_PAIR *eap2vp(EAP_DS *eap_ds,
        /*
         *      Hand-build an EAP packet from the crap in PEAP version 0.
         */
-       vp->strvalue[0] = PW_EAP_RESPONSE;
-       vp->strvalue[1] = eap_ds->response->id;
-       vp->strvalue[2] = 0;
-       vp->strvalue[3] = EAP_HEADER_LEN + data_len;
+       vp->vp_strvalue[0] = PW_EAP_RESPONSE;
+       vp->vp_strvalue[1] = eap_ds->response->id;
+       vp->vp_strvalue[2] = 0;
+       vp->vp_strvalue[3] = EAP_HEADER_LEN + data_len;
 
-       memcpy(vp->strvalue + EAP_HEADER_LEN, data, data_len);
+       memcpy(vp->vp_strvalue + EAP_HEADER_LEN, data, data_len);
        vp->length = EAP_HEADER_LEN + data_len;
 
        return vp;
@@ -201,7 +206,7 @@ static int vp2eap(tls_session_t *tls_session, VALUE_PAIR *vp)
                if (debug_flag > 0) for (i = 0; i < total; i++) {
                        if ((i & 0x0f) == 0) printf("  PEAP tunnel data out %04x: ", i);
 
-                       printf("%02x ", vp->strvalue[i + 4]);
+                       printf("%02x ", vp->vp_strvalue[i + 4]);
 
                        if ((i & 0x0f) == 0x0f) printf("\n");
                }
@@ -213,10 +218,10 @@ static int vp2eap(tls_session_t *tls_session, VALUE_PAIR *vp)
         *      Send the EAP data, WITHOUT the header.
         */
 #if 1
-       (tls_session->record_plus)(&tls_session->clean_in, vp->strvalue + EAP_HEADER_LEN,
+       (tls_session->record_plus)(&tls_session->clean_in, vp->vp_strvalue + EAP_HEADER_LEN,
                vp->length - EAP_HEADER_LEN);
 #else
-       (tls_session->record_plus)(&tls_session->clean_in, vp->strvalue, vp->length);
+       (tls_session->record_plus)(&tls_session->clean_in, vp->vp_strvalue, vp->length);
 #endif
        tls_handshake_send(tls_session);
 
@@ -671,10 +676,10 @@ int eappeap_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                        t->username = pairmake("User-Name", "", T_OP_EQ);
                        rad_assert(t->username != NULL);
 
-                       memcpy(t->username->strvalue, data + 1, data_len - 1);
+                       memcpy(t->username->vp_strvalue, data + 1, data_len - 1);
                        t->username->length = data_len - 1;
-                       t->username->strvalue[t->username->length] = 0;
-                       DEBUG2("  PEAP: Got tunneled identity of %s", t->username->strvalue);
+                       t->username->vp_strvalue[t->username->length] = 0;
+                       DEBUG2("  PEAP: Got tunneled identity of %s", t->username->vp_strvalue);
 
                        /*
                         *      If there's a default EAP type,
@@ -694,7 +699,7 @@ int eappeap_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                pairadd(&fake->packet->vps, vp);
                fake->username = pairfind(fake->packet->vps, PW_USER_NAME);
                DEBUG2("  PEAP: Setting User-Name to %s",
-                      fake->username->strvalue);
+                      fake->username->vp_strvalue);
        }
 
        /*
@@ -702,7 +707,7 @@ int eappeap_process(EAP_HANDLER *handler, tls_session_t *tls_session)
         */
        if (t->state) {
                DEBUG2("  PEAP: Adding old state with %02x %02x",
-                      t->state->strvalue[0], t->state->strvalue[1]);
+                      t->state->vp_strvalue[0], t->state->vp_strvalue[1]);
                vp = paircopy(t->state);
                if (vp) pairadd(&fake->packet->vps, vp);
        }
@@ -867,7 +872,7 @@ int eappeap_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                                 *      done.  Handle it like normal.
                                 */
                                if ((fake->options & RAD_REQUEST_OPTION_PROXY_EAP) == 0) {
-                                       DEBUG2("    PEAP: Cancelling proxy to realm %s until the tunneled EAP session has been established", vp->strvalue);
+                                       DEBUG2("    PEAP: Cancelling proxy to realm %s until the tunneled EAP session has been established", vp->vp_strvalue);
                                        goto do_process;
                                }
 
@@ -880,7 +885,7 @@ int eappeap_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                                           PW_EAP_MESSAGE);
                        }
 
-                       DEBUG2("  PEAP: Tunneled authentication will be proxied to %s", vp->strvalue);
+                       DEBUG2("  PEAP: Tunneled authentication will be proxied to %s", vp->vp_strvalue);
 
                        /*
                         *      Tell the original request that it's going
index 59d8b2c..5aab06a 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 #include "eap_peap.h"
 
 typedef struct rlm_eap_peap_t {
@@ -73,7 +77,6 @@ static int eappeap_detach(void *arg)
 {
        rlm_eap_peap_t *inst = (rlm_eap_peap_t *) arg;
 
-       if (inst->default_eap_type_name) free(inst->default_eap_type_name);
 
        free(inst);
 
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/AES.cpp b/src/modules/rlm_eap/types/rlm_eap_psk/AES.cpp
new file mode 100644 (file)
index 0000000..5498624
--- /dev/null
@@ -0,0 +1,572 @@
+/**\r
+ * AES.cpp\r
+ *\r
+ * The Advanced Encryption Standard (AES, aka AES) block cipher,\r
+ * designed by J. Daemen and V. Rijmen.\r
+ *\r
+ * @author Paulo S. L. M. Barreto\r
+ *\r
+ * This software is hereby placed in the public domain.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\r
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+#include <freeradius-devel/ident.h>\r
+RCSID("$Id$")\r
+\r
+#include <assert.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+#include "AES.h"\r
+#include "AES.tab"\r
+\r
+#define FULL_UNROLL\r
+\r
+#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)\r
+\r
+#ifdef _MSC_VER\r
+#define GETWORD(p) SWAP(*((uint *)(p)))\r
+#define PUTWORD(ct, st) { *((uint *)(ct)) = SWAP((st)); }\r
+#else\r
+#define GETWORD(pt) (((uint)(pt)[0] << 24) ^ ((uint)(pt)[1] << 16) ^ ((uint)(pt)[2] <<  8) ^ ((uint)(pt)[3]))\r
+#define PUTWORD(ct, st) { (ct)[0] = (byte)((st) >> 24); (ct)[1] = (byte)((st) >> 16); (ct)[2] = (byte)((st) >>  8); (ct)[3] = (byte)(st); }\r
+#endif\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// Construction/Destruction\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+AES::AES() {\r
+}\r
+\r
+AES::~AES() {\r
+       Nr = 0;\r
+       memset(e_sched, 0, sizeof(e_sched));\r
+       memset(d_sched, 0, sizeof(d_sched));\r
+}\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// Support methods\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+void AES::ExpandKey(const byte *cipherKey, uint keyBits) {\r
+    uint *rek = e_sched;\r
+       int i = 0;\r
+       uint temp;\r
+\r
+       rek[0] = GETWORD(cipherKey     );\r
+       rek[1] = GETWORD(cipherKey +  4);\r
+       rek[2] = GETWORD(cipherKey +  8);\r
+       rek[3] = GETWORD(cipherKey + 12);\r
+       if (keyBits == 128) {\r
+               for (;;) {\r
+                       temp  = rek[3];\r
+                       rek[4] = rek[0] ^\r
+                               (Te4[(temp >> 16) & 0xff] & 0xff000000) ^\r
+                               (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^\r
+                               (Te4[(temp      ) & 0xff] & 0x0000ff00) ^\r
+                               (Te4[(temp >> 24)       ] & 0x000000ff) ^\r
+                               rcon[i];\r
+                       rek[5] = rek[1] ^ rek[4];\r
+                       rek[6] = rek[2] ^ rek[5];\r
+                       rek[7] = rek[3] ^ rek[6];\r
+                       if (++i == 10) {\r
+                               Nr = 10;\r
+                               return;\r
+                       }\r
+                       rek += 4;\r
+               }\r
+       }\r
+       rek[4] = GETWORD(cipherKey + 16);\r
+       rek[5] = GETWORD(cipherKey + 20);\r
+       if (keyBits == 192) {\r
+               for (;;) {\r
+                       temp = rek[ 5];\r
+                       rek[ 6] = rek[ 0] ^\r
+                               (Te4[(temp >> 16) & 0xff] & 0xff000000) ^\r
+                               (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^\r
+                               (Te4[(temp      ) & 0xff] & 0x0000ff00) ^\r
+                               (Te4[(temp >> 24)       ] & 0x000000ff) ^\r
+                               rcon[i];\r
+                       rek[ 7] = rek[ 1] ^ rek[ 6];\r
+                       rek[ 8] = rek[ 2] ^ rek[ 7];\r
+                       rek[ 9] = rek[ 3] ^ rek[ 8];\r
+                       if (++i == 8) {\r
+                               Nr = 12;\r
+                               return;\r
+                       }\r
+                       rek[10] = rek[ 4] ^ rek[ 9];\r
+                       rek[11] = rek[ 5] ^ rek[10];\r
+                       rek += 6;\r
+               }\r
+       }\r
+       rek[6] = GETWORD(cipherKey + 24);\r
+       rek[7] = GETWORD(cipherKey + 28);\r
+       if (keyBits == 256) {\r
+        for (;;) {\r
+               temp = rek[ 7];\r
+               rek[ 8] = rek[ 0] ^\r
+                       (Te4[(temp >> 16) & 0xff] & 0xff000000) ^\r
+                       (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^\r
+                       (Te4[(temp      ) & 0xff] & 0x0000ff00) ^\r
+                       (Te4[(temp >> 24)       ] & 0x000000ff) ^\r
+                       rcon[i];\r
+               rek[ 9] = rek[ 1] ^ rek[ 8];\r
+               rek[10] = rek[ 2] ^ rek[ 9];\r
+               rek[11] = rek[ 3] ^ rek[10];\r
+                       if (++i == 7) {\r
+                               Nr = 14;\r
+                               return;\r
+                       }\r
+               temp = rek[11];\r
+               rek[12] = rek[ 4] ^\r
+                       (Te4[(temp >> 24)       ] & 0xff000000) ^\r
+                       (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^\r
+                       (Te4[(temp >>  8) & 0xff] & 0x0000ff00) ^\r
+                       (Te4[(temp      ) & 0xff] & 0x000000ff);\r
+               rek[13] = rek[ 5] ^ rek[12];\r
+               rek[14] = rek[ 6] ^ rek[13];\r
+               rek[15] = rek[ 7] ^ rek[14];\r
+\r
+                       rek += 8;\r
+        }\r
+       }\r
+       Nr = 0;\r
+}\r
+\r
+void AES::InvertKey() {\r
+    uint *rek = e_sched;\r
+    uint *rdk = d_sched;\r
+       uint r;\r
+\r
+    assert(Nr == 10 || Nr == 12 || Nr == 14);\r
+    rek += 4*Nr;\r
+       /* apply the inverse MixColumn transform to all round keys but the first and the last: */\r
+    memcpy(rdk, rek, 16);\r
+       rdk += 4;\r
+       rek -= 4;\r
+       for (r = 1; r < Nr; r++) {\r
+               rdk[0] =\r
+                       Td0[Te4[(rek[0] >> 24)       ] & 0xff] ^\r
+                       Td1[Te4[(rek[0] >> 16) & 0xff] & 0xff] ^\r
+                       Td2[Te4[(rek[0] >>  8) & 0xff] & 0xff] ^\r
+                       Td3[Te4[(rek[0]      ) & 0xff] & 0xff];\r
+               rdk[1] =\r
+                       Td0[Te4[(rek[1] >> 24)       ] & 0xff] ^\r
+                       Td1[Te4[(rek[1] >> 16) & 0xff] & 0xff] ^\r
+                       Td2[Te4[(rek[1] >>  8) & 0xff] & 0xff] ^\r
+                       Td3[Te4[(rek[1]      ) & 0xff] & 0xff];\r
+               rdk[2] =\r
+                       Td0[Te4[(rek[2] >> 24)       ] & 0xff] ^\r
+                       Td1[Te4[(rek[2] >> 16) & 0xff] & 0xff] ^\r
+                       Td2[Te4[(rek[2] >>  8) & 0xff] & 0xff] ^\r
+                       Td3[Te4[(rek[2]      ) & 0xff] & 0xff];\r
+               rdk[3] =\r
+                       Td0[Te4[(rek[3] >> 24)       ] & 0xff] ^\r
+                       Td1[Te4[(rek[3] >> 16) & 0xff] & 0xff] ^\r
+                       Td2[Te4[(rek[3] >>  8) & 0xff] & 0xff] ^\r
+                       Td3[Te4[(rek[3]      ) & 0xff] & 0xff];\r
+               rdk += 4;\r
+               rek -= 4;\r
+       }\r
+    memcpy(rdk, rek, 16);\r
+}\r
+\r
+//////////////////////////////////////////////////////////////////////\r
+// Public Interface\r
+//////////////////////////////////////////////////////////////////////\r
+\r
+void AES::makeKey(const byte *cipherKey, uint keySize, uint dir) {\r
+    switch (keySize) {\r
+    case  16: case  24: case  32:\r
+        keySize <<= 3; // key size is now in bits\r
+        break;\r
+    case 128: case 192: case 256:\r
+        break;\r
+    default:\r
+        assert(keySize == 16 || keySize == 24 || keySize == 32 || keySize == 128 || keySize == 192 || keySize == 256);\r
+    }\r
+    assert(dir >= DIR_NONE && dir <= DIR_BOTH);\r
+    if (dir != DIR_NONE) {\r
+        ExpandKey(cipherKey, keySize);\r
+           if (dir & DIR_DECRYPT) {\r
+            InvertKey();\r
+           }\r
+    }\r
+}\r
+\r
+void AES::encrypt(const byte *pt, byte *ct) {\r
+    uint *rek = e_sched;\r
+       uint s0, s1, s2, s3, t0, t1, t2, t3;\r
+#ifndef FULL_UNROLL\r
+    int r;\r
+#endif /* ?FULL_UNROLL */\r
+\r
+    /*\r
+        * map byte array block to cipher state\r
+        * and add initial round key:\r
+        */\r
+       s0 = GETWORD(pt     ) ^ rek[0];\r
+       s1 = GETWORD(pt +  4) ^ rek[1];\r
+       s2 = GETWORD(pt +  8) ^ rek[2];\r
+       s3 = GETWORD(pt + 12) ^ rek[3];\r
+#ifdef FULL_UNROLL\r
+    /* round 1: */\r
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[ 4];\r
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[ 5];\r
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[ 6];\r
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[ 7];\r
+       /* round 2: */\r
+       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rek[ 8];\r
+       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rek[ 9];\r
+       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rek[10];\r
+       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rek[11];\r
+    /* round 3: */\r
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[12];\r
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[13];\r
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[14];\r
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[15];\r
+       /* round 4: */\r
+       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rek[16];\r
+       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rek[17];\r
+       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rek[18];\r
+       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rek[19];\r
+    /* round 5: */\r
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[20];\r
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[21];\r
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[22];\r
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[23];\r
+       /* round 6: */\r
+       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rek[24];\r
+       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rek[25];\r
+       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rek[26];\r
+       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rek[27];\r
+    /* round 7: */\r
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[28];\r
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[29];\r
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[30];\r
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[31];\r
+       /* round 8: */\r
+       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rek[32];\r
+       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rek[33];\r
+       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rek[34];\r
+       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rek[35];\r
+    /* round 9: */\r
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[36];\r
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[37];\r
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[38];\r
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[39];\r
+    if (Nr > 10) {\r
+        /* round 10: */\r
+        s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rek[40];\r
+        s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rek[41];\r
+        s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rek[42];\r
+        s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rek[43];\r
+        /* round 11: */\r
+        t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[44];\r
+        t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[45];\r
+        t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[46];\r
+        t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[47];\r
+        if (Nr > 12) {\r
+            /* round 12: */\r
+            s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rek[48];\r
+            s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rek[49];\r
+            s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rek[50];\r
+            s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rek[51];\r
+            /* round 13: */\r
+            t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rek[52];\r
+            t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rek[53];\r
+            t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rek[54];\r
+            t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rek[55];\r
+        }\r
+    }\r
+    rek += Nr << 2;\r
+#else  /* !FULL_UNROLL */\r
+    /*\r
+        * Nr - 1 full rounds:\r
+        */\r
+    r = Nr >> 1;\r
+    for (;;) {\r
+        t0 =\r
+            Te0[(s0 >> 24)       ] ^\r
+            Te1[(s1 >> 16) & 0xff] ^\r
+            Te2[(s2 >>  8) & 0xff] ^\r
+            Te3[(s3      ) & 0xff] ^\r
+            rek[4];\r
+        t1 =\r
+            Te0[(s1 >> 24)       ] ^\r
+            Te1[(s2 >> 16) & 0xff] ^\r
+            Te2[(s3 >>  8) & 0xff] ^\r
+            Te3[(s0      ) & 0xff] ^\r
+            rek[5];\r
+        t2 =\r
+            Te0[(s2 >> 24)       ] ^\r
+            Te1[(s3 >> 16) & 0xff] ^\r
+            Te2[(s0 >>  8) & 0xff] ^\r
+            Te3[(s1      ) & 0xff] ^\r
+            rek[6];\r
+        t3 =\r
+            Te0[(s3 >> 24)       ] ^\r
+            Te1[(s0 >> 16) & 0xff] ^\r
+            Te2[(s1 >>  8) & 0xff] ^\r
+            Te3[(s2      ) & 0xff] ^\r
+            rek[7];\r
+\r
+        rek += 8;\r
+        if (--r == 0) {\r
+            break;\r
+        }\r
+\r
+        s0 =\r
+            Te0[(t0 >> 24)       ] ^\r
+            Te1[(t1 >> 16) & 0xff] ^\r
+            Te2[(t2 >>  8) & 0xff] ^\r
+            Te3[(t3      ) & 0xff] ^\r
+            rek[0];\r
+        s1 =\r
+            Te0[(t1 >> 24)       ] ^\r
+            Te1[(t2 >> 16) & 0xff] ^\r
+            Te2[(t3 >>  8) & 0xff] ^\r
+            Te3[(t0      ) & 0xff] ^\r
+            rek[1];\r
+        s2 =\r
+            Te0[(t2 >> 24)       ] ^\r
+            Te1[(t3 >> 16) & 0xff] ^\r
+            Te2[(t0 >>  8) & 0xff] ^\r
+            Te3[(t1      ) & 0xff] ^\r
+            rek[2];\r
+        s3 =\r
+            Te0[(t3 >> 24)       ] ^\r
+            Te1[(t0 >> 16) & 0xff] ^\r
+            Te2[(t1 >>  8) & 0xff] ^\r
+            Te3[(t2      ) & 0xff] ^\r
+            rek[3];\r
+    }\r
+#endif /* ?FULL_UNROLL */\r
+    /*\r
+        * apply last round and\r
+        * map cipher state to byte array block:\r
+        */\r
+       s0 =\r
+               (Te4[(t0 >> 24)       ] & 0xff000000) ^\r
+               (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^\r
+               (Te4[(t2 >>  8) & 0xff] & 0x0000ff00) ^\r
+               (Te4[(t3      ) & 0xff] & 0x000000ff) ^\r
+               rek[0];\r
+       PUTWORD(ct     , s0);\r
+       s1 =\r
+               (Te4[(t1 >> 24)       ] & 0xff000000) ^\r
+               (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^\r
+               (Te4[(t3 >>  8) & 0xff] & 0x0000ff00) ^\r
+               (Te4[(t0      ) & 0xff] & 0x000000ff) ^\r
+               rek[1];\r
+       PUTWORD(ct +  4, s1);\r
+       s2 =\r
+               (Te4[(t2 >> 24)       ] & 0xff000000) ^\r
+               (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^\r
+               (Te4[(t0 >>  8) & 0xff] & 0x0000ff00) ^\r
+               (Te4[(t1      ) & 0xff] & 0x000000ff) ^\r
+               rek[2];\r
+       PUTWORD(ct +  8, s2);\r
+       s3 =\r
+               (Te4[(t3 >> 24)       ] & 0xff000000) ^\r
+               (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^\r
+               (Te4[(t1 >>  8) & 0xff] & 0x0000ff00) ^\r
+               (Te4[(t2      ) & 0xff] & 0x000000ff) ^\r
+               rek[3];\r
+       PUTWORD(ct + 12, s3);\r
+}\r
+\r
+void AES::decrypt(const byte *ct, byte *pt) {\r
+    uint *rdk = d_sched;\r
+       uint s0, s1, s2, s3, t0, t1, t2, t3;\r
+#ifndef FULL_UNROLL\r
+    int r;\r
+#endif /* ?FULL_UNROLL */\r
+\r
+    /*\r
+        * map byte array block to cipher state\r
+        * and add initial round key:\r
+        */\r
+    s0 = GETWORD(ct     ) ^ rdk[0];\r
+    s1 = GETWORD(ct +  4) ^ rdk[1];\r
+    s2 = GETWORD(ct +  8) ^ rdk[2];\r
+    s3 = GETWORD(ct + 12) ^ rdk[3];\r
+#ifdef FULL_UNROLL\r
+    /* round 1: */\r
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[ 4];\r
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[ 5];\r
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[ 6];\r
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[ 7];\r
+    /* round 2: */\r
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rdk[ 8];\r
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rdk[ 9];\r
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rdk[10];\r
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rdk[11];\r
+    /* round 3: */\r
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[12];\r
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[13];\r
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[14];\r
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[15];\r
+    /* round 4: */\r
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rdk[16];\r
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rdk[17];\r
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rdk[18];\r
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rdk[19];\r
+    /* round 5: */\r
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[20];\r
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[21];\r
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[22];\r
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[23];\r
+    /* round 6: */\r
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rdk[24];\r
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rdk[25];\r
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rdk[26];\r
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rdk[27];\r
+    /* round 7: */\r
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[28];\r
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[29];\r
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[30];\r
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[31];\r
+    /* round 8: */\r
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rdk[32];\r
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rdk[33];\r
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rdk[34];\r
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rdk[35];\r
+    /* round 9: */\r
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[36];\r
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[37];\r
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[38];\r
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[39];\r
+    if (Nr > 10) {\r
+        /* round 10: */\r
+        s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rdk[40];\r
+        s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rdk[41];\r
+        s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rdk[42];\r
+        s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rdk[43];\r
+        /* round 11: */\r
+        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[44];\r
+        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[45];\r
+        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[46];\r
+        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[47];\r
+        if (Nr > 12) {\r
+            /* round 12: */\r
+            s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rdk[48];\r
+            s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rdk[49];\r
+            s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rdk[50];\r
+            s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rdk[51];\r
+            /* round 13: */\r
+            t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rdk[52];\r
+            t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rdk[53];\r
+            t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rdk[54];\r
+            t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rdk[55];\r
+        }\r
+    }\r
+       rdk += Nr << 2;\r
+#else  /* !FULL_UNROLL */\r
+    /*\r
+     * Nr - 1 full rounds:\r
+     */\r
+    r = Nr >> 1;\r
+    for (;;) {\r
+        t0 =\r
+            Td0[(s0 >> 24)       ] ^\r
+            Td1[(s3 >> 16) & 0xff] ^\r
+            Td2[(s2 >>  8) & 0xff] ^\r
+            Td3[(s1      ) & 0xff] ^\r
+            rdk[4];\r
+        t1 =\r
+            Td0[(s1 >> 24)       ] ^\r
+            Td1[(s0 >> 16) & 0xff] ^\r
+            Td2[(s3 >>  8) & 0xff] ^\r
+            Td3[(s2      ) & 0xff] ^\r
+            rdk[5];\r
+        t2 =\r
+            Td0[(s2 >> 24)       ] ^\r
+            Td1[(s1 >> 16) & 0xff] ^\r
+            Td2[(s0 >>  8) & 0xff] ^\r
+            Td3[(s3      ) & 0xff] ^\r
+            rdk[6];\r
+        t3 =\r
+            Td0[(s3 >> 24)       ] ^\r
+            Td1[(s2 >> 16) & 0xff] ^\r
+            Td2[(s1 >>  8) & 0xff] ^\r
+            Td3[(s0      ) & 0xff] ^\r
+            rdk[7];\r
+\r
+        rdk += 8;\r
+        if (--r == 0) {\r
+            break;\r
+        }\r
+\r
+        s0 =\r
+            Td0[(t0 >> 24)       ] ^\r
+            Td1[(t3 >> 16) & 0xff] ^\r
+            Td2[(t2 >>  8) & 0xff] ^\r
+            Td3[(t1      ) & 0xff] ^\r
+            rdk[0];\r
+        s1 =\r
+            Td0[(t1 >> 24)       ] ^\r
+            Td1[(t0 >> 16) & 0xff] ^\r
+            Td2[(t3 >>  8) & 0xff] ^\r
+            Td3[(t2      ) & 0xff] ^\r
+            rdk[1];\r
+        s2 =\r
+            Td0[(t2 >> 24)       ] ^\r
+            Td1[(t1 >> 16) & 0xff] ^\r
+            Td2[(t0 >>  8) & 0xff] ^\r
+            Td3[(t3      ) & 0xff] ^\r
+            rdk[2];\r
+        s3 =\r
+            Td0[(t3 >> 24)       ] ^\r
+            Td1[(t2 >> 16) & 0xff] ^\r
+            Td2[(t1 >>  8) & 0xff] ^\r
+            Td3[(t0      ) & 0xff] ^\r
+            rdk[3];\r
+    }\r
+#endif /* ?FULL_UNROLL */\r
+    /*\r
+        * apply last round and\r
+        * map cipher state to byte array block:\r
+        */\r
+       s0 =\r
+               (Td4[(t0 >> 24)       ] & 0xff000000) ^\r
+               (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^\r
+               (Td4[(t2 >>  8) & 0xff] & 0x0000ff00) ^\r
+               (Td4[(t1      ) & 0xff] & 0x000000ff) ^\r
+               rdk[0];\r
+       PUTWORD(pt     , s0);\r
+       s1 =\r
+               (Td4[(t1 >> 24)       ] & 0xff000000) ^\r
+               (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^\r
+               (Td4[(t3 >>  8) & 0xff] & 0x0000ff00) ^\r
+               (Td4[(t2      ) & 0xff] & 0x000000ff) ^\r
+               rdk[1];\r
+       PUTWORD(pt +  4, s1);\r
+       s2 =\r
+               (Td4[(t2 >> 24)       ] & 0xff000000) ^\r
+               (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^\r
+               (Td4[(t0 >>  8) & 0xff] & 0x0000ff00) ^\r
+               (Td4[(t3      ) & 0xff] & 0x000000ff) ^\r
+               rdk[2];\r
+       PUTWORD(pt +  8, s2);\r
+       s3 =\r
+               (Td4[(t3 >> 24)       ] & 0xff000000) ^\r
+               (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^\r
+               (Td4[(t1 >>  8) & 0xff] & 0x0000ff00) ^\r
+               (Td4[(t0      ) & 0xff] & 0x000000ff) ^\r
+               rdk[3];\r
+       PUTWORD(pt + 12, s3);\r
+}\r
+\r
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/AES.h b/src/modules/rlm_eap/types/rlm_eap_psk/AES.h
new file mode 100644 (file)
index 0000000..4505c27
--- /dev/null
@@ -0,0 +1,133 @@
+/**\r
+ * AES.h\r
+ *\r
+ * The Advanced Encryption Standard (AES, aka AES) block cipher,\r
+ * designed by J. Daemen and V. Rijmen.\r
+ *\r
+ * @author Paulo S. L. M. Barreto\r
+ *\r
+ * This software is hereby placed in the public domain.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\r
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+#ifndef __AES_H\r
+#define __AES_H\r
+\r
+#include <freeradius-devel/ident.h>\r
+RCSIDH(AES_H, "$Id$")\r
+\r
+#include "BlockCipher.h"\r
+\r
+#ifndef USUAL_TYPES\r
+#define USUAL_TYPES\r
+typedef unsigned char   byte;\r
+typedef unsigned long   uint;   /* assuming sizeof(uint) == 4 */\r
+#endif /* USUAL_TYPES */\r
+\r
+#ifndef AES_BLOCKBITS\r
+#define AES_BLOCKBITS   128\r
+#endif\r
+#if AES_BLOCKBITS != 128\r
+#error "AES_BLOCKBITS must be 128"\r
+#endif\r
+\r
+#ifndef AES_BLOCKSIZE\r
+#define AES_BLOCKSIZE   16 /* bytes */\r
+#endif\r
+#if AES_BLOCKSIZE != 16\r
+#error "AES_BLOCKSIZE must be 16"\r
+#endif\r
+\r
+#ifndef AES_MINKEYBITS\r
+#define AES_MINKEYBITS  128\r
+#endif\r
+#if AES_MINKEYBITS != 128\r
+#error "AES_MINKEYBITS must be 128"\r
+#endif\r
+\r
+#ifndef AES_MINKEYSIZE\r
+#define AES_MINKEYSIZE  16 /* bytes */\r
+#endif\r
+#if AES_MINKEYSIZE != 16\r
+#error "AES_MINKEYSIZE must be 16"\r
+#endif\r
+\r
+#ifndef AES_MAXKEYBITS\r
+#define AES_MAXKEYBITS  256\r
+#endif\r
+#if AES_MAXKEYBITS != 256\r
+#error "AES_MAXKEYBITS must be 256"\r
+#endif\r
+\r
+#ifndef AES_MAXKEYSIZE\r
+#define AES_MAXKEYSIZE  32 /* bytes */\r
+#endif\r
+#if AES_MAXKEYSIZE != 32\r
+#error "AES_MAXKEYSIZE must be 32"\r
+#endif\r
+\r
+#define MAXKC  (AES_MAXKEYBITS/32)\r
+#define MAXKB  (AES_MAXKEYBITS/8)\r
+#define MAXNR  14\r
+\r
+class AES: public BlockCipher {\r
+public:\r
+\r
+       AES();\r
+       virtual ~AES();\r
+\r
+    /**\r
+     * Block size in bits.\r
+     */\r
+    inline uint blockBits() const {\r
+               return AES_BLOCKBITS;\r
+       }\r
+\r
+    /**\r
+     * Block size in bytes.\r
+     */\r
+    inline uint blockSize() const {\r
+               return AES_BLOCKSIZE;\r
+       }\r
+\r
+    /**\r
+     * Key size in bits.\r
+     */\r
+       inline uint keyBits() const {\r
+               return (Nr - 6) << 5;\r
+       }\r
+\r
+    /**\r
+     * Key size in bytes.\r
+     */\r
+       inline uint keySize() const {\r
+               return (Nr - 6) << 2;\r
+       }\r
+\r
+    void makeKey(const byte *cipherKey, uint keyBits, uint dir);\r
+\r
+    void encrypt(const byte *pt, byte *ct);\r
+\r
+    void decrypt(const byte *ct, byte *pt);\r
+\r
+private:\r
+    // static void Initialize();\r
+       void ExpandKey(const byte *cipherKey, uint keyBits);\r
+       void InvertKey();\r
+       uint Nr;\r
+       uint e_sched[4*(MAXNR + 1)];\r
+       uint d_sched[4*(MAXNR + 1)];\r
+};\r
+\r
+#endif /* __AES_H */\r
+\r
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/BlockCipher.h b/src/modules/rlm_eap/types/rlm_eap_psk/BlockCipher.h
new file mode 100644 (file)
index 0000000..919569f
--- /dev/null
@@ -0,0 +1,93 @@
+/**\r
+ * BlockCipher.h\r
+ *\r
+ * A simple abstraction for the basic functionality of a block cipher engine.\r
+ *\r
+ * @author Paulo S. L. M. Barreto\r
+ *\r
+ * @version 2.0\r
+ *\r
+ * This software is hereby placed in the public domain.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\r
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+#ifndef __BLOCKCIPHER_H\r
+#define __BLOCKCIPHER_H\r
+\r
+#include <freeradius-devel/ident.h>\r
+RCSIDH(BlockCipher_h, "$Id$")\r
+\r
+#include "/usr/include/sys/types.h"\r
+\r
+#ifndef USUAL_TYPES\r
+#define USUAL_TYPES\r
+typedef unsigned char   byte;\r
+//typedef unsigned long   uint;   /* assuming sizeof(uint) == 4 */\r
+#endif /* USUAL_TYPES */\r
+\r
+#define DIR_NONE    0\r
+#define DIR_ENCRYPT 1\r
+#define DIR_DECRYPT 2\r
+#define DIR_BOTH    (DIR_ENCRYPT | DIR_DECRYPT) /* both directions */\r
+\r
+class BlockCipher {\r
+public:\r
+\r
+    /**\r
+     * Cipher's block size in bits.\r
+     */\r
+    virtual uint blockBits() const = 0;\r
+\r
+    /**\r
+     * Cipher's block size in bytes.\r
+     */\r
+       virtual uint blockSize() const = 0;\r
+\r
+    /**\r
+     * Cipher's key size in bits.\r
+     */\r
+       virtual uint keyBits() const = 0;\r
+\r
+    /**\r
+     * Cipher's key size in bytes.\r
+     */\r
+    virtual uint keySize() const = 0;\r
+\r
+    /**\r
+     * Setup the key schedule for encryption, decryption, or both.\r
+     *\r
+     * @param   cipherKey   the cipher key.\r
+     * @param   keyBits     size of the cipher key in bits.\r
+     * @param   direction   cipher direction (DIR_ENCRYPT, DIR_DECRYPT, or DIR_BOTH).\r
+     */\r
+    virtual void makeKey(const byte *cipherKey, uint keyBits, uint dir) = 0;\r
+\r
+    /**\r
+     * Encrypt exactly one block of plaintext.\r
+     *\r
+     * @param   pt          plaintext block.\r
+     * @param   ct          ciphertext block.\r
+     */\r
+    virtual void encrypt(const byte *pt, byte *ct) = 0;\r
+\r
+    /**\r
+     * Decrypt exactly one block of ciphertext.\r
+     *\r
+     * @param   ct          ciphertext block.\r
+     * @param   pt          plaintext block.\r
+     */\r
+    virtual void decrypt(const byte *ct, byte *pt) = 0;\r
+\r
+};\r
+\r
+#endif /* __BLOCKCIPHER_H */\r
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/CTR.cpp b/src/modules/rlm_eap/types/rlm_eap_psk/CTR.cpp
new file mode 100644 (file)
index 0000000..0a6a499
--- /dev/null
@@ -0,0 +1,80 @@
+/*\r
+ * CTR.cpp\r
+ *\r
+ * The counter (CTR) mode of operation for block ciphers.\r
+ *\r
+ * @author Paulo S. L. M. Barreto\r
+ *\r
+ * This software is hereby placed in the public domain.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\r
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+#include <freeradius-devel/ident.h>\r
+RCSID("$Id$")\r
+\r
+#include <assert.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+#include "CTR.h"\r
+\r
+CTR::CTR(BlockCipher* E) {\r
+    this->E = E;\r
+    block_size = E->blockSize();\r
+    N = (byte *)calloc(block_size, 1);\r
+    S = (byte *)calloc(block_size, 1);\r
+    s = 0;\r
+}\r
+\r
+CTR::~CTR() {\r
+    memset(N, (byte)0, block_size); free(N);\r
+    memset(S, (byte)0, block_size); free(S);\r
+}\r
+\r
+void CTR::init(const byte* N) {\r
+    // initialize nonce:\r
+    memcpy(this->N, N, block_size);\r
+    E->encrypt(N, S); // S = E_K(N)\r
+    s = block_size;\r
+}\r
+\r
+void CTR::update(const byte* M, uint m, byte* C) {\r
+    uint i = block_size - s;\r
+    uint j = 0;\r
+    while (m >= s) {\r
+        for (uint b = 0; b < s; b++) {\r
+            C[j + b] = (byte)(M[j + b] ^ S[i + b]);\r
+        }\r
+        // proceed to the next block:\r
+        m -= s;\r
+        j += s;\r
+        // increment the nonce:\r
+        for (uint n = block_size - 1; n >= 0; n--) {\r
+            if ((++N[n] & 0xff) != 0) {\r
+                break;\r
+            }\r
+        }\r
+        E->encrypt(N, S);\r
+        s = block_size;\r
+        i = 0;\r
+    }\r
+    //assert(m < s);\r
+    // process remaining chunk (m bytes):\r
+    for (uint b = 0; b < m; b++) {\r
+        C[j + b] = (byte)(M[j + b] ^ S[i + b]);\r
+    }\r
+    s -= m;\r
+    //assert(0 < s && s <= block_size);\r
+}\r
+\r
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/CTR.h b/src/modules/rlm_eap/types/rlm_eap_psk/CTR.h
new file mode 100644 (file)
index 0000000..0a6307c
--- /dev/null
@@ -0,0 +1,67 @@
+/*\r
+ * CTR.h\r
+ *\r
+ * The counter (CTR) mode of operation for block ciphers.\r
+ *\r
+ * @author Paulo S. L. M. Barreto\r
+ *\r
+ * This software is hereby placed in the public domain.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\r
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+#ifndef __CTR_H\r
+#define __CTR_H\r
+\r
+#include <freeradius-devel/ident.h>\r
+RCSIDH(CTR_h, "$Id$")\r
+\r
+#include "BlockCipher.h"\r
+\r
+#ifndef USUAL_TYPES\r
+#define USUAL_TYPES\r
+typedef unsigned char   byte;\r
+typedef unsigned long   uint;   /* assuming sizeof(uint) == 4 */\r
+#endif /* USUAL_TYPES */\r
+\r
+class CTR {\r
+public:\r
+\r
+    CTR(BlockCipher* E);\r
+    virtual ~CTR();\r
+\r
+    /**\r
+     * Start encrypting/decrypting a message using a given nonce.\r
+     *\r
+     * @param   N   the normalized nonce (initial counter value)\r
+     */\r
+    void init(const byte* N);\r
+\r
+    /**\r
+     * Either encrypt or decrypt a message chunk.\r
+     *\r
+     * @param   M   message chunk\r
+     * @param   m   its length in bytes\r
+     * @param   C   the resulting encrypted/decrypted message chunk\r
+     */\r
+    void update(const byte* M, uint m, byte* C);\r
+\r
+private:\r
+    BlockCipher *E; // block cipher context\r
+    uint block_size;\r
+    byte* N;        // CTR counter  (block_size bytes)\r
+    byte* S;        // CTR mask     (block_size bytes)\r
+    uint s;         // available mask bytes on S\r
+};\r
+\r
+#endif /* __CTR_H */\r
+\r
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/EAX.cpp b/src/modules/rlm_eap/types/rlm_eap_psk/EAX.cpp
new file mode 100644 (file)
index 0000000..e28cd1d
--- /dev/null
@@ -0,0 +1,254 @@
+/*\r
+ * EAX.cpp\r
+ *\r
+ * The EAX authenticated encryption mode of operation,\r
+ * designed by M. Bellare, P. Rogaway and D. Wagner.\r
+ *\r
+ * @author Paulo S. L. M. Barreto\r
+ *\r
+ * @version 2.0\r
+ *\r
+ * This software is hereby placed in the public domain.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\r
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+#include <freeradius-devel/ident.h>\r
+RCSID("$Id$")\r
+\r
+#include <assert.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+#include "EAX.h"\r
+\r
+EAX::EAX() {\r
+       _E = 0; // block cipher context\r
+       tag_size = 0;\r
+       block_size = 0;\r
+       t_n = 0;      // [t]_n\r
+       _C = 0;       // CTR context\r
+       nt = 0;\r
+       ht = 0;\r
+       mt = 0;\r
+}\r
+\r
+/*********************************************************************\r
+ * Calls common to incremental and non-incremental API\r
+ ********************************************************************/\r
+\r
+void EAX::initialize(const byte* K, uint k, uint t, BlockCipher* E) {\r
+       if (E == 0) {\r
+               throw "Invalid cipher";\r
+       }\r
+    if (K == 0) {\r
+        throw "Invalid key size";\r
+    }\r
+    if (t > E->blockSize()) {\r
+        throw "Invalid tag size";\r
+    }\r
+    _E = E;\r
+    _E->makeKey(K, k, DIR_ENCRYPT);\r
+    _C = new CTR(_E);\r
+    tag_size = t;\r
+    block_size = _E->blockSize();\r
+    t_n = (byte *)calloc(block_size, 1);\r
+    nt = (byte *)calloc(block_size, 1);\r
+    ht = (byte *)calloc(block_size, 1);\r
+    mt = (byte *)calloc(block_size, 1);\r
+}\r
+\r
+/**\r
+ * Session is over; destroy all key material and cleanup!\r
+ */\r
+EAX::~EAX() {\r
+       if (_E != 0) {\r
+               t_n[block_size - 1] = 0;\r
+               delete _C;\r
+               memset(nt, (byte)0, block_size);\r
+               memset(ht, (byte)0, block_size);\r
+               memset(mt, (byte)0, block_size);\r
+       }\r
+}\r
+\r
+/**\r
+ * Supply a message header. The header "grows" with each call\r
+ * until a eax_provide_header() call is made that follows a\r
+ * eax_encrypt(), eax_decrypt(), eax_provide_plaintext(),\r
+ * eax_provide_ciphertext() or eax_compute_plaintext() call.\r
+ * That starts reinitializes the header.\r
+ */\r
+void EAX::provideHeader(const byte* H, uint h) {\r
+    if (H == 0 && h > 0) {\r
+        throw "Invalid header";\r
+    }\r
+    _H.update(H, h);\r
+}\r
+\r
+\r
+/*********************************************************************\r
+ * All-in-one, non-incremental interface\r
+ ********************************************************************/\r
+\r
+/**\r
+ * Encrypt the given message with the given key, nonce and header.\r
+ * Specify the header (if nonempty) with eax_provide_header().\r
+ */\r
+void EAX::encrypt(\r
+        const byte* N,  // the nonce and\r
+        uint n,         // its length (in bytes), and\r
+        const byte* M,  // the plaintext and\r
+        uint m,         // its length (in bytes).\r
+        byte* C,        // The m-byte ciphertext\r
+        byte* T) {      // and the tag T are returned.\r
+    provideNonce(N, n);\r
+    computeCiphertext(M, m, C);\r
+    if (T != 0) {\r
+        computeTag(T);\r
+    }\r
+}\r
+\r
+/**\r
+ * Decrypt the given ciphertext with the given key, nonce and header.\r
+ * Specify the header (if nonempty) with eax_provide_header().\r
+ * Returns 1 for a valid ciphertext, 0 for an invalid ciphertext and for invalid or missing parameters.\r
+ */\r
+bool EAX::decrypt(\r
+        const byte* N,  // the nonce and\r
+        uint n,         // its length (in bytes), and\r
+        const byte* C,  // the ciphertext and\r
+        uint c,         // its length (in bytes), and\r
+        const byte* T,  // the tag.\r
+        byte* P) {      // if valid, return the c-byte plaintext.\r
+    provideNonce(N, n);\r
+    provideCiphertext(C, c);\r
+    if (checkTag(T)) {\r
+        computePlaintext(C, c, P);\r
+        return true;\r
+    } else {\r
+        return false;\r
+    }\r
+}\r
+\r
+\r
+/*********************************************************************\r
+ * Incremental interface\r
+ ********************************************************************/\r
+\r
+/**\r
+ * Provide a nonce. For encryption, do this before calling\r
+ * eax_compute_ciphertext() and eax_compute_tag();\r
+ * for decryption, do this before calling\r
+ * eax_provide_ciphertext(), eax_check_tag, or eax_compute_plaintext().\r
+ */\r
+void EAX::provideNonce(const byte* N, uint n) {\r
+    if (N == 0 && n > 0) {\r
+        throw "Invalid nonce";\r
+    }\r
+    // nonce OMAC:\r
+    t_n[block_size - 1] = 0;\r
+    _N.init(_E);\r
+    _N.update(t_n, block_size);\r
+    _N.update(N, n);\r
+    _N.final(nt);\r
+    _C->init(nt); // N <- OMAC_K^0(N)\r
+    memset(nt, (byte)0, block_size);\r
+    // header OMAC:\r
+    t_n[block_size - 1] = 1;\r
+    _H.init(_E);\r
+    _H.update(t_n, block_size);\r
+    // message OMAC:\r
+    t_n[block_size - 1] = 2;\r
+    _M.init(_E);\r
+    _M.update(t_n, block_size);\r
+}\r
+\r
+/**\r
+ * Encrypt a message or a part of a message.\r
+ * The nonce needs already to have been\r
+ * specified by a call to eax_provide_nonce().\r
+ */\r
+void EAX::computeCiphertext(const byte* M, uint m, byte* C) {\r
+    if (M == 0 && m > 0 ||\r
+        C == 0) {\r
+        throw "Invalid buffer(s)";\r
+    }\r
+    _C->update(M, m, C);\r
+    _M.update(C, m);\r
+}\r
+\r
+/**\r
+ * Message and header finished: compute the authentication tag that is a part\r
+ * of the complete ciphertext.\r
+ */\r
+void EAX::computeTag(byte* T) {     // compute the tag T.\r
+    if (T == 0 && tag_size > 0) {\r
+        throw "Invalid tag";\r
+    }\r
+    //assert(M.t < block_size);   // at least [t]_n must have been provided\r
+    _N.final(nt);\r
+    _H.final(ht);\r
+    _M.final(mt);\r
+    for (uint i = 0; i < tag_size; i++) {\r
+        T[i] = (byte)(nt[i] ^ ht[i] ^ mt[i]);\r
+    }\r
+}\r
+\r
+/**\r
+ * Supply the ciphertext, or the next piece of ciphertext.\r
+ * This is used to check for the subsequent authenticity check eax_check_tag().\r
+ */\r
+void EAX::provideCiphertext(const byte* C, uint c) {\r
+    if (C == 0 && c > 0) {\r
+        throw "Invalid ciphertext";\r
+    }\r
+    _M.update(C, c);\r
+}\r
+\r
+/**\r
+ * The nonce, ciphertext and header have all been fully provided; check if\r
+ * they are valid for the given tag.\r
+ * Returns true for a valid ciphertext, false for an invalid ciphertext\r
+ * (in which case plaintext/ciphertext might be zeroized as well).\r
+ */\r
+bool EAX::checkTag(const byte* T) {\r
+    if (T == 0 && tag_size > 0) {\r
+        throw "Invalid tag";\r
+    }\r
+    //assert(M.t < block_size);   // at least [t]_n must have been provided\r
+    _N.final(nt);\r
+    _H.final(ht);\r
+    _M.final(mt);\r
+    for (uint i = 0; i < tag_size; i++) {\r
+        if (T[i] != (byte)(nt[i] ^ ht[i] ^ mt[i])) {\r
+            return false;\r
+        }\r
+    }\r
+    return true;\r
+}\r
+\r
+/**\r
+ * Recover the plaintext from the provided ciphertext.\r
+ * A call to eax_provide_nonce() needs to precede this call.\r
+ * The caller is responsible for separately checking if the ciphertext is valid.\r
+ * Normally this would be done before computing the plaintext with\r
+ * eax_compute_plaintext().\r
+ */\r
+void EAX::computePlaintext(const byte* C, uint c, byte* P) {\r
+    if (C == 0 && c > 0 ||\r
+        P == 0) {\r
+        throw "Invalid buffer(s)";\r
+    }\r
+    _C->update(C, c, P);\r
+}\r
+\r
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/EAX.h b/src/modules/rlm_eap/types/rlm_eap_psk/EAX.h
new file mode 100644 (file)
index 0000000..64062dd
--- /dev/null
@@ -0,0 +1,163 @@
+/*\r
+ * EAX.h\r
+ *\r
+ * The EAX authenticated encryption mode of operation,\r
+ * designed by M. Bellare, P. Rogaway and D. Wagner.\r
+ *\r
+ * @author Paulo S. L. M. Barreto\r
+ *\r
+ * @version 2.0\r
+ *\r
+ * This software is hereby placed in the public domain.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\r
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+#ifndef __EAX_H\r
+#define __EAX_H\r
+\r
+#include <freeradius-devel/ident.h>\r
+RCSIDH(EAX_h, "$Id$")\r
+\r
+#include "BlockCipher.h"\r
+#include "OMAC.h"\r
+#include "CTR.h"\r
+\r
+#ifndef USUAL_TYPES\r
+#define USUAL_TYPES\r
+typedef unsigned char   byte;\r
+typedef unsigned long   uint;   /* assuming sizeof(uint) == 4 */\r
+#endif /* USUAL_TYPES */\r
+\r
+class EAX {\r
+public:\r
+\r
+       EAX();\r
+\r
+    /**\r
+     * Key and parameter setup to init a EAX context data structure.\r
+     */\r
+    void initialize(const byte* K, uint k, uint t, BlockCipher* E);\r
+\r
+    /**\r
+     * Session is over; destroy all key material and cleanup!\r
+     */\r
+    virtual ~EAX();\r
+\r
+    /*********************************************************************\r
+     * Calls common to incremental and non-incremental API\r
+     ********************************************************************/\r
+\r
+    /**\r
+     * Supply a message header. The header "grows" with each call\r
+     * until a eax_provide_header() call is made that follows a\r
+     * eax_encrypt(), eax_decrypt(), eax_provide_plaintext(),\r
+     * eax_provide_ciphertext() or eax_compute_plaintext() call.\r
+     * That starts reinitializes the header.\r
+     */\r
+    void provideHeader(const byte* H, uint h);\r
+\r
+\r
+    /*********************************************************************\r
+     * All-in-one, non-incremental interface\r
+     ********************************************************************/\r
+\r
+    /**\r
+     * Encrypt the given message with the given key, nonce and header.\r
+     * Specify the header (if nonempty) with eax_provide_header().\r
+     */\r
+    void encrypt(\r
+            const byte* N,  // the nonce and\r
+            uint n,         // its length (in bytes), and\r
+            const byte* M,  // the plaintext and\r
+            uint m,         // its length (in bytes).\r
+            byte* C,        // The m-byte ciphertext\r
+            byte* T);\r
+\r
+    /**\r
+     * Decrypt the given ciphertext with the given key, nonce and header.\r
+     * Specify the header (if nonempty) with eax_provide_header().\r
+     * Returns 1 for a valid ciphertext, 0 for an invalid ciphertext and for invalid or missing parameters.\r
+     */\r
+    bool decrypt(\r
+            const byte* N,  // the nonce and\r
+            uint n,         // its length (in bytes), and\r
+            const byte* C,  // the ciphertext and\r
+            uint c,         // its length (in bytes), and\r
+            const byte* T,  // the tag.\r
+            byte* P);\r
+\r
+\r
+    /*********************************************************************\r
+     * Incremental interface\r
+     ********************************************************************/\r
+\r
+    /**\r
+     * Provide a nonce. For encryption, do this before calling\r
+     * eax_compute_ciphertext() and eax_compute_tag();\r
+     * for decryption, do this before calling\r
+     * eax_provide_ciphertext(), eax_check_tag, or eax_compute_plaintext().\r
+     */\r
+    void provideNonce(const byte* N, uint n);\r
+\r
+    /**\r
+     * Encrypt a message or a part of a message.\r
+     * The nonce needs already to have been\r
+     * specified by a call to eax_provide_nonce().\r
+     */\r
+    void computeCiphertext(const byte* M, uint m, byte* C);\r
+\r
+    /**\r
+     * Message and header finished: compute the authentication tag that is a part\r
+     * of the complete ciphertext.\r
+     */\r
+    void computeTag(byte* T);\r
+\r
+    /**\r
+     * Supply the ciphertext, or the next piece of ciphertext.\r
+     * This is used to check for the subsequent authenticity check eax_check_tag().\r
+     */\r
+    void provideCiphertext(const byte* C, uint c);\r
+\r
+    /**\r
+     * The nonce, ciphertext and header have all been fully provided; check if\r
+     * they are valid for the given tag.\r
+     * Returns true for a valid ciphertext, false for an invalid ciphertext\r
+     * (in which case plaintext/ciphertext might be zeroized as well).\r
+     */\r
+    bool checkTag(const byte* T);\r
+\r
+    /**\r
+     * Recover the plaintext from the provided ciphertext.\r
+     * A call to eax_provide_nonce() needs to precede this call.\r
+     * The caller is responsible for separately checking if the ciphertext is valid.\r
+     * Normally this would be done before computing the plaintext with\r
+     * eax_compute_plaintext().\r
+     */\r
+    void computePlaintext(const byte* C, uint c, byte* P);\r
+\r
+private:\r
+    BlockCipher* _E;// block cipher context\r
+    uint tag_size;\r
+    uint block_size;\r
+    byte* t_n;      // [t]_n\r
+    OMAC _N;        // nonce OMAC\r
+    OMAC _H;        // header OMAC\r
+    OMAC _M;        // message OMAC\r
+    CTR* _C;        // CTR context\r
+    byte* nt;\r
+    byte* ht;\r
+    byte* mt;\r
+};\r
+\r
+#endif /* __EAX_H */\r
+\r
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/Makefile.in b/src/modules/rlm_eap/types/rlm_eap_psk/Makefile.in
new file mode 100644 (file)
index 0000000..7d4aac9
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# $Id$
+#
+
+TARGET      = rlm_eap_psk
+SRCS        = rlm_eap_psk.cpp eap_psk.cpp eap_psk_ssm.cpp AES.cpp OMAC.cpp CTR.cpp EAX.cpp SOBMMO.cpp userinfo.c
+HEADERS     = eap_psk.h eap_psk_ssm.h AES.h OMAC.h CTR.h EAX.h BlockCipher.h SOBMMO.h userinfo.h
+RLM_CFLAGS  = $(INCLTDL) -I../.. -I../../libeap
+RLM_LIBS    = -lstdc++
+RLM_INSTALL =
+
+RLM_DIR=../../
+include ${RLM_DIR}../rules.mak
+
+$(LT_OBJS): $(HEADERS)
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/OMAC.cpp b/src/modules/rlm_eap/types/rlm_eap_psk/OMAC.cpp
new file mode 100644 (file)
index 0000000..8c1cf84
--- /dev/null
@@ -0,0 +1,130 @@
+/*\r
+ * OMAC.cpp\r
+ *\r
+ * The One-key CBC MAC (OMAC) message authentication code,\r
+ * designed by T. Iwata and K. Kurosawa.\r
+ *\r
+ * @author Paulo S. L. M. Barreto\r
+ *\r
+ * @version 2.0\r
+ *\r
+ * This software is hereby placed in the public domain.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\r
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+#include <freeradius-devel/ident.h>\r
+RCSID("$Id$")\r
+\r
+#include <assert.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+#include "OMAC.h"\r
+\r
+OMAC::OMAC() {\r
+    _E = 0;\r
+    block_size = 0;\r
+    t = 0;\r
+    mask = 0;\r
+    ready = 0;\r
+    memset(L, (byte)0, sizeof(L));\r
+    memset(T, (byte)0, sizeof(L));\r
+}\r
+\r
+OMAC::~OMAC() {\r
+    _E = 0;\r
+    block_size = 0;\r
+    t = 0;\r
+    mask = 0;\r
+    ready = 0;\r
+    memset(L, (byte)0, sizeof(L));\r
+    memset(T, (byte)0, sizeof(L));\r
+}\r
+\r
+void OMAC::init(BlockCipher* E) {\r
+    if (E == 0) {\r
+        throw "Invalid block cipher";\r
+    }\r
+    _E = E;\r
+    t = block_size = _E->blockSize();\r
+    if (block_size != 16 && block_size != 8) {\r
+        throw "Block size not supported";\r
+    }\r
+    mask = (block_size == 16) ? 0x87 : 0x1B;\r
+    // compute padding mask:\r
+    memset(L, (byte)0, block_size);\r
+    _E->encrypt(L, L); // L = E_K(0^n)\r
+    uint c = L[0] & 0x80; // carry\r
+    for (uint b = 0; b < block_size - 1; b++) {\r
+        L[b] = (byte)((L[b] << 1) | ((L[b + 1] & 0xff) >> 7));\r
+    }\r
+    L[block_size - 1] = (byte)((L[block_size - 1] << 1) ^ (c != 0 ? mask : 0)); // B = 2L\r
+    // initialize tag accumulator\r
+    memset(T, (byte)0, block_size);\r
+    ready = 0;\r
+}\r
+\r
+void OMAC::update(const byte* M, uint m) {\r
+    if (_E == 0) {\r
+        throw "OMAC computation not initialized";\r
+    }\r
+    uint i = block_size - t;\r
+    uint j = 0;\r
+    while (m > t) { // N.B. m is strictly larger than t!\r
+        // complete tag block:\r
+        for (uint b = 0; b < t; b++) {\r
+            T[i + b] ^= M[j + b];\r
+        }\r
+        _E->encrypt(T, T); // since there is more data, no padding applies\r
+        // proceed to the next block:\r
+        m -= t;\r
+        j += t;\r
+        t = block_size;\r
+        i = 0;\r
+        //assert(m > 0);\r
+    }\r
+    // process remaining chunk (m bytes):\r
+    for (uint b = 0; b < m; b++) {\r
+        T[i + b] ^= M[j + b];\r
+    }\r
+    t -= m;\r
+    //assert(m == 0 || t < block_size); // m == 0 here only occurs if m == 0 from the very beginning\r
+}\r
+\r
+void OMAC::final(byte* tag) {\r
+    if (_E != 0) {\r
+        // compute padding:\r
+        if (t > 0) {\r
+            // compute special padding mask:\r
+            uint c = L[0] & 0x80; // carry\r
+            for (uint b = 0; b < block_size - 1; b++) {\r
+                L[b] = (byte)((L[b] << 1) | ((L[b + 1] & 0xff) >> 7));\r
+            }\r
+            L[block_size - 1] = (byte)((L[block_size - 1] << 1) ^ (c != 0 ? mask : 0)); // P = 4L\r
+            // pad incomplete block:\r
+            T[block_size - t] ^= 0x80; // padding toggle\r
+            t = 0;\r
+        }\r
+        for (uint b = 0; b < block_size; b++) {\r
+            T[b] ^= L[b];\r
+        }\r
+        _E->encrypt(T, T); // T contains the complete tag\r
+        ready = 1; // OMAC tag available\r
+        _E = 0; // OMAC computation is complete; context no longer initialized\r
+    } else if (!ready) {\r
+        throw "OMAC computation not initialized";\r
+    }\r
+    memcpy(tag, T, block_size);\r
+}\r
+\r
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/OMAC.h b/src/modules/rlm_eap/types/rlm_eap_psk/OMAC.h
new file mode 100644 (file)
index 0000000..62f364a
--- /dev/null
@@ -0,0 +1,93 @@
+/*\r
+ * OMAC.h\r
+ *\r
+ * The One-key CBC MAC (OMAC) message authentication code,\r
+ * designed by T. Iwata and K. Kurosawa.\r
+ *\r
+ * @author Paulo S. L. M. Barreto\r
+ *\r
+ * @version 2.0\r
+ *\r
+ * This software is hereby placed in the public domain.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\r
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+#ifndef __OMAC_H\r
+#define __OMAC_H\r
+\r
+#include <freeradius-devel/ident.h>\r
+RCSIDH(OMAC_h, "$Id$")\r
+\r
+#include "BlockCipher.h"\r
+\r
+#ifndef USUAL_TYPES\r
+#define USUAL_TYPES\r
+typedef unsigned char   byte;\r
+typedef unsigned long   uint;   /* assuming sizeof(uint) == 4 */\r
+#endif /* USUAL_TYPES */\r
+\r
+#define OMAC_MAXBLOCKSIZE   16\r
+\r
+class OMAC {\r
+public:\r
+\r
+    OMAC();\r
+\r
+    virtual ~OMAC();\r
+\r
+    /**\r
+     * Start computing an OMAC tag by selecting the underlying block cipher.\r
+     *\r
+     * @param   E   block cipher underlying OMAC computation.\r
+     *              CAVEAT: in the current implementation the block size\r
+     *              must be either 16 or 8.\r
+     */\r
+    void init(BlockCipher* E);\r
+\r
+    /**\r
+     * Update the OMAC tag computation with a message chunk.\r
+     *\r
+     * @param   M   message chunk\r
+     * @param   m   its length in bytes\r
+     */\r
+    void update(const byte* M, uint m);\r
+\r
+    /**\r
+     * Complete the computation of the OMAC tag, or simply\r
+     * get the finished OMAC tag if available.\r
+     *\r
+     * @return  the OMAC tag.\r
+     */\r
+    void final(byte *tag);\r
+\r
+    /**\r
+     * Get the default tag size for the underlying block cipher.\r
+     *\r
+     * @return the default tag size in bytes.\r
+     */\r
+    uint tagSize() {\r
+        return block_size;\r
+    }\r
+\r
+private:\r
+    BlockCipher *_E;            // block cipher context\r
+    uint block_size;\r
+    uint t;                     // remaining space on T, in bytes\r
+    uint mask;\r
+    uint ready;\r
+    byte L[OMAC_MAXBLOCKSIZE];  // OMAC padding (block_size bytes): B = 2L, P = 4L\r
+    byte T[OMAC_MAXBLOCKSIZE];  // OMAC tag     (block_size bytes)\r
+};\r
+\r
+#endif /* __OMAC_H */\r
+\r
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/SOBMMO.cpp b/src/modules/rlm_eap/types/rlm_eap_psk/SOBMMO.cpp
new file mode 100644 (file)
index 0000000..93afbb5
--- /dev/null
@@ -0,0 +1,130 @@
+/**
+ *@memo        Implementation of the modified counter mode
+ *@doc          
+ *@author      A. MAGNIEZ (FT R&D - DTL/SSR) 
+ *
+ * Copyright 2006 The FreeRADIUS server project
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include "SOBMMO.h"
+#include <stdlib.h>
+#include <string.h>
+#include "eap_psk.h"
+
+/**
+ *@memo                default constructor
+ */
+SOBMMO::SOBMMO():sizeBlock(0),nbOutputBlocks(0),outputBlocks(NULL) {
+}
+
+/**
+ *@memo                default destructor
+ */
+SOBMMO::~SOBMMO() {
+  if(outputBlocks!=NULL) {
+    free(outputBlocks);
+  }
+}
+
+/**
+ *@memo                this function initializes the modified counter mode
+ *@param       K, the dedicated key (its size must be equal to the block size of E)
+ *@param       E, the block cipher context
+ *@param       inputBlock, the input block (its size must be equal to the block size of E)
+ *@param       nb, the number of wanted output blocks
+ *@param       counterValues, the counter values (its size must be nbOutputBlock*sizeBlock)
+ *@return      1 if the output blocks have been produced, 0 in the other cases.
+ */
+int SOBMMO::initialize(const byte* K, BlockCipher* E,const byte* inputBlock,int nb,const byte* counterValues){
+  int i; // iterator
+  char hexstr[1024];
+  byte buf[16];
+  
+  sizeBlock=E->blockSize();
+  nbOutputBlocks=nb;
+
+  
+  // allocate memory for the output blocks
+  outputBlocks=(byte *)malloc(sizeBlock*nbOutputBlocks);
+  if(outputBlocks==NULL){
+    return 0;
+  }
+  
+  // debug traces
+  pskConvertHex((char *)K, (char *)&hexstr, sizeBlock);
+  DEBUG2("SOBMMO::initialize: K=");
+  DEBUG2((char *)&hexstr);
+  
+  pskConvertHex((char *)inputBlock, (char *)&hexstr, sizeBlock);
+  DEBUG2("SOBMMO::initialize: inputBlock=");
+  DEBUG2((char *)&hexstr);
+  
+  pskConvertHex((char *)counterValues, (char *)&hexstr, sizeBlock*nbOutputBlocks);
+  DEBUG2("SOBMMO::initialize: counterValues=");
+  DEBUG2((char *)&hexstr);
+  
+  E->makeKey(K,sizeBlock,DIR_ENCRYPT);
+  E->encrypt(inputBlock,outputBlocks);
+  
+  // duplicate the first result
+  for(i=1;i<nbOutputBlocks;i++)
+    {
+      memcpy(outputBlocks+i*sizeBlock,outputBlocks,sizeBlock);
+    }
+  
+  pskConvertHex((char *)outputBlocks, (char *)&hexstr, nbOutputBlocks*sizeBlock);
+  DEBUG2("SOBMMO::initialize: outputBlocks before XOR=");
+  DEBUG2((char *)&hexstr);
+  
+  // XOR counter values
+  for(i=0;i<(nbOutputBlocks*sizeBlock);i++)
+    {
+      *(outputBlocks+i)=(*(outputBlocks+i))^(*(counterValues+i));
+    }
+  
+  pskConvertHex((char *)outputBlocks, (char *)&hexstr, nbOutputBlocks*sizeBlock);
+  DEBUG2("SOBMMO::initialize: outputBlocks after XOR=");
+  DEBUG2((char *)&hexstr);
+  
+  // in order to check that AES(K,M) is valid
+  E->encrypt(outputBlocks,buf);
+  pskConvertHex((char *)buf, (char *)&hexstr, 16);
+  DEBUG2("SOBMMO::initialize: buf=");
+  DEBUG2((char *)&hexstr);
+  
+  // produce each output block
+  for(i=0;i<nbOutputBlocks;i++)
+    {
+      E->encrypt(outputBlocks+i*sizeBlock,outputBlocks+i*sizeBlock); // Be careful, pt=ct !!! TBTested
+    }
+  
+  pskConvertHex((char *)outputBlocks, (char *)&hexstr, nbOutputBlocks*sizeBlock);
+  DEBUG2("SOBMMO::initialize: produced output blocks=");
+  DEBUG2((char *)&hexstr);
+  
+  return 1;
+  
+}
+
+
+/**
+ *@memo                this function returns an output block
+ *@param       id, the number of the wanted output block (the numerotation begins at 1 !!)
+ */
+byte* SOBMMO::getOutputBlock(int id){
+  byte* output=NULL;
+  
+  if(id<1 || id>nbOutputBlocks) {
+    return NULL;
+  }
+  
+  output=(byte*)malloc(sizeBlock);
+  if(output==NULL){
+    return NULL;
+  }
+  memcpy(output,outputBlocks+(id-1)*sizeBlock,sizeBlock);
+  return output;
+}
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/SOBMMO.h b/src/modules/rlm_eap/types/rlm_eap_psk/SOBMMO.h
new file mode 100644 (file)
index 0000000..4f1796b
--- /dev/null
@@ -0,0 +1,35 @@
+/**\r
+ *@memo        Implementation of the modified counter mode\r
+ *@doc          \r
+ *@author      A. MAGNIEZ (FT R&D - DTL/SSR) \r
+ *\r
+ * Copyright 2006 The FreeRADIUS server project\r
+ */\r
+\r
+#ifndef _SOBMMO_H_\r
+#define _SOBMMO_H_\r
+\r
+#include <freeradius-devel/ident.h>\r
+RCSIDH(SOBMMO_h, "$Id$")\r
+\r
+#include "BlockCipher.h"\r
+\r
+\r
+class SOBMMO {\r
+ public:\r
+  \r
+  SOBMMO();\r
+  \r
+  int initialize(const byte* K, BlockCipher* E,const byte* inputBlock,int nb,const byte* counterValues);\r
+  \r
+  byte* getOutputBlock(int id);\r
+  \r
+  virtual ~SOBMMO();\r
+  \r
+private:\r
+  int sizeBlock; //the size of a block cipher (input and output) in bytes\r
+  int nbOutputBlocks; //number of required output blocks\r
+  byte* outputBlocks; //pointer to output blocks\r
+};\r
+\r
+#endif\r
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/eap_psk.cpp b/src/modules/rlm_eap/types/rlm_eap_psk/eap_psk.cpp
new file mode 100644 (file)
index 0000000..46f9379
--- /dev/null
@@ -0,0 +1,123 @@
+/* $Id$ */
+
+/*
+ * eap_psk.cpp
+ *
+ * Implementation of the EAP-PSK packet management
+ *
+ * 
+ * Copyright (C) France Télécom R&D (DR&D/MAPS/NSS)
+ *
+ * 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 2006 The FreeRADIUS server project
+ *
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "eap_psk.h"
+
+
+/*
+ *
+ *  PSK Packet Format in EAP 
+ *  --- ------ ------ -- ---
+ * 0                   1                   2                   3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |     Code      |   Identifier  |            Length             |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |     Type      |   Data
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+
+int pskConvertHex(char *inbytes, char *outstr, int numbytes)
+{
+       int i;
+       char buildstr[1024], tempstr[10];
+
+       memset(buildstr, 0, 1024);
+
+       for (i=0;i<numbytes;i++)
+       {
+               sprintf((char *)tempstr, "%02X",(unsigned char)inbytes[i]);
+               strcat((char *)buildstr, (char *)tempstr);
+       }
+       strcpy(outstr, (char *)buildstr);
+
+       return 1;
+}
+
+
+int pskHex2Bin(const char *hex, unsigned char *bin, int numbytes) {
+    int len = strlen(hex);
+    char c;
+    int i;
+    unsigned char v;
+    for (i = 0; i < numbytes; i++) {
+        c = hex[2*i];
+        if (c >= '0' && c <= '9') {
+            v = c - '0';
+        } else if (c >= 'A' && c <= 'F') {
+         v = c - 'A' + 10;
+        } else if (c >= 'a' && c <= 'f') {
+         v = c - 'a' + 10;
+        } else {
+         //v = 0;
+         return 0; // non hexa character
+        }
+        v <<= 4;
+        c = hex[2*i + 1];
+        if (c >= '0' && c <= '9') {
+         v += c - '0';
+        } else if (c >= 'A' && c <= 'F') {
+         v += c - 'A' + 10;
+        } else if (c >= 'a' && c <= 'f') {
+         v += c - 'a' + 10;
+        } else {
+         //v = 0;
+         return 0; // non hexa character
+        }
+        bin[i] = v;
+    }
+    return 1;
+}
+
+
+int pskGetRandomBytes(void *buf, int nbytes){
+  FILE *fptr=NULL;
+  int written=0;
+  
+  if((fptr = fopen("/dev/urandom","r")) == NULL) {
+    radlog(L_ERR,"pskGetRandomBytes: urandom device not accessible");
+    return 0;
+  }
+  
+  if((written = fread(buf,1,nbytes,fptr)) != nbytes) {
+    radlog(L_ERR,"pskGetRandomBytes: number not generated");
+    return 0;
+  }     
+  
+  fclose(fptr);
+  
+  return 1;
+}
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/eap_psk.h b/src/modules/rlm_eap/types/rlm_eap_psk/eap_psk.h
new file mode 100644 (file)
index 0000000..5f5a654
--- /dev/null
@@ -0,0 +1,150 @@
+/* $Id$ */
+
+/*
+ * eap_psk.h
+ *
+ * Implementation of the EAP-PSK packet management
+ *
+ * 
+ * Copyright (C) France Télécom R&D (DR&D/MAPS/NSS)
+ *
+ * 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 2006 The FreeRADIUS server project
+ *
+ */
+
+
+
+#ifndef _EAP_PSK_H
+#define _EAP_PSK_H
+
+#include <freeradius-devel/ident.h>
+RCSIDH(eap_psk_h, "$Id$")
+
+#include "eap.h"
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+// EAP-PSK Type
+#define EAPPSK_TYPE 255
+
+// EXT_Payload maximum length in bytes
+#define EXT_PAYLOAD_MAX_LEN 977
+
+#define PSK_PCHANNEL_REPLAY_COUNTER_SIZE sizeof(unsigned long int) // size in octets
+#define PSK_KEY_SIZE (PSK_AK_SIZE+PSK_KDK_SIZE)                    // size in octets
+#define PSK_AK_SIZE 16                                             // size in octets
+#define PSK_KDK_SIZE 16                                            // size in octets
+#define PSK_TEK_SIZE 16                                            // size in octets
+#define PSK_MSK_SIZE 64                                            // size in octets
+#define PSK_EMSK_SIZE 64                                           // size in octets
+#define PSK_RANDOM_NUMBER_SIZE 16                                  // size in octets
+#define PSK_MAC_SIZE 16                                            // size in octets
+#define EAP_HEADER_SIZE 5                                          // size in octets
+#define PSK_SIZE 16
+
+
+
+// EAP-PSK attribute flags
+#define PSK_STATUS_CONT            0x40
+#define PSK_STATUS_DONE_FAILURE    0xC0
+#define PSK_STATUS_DONE_SUCCESS    0x80
+
+#define PSK_IS_EXT                 0x20
+
+
+// the EAP-PSK configuration parameters
+typedef struct eap_psk_conf {
+  unsigned char        *privateKey;           // the server private key
+  unsigned char        *id_s;                 // the server name
+  unsigned int ldapSupport;           // if an LDAP directory is used
+  unsigned char        *peerNaiAttribute;     // the LDAP attribute name which corresponds to the peer NAI
+  unsigned char        *peerKeyAttribute;     // the LDAP attribute name which corresponds to the peer Key = AK || KDK
+  unsigned char  *usersFilePath;       // the EAP-PSK users file path
+  unsigned int   nbRetry;              // the number of bad authorized responses while the EAP-PSK authentication
+  unsigned int   maxDelay;                // the maximum interval in seconds between two correct responses
+} PSK_CONF;
+
+  
+// data format of the first EAP-PSK message
+typedef struct psk_message_1 {
+  unsigned char rand_s[PSK_RANDOM_NUMBER_SIZE];
+}psk_message_1;
+
+// data format of the second EAP-PSK message
+typedef struct psk_message_2 {
+  unsigned char rand_p[PSK_RANDOM_NUMBER_SIZE];
+  unsigned char mac_p[16];
+  unsigned char *id_p;
+}psk_message_2;
+
+// data format of the third EAP-PSK message
+typedef struct psk_message_3 {
+  unsigned char mac_s[16];
+  unsigned long int nonce;
+  unsigned char tag[16];
+  unsigned char flags;
+  unsigned char ext_type;
+  unsigned char *extPayload;
+}psk_message_3;
+
+// data format of the fourth EAP-PSK message
+typedef struct psk_message_4 {
+  unsigned long int nonce;
+  unsigned char tag[16];
+  unsigned char flags;
+  unsigned char ext_type;
+  unsigned char *ext_payload;
+}psk_message_4;
+
+
+/** 
+ *@memo                this function converts a string into hexa
+ *@param    inbytes, pointer to a string
+ *@param    outstr, pointer to the hexa conversion
+ *@param    numbytes, number of bytes to convert
+ *@return      0 if an error has occured
+ */
+int pskConvertHex(char *inbytes, char *outstr, int numbytes);
+
+
+/**
+ *@memo                this function converts a string which contains hexa characters into hexa
+ *@param    inbytes, the string to convert
+ *@param       outstr, the conversion in hexa
+ *@param       numbytes, the number of bytes to convert
+ *@return      0 if an error has occured
+ */
+int pskHex2Bin(const char *hex, unsigned char *bin, int numbytes);
+
+
+/** 
+ *@memo                this function delivers random bytes
+ *@param    buf, pointer to the buffer to fill
+ *@param    nbytes, number of bytes to generate
+ *@return   0 if an error has occured
+ */
+int pskGetRandomBytes(void *buf, int nbytes);
+  
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /*_EAP_PSK_H*/
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/eap_psk_ssm.cpp b/src/modules/rlm_eap/types/rlm_eap_psk/eap_psk_ssm.cpp
new file mode 100644 (file)
index 0000000..c06636e
--- /dev/null
@@ -0,0 +1,800 @@
+/* $Id$ */
+
+/*
+ * eap_psk_ssm.cpp
+ *
+ * Implementation of the Server State Machine (SSM)
+ *
+ * 
+ * Copyright (C) France Télécom R&D (DR&D/MAPS/NSS)
+ *
+ * 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 2006 The FreeRADIUS server project
+ *
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+
+#include "autoconf.h"
+#include "libradius.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "radiusd.h"
+#include "modpriv.h"
+#include "modules.h"
+#include "modcall.h"
+#include "conffile.h"
+#include "ltdl.h"
+
+
+#include "eap_psk_ssm.h"
+#include "AES.h"
+#include "OMAC.h"
+#include "EAX.h"
+#include "SOBMMO.h"
+
+#include "userinfo.h"
+
+
+/*  PSK Packet Format in EAP 
+ *  --- ------ ------ -- ---
+ * 0                   1                   2                   3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |     Code      |   Identifier  |            Length             |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |     Type      |   Data 
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-
+ */
+
+
+int pskProcess(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *recvPacket, EAP_PACKET *sentPacket){
+
+  // error cases
+  if(conf==NULL || session==NULL)
+    {
+      radlog(L_ERR,"rlm_eap_psk: Cannot authenticate without EAP-PSK configuration and session information");
+      return 0;
+    }
+  
+  if(recvPacket && (recvPacket->code!=PW_EAP_RESPONSE || recvPacket->type.type!=EAPPSK_TYPE))
+    {
+      radlog(L_ERR,"pskProcess: EAP-PSK Response expected");
+      return 0;
+    }  
+
+  switch(session->state)
+    {
+    case INIT: return pskInit(conf,session,sentPacket);
+    case RANDSENT:
+               if(recvPacket) return pskRandSent(conf,session, recvPacket,sentPacket);
+    case PCHANNEL: 
+               if(recvPacket) return pskPChannel(conf,session,recvPacket,sentPacket);
+    default:
+      radlog(L_ERR,"pskProcess: Impossible to process the EAP-PSK authentication");
+      return 0;
+    }
+
+}
+
+
+int pskInit(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *sentPacket){
+
+  char hexstr[1024];
+  
+  session->nbRetry=0;
+  session->pChannelReplayCounter=0;
+  session->authStatus=PSK_STATUS_CONT;
+  session->isSupportedExt=1;
+  session->extType=0;
+  
+  sentPacket->code=PW_EAP_REQUEST;
+  sentPacket->length=PSK_RANDOM_NUMBER_SIZE+EAP_HEADER_SIZE;
+  sentPacket->type.type=EAPPSK_TYPE;
+  sentPacket->type.length=PSK_RANDOM_NUMBER_SIZE;
+  sentPacket->type.data=NULL;
+  sentPacket->type.data=(unsigned char*)malloc(PSK_RANDOM_NUMBER_SIZE);
+  
+  if(sentPacket->type.data==NULL)
+    {
+      radlog(L_ERR,"pskInit: Out of memory");
+      return 0;
+    }
+  
+  // generate a 128-bit random value and put this value in session->rand_s
+  if(!pskGetRandomBytes(sentPacket->type.data,PSK_RANDOM_NUMBER_SIZE)) {
+    radlog(L_ERR,"pskInit: problem during random number generation");
+    return 0;
+  }
+  
+  pskConvertHex((char *)sentPacket->type.data, (char *)hexstr,PSK_RANDOM_NUMBER_SIZE);
+  DEBUG2("pskInit: random number RA :");
+  DEBUG2((char *)hexstr);
+  
+  // save this value in session information
+  memcpy(session->rand_s,sentPacket->type.data,PSK_RANDOM_NUMBER_SIZE);
+  
+  session->state=RANDSENT;
+  return 1;
+  
+}
+
+
+int pskRandSent(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *recvPacket, EAP_PACKET *sentPacket){
+  
+  /* the received packet is shown below
+   * 
+   * 0                   1                   2                   3
+   * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   * |    Code=2     |  Identifier   |            Length             |
+   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   * |  Type EAP-PSK |                                               |
+   * +-+-+-+-+-+-+-+-+                                               +
+   * |                                                               |
+   * +                                                               +
+   * |                             RAND_P                            |
+   * +                                                               +
+   * |                                                               |
+   * +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   * |               |                                               |
+   * +-+-+-+-+-+-+-+-+                                               +
+   * |                                                               |
+   * +                                                               +
+   * |                             MAC_P                             |
+   * +                                                               +
+   * |                                                               |
+   * +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   * |               |                                               |
+   * +-+-+-+-+-+-+-+-+                                               :
+   * :                              ID_P                             :
+   * :                                                               :
+   * +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   * |                               |
+   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   */
+
+
+  psk_message_2 *psk_msg_2;
+  psk_message_3 *psk_msg_3;
+  int identitySize;
+  char hexstr[1024];
+  unsigned char buffer[PSK_MAC_SIZE];
+  unsigned char *data;
+  unsigned char *ptr;
+  unsigned char buftmp[PSK_AK_SIZE+PSK_KDK_SIZE];
+  
+  //user profile
+  userinfo_t*    uinfo = NULL;
+  
+  char **psk_vals;
+  char *psk_val;
+  int i=0;
+  char **atts;
+  unsigned char privateKey[PSK_SIZE];
+
+  // for the mac calculation
+  OMAC om;
+  AES c;
+  
+  // for the key derivation
+  SOBMMO sob;
+  unsigned char *block;
+  // counter values
+  unsigned char counterValues[]={      
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09};
+  
+
+  // for the pchannel
+  unsigned char nn[PSK_RANDOM_NUMBER_SIZE];
+  unsigned char eapHeader[EAP_HEADER_SIZE];
+  EAX eax;
+
+
+
+  if(recvPacket->length<(EAP_HEADER_SIZE+PSK_RANDOM_NUMBER_SIZE+PSK_MAC_SIZE+1))
+    {
+      // the packet is malformed
+      DEBUG2("pskPChannel: the packet is malformed: the authentication must fail");
+      sentPacket->code=PW_EAP_FAILURE;
+      
+      return 1;
+    }
+  
+  // retrieve the identity of the peer, ID_P
+  identitySize=recvPacket->length-(EAP_HEADER_SIZE+PSK_RANDOM_NUMBER_SIZE+PSK_MAC_SIZE);
+  session->id_p=(unsigned char *)malloc(identitySize+1);
+  if(session->id_p==NULL)
+    {
+      radlog(L_ERR,"pskRandSent: Out of memory");
+      return 0;
+    }
+  psk_msg_2=(psk_message_2*)recvPacket->type.data;
+  memcpy(session->id_p,&(psk_msg_2->id_p),identitySize);
+  session->id_p[identitySize]='\0'; 
+
+  // search the peer identity in the user file whose path is conf->usersFilePath
+  
+  uinfo = pskGetUserInfo((char*)conf->usersFilePath, (char*)session->id_p);
+  if (uinfo)
+    {
+      
+      DEBUG2("pskRandSent: identity successfully checked");
+      DEBUG2("pskRandSent: saving peer information");
+      
+      // save keys                                                    
+      memcpy(session->ak,uinfo->AK,PSK_AK_SIZE);
+      memcpy(session->kdk,uinfo->KDK,PSK_KDK_SIZE);
+      
+      DEBUG2("pskRandSent: found user %s in %s",session->id_p, conf->usersFilePath);
+      
+      free(uinfo);
+      
+    } else {
+      
+      // the peer identity wasn't found
+      DEBUG2("pskRandSent: the peer identity isn't valid");
+      DEBUG2("pskRandSent: the authentication must fail");
+      sentPacket->code=PW_EAP_FAILURE;
+      
+      return 1;  
+    }
+  
+  // calculate the following MAC: MAC(session->ak, ID_P || conf->id_s || session->rand_s || RAND_P)
+  
+  // making the formula
+  data=(unsigned char *)malloc(strlen((char*)session->id_p)+strlen((char*)conf->id_s)+2*PSK_RANDOM_NUMBER_SIZE);
+  if(data==NULL) {
+    radlog(L_ERR,"pskRandSent: out of memory");
+    return 0;
+  }
+  ptr=data;
+  memcpy(ptr,session->id_p,strlen((char*)session->id_p));
+  ptr+=strlen((char*)session->id_p);
+  memcpy(ptr,conf->id_s,strlen((char*)conf->id_s));
+  ptr+=strlen((char*)conf->id_s);
+  memcpy(ptr,session->rand_s,PSK_RANDOM_NUMBER_SIZE);
+  ptr+=PSK_RANDOM_NUMBER_SIZE;
+  memcpy(ptr,psk_msg_2->rand_p,PSK_RANDOM_NUMBER_SIZE);
+  
+  pskConvertHex((char *)data, (char *)hexstr,strlen((char*)session->id_p)+strlen((char*)conf->id_s)+2*PSK_RANDOM_NUMBER_SIZE);
+  DEBUG2("pskRandSent: [B||A||RA||RB] :");
+  DEBUG2((char *)hexstr);
+  
+  pskConvertHex((char *)(session->ak), (char *)hexstr,PSK_AK_SIZE);
+  DEBUG2("pskRandSent: AK :");
+  DEBUG2((char *)hexstr);
+
+
+  // obtain the mac
+
+  c.makeKey(session->ak,PSK_AK_SIZE,DIR_ENCRYPT);
+  om.init(&c);
+  om.update(data,strlen((char*)session->id_p)+strlen((char*)conf->id_s)+2*PSK_RANDOM_NUMBER_SIZE);
+  om.final(buffer);
+  free(data);
+  
+  pskConvertHex((char *)buffer, (char *)hexstr,PSK_MAC_SIZE);
+  DEBUG2("pskRandSent: MAC of [B||A||RA||RB] :");
+  DEBUG2((char *)hexstr);
+  
+
+  if(memcmp(buffer,psk_msg_2->mac_p,PSK_MAC_SIZE))
+    {
+      // the received MAC attribute is not correct
+      DEBUG2("pskRandSent: the received MAC attribute isn't correct");
+      DEBUG2("pskRandSent: the authentication must fail");
+      sentPacket->code=PW_EAP_FAILURE;
+      
+      return 1;
+    }
+
+  
+  DEBUG2("pskRandSent: the received MAC attribute is correct");
+  
+  // KEY DERIVATION
+  
+  // initialize the sobmmo
+  sob.initialize(session->kdk,&c,psk_msg_2->rand_p,9,counterValues);
+  
+  // get the TEK
+  block=sob.getOutputBlock(1);
+  memcpy(session->tek,block,PSK_TEK_SIZE);
+  free(block);
+  
+  pskConvertHex((char *)session->tek, (char *)hexstr, PSK_TEK_SIZE);
+  DEBUG2("pskRandSent: TEK :");
+  DEBUG2((char *)hexstr);
+  
+  // get the MSK
+  for(int i=0;i<4;i++)
+    {
+      block=sob.getOutputBlock(i+2);
+      memcpy(&session->msk[i*16],block,16);
+      free(block);
+    }
+                              
+  pskConvertHex((char *)session->msk, (char *)hexstr, PSK_MSK_SIZE);
+  DEBUG2("pskRandSent: MSK :");
+  DEBUG2((char *)hexstr);
+  
+  // get the EMSK
+  for(int i=0;i<4;i++)
+    {
+      block=sob.getOutputBlock(i+6);
+      memcpy(&session->emsk[i*16],block,16);
+      free(block);
+    }
+  
+  pskConvertHex((char *)session->emsk, (char *)hexstr, PSK_EMSK_SIZE);
+  DEBUG2("pskRandSent: EMSK :");
+  DEBUG2((char *)hexstr);
+                              
+                              
+  // obtain the mac of [A||RB]
+  data=(unsigned char *)malloc(strlen((char*)conf->id_s)+PSK_RANDOM_NUMBER_SIZE);
+  if(data==NULL) {
+    radlog(L_ERR,"pskRandSent: out of memory");
+    return 0;
+  }
+  memcpy(data,conf->id_s,strlen((char*)conf->id_s));
+  memcpy(data+strlen((char*)conf->id_s),psk_msg_2->rand_p,PSK_RANDOM_NUMBER_SIZE);
+  
+  pskConvertHex((char *)data, (char *)hexstr,strlen((char*)conf->id_s)+PSK_RANDOM_NUMBER_SIZE);
+  DEBUG2("pskRandSent: [A||RB] :");
+  DEBUG2((char *)hexstr);
+  
+  c.makeKey(session->ak,PSK_AK_SIZE,DIR_ENCRYPT);
+  om.init(&c);
+  om.update(data,strlen((char*)conf->id_s)+PSK_RANDOM_NUMBER_SIZE);
+  om.final(buffer);
+  free(data);
+  
+  pskConvertHex((char *)&buffer, (char *)hexstr,16);
+  DEBUG2("pskRandSent: MAC of [A||RB] :");
+  DEBUG2((char *)hexstr);
+  
+
+  if(session->extType==0)
+    {
+      // standard authentication
+      
+      sentPacket->code=PW_EAP_REQUEST;
+      sentPacket->length=EAP_HEADER_SIZE+2*PSK_MAC_SIZE+PSK_PCHANNEL_REPLAY_COUNTER_SIZE+1;
+      sentPacket->type.type=EAPPSK_TYPE;
+      sentPacket->type.length=2*PSK_MAC_SIZE+PSK_PCHANNEL_REPLAY_COUNTER_SIZE+1;
+      sentPacket->type.data=NULL;
+      sentPacket->type.data=(unsigned char*)malloc(2*PSK_MAC_SIZE+PSK_PCHANNEL_REPLAY_COUNTER_SIZE+1);
+      
+      if(sentPacket->type.data==NULL)
+       {
+         radlog(L_ERR,"pskRandSent: Out of memory");
+         return 0;
+       }
+
+      psk_msg_3=(psk_message_3*)sentPacket->type.data;
+
+      // add to sentPacket the following MAC: MAC(session->AK, conf->id_s || RAND_P)
+      memcpy(psk_msg_3->mac_s,buffer,PSK_MAC_SIZE);
+
+      // add to sentPacket the following information: 
+      // R = DONE_SUCCESS (the R flag is equal to session->authStatus)
+      // E=0
+      psk_msg_3->nonce=htonl(session->pChannelReplayCounter);
+      
+      // calculate the EAP header
+      eapHeader[0]=sentPacket->code;
+      eapHeader[1]=(recvPacket->id)+1; // we suppose that the identifier is incremented by 1
+
+      sentPacket->length=htons(sentPacket->length);
+      memcpy(&(eapHeader[2]),&(sentPacket->length),2);
+      sentPacket->length=ntohs(sentPacket->length);
+
+      eapHeader[4]=sentPacket->type.type;
+
+      pskConvertHex((char *)eapHeader, (char *)hexstr,EAP_HEADER_SIZE);
+      DEBUG2("pskRandSent: eapHeader :");
+      DEBUG2((char *)hexstr);
+      
+      // the replay counter is the least significant bytes of the nonce !
+      memset(nn,0,PSK_RANDOM_NUMBER_SIZE);
+      memcpy(&nn[PSK_RANDOM_NUMBER_SIZE-PSK_PCHANNEL_REPLAY_COUNTER_SIZE],&(psk_msg_3->nonce),PSK_PCHANNEL_REPLAY_COUNTER_SIZE);
+
+      pskConvertHex((char *)nn, (char *)hexstr,PSK_RANDOM_NUMBER_SIZE);
+      DEBUG2("pskRandSent: nn :");
+      DEBUG2((char *)hexstr);
+
+      session->authStatus=PSK_STATUS_DONE_SUCCESS;
+
+      // EAX encryption
+      
+      eax.initialize(session->tek, PSK_TEK_SIZE, AES_BLOCKSIZE, &c);
+
+      eax.provideNonce((byte*)nn,PSK_RANDOM_NUMBER_SIZE);
+      eax.provideHeader((byte*)eapHeader,EAP_HEADER_SIZE);
+      eax.computeCiphertext((byte*)&(session->authStatus),sizeof(session->authStatus),(byte*)&(psk_msg_3->flags));
+      eax.computeTag((byte*)psk_msg_3->tag);
+       
+      // !!! BE CAREFUL !!! 
+      // the authorization isn't taken into account in this implementation
+      // that's why R=DONE_SUCCESS
+      
+    } else {
+      // extended authentication
+      
+
+      // !!!!! NOT IMPLEMENTED !!!!!!
+      return 0;
+
+      /*
+
+      // call the extension which must update the session->authStatus, i.e. the result of the EAP-PSK authentication
+      // see the pskExtension function declaration for more details
+      void *payloadOut=NULL;
+      int sizePayloadOut=0;
+      int resul;
+      resul=pskExtension(conf,session,PSK_STATUS_CONT,NULL,0,&payloadOut,&sizePayloadOut);
+
+      if(!resul || (sizePayloadOut<1) || (sizePayloadOut>EXT_PAYLOAD_MAX_LEN))
+       {
+         //the extension has failed
+         // the authentication must fail
+         // the sentPacket must be a EAP_Failure packet
+         return 1;
+       }
+      
+      // add to sentPacket the following information:
+      // R = CONT or DONE_FAILURE or DONE_SUCCESS thanks to session->authStatus
+      // E = 1
+      // EXT_Type=session->extType
+      // EXT_payload=payloadOut
+      
+      */
+      
+    }   
+
+  session->pChannelReplayCounter++;
+
+  session->state=PCHANNEL;
+  
+
+  return 1;
+  
+}
+
+
+
+int pskPChannel(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *recvPacket, EAP_PACKET *sentPacket){
+
+  /* the received packet is shown below
+   *
+   * 0                   1                   2                   3
+   * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   * |    Code=2     |  Identifier   |            Length             |
+   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   * |  Type EAP-PSK |               Nonce...                                                                      :
+   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   *     ...Nonce    |                                               |
+   * +-+-+-+-+-+-+-+-+                                               +
+   * |                                                               |
+   * +                                                               +
+   * |                             TAG                               |
+   * +                                                               +
+   * |                                                               |
+   * +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   * |               | R |E| Reserved|EXT_Type (opt)|                |
+   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++                +
+   * :                                                               :
+   * :        EXT_Payload (optional)                                 :
+   * +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   * |                               |
+   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   *
+   * EXT_Type and EXT_Payload must be in the EAP packet when E is set to 1
+   * EXT_Payload could be null
+   *
+  */
+
+  psk_message_4 *psk_msg_4;
+
+  // for the pchannel
+  unsigned char eapHeader[EAP_HEADER_SIZE];
+  unsigned char nn[PSK_RANDOM_NUMBER_SIZE];
+  EAX eax;
+  AES c;
+  bool st;
+  unsigned char flags;
+  
+  if(recvPacket->length<(EAP_HEADER_SIZE+PSK_PCHANNEL_REPLAY_COUNTER_SIZE+PSK_MAC_SIZE+1))
+    {  
+      // the packet is malformed
+      // the session->nbRetry isn't incremented
+      // sentPacket must be the previous request sent by the server ###### PB TIMER ########
+      
+      DEBUG2("pskPChannel: receiving a invalid EAP-PSK packet: the packet is malformed");
+      DEBUG2("pskPChannel: the authentication must fail");
+      sentPacket->code=PW_EAP_FAILURE;
+      
+      return 1;  
+    }
+  
+  
+  psk_msg_4=(psk_message_4*)recvPacket->type.data;
+
+
+  if(ntohl(psk_msg_4->nonce)!=session->pChannelReplayCounter)
+    {
+      // the received packet isn't awaited
+      // the session->nbRetry isn't incremented
+      // sentPacket must be the previous request sent by the server
+
+      DEBUG2("pskPChannel: receiving a invalid EAP-PSK packet: the replay counter isn't valid");
+      DEBUG2("pskPChannel: the authentication must fail");
+      sentPacket->code=PW_EAP_FAILURE;
+      
+      return 1;  
+    }
+  
+  // decrypt the received packet with the EAX mode and check the EAP header
+
+   // calculate the EAP header
+  eapHeader[0]=recvPacket->code;
+  eapHeader[1]=recvPacket->id;
+  
+  recvPacket->length=htons(recvPacket->length);
+  memcpy(&(eapHeader[2]),&(recvPacket->length),2);
+  recvPacket->length=ntohs(recvPacket->length);
+  
+  eapHeader[4]=recvPacket->type.type;
+  
+  // the replay counter is the least significant bytes of the nonce !
+  memset(nn,0,PSK_RANDOM_NUMBER_SIZE);
+  memcpy(&nn[PSK_RANDOM_NUMBER_SIZE-PSK_PCHANNEL_REPLAY_COUNTER_SIZE],&(psk_msg_4->nonce),PSK_PCHANNEL_REPLAY_COUNTER_SIZE);
+
+  // EAX encryption
+  
+  eax.initialize(session->tek, PSK_TEK_SIZE, AES_BLOCKSIZE, &c);
+    
+  eax.provideNonce((byte*)nn,PSK_RANDOM_NUMBER_SIZE);
+  eax.provideHeader((byte*)eapHeader,EAP_HEADER_SIZE);
+  eax.provideCiphertext((byte*)&(psk_msg_4->flags),sizeof(psk_msg_4->flags));
+  st=eax.checkTag((byte*)psk_msg_4->tag);
+  
+  if(!st){
+    // the decryption ends by a failure
+    
+    DEBUG2("pskPChannel: receiving a invalid EAP-PSK packet: the decryption fails");
+    DEBUG2("pskPChannel: the authentication must fail");
+    sentPacket->code=PW_EAP_FAILURE;
+    
+    return 1;      
+  }
+
+  
+  eax.computePlaintext((byte*)&(psk_msg_4->flags),sizeof(psk_msg_4->flags),(byte*)&flags);
+  
+  if((((flags & PSK_IS_EXT)==PSK_IS_EXT) && recvPacket->length<(EAP_HEADER_SIZE+PSK_PCHANNEL_REPLAY_COUNTER_SIZE+PSK_MAC_SIZE+2)) || (((flags & PSK_IS_EXT)==0) && recvPacket->length!=(EAP_HEADER_SIZE+PSK_PCHANNEL_REPLAY_COUNTER_SIZE+PSK_MAC_SIZE+1)))
+    {
+      // the packet is malformed
+      // the authentication must fail
+      // the sentPacket must be a EAP_Failure packet
+
+      DEBUG2("pskPChannel: the packet is malformed: the authentication must fail");
+      sentPacket->code=PW_EAP_FAILURE;
+      
+      return 1;
+     }
+  
+
+   if(session->extType==0 && ((flags & PSK_IS_EXT)==PSK_IS_EXT))
+     {
+       // error: standard authentication awaited
+       // the authentication must fail
+       // the sentPacket must be a EAP_Failure packet
+       
+       DEBUG2("pskPChannel: the packet is malformed: the authentication must fail");
+       sentPacket->code=PW_EAP_FAILURE;
+       
+       return 1;
+     }
+
+   if(session->extType!=0 && ((flags & PSK_IS_EXT)==0))
+     {
+       // error: extended authentication awaited
+       // the authentication must fail
+       // the sentPacket must be a EAP_Failure packet
+
+       DEBUG2("pskPChannel: the packet is malformed: the authentication must fail");
+       sentPacket->code=PW_EAP_FAILURE;
+
+       return 1;
+     }
+
+   if((flags & PSK_IS_EXT)==0)
+     {
+       // standard authentication
+       
+       if(((flags & PSK_STATUS_DONE_SUCCESS)==PSK_STATUS_DONE_SUCCESS) && session->authStatus==PSK_STATUS_DONE_SUCCESS)
+        {
+          // sentPacket must be an EAP_Success packet
+          // indicate to the lower layer that the MSK and the EMSK are ready
+          // the EAP-PSK authentication will end after sending sentPacket
+
+          sentPacket->code=PW_EAP_SUCCESS;
+
+        } else {
+          // sentPacket must be an EAP_Failure packet
+          // the EAP-PSK authentication will end after sending sentPacket
+
+          sentPacket->code=PW_EAP_FAILURE;
+
+        }
+       
+     } else {
+       // extended authentication
+
+
+       // !!!!! NOT IMPLEMENTED !!!!!
+       return 0;
+
+
+       /*              
+       if(session->isSupportedExt)
+        {
+          
+          if(recvPacket->data.EXT_Payload)
+            {
+
+              // call the extension which must update the session->authStatus, i.e. the result of the EAP-PSK authentication
+              // see the pskExtension function declaration for more details
+              void *payloadOut=NULL;
+              int sizePayloadOut=0;
+              int sizePayloadIn=recvPacket->length-27; // (27=5+16+4+1+1)
+              int resul;
+              resul=pskExtension(conf,session,recvPacket->data.R,recvPacket->data.EXT_Payload,sizePayloadIn,&payloadOut,&sizePayloadOut); 
+              
+              if(!resul || (sizePayloadOut<1) || (sizePayloadOut>EXT_PAYLOAD_MAX_LEN))
+                {
+                  //the extension has failed
+                  // the authentication must fail
+                  // the sentPacket must be a EAP_Failure packet
+                  return 1;
+                }
+              
+              if(recvPacket->data.R != CONT) {
+                // sentPacket must be an EAP_Success packet or an EAP_Failure packet thanks to the server policy and the received R flag
+                // indicate to the lower layer that the MSK and the EMSK are ready in case an EAP_Success packet must be sent
+                // the EAP-PSK authentication will end after sending sentPacket
+                return 1;
+              }
+              
+              // add to sentPacket the following information:
+              // R = CONT or DONE_FAILURE or DONE_SUCCESS thanks to session->authStatus
+              // E = 1
+              // EXT_Type=session->extType
+              // EXT_payload=payloadOut
+              
+            } else {
+              // the peer doesn't support the specified extension
+
+              session->isSupportedExt=0;
+
+              if(recvPacket->data.R != CONT) {
+                // sentPacket must be an EAP_Success packet or an EAP_Failure packet thanks to the server policy and the received R flag
+                // indicate to the lower layer that the MSK and the EMSK are ready in case of an EAP_Success packet must be sent
+                // the EAP-PSK authentication will end after sending sentPacket
+                return 1;
+              }
+              
+              // add to sentPacket the following information:
+              // R = DONE_FAILURE or DONE_SUCCESS thanks to the server policy
+              // E = 1
+              // EXT_Type=session->extType
+            }
+          
+        } else {
+          
+           if(recvPacket->data.R != CONT && recvPacket->data.EXT_Payload==NULL) {
+             // sentPacket must be an EAP_Success packet or an EAP_Failure packet thanks to the server policy and the received R flag
+             // indicate to the lower layer that the MSK and the EMSK are ready in case of an EAP_Success packet must be sent
+             // the EAP-PSK authentication will end after sending sentPacket
+             return 1;
+
+           } else {
+             // the packet is malformed
+             // the authentication must fail
+             // the sentPacket must be a EAP_Failure packet
+             return 1;
+           }
+             
+        }
+       */
+       
+       session->pChannelReplayCounter++;
+       // use the EAX mode to encrypt the EXT_Payload and protect the EAP header
+       
+       // !!!! NOT IMPLEMENTED !!!!
+       // only standard authentication supported
+
+       session->pChannelReplayCounter++;
+       
+     }
+   
+   // stay in this state
+   return 1;
+   
+}                      
+
+
+
+int pskExtension(PSK_CONF *conf, PSK_SESSION *session, unsigned short receivedStatus, void *dataIn, int sizeDataIn, void **dataOut, int *sizeDataOut){
+  
+  // this functionality makes it possible to do authorization, account refilling...
+
+  // this function must update the session->authStatus variable thanks to its policy, the received R flag, i.e. the receivedStatus variable, and the received data
+  
+  // !!! Be careful !!!
+  // dataOut mustn't be NULL
+
+  // !!!! NOT IMPLEMENTED !!!!
+  return 0;
+
+}
+
+
+
+/** 
+ *@memo                this function frees the session data
+ *@param        opaque, pointer to a structure which contains information session
+ */
+void pskFreeSession(void *opaque){
+  PSK_SESSION *session;
+  
+  DEBUG2("pskFreeSession:");
+  
+  if(!opaque) return;
+  
+  session=(PSK_SESSION *)opaque;
+  if(!session) return;
+  
+  if(session->id_p) {
+    free(session->id_p);
+  }
+
+  free(session);
+  
+  opaque=NULL;
+  
+  DEBUG2("pskFreeSession: finished");
+
+}
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/eap_psk_ssm.h b/src/modules/rlm_eap/types/rlm_eap_psk/eap_psk_ssm.h
new file mode 100644 (file)
index 0000000..efe1c53
--- /dev/null
@@ -0,0 +1,139 @@
+/* $Id$ */
+
+/*
+ * eap_psk_ssm.h
+ *
+ * Implementation of the Server State Machine (SSM)
+ *
+ * 
+ * Copyright (C) France Télécom R&D (DR&D/MAPS/NSS)
+ *
+ * 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 2006 The FreeRADIUS server project
+ *
+ */
+
+#ifndef _EAP_PSK_SSM_H
+#define _EAP_PSK_SSM_H
+
+#include <freeradius-devel/ident.h>
+RCSIDH(eap_psk_ssm_h, "$Id$")
+
+#include "eap_psk.h"
+#include "eap.h"
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+
+// server states
+typedef enum {
+  INIT,       // the server state machine starts in the INIT state
+  RANDSENT,
+  PCHANNEL             
+}PSK_STATE;
+
+
+// information which must be kept during the EAP-PSK session
+typedef struct psk_session_t {
+  PSK_STATE state;                                       // state of the server state machine
+  unsigned char rand_s[PSK_RANDOM_NUMBER_SIZE];          // random number generated by the server
+  unsigned char *id_p;                                   // peer identity
+  unsigned char ak[PSK_AK_SIZE];                         // authentication key
+  unsigned char kdk[PSK_KDK_SIZE];                       // derivation key
+  unsigned char tek[PSK_TEK_SIZE];                       // TEK key
+  unsigned char msk[PSK_MSK_SIZE];                       // MSK key
+  unsigned char emsk[PSK_EMSK_SIZE];                     // EMSK key
+  unsigned int nbRetry;                                  // the current number of request re emissions
+  unsigned long int pChannelReplayCounter;               // the p-channel replay counter
+  unsigned char extType;                                // the extension type if evolved authentication is used, else 0
+  unsigned char authStatus;                             // the latest R flag sent by the server
+  unsigned char isSupportedExt;                          // 0 if the peer doesn't support the specified extension
+}PSK_SESSION;
+
+
+/** 
+ *@memo                this function is the entry point of the server state machine
+ *@param        conf, pointer to the current configuration of EAP-PSK
+ *@param        session, pointer to a structure which contains information session
+ *@param        recvPacket, pointer to a received EAP_PACKET
+ *@param        sentPacket, pointer to the EAP_PACKET to send
+ *@return       0 if an error has occured
+ */
+  int pskProcess(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *recvPacket, EAP_PACKET *sentPacket);
+
+
+/** 
+ *@memo                this function corresponds to the first state of the server state machine
+ *@param        conf, pointer to the current configuration of EAP-PSK
+ *@param        session, pointer to a structure which contains information session
+ *@param        sentPacket, pointer to the EAP_PACKET to send
+ *@return       0 if an error has occured
+ */
+  int pskInit(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *sentPacket);
+
+
+/** 
+ *@memo                this function corresponds to the second state of the server state machine
+ *@param        conf, pointer to the current configuration of EAP-PSK
+ *@param        session, pointer to a structure which contains information session
+ *@param        recvPacket, pointer to a received EAP_PACKET
+ *@param        sentPacket, pointer to the EAP_PACKET to send
+ *@return       0 if an error has occured
+ */
+  int pskRandSent(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *recvPacket, EAP_PACKET *sentPacket);
+
+
+/** 
+ *@memo                this function corresponds to the third state of the server state machine
+ *@param        conf, pointer to the current configuration of EAP-PSK
+ *@param        session, pointer to a structure which contains information session
+ *@param        recvPacket, pointer to a received EAP_PACKET
+ *@param        sentPacket, pointer to the EAP_PACKET to send
+ *@return       0 if no error has occured
+ */
+  int pskPChannel(PSK_CONF *conf, PSK_SESSION *session, EAP_PACKET *recvPacket, EAP_PACKET *sentPacket);                       
+
+
+/** 
+ *@memo                this function contains the extension to EAP-PSK
+ *@param        conf, pointer to the current configuration of EAP-PSK
+ *@param        session, pointer to a structure which contains information session
+ *@param        receivedStatus, the latest R flag sent by the peer
+ *@param        dataIn, pointer to the received data
+ *@param        sizeDataIn, size of the received data
+ *@param        dataOut, pointer to a pointer that points data to send
+ *@param        sizeDataOut, pointer to the size of data to be sent (sizeDataOut must be at most equal to EXT_PAYLAOD_MAX_LEN)
+ *@return       0 if an error has occured
+ */
+  int pskExtension(PSK_CONF *conf, PSK_SESSION *session, unsigned short receivedStatus, void *dataIn, int sizeDataIn, void **dataOut, int *sizeDataOut);
+
+
+/** 
+ *@memo                this function frees an existing session from memory
+ *@param        opaque, pointer to a structure which contains information session
+ */
+  void pskFreeSession(void *opaque);
+  
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /*_EAP_PSK_SSM_H*/
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/rlm_eap_psk.cpp b/src/modules/rlm_eap/types/rlm_eap_psk/rlm_eap_psk.cpp
new file mode 100644 (file)
index 0000000..a6678fd
--- /dev/null
@@ -0,0 +1,220 @@
+/* $Id$ */
+
+/*
+ * rlm_eap_psk.cpp
+ *
+ * Implementation of the interface between the radius server and 
+ * the eap-psk protocol
+ *
+ * 
+ * Copyright (C) France Télécom R&D (DR&D/MAPS/NSS)
+ *
+ * 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 2006 The FreeRADIUS server project
+ *
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+
+
+#include "autoconf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#include "eap_psk.h"
+#include "eap_psk_ssm.h"
+
+static CONF_PARSER moduleConfig[] = {
+       { "private_key", PW_TYPE_STRING_PTR,
+         offsetof(PSK_CONF, privateKey), NULL, NULL },
+       { "server_name", PW_TYPE_STRING_PTR,
+         offsetof(PSK_CONF, id_s), NULL, "pskserver" },
+       { "peer_nai_attribute", PW_TYPE_STRING_PTR,
+         offsetof(PSK_CONF, peerNaiAttribute), NULL, "eapPskPeerNAI" },
+       { "peer_key_attribute", PW_TYPE_STRING_PTR,
+         offsetof(PSK_CONF, peerKeyAttribute), NULL, "eapPskPeerKey" },
+       { "users_file_path", PW_TYPE_STRING_PTR,
+         offsetof(PSK_CONF, usersFilePath), NULL, "/etc/raddb/users.psk" },
+       { "nb_retry", PW_TYPE_INTEGER,
+         offsetof(PSK_CONF, nbRetry), NULL, "3" },
+       { "max_delay", PW_TYPE_INTEGER,
+         offsetof(PSK_CONF, maxDelay), NULL, "5" },
+       { NULL, -1, 0, NULL, NULL }           /* end the list */
+};
+
+
+/** 
+ *@memo                this function add value pair to reply
+ */
+static void addReply(VALUE_PAIR** vp, 
+                     const char* name, unsigned char* value, int len)
+{
+       VALUE_PAIR *reply_attr;
+       reply_attr = pairmake(name, "", T_OP_EQ);
+       if (!reply_attr) {
+               DEBUG("rlm_eap_psk: "
+                     "add_reply failed to create attribute %s: %s\n", 
+                     name, librad_errstr);
+               return;
+       }
+
+       memcpy(reply_attr->vp_octets, value, len);
+       reply_attr->length = len;
+       pairadd(vp, reply_attr);
+}
+
+/*
+ *@memo        this function detaches the module
+ */
+static int pskDetach(void *arg)
+{
+       PSK_CONF *inst = (PSK_CONF *) arg;
+
+       if (inst->privateKey) free(inst->privateKey);
+       if (inst->id_s) free(inst->id_s);
+       if (inst->peerNaiAttribute) free(inst->peerNaiAttribute);
+       if (inst->peerKeyAttribute) free(inst->peerKeyAttribute);
+       if(inst->usersFilePath) free(inst->usersFilePath);
+
+       free(inst);
+
+       return 0;
+}
+
+
+/*
+ *@memo                 this function attaches the module
+ */
+static int pskAttach(CONF_SECTION *cs, void **instance)
+{
+       PSK_CONF *inst;
+
+       inst = (PSK_CONF*)malloc(sizeof(*inst));
+       if (!inst) {
+               radlog(L_ERR, "rlm_eap_psk: out of memory");
+               return -1;
+       }
+       memset(inst, 0, sizeof(*inst));
+
+       // parse the configuration attributes
+       if (cf_section_parse(cs, inst, moduleConfig) < 0) {
+         pskDetach(inst);
+         return -1;
+       }
+       
+       *instance = inst;
+       return 0;
+}
+
+
+
+/** 
+ *@memo                this function begins the conversation when the EAP-Identity response is received
+ *              send an initial eap-psk request, ie IDREQ
+ *@param        handler, pointer to specific information about the eap-psk protocol
+ */
+static int pskInitiate(void *type_arg, EAP_HANDLER *handler)
+{
+  PSK_SESSION *session;
+  PSK_CONF *conf=(PSK_CONF*)type_arg;
+
+  if(conf==NULL)
+    {
+      radlog(L_ERR,"rlm_eap_psk: Cannot initiate EAP-PSK without having its configuration");
+      return 0;
+    }
+
+  DEBUG2("rlm_eap_psk: privateKey: %s",conf->privateKey);
+  DEBUG2("rlm_eap_psk: id_s: %s", conf->id_s);
+  DEBUG2("rlm_eap_psk: peerNaiAttribute: %s", conf->peerNaiAttribute);
+  DEBUG2("rlm_eap_psk: peerKeyAttribute: %s", conf->peerKeyAttribute);
+  DEBUG2("rlm_eap_psk: usersFilePath: %s", conf->usersFilePath);
+
+  // allocate memory in order to save the state of session
+  handler->opaque=malloc(sizeof(PSK_SESSION));
+  if(!handler->opaque) {
+    radlog(L_ERR,"rlm_eap_psk: Out of memory");
+    return 0;
+  }
+
+  // save this pointer in the handler
+  session=(PSK_SESSION *)handler->opaque;
+  handler->free_opaque=pskFreeSession;
+
+  // initializing session information
+  memset(session,0,sizeof(PSK_SESSION));
+  session->state=INIT;
+   
+  handler->stage=AUTHENTICATE;
+
+  // initiate the eap-psk protocol
+  return pskProcess(conf,session,NULL,handler->eap_ds->request);
+  
+}
+
+
+
+
+/** 
+ *@memo                this function uses specific EAP-Type authentication mechanism to authenticate the user
+ *              may be called many times
+ *@param        handler, pointer to specific information about the eap-psk protocol
+ */
+static int pskAuthenticate(void *arg, EAP_HANDLER *handler)
+{
+  PSK_SESSION *session;
+  PSK_CONF *conf=(PSK_CONF*)arg;
+  int resul;
+  
+  if(conf==NULL)
+    {
+      radlog(L_ERR,"rlm_eap_psk: Cannot authenticate without having EAP-PSK configuration");
+      return 0;
+    }
+  
+  if(!handler->opaque) {
+    radlog(L_ERR,"rlm_eap_psk: Cannot authenticate without EAP-PSK session information");
+    return 0;
+  }
+  
+  // find the session information
+  session=(PSK_SESSION *)handler->opaque;
+
+  resul=pskProcess(conf,session,handler->eap_ds->response,handler->eap_ds->request);
+  
+  if(handler->eap_ds->request->code==PW_EAP_SUCCESS) {
+    // sending keys
+    addReply(&handler->request->reply->vps,"MS-MPPE-Recv-Key",session->msk,32);
+    addReply(&handler->request->reply->vps,"MS-MPPE-Send-Key",&session->msk[32],32);
+  }
+  
+  return resul;
+  
+}
+
+
+EAP_TYPE rlm_eap_psk = {
+       "eap_psk",
+       pskAttach,              // attach
+       pskInitiate,            // Start the initial request, after Identity
+       NULL,
+       pskAuthenticate,        // authentication
+       pskDetach               // detach
+};
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/userinfo.c b/src/modules/rlm_eap/types/rlm_eap_psk/userinfo.c
new file mode 100644 (file)
index 0000000..6b39f1a
--- /dev/null
@@ -0,0 +1,153 @@
+/* $Id$ */
+
+
+/*
+ * userinfo.c
+ *
+ * Implementation of the user management
+ *
+ * 
+ * Copyright (C) France Télécom R&D (DR&D/MAPS/NSS)
+ *
+ * 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 2006 The FreeRADIUS server project
+ *
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "userinfo.h"
+#include "eap_psk_ssm.h"
+#include "eap_psk.h"  //hex2Bin()
+
+
+
+userinfo_t*   pskGetUserInfo(char* path, char* peerID)
+{
+    FILE*       fp;
+    char        buff[1024]; //FIXME: give the buffer a proper size 
+                            //when we know more about ID length
+    userinfo_t* uinfo = NULL;
+    int         found = 0;
+    char*       AK = NULL;
+    char*       KDK = NULL;
+       int res;
+
+    fp = fopen(path, "r");
+    if (fp == NULL)
+       {
+           radlog(L_ERR, "pskGetUserInfo: failed to open PSK users file");
+           return NULL;
+       }
+    
+    while (!found && fgets(buff, sizeof(buff), fp)) 
+       {
+         unsigned int     i = 0;
+
+           // ignore comments
+           if (buff[0] == '#')
+               continue;
+
+           // read this login name
+           while (! isspace(buff[i]))
+               i++;
+           
+           // is it the one we looking for?
+           if ((i != strlen(peerID)) 
+               || (strncmp(peerID, buff, i) != 0))
+               continue;
+           else
+               found = 1;
+           
+           // skip spaces 
+           while (isspace(buff[i]))
+               i++;
+           
+           // prepare to store user info
+           uinfo = (userinfo_t*) malloc(sizeof(userinfo_t));
+           if (uinfo == NULL)
+               {
+                   radlog(L_ERR, "pskGetUserInfo: out of memory");
+                   return NULL;
+               }
+
+           //get AK  
+           AK = strndup(buff + i, PSK_AK_STRLEN);
+            if (AK == NULL) {
+                radlog(L_ERR, "pskGetUserInfo: out of memory");
+                               free(uinfo);
+                               return NULL;
+           }
+           //FIXME: shouldnt we check the key size?
+           /*
+             else if (strlen(AK) != 32) {
+             log();
+             return NULL;
+             }
+           */
+           res=pskHex2Bin(AK, &(uinfo->AK),PSK_AK_SIZE);
+
+               if(!res)
+               {
+                       radlog(L_ERR, "pskGetUserInfo: the key isn't in hexadecimal format");
+                       free(uinfo);
+                       free(AK);
+                       return NULL;
+               }
+                  
+           //get KDK
+           KDK = strndup(buff + i + PSK_AK_STRLEN, PSK_KDK_STRLEN);
+           if (KDK == NULL) {
+                       radlog(L_ERR, "psk_get_user_info: out of memory");
+                       free(uinfo);
+                       free(AK);
+                       return NULL;
+           }
+           //FIXME: shouldnt we check the key size?
+           /*
+             else if (strlen(KDK) != 32) { 
+             log();
+             return NULL;
+             }             
+           */
+           res=pskHex2Bin(KDK, &(uinfo->KDK),PSK_KDK_SIZE);
+
+               if(!res)
+               {
+                       radlog(L_ERR, "pskGetUserInfo: the key isn't in hexadecimal format");
+                       free(uinfo);
+                       free(AK);
+                       free(KDK);
+                       return NULL;
+               }
+          
+           free(AK);
+           free(KDK);
+       }
+   
+    
+    // if user was not found, NULL is returned
+    fclose(fp);
+    return uinfo;
+}
+
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/userinfo.h b/src/modules/rlm_eap/types/rlm_eap_psk/userinfo.h
new file mode 100644 (file)
index 0000000..7eb5b37
--- /dev/null
@@ -0,0 +1,72 @@
+/* $Id$ */
+
+
+/*
+ * userinfo.h
+ *
+ * Implementation of the user management
+ *
+ * 
+ * Copyright (C) France Télécom R&D (DR&D/MAPS/NSS)
+ *
+ * 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 2006 The FreeRADIUS server project
+ *
+ */
+
+#ifndef __USERINFO_H__
+#define __USERINFO_H__
+
+#include <freeradius-devel/ident.h>
+RCSIDH(userinfo_h, "$Id$")
+
+
+#include "eap_psk_ssm.h" // PSK_AK/KDK_SIZE
+
+
+
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+typedef struct s_userinfo {
+    //    char*          name;
+    unsigned char  AK[PSK_AK_SIZE];
+    unsigned char  KDK[PSK_KDK_SIZE];
+    //    s_userinfo*  next;
+} userinfo_t;
+
+
+
+
+#define   ASCII_PER_BYTE     2
+#define   PSK_AK_STRLEN      (PSK_AK_SIZE*ASCII_PER_BYTE)
+#define   PSK_KDK_STRLEN     (PSK_KDK_SIZE*ASCII_PER_BYTE)
+
+
+
+
+userinfo_t*  pskGetUserInfo(char*  filename, char*  peerID);
+
+//int        psk_user_free(); //A VOIR
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /*__USERINFO_H__*/
diff --git a/src/modules/rlm_eap/types/rlm_eap_psk/users.psk b/src/modules/rlm_eap/types/rlm_eap_psk/users.psk
new file mode 100644 (file)
index 0000000..e5e5c8b
--- /dev/null
@@ -0,0 +1,12 @@
+# usernames and keys are supposed to be on the same line, separated by
+# white spaces or tabs 
+# reading stops after EOF or white line
+#
+
+#user example
+aurelien        9A33DC804926D834894423BDEA4BAA59F6294F39A00D960B3A0DBB404DC62C5C
+
+
+
+
+
diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/Makefile b/src/modules/rlm_eap/types/rlm_eap_sim/Makefile
new file mode 100644 (file)
index 0000000..56b5318
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# Makefile
+#
+# Version:     $Id$
+#
+
+TARGET      = rlm_eap_sim
+SRCS        = rlm_eap_sim.c
+HEADERS     =
+RLM_CFLAGS  = $(INCLTDL) -I../.. -I../../libeap
+RLM_LIBS    =  ../../libeap/libeap.la
+RLM_INSTALL =
+
+RLM_DIR=../../
+include ${RLM_DIR}../rules.mak
+
+$(LT_OBJS): $(HEADERS)
diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/Makefile.in b/src/modules/rlm_eap/types/rlm_eap_sim/Makefile.in
deleted file mode 100644 (file)
index 9c588df..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# $Id$
-#
-
-TARGET      = @targetname@
-SRCS        = rlm_eap_sim.c 
-HEADERS     =
-RLM_CFLAGS  = -I../.. -I../../libeap $(INCLTDL)
-RLM_LIBS    = ../../libeap/libeap.la
-RLM_INSTALL =
-
-RLM_DIR=../../
-include ${RLM_DIR}../rules.mak
-
-$(LT_OBJS): $(HEADERS)
diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/configure b/src/modules/rlm_eap/types/rlm_eap_sim/configure
deleted file mode 100644 (file)
index c03f8e4..0000000
+++ /dev/null
@@ -1,3127 +0,0 @@
-#! /bin/sh
-# From configure.in Revision: 1.3.4.1 .
-# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59.
-#
-# Copyright (C) 2003 Free Software Foundation, Inc.
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-## --------------------- ##
-## M4sh Initialization.  ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
-  set -o posix
-fi
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
-  as_unset=unset
-else
-  as_unset=false
-fi
-
-
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
-  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
-  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
-  LC_TELEPHONE LC_TIME
-do
-  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
-    eval $as_var=C; export $as_var
-  else
-    $as_unset $as_var
-  fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
-  as_basename=basename
-else
-  as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
-        X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)$' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
-         /^X\/\(\/\/\)$/{ s//\1/; q; }
-         /^X\/\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-
-
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
-fi
-
-
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
-  # Find who we are.  Look in the path if we contain no path at all
-  # relative or not.
-  case $0 in
-    *[\\/]* ) as_myself=$0 ;;
-    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
-       ;;
-  esac
-  # We did not find ourselves, most probably we were run as `sh COMMAND'
-  # in which case we are not to be found in the path.
-  if test "x$as_myself" = x; then
-    as_myself=$0
-  fi
-  if test ! -f "$as_myself"; then
-    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
-   { (exit 1); exit 1; }; }
-  fi
-  case $CONFIG_SHELL in
-  '')
-    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for as_base in sh bash ksh sh5; do
-        case $as_dir in
-        /*)
-          if ("$as_dir/$as_base" -c '
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
-            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
-            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
-            CONFIG_SHELL=$as_dir/$as_base
-            export CONFIG_SHELL
-            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
-          fi;;
-        esac
-       done
-done
-;;
-  esac
-
-  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
-  # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line before each line; the second 'sed' does the real
-  # work.  The second script uses 'N' to pair each line-number line
-  # with the numbered line, and appends trailing '-' during
-  # substitution so that $LINENO is not a special case at line end.
-  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
-  sed '=' <$as_myself |
-    sed '
-      N
-      s,$,-,
-      : loop
-      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
-      t loop
-      s,-$,,
-      s,^['$as_cr_digits']*\n,,
-    ' >$as_me.lineno &&
-  chmod +x $as_me.lineno ||
-    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
-   { (exit 1); exit 1; }; }
-
-  # Don't try to exec as it changes $[0], causing all sort of problems
-  # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensible to this).
-  . ./$as_me.lineno
-  # Exit status is that of the last command.
-  exit
-}
-
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
-  *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T='     ' ;;
-  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
-  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
-  # We could just check for DJGPP; but this test a) works b) is more generic
-  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
-  if test -f conf$$.exe; then
-    # Don't use ln at all; we don't have any links
-    as_ln_s='cp -p'
-  else
-    as_ln_s='ln -s'
-  fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s=ln
-else
-  as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.file
-
-if mkdir -p . 2>/dev/null; then
-  as_mkdir_p=:
-else
-  test -d ./-p && rmdir ./-p
-  as_mkdir_p=false
-fi
-
-as_executable_p="test -f"
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS="  $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
-
-# Name of the host.
-# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
-# so uname gets run too.
-ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
-
-exec 6>&1
-
-#
-# Initializations.
-#
-ac_default_prefix=/usr/local
-ac_config_libobj_dir=.
-cross_compiling=no
-subdirs=
-MFLAGS=
-MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-# Maximum number of lines to put in a shell here document.
-# This variable seems obsolete.  It should probably be removed, and
-# only ac_max_sed_lines should be used.
-: ${ac_max_here_lines=38}
-
-# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-
-ac_unique_file="rlm_eap_sim.c"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT eap_sim_ldflags eap_sim_cflags targetname LIBOBJS LTLIBOBJS'
-ac_subst_files=''
-
-# Initialize some variables set by options.
-ac_init_help=
-ac_init_version=false
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-cache_file=/dev/null
-exec_prefix=NONE
-no_create=
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-verbose=
-x_includes=NONE
-x_libraries=NONE
-
-# Installation directory options.
-# These are left unexpanded so users can "make install exec_prefix=/foo"
-# and all the variables that are supposed to be based on exec_prefix
-# by default will actually change.
-# Use braces instead of parens because sh, perl, etc. also accept them.
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-libdir='${exec_prefix}/lib'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-infodir='${prefix}/info'
-mandir='${prefix}/man'
-
-ac_prev=
-for ac_option
-do
-  # If the previous option needs an argument, assign it.
-  if test -n "$ac_prev"; then
-    eval "$ac_prev=\$ac_option"
-    ac_prev=
-    continue
-  fi
-
-  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
-
-  # Accept the important Cygnus configure options, so we can diagnose typos.
-
-  case $ac_option in
-
-  -bindir | --bindir | --bindi | --bind | --bin | --bi)
-    ac_prev=bindir ;;
-  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
-    bindir=$ac_optarg ;;
-
-  -build | --build | --buil | --bui | --bu)
-    ac_prev=build_alias ;;
-  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
-    build_alias=$ac_optarg ;;
-
-  -cache-file | --cache-file | --cache-fil | --cache-fi \
-  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
-    ac_prev=cache_file ;;
-  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
-  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
-    cache_file=$ac_optarg ;;
-
-  --config-cache | -C)
-    cache_file=config.cache ;;
-
-  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
-    ac_prev=datadir ;;
-  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
-  | --da=*)
-    datadir=$ac_optarg ;;
-
-  -disable-* | --disable-*)
-    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
-   { (exit 1); exit 1; }; }
-    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
-    eval "enable_$ac_feature=no" ;;
-
-  -enable-* | --enable-*)
-    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
-   { (exit 1); exit 1; }; }
-    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
-    case $ac_option in
-      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
-      *) ac_optarg=yes ;;
-    esac
-    eval "enable_$ac_feature='$ac_optarg'" ;;
-
-  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
-  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
-  | --exec | --exe | --ex)
-    ac_prev=exec_prefix ;;
-  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
-  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
-  | --exec=* | --exe=* | --ex=*)
-    exec_prefix=$ac_optarg ;;
-
-  -gas | --gas | --ga | --g)
-    # Obsolete; use --with-gas.
-    with_gas=yes ;;
-
-  -help | --help | --hel | --he | -h)
-    ac_init_help=long ;;
-  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
-    ac_init_help=recursive ;;
-  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
-    ac_init_help=short ;;
-
-  -host | --host | --hos | --ho)
-    ac_prev=host_alias ;;
-  -host=* | --host=* | --hos=* | --ho=*)
-    host_alias=$ac_optarg ;;
-
-  -includedir | --includedir | --includedi | --included | --include \
-  | --includ | --inclu | --incl | --inc)
-    ac_prev=includedir ;;
-  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
-  | --includ=* | --inclu=* | --incl=* | --inc=*)
-    includedir=$ac_optarg ;;
-
-  -infodir | --infodir | --infodi | --infod | --info | --inf)
-    ac_prev=infodir ;;
-  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
-    infodir=$ac_optarg ;;
-
-  -libdir | --libdir | --libdi | --libd)
-    ac_prev=libdir ;;
-  -libdir=* | --libdir=* | --libdi=* | --libd=*)
-    libdir=$ac_optarg ;;
-
-  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
-  | --libexe | --libex | --libe)
-    ac_prev=libexecdir ;;
-  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
-  | --libexe=* | --libex=* | --libe=*)
-    libexecdir=$ac_optarg ;;
-
-  -localstatedir | --localstatedir | --localstatedi | --localstated \
-  | --localstate | --localstat | --localsta | --localst \
-  | --locals | --local | --loca | --loc | --lo)
-    ac_prev=localstatedir ;;
-  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
-  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
-  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
-    localstatedir=$ac_optarg ;;
-
-  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
-    ac_prev=mandir ;;
-  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
-    mandir=$ac_optarg ;;
-
-  -nfp | --nfp | --nf)
-    # Obsolete; use --without-fp.
-    with_fp=no ;;
-
-  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
-  | --no-cr | --no-c | -n)
-    no_create=yes ;;
-
-  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
-  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
-    no_recursion=yes ;;
-
-  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
-  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
-  | --oldin | --oldi | --old | --ol | --o)
-    ac_prev=oldincludedir ;;
-  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
-  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
-  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
-    oldincludedir=$ac_optarg ;;
-
-  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
-    ac_prev=prefix ;;
-  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
-    prefix=$ac_optarg ;;
-
-  -program-prefix | --program-prefix | --program-prefi | --program-pref \
-  | --program-pre | --program-pr | --program-p)
-    ac_prev=program_prefix ;;
-  -program-prefix=* | --program-prefix=* | --program-prefi=* \
-  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
-    program_prefix=$ac_optarg ;;
-
-  -program-suffix | --program-suffix | --program-suffi | --program-suff \
-  | --program-suf | --program-su | --program-s)
-    ac_prev=program_suffix ;;
-  -program-suffix=* | --program-suffix=* | --program-suffi=* \
-  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
-    program_suffix=$ac_optarg ;;
-
-  -program-transform-name | --program-transform-name \
-  | --program-transform-nam | --program-transform-na \
-  | --program-transform-n | --program-transform- \
-  | --program-transform | --program-transfor \
-  | --program-transfo | --program-transf \
-  | --program-trans | --program-tran \
-  | --progr-tra | --program-tr | --program-t)
-    ac_prev=program_transform_name ;;
-  -program-transform-name=* | --program-transform-name=* \
-  | --program-transform-nam=* | --program-transform-na=* \
-  | --program-transform-n=* | --program-transform-=* \
-  | --program-transform=* | --program-transfor=* \
-  | --program-transfo=* | --program-transf=* \
-  | --program-trans=* | --program-tran=* \
-  | --progr-tra=* | --program-tr=* | --program-t=*)
-    program_transform_name=$ac_optarg ;;
-
-  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-  | -silent | --silent | --silen | --sile | --sil)
-    silent=yes ;;
-
-  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
-    ac_prev=sbindir ;;
-  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
-  | --sbi=* | --sb=*)
-    sbindir=$ac_optarg ;;
-
-  -sharedstatedir | --sharedstatedir | --sharedstatedi \
-  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
-  | --sharedst | --shareds | --shared | --share | --shar \
-  | --sha | --sh)
-    ac_prev=sharedstatedir ;;
-  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
-  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
-  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
-  | --sha=* | --sh=*)
-    sharedstatedir=$ac_optarg ;;
-
-  -site | --site | --sit)
-    ac_prev=site ;;
-  -site=* | --site=* | --sit=*)
-    site=$ac_optarg ;;
-
-  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
-    ac_prev=srcdir ;;
-  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
-    srcdir=$ac_optarg ;;
-
-  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
-  | --syscon | --sysco | --sysc | --sys | --sy)
-    ac_prev=sysconfdir ;;
-  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
-  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
-    sysconfdir=$ac_optarg ;;
-
-  -target | --target | --targe | --targ | --tar | --ta | --t)
-    ac_prev=target_alias ;;
-  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
-    target_alias=$ac_optarg ;;
-
-  -v | -verbose | --verbose | --verbos | --verbo | --verb)
-    verbose=yes ;;
-
-  -version | --version | --versio | --versi | --vers | -V)
-    ac_init_version=: ;;
-
-  -with-* | --with-*)
-    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid package name: $ac_package" >&2
-   { (exit 1); exit 1; }; }
-    ac_package=`echo $ac_package| sed 's/-/_/g'`
-    case $ac_option in
-      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
-      *) ac_optarg=yes ;;
-    esac
-    eval "with_$ac_package='$ac_optarg'" ;;
-
-  -without-* | --without-*)
-    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid package name: $ac_package" >&2
-   { (exit 1); exit 1; }; }
-    ac_package=`echo $ac_package | sed 's/-/_/g'`
-    eval "with_$ac_package=no" ;;
-
-  --x)
-    # Obsolete; use --with-x.
-    with_x=yes ;;
-
-  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
-  | --x-incl | --x-inc | --x-in | --x-i)
-    ac_prev=x_includes ;;
-  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
-  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
-    x_includes=$ac_optarg ;;
-
-  -x-libraries | --x-libraries | --x-librarie | --x-librari \
-  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
-    ac_prev=x_libraries ;;
-  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
-  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
-    x_libraries=$ac_optarg ;;
-
-  -*) { echo "$as_me: error: unrecognized option: $ac_option
-Try \`$0 --help' for more information." >&2
-   { (exit 1); exit 1; }; }
-    ;;
-
-  *=*)
-    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
-   { (exit 1); exit 1; }; }
-    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
-    eval "$ac_envvar='$ac_optarg'"
-    export $ac_envvar ;;
-
-  *)
-    # FIXME: should be removed in autoconf 3.0.
-    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
-    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
-    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
-    ;;
-
-  esac
-done
-
-if test -n "$ac_prev"; then
-  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
-  { echo "$as_me: error: missing argument to $ac_option" >&2
-   { (exit 1); exit 1; }; }
-fi
-
-# Be sure to have absolute paths.
-for ac_var in exec_prefix prefix
-do
-  eval ac_val=$`echo $ac_var`
-  case $ac_val in
-    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
-    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
-   { (exit 1); exit 1; }; };;
-  esac
-done
-
-# Be sure to have absolute paths.
-for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
-             localstatedir libdir includedir oldincludedir infodir mandir
-do
-  eval ac_val=$`echo $ac_var`
-  case $ac_val in
-    [\\/$]* | ?:[\\/]* ) ;;
-    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
-   { (exit 1); exit 1; }; };;
-  esac
-done
-
-# There might be people who depend on the old broken behavior: `$host'
-# used to hold the argument of --host etc.
-# FIXME: To remove some day.
-build=$build_alias
-host=$host_alias
-target=$target_alias
-
-# FIXME: To remove some day.
-if test "x$host_alias" != x; then
-  if test "x$build_alias" = x; then
-    cross_compiling=maybe
-    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
-    If a cross compiler is detected then cross compile mode will be used." >&2
-  elif test "x$build_alias" != "x$host_alias"; then
-    cross_compiling=yes
-  fi
-fi
-
-ac_tool_prefix=
-test -n "$host_alias" && ac_tool_prefix=$host_alias-
-
-test "$silent" = yes && exec 6>/dev/null
-
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
-  ac_srcdir_defaulted=yes
-  # Try the directory containing this script, then its parent.
-  ac_confdir=`(dirname "$0") 2>/dev/null ||
-$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$0" : 'X\(//\)[^/]' \| \
-        X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X"$0" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-         /^X\(\/\/\)$/{ s//\1/; q; }
-         /^X\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-  srcdir=$ac_confdir
-  if test ! -r $srcdir/$ac_unique_file; then
-    srcdir=..
-  fi
-else
-  ac_srcdir_defaulted=no
-fi
-if test ! -r $srcdir/$ac_unique_file; then
-  if test "$ac_srcdir_defaulted" = yes; then
-    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
-   { (exit 1); exit 1; }; }
-  else
-    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
-   { (exit 1); exit 1; }; }
-  fi
-fi
-(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
-  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
-   { (exit 1); exit 1; }; }
-srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
-ac_env_build_alias_set=${build_alias+set}
-ac_env_build_alias_value=$build_alias
-ac_cv_env_build_alias_set=${build_alias+set}
-ac_cv_env_build_alias_value=$build_alias
-ac_env_host_alias_set=${host_alias+set}
-ac_env_host_alias_value=$host_alias
-ac_cv_env_host_alias_set=${host_alias+set}
-ac_cv_env_host_alias_value=$host_alias
-ac_env_target_alias_set=${target_alias+set}
-ac_env_target_alias_value=$target_alias
-ac_cv_env_target_alias_set=${target_alias+set}
-ac_cv_env_target_alias_value=$target_alias
-ac_env_CC_set=${CC+set}
-ac_env_CC_value=$CC
-ac_cv_env_CC_set=${CC+set}
-ac_cv_env_CC_value=$CC
-ac_env_CFLAGS_set=${CFLAGS+set}
-ac_env_CFLAGS_value=$CFLAGS
-ac_cv_env_CFLAGS_set=${CFLAGS+set}
-ac_cv_env_CFLAGS_value=$CFLAGS
-ac_env_LDFLAGS_set=${LDFLAGS+set}
-ac_env_LDFLAGS_value=$LDFLAGS
-ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
-ac_cv_env_LDFLAGS_value=$LDFLAGS
-ac_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_env_CPPFLAGS_value=$CPPFLAGS
-ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_cv_env_CPPFLAGS_value=$CPPFLAGS
-
-#
-# Report the --help message.
-#
-if test "$ac_init_help" = "long"; then
-  # Omit some internal or obsolete options to make the list less imposing.
-  # This message is too long to be a string in the A/UX 3.1 sh.
-  cat <<_ACEOF
-\`configure' configures this package to adapt to many kinds of systems.
-
-Usage: $0 [OPTION]... [VAR=VALUE]...
-
-To assign environment variables (e.g., CC, CFLAGS...), specify them as
-VAR=VALUE.  See below for descriptions of some of the useful variables.
-
-Defaults for the options are specified in brackets.
-
-Configuration:
-  -h, --help              display this help and exit
-      --help=short        display options specific to this package
-      --help=recursive    display the short help of all the included packages
-  -V, --version           display version information and exit
-  -q, --quiet, --silent   do not print \`checking...' messages
-      --cache-file=FILE   cache test results in FILE [disabled]
-  -C, --config-cache      alias for \`--cache-file=config.cache'
-  -n, --no-create         do not create output files
-      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
-
-_ACEOF
-
-  cat <<_ACEOF
-Installation directories:
-  --prefix=PREFIX         install architecture-independent files in PREFIX
-                         [$ac_default_prefix]
-  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
-                         [PREFIX]
-
-By default, \`make install' will install all the files in
-\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
-an installation prefix other than \`$ac_default_prefix' using \`--prefix',
-for instance \`--prefix=\$HOME'.
-
-For better control, use the options below.
-
-Fine tuning of the installation directories:
-  --bindir=DIR           user executables [EPREFIX/bin]
-  --sbindir=DIR          system admin executables [EPREFIX/sbin]
-  --libexecdir=DIR       program executables [EPREFIX/libexec]
-  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
-  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
-  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
-  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
-  --libdir=DIR           object code libraries [EPREFIX/lib]
-  --includedir=DIR       C header files [PREFIX/include]
-  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
-  --infodir=DIR          info documentation [PREFIX/info]
-  --mandir=DIR           man documentation [PREFIX/man]
-_ACEOF
-
-  cat <<\_ACEOF
-_ACEOF
-fi
-
-if test -n "$ac_init_help"; then
-
-  cat <<\_ACEOF
-
-Some influential environment variables:
-  CC          C compiler command
-  CFLAGS      C compiler flags
-  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
-              nonstandard directory <lib dir>
-  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
-              headers in a nonstandard directory <include dir>
-
-Use these variables to override the choices made by `configure' or to help
-it to find libraries and programs with nonstandard names/locations.
-
-_ACEOF
-fi
-
-if test "$ac_init_help" = "recursive"; then
-  # If there are subdirs, report their specific --help.
-  ac_popdir=`pwd`
-  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
-    test -d $ac_dir || continue
-    ac_builddir=.
-
-if test "$ac_dir" != .; then
-  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A "../" for each directory in $ac_dir_suffix.
-  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
-  ac_dir_suffix= ac_top_builddir=
-fi
-
-case $srcdir in
-  .)  # No --srcdir option.  We are building in place.
-    ac_srcdir=.
-    if test -z "$ac_top_builddir"; then
-       ac_top_srcdir=.
-    else
-       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
-    fi ;;
-  [\\/]* | ?:[\\/]* )  # Absolute path.
-    ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir ;;
-  *) # Relative path.
-    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
-  case "$ac_dir" in
-  .) ac_abs_builddir=`pwd`;;
-  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
-  *) ac_abs_builddir=`pwd`/"$ac_dir";;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
-  case ${ac_top_builddir}. in
-  .) ac_abs_top_builddir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
-  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
-  case $ac_srcdir in
-  .) ac_abs_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
-  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
-  case $ac_top_srcdir in
-  .) ac_abs_top_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
-  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
-  esac;;
-esac
-
-    cd $ac_dir
-    # Check for guested configure; otherwise get Cygnus style configure.
-    if test -f $ac_srcdir/configure.gnu; then
-      echo
-      $SHELL $ac_srcdir/configure.gnu  --help=recursive
-    elif test -f $ac_srcdir/configure; then
-      echo
-      $SHELL $ac_srcdir/configure  --help=recursive
-    elif test -f $ac_srcdir/configure.ac ||
-          test -f $ac_srcdir/configure.in; then
-      echo
-      $ac_configure --help
-    else
-      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
-    fi
-    cd $ac_popdir
-  done
-fi
-
-test -n "$ac_init_help" && exit 0
-if $ac_init_version; then
-  cat <<\_ACEOF
-
-Copyright (C) 2003 Free Software Foundation, Inc.
-This configure script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it.
-_ACEOF
-  exit 0
-fi
-exec 5>config.log
-cat >&5 <<_ACEOF
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-
-It was created by $as_me, which was
-generated by GNU Autoconf 2.59.  Invocation command line was
-
-  $ $0 $@
-
-_ACEOF
-{
-cat <<_ASUNAME
-## --------- ##
-## Platform. ##
-## --------- ##
-
-hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
-/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
-
-/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
-/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
-hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
-/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
-/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
-/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
-
-_ASUNAME
-
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  echo "PATH: $as_dir"
-done
-
-} >&5
-
-cat >&5 <<_ACEOF
-
-
-## ----------- ##
-## Core tests. ##
-## ----------- ##
-
-_ACEOF
-
-
-# Keep a trace of the command line.
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Strip out --silent because we don't want to record it for future runs.
-# Also quote any args containing shell meta-characters.
-# Make two passes to allow for proper duplicate-argument suppression.
-ac_configure_args=
-ac_configure_args0=
-ac_configure_args1=
-ac_sep=
-ac_must_keep_next=false
-for ac_pass in 1 2
-do
-  for ac_arg
-  do
-    case $ac_arg in
-    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
-    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-    | -silent | --silent | --silen | --sile | --sil)
-      continue ;;
-    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
-      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
-    esac
-    case $ac_pass in
-    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
-    2)
-      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
-      if test $ac_must_keep_next = true; then
-       ac_must_keep_next=false # Got value, back to normal.
-      else
-       case $ac_arg in
-         *=* | --config-cache | -C | -disable-* | --disable-* \
-         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
-         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
-         | -with-* | --with-* | -without-* | --without-* | --x)
-           case "$ac_configure_args0 " in
-             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
-           esac
-           ;;
-         -* ) ac_must_keep_next=true ;;
-       esac
-      fi
-      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
-      # Get rid of the leading space.
-      ac_sep=" "
-      ;;
-    esac
-  done
-done
-$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
-$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
-
-# When interrupted or exit'd, cleanup temporary files, and complete
-# config.log.  We remove comments because anyway the quotes in there
-# would cause problems or look ugly.
-# WARNING: Be sure not to use single quotes in there, as some shells,
-# such as our DU 5.0 friend, will then `close' the trap.
-trap 'exit_status=$?
-  # Save into config.log some information that might help in debugging.
-  {
-    echo
-
-    cat <<\_ASBOX
-## ---------------- ##
-## Cache variables. ##
-## ---------------- ##
-_ASBOX
-    echo
-    # The following way of writing the cache mishandles newlines in values,
-{
-  (set) 2>&1 |
-    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
-    *ac_space=\ *)
-      sed -n \
-       "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
-         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
-      ;;
-    *)
-      sed -n \
-       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
-      ;;
-    esac;
-}
-    echo
-
-    cat <<\_ASBOX
-## ----------------- ##
-## Output variables. ##
-## ----------------- ##
-_ASBOX
-    echo
-    for ac_var in $ac_subst_vars
-    do
-      eval ac_val=$`echo $ac_var`
-      echo "$ac_var='"'"'$ac_val'"'"'"
-    done | sort
-    echo
-
-    if test -n "$ac_subst_files"; then
-      cat <<\_ASBOX
-## ------------- ##
-## Output files. ##
-## ------------- ##
-_ASBOX
-      echo
-      for ac_var in $ac_subst_files
-      do
-       eval ac_val=$`echo $ac_var`
-       echo "$ac_var='"'"'$ac_val'"'"'"
-      done | sort
-      echo
-    fi
-
-    if test -s confdefs.h; then
-      cat <<\_ASBOX
-## ----------- ##
-## confdefs.h. ##
-## ----------- ##
-_ASBOX
-      echo
-      sed "/^$/d" confdefs.h | sort
-      echo
-    fi
-    test "$ac_signal" != 0 &&
-      echo "$as_me: caught signal $ac_signal"
-    echo "$as_me: exit $exit_status"
-  } >&5
-  rm -f core *.core &&
-  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
-    exit $exit_status
-     ' 0
-for ac_signal in 1 2 13 15; do
-  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
-done
-ac_signal=0
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo >confdefs.h
-
-# Predefined preprocessor variables.
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
-
-
-# Let the site file select an alternate cache file if it wants to.
-# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
-  if test "x$prefix" != xNONE; then
-    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
-  else
-    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
-  fi
-fi
-for ac_site_file in $CONFIG_SITE; do
-  if test -r "$ac_site_file"; then
-    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
-echo "$as_me: loading site script $ac_site_file" >&6;}
-    sed 's/^/| /' "$ac_site_file" >&5
-    . "$ac_site_file"
-  fi
-done
-
-if test -r "$cache_file"; then
-  # Some versions of bash will fail to source /dev/null (special
-  # files actually), so we avoid doing that.
-  if test -f "$cache_file"; then
-    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
-echo "$as_me: loading cache $cache_file" >&6;}
-    case $cache_file in
-      [\\/]* | ?:[\\/]* ) . $cache_file;;
-      *)                      . ./$cache_file;;
-    esac
-  fi
-else
-  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
-echo "$as_me: creating cache $cache_file" >&6;}
-  >$cache_file
-fi
-
-# Check that the precious variables saved in the cache have kept the same
-# value.
-ac_cache_corrupted=false
-for ac_var in `(set) 2>&1 |
-              sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
-  eval ac_old_set=\$ac_cv_env_${ac_var}_set
-  eval ac_new_set=\$ac_env_${ac_var}_set
-  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
-  eval ac_new_val="\$ac_env_${ac_var}_value"
-  case $ac_old_set,$ac_new_set in
-    set,)
-      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
-      ac_cache_corrupted=: ;;
-    ,set)
-      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
-      ac_cache_corrupted=: ;;
-    ,);;
-    *)
-      if test "x$ac_old_val" != "x$ac_new_val"; then
-       { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
-echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
-       { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
-echo "$as_me:   former value:  $ac_old_val" >&2;}
-       { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
-echo "$as_me:   current value: $ac_new_val" >&2;}
-       ac_cache_corrupted=:
-      fi;;
-  esac
-  # Pass precious variables to config.status.
-  if test "$ac_new_set" = set; then
-    case $ac_new_val in
-    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
-      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
-    *) ac_arg=$ac_var=$ac_new_val ;;
-    esac
-    case " $ac_configure_args " in
-      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
-      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
-    esac
-  fi
-done
-if $ac_cache_corrupted; then
-  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
-echo "$as_me: error: changes in the environment can compromise the build" >&2;}
-  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
-echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-fail=
-SMART_LIBS=
-SMART_CLFAGS=
-if test x$with_rlm_eap_sim != xno; then
-
-       ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}gcc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_CC"; then
-  ac_ct_CC=$CC
-  # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="gcc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  CC=$ac_ct_CC
-else
-  CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
-  if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_CC"; then
-  ac_ct_CC=$CC
-  # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  CC=$ac_ct_CC
-else
-  CC="$ac_cv_prog_CC"
-fi
-
-fi
-if test -z "$CC"; then
-  # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-  ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
-       ac_prog_rejected=yes
-       continue
-     fi
-    ac_cv_prog_CC="cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-if test $ac_prog_rejected = yes; then
-  # We found a bogon in the path, so make sure we never use it.
-  set dummy $ac_cv_prog_CC
-  shift
-  if test $# != 0; then
-    # We chose a different compiler from the bogus one.
-    # However, it has the same basename, so the bogon will be chosen
-    # first if we set CC to just the basename; use the full file name.
-    shift
-    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
-  fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$CC"; then
-  if test -n "$ac_tool_prefix"; then
-  for ac_prog in cl
-  do
-    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-    test -n "$CC" && break
-  done
-fi
-if test -z "$CC"; then
-  ac_ct_CC=$CC
-  for ac_prog in cl
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  test -n "$ac_ct_CC" && break
-done
-
-  CC=$ac_ct_CC
-fi
-
-fi
-
-
-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-
-# Provide some information about the compiler.
-echo "$as_me:$LINENO:" \
-     "checking for C compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
-  (eval $ac_compiler --version </dev/null >&5) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
-  (eval $ac_compiler -v </dev/null >&5) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
-  (eval $ac_compiler -V </dev/null >&5) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.exe b.out"
-# Try to create an executable without -o first, disregard a.out.
-# It will help us diagnose broken compilers, and finding out an intuition
-# of exeext.
-echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
-echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
-ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
-  (eval $ac_link_default) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  # Find the output, starting from the most likely.  This scheme is
-# not robust to junk in `.', hence go to wildcards (a.*) only as a last
-# resort.
-
-# Be careful to initialize this variable, since it used to be cached.
-# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
-ac_cv_exeext=
-# b.out is created by i960 compilers.
-for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
-do
-  test -f "$ac_file" || continue
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
-       ;;
-    conftest.$ac_ext )
-       # This is the source file.
-       ;;
-    [ab].out )
-       # We found the default executable, but exeext='' is most
-       # certainly right.
-       break;;
-    *.* )
-       ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-       # FIXME: I believe we export ac_cv_exeext for Libtool,
-       # but it would be cool to find out if it's true.  Does anybody
-       # maintain Libtool? --akim.
-       export ac_cv_exeext
-       break;;
-    * )
-       break;;
-  esac
-done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
-See \`config.log' for more details." >&5
-echo "$as_me: error: C compiler cannot create executables
-See \`config.log' for more details." >&2;}
-   { (exit 77); exit 77; }; }
-fi
-
-ac_exeext=$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6
-
-# Check the compiler produces executables we can run.  If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether the C compiler works" >&5
-echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
-# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
-  if { ac_try='./$ac_file'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-    cross_compiling=no
-  else
-    if test "$cross_compiling" = maybe; then
-       cross_compiling=yes
-    else
-       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-    fi
-  fi
-fi
-echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
-
-rm -f a.out a.exe conftest$ac_cv_exeext b.out
-ac_clean_files=$ac_clean_files_save
-# Check the compiler produces executables we can run.  If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
-echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
-echo "$as_me:$LINENO: result: $cross_compiling" >&5
-echo "${ECHO_T}$cross_compiling" >&6
-
-echo "$as_me:$LINENO: checking for suffix of executables" >&5
-echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  # If both `conftest.exe' and `conftest' are `present' (well, observable)
-# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
-# work properly (i.e., refer to `conftest.exe'), while it won't with
-# `rm'.
-for ac_file in conftest.exe conftest conftest.*; do
-  test -f "$ac_file" || continue
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
-    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-         export ac_cv_exeext
-         break;;
-    * ) break;;
-  esac
-done
-else
-  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
-echo "${ECHO_T}$ac_cv_exeext" >&6
-
-rm -f conftest.$ac_ext
-EXEEXT=$ac_cv_exeext
-ac_exeext=$EXEEXT
-echo "$as_me:$LINENO: checking for suffix of object files" >&5
-echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
-if test "${ac_cv_objext+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.o conftest.obj
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
-    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
-       break;;
-  esac
-done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest.$ac_cv_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
-echo "${ECHO_T}$ac_cv_objext" >&6
-OBJEXT=$ac_cv_objext
-ac_objext=$OBJEXT
-echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-#ifndef __GNUC__
-       choke me
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_compiler_gnu=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_compiler_gnu=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
-fi
-echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
-GCC=`test $ac_compiler_gnu = yes && echo yes`
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-CFLAGS="-g"
-echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_g+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_prog_cc_g=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_prog_cc_g=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
-if test "$ac_test_CFLAGS" = set; then
-  CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
-  if test "$GCC" = yes; then
-    CFLAGS="-g -O2"
-  else
-    CFLAGS="-g"
-  fi
-else
-  if test "$GCC" = yes; then
-    CFLAGS="-O2"
-  else
-    CFLAGS=
-  fi
-fi
-echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
-echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_stdc+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_prog_cc_stdc=no
-ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
-     char **p;
-     int i;
-{
-  return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
-  char *s;
-  va_list v;
-  va_start (v,p);
-  s = g (p, va_arg (v,int));
-  va_end (v);
-  return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
-   function prototypes and stuff, but not '\xHH' hex character constants.
-   These don't provoke an error unfortunately, instead are silently treated
-   as 'x'.  The following induces an error, until -std1 is added to get
-   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
-   array size at least.  It's necessary to write '\x00'==0 to get something
-   that's true only with -std1.  */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
-
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
-  ;
-  return 0;
-}
-_ACEOF
-# Don't try gcc -ansi; that turns off useful extensions and
-# breaks some systems' header files.
-# AIX                  -qlanglvl=ansi
-# Ultrix and OSF/1     -std1
-# HP-UX 10.20 and later        -Ae
-# HP-UX older versions -Aa -D_HPUX_SOURCE
-# SVR4                 -Xc -D__EXTENSIONS__
-for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
-  CC="$ac_save_CC $ac_arg"
-  rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_prog_cc_stdc=$ac_arg
-break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext
-done
-rm -f conftest.$ac_ext conftest.$ac_objext
-CC=$ac_save_CC
-
-fi
-
-case "x$ac_cv_prog_cc_stdc" in
-  x|xno)
-    echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6 ;;
-  *)
-    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
-    CC="$CC $ac_cv_prog_cc_stdc" ;;
-esac
-
-# Some people use a C++ compiler to compile C.  Since we use `exit',
-# in C++ we need to declare it.  In case someone uses the same compiler
-# for both compiling C and C++ we need to have the C++ compiler decide
-# the declaration of exit, since it's the most demanding environment.
-cat >conftest.$ac_ext <<_ACEOF
-#ifndef __cplusplus
-  choke me
-#endif
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  for ac_declaration in \
-   '' \
-   'extern "C" void std::exit (int) throw (); using std::exit;' \
-   'extern "C" void std::exit (int); using std::exit;' \
-   'extern "C" void exit (int) throw ();' \
-   'extern "C" void exit (int);' \
-   'void exit (int);'
-do
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_declaration
-#include <stdlib.h>
-int
-main ()
-{
-exit (42);
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-continue
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_declaration
-int
-main ()
-{
-exit (42);
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-rm -f conftest*
-if test -n "$ac_declaration"; then
-  echo '#ifdef __cplusplus' >>confdefs.h
-  echo $ac_declaration      >>confdefs.h
-  echo '#endif'             >>confdefs.h
-fi
-
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-       targetname=rlm_eap_sim
-else
-       targetname=
-       echo \*\*\* module rlm_eap_sim is disabled.
-fi
-
-if test x"$fail" != x""; then
-       if test x"${enable_strict_dependencies}" = x"yes"; then
-               { { echo "$as_me:$LINENO: error: set --without-rlm_eap_sim to disable it explicitly." >&5
-echo "$as_me: error: set --without-rlm_eap_sim to disable it explicitly." >&2;}
-   { (exit 1); exit 1; }; }
-       else
-               { echo "$as_me:$LINENO: WARNING: silently not building rlm_eap_sim." >&5
-echo "$as_me: WARNING: silently not building rlm_eap_sim." >&2;}
-               { echo "$as_me:$LINENO: WARNING: FAILURE: rlm_eap_sim requires: $fail." >&5
-echo "$as_me: WARNING: FAILURE: rlm_eap_sim requires: $fail." >&2;}
-               if test x"$headersuggestion" != x; then
-                       { echo "$as_me:$LINENO: WARNING: $headersuggestion" >&5
-echo "$as_me: WARNING: $headersuggestion" >&2;}
-               fi
-               if test x"$libsuggestion" != x; then
-                       { echo "$as_me:$LINENO: WARNING: $libsuggestion" >&5
-echo "$as_me: WARNING: $libsuggestion" >&2;}
-               fi
-               targetname=""
-       fi
-fi
-
-eap_sim_ldflags=$SMART_LIBS
-eap_sim_cflags=$SMART_CFLAGS
-
-
-
-          ac_config_files="$ac_config_files Makefile"
-cat >confcache <<\_ACEOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs, see configure's option --config-cache.
-# It is not useful on other systems.  If it contains results you don't
-# want to keep, you may remove or edit it.
-#
-# config.status only pays attention to the cache file if you give it
-# the --recheck option to rerun configure.
-#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
-# following values.
-
-_ACEOF
-
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-{
-  (set) 2>&1 |
-    case `(ac_space=' '; set | grep ac_space) 2>&1` in
-    *ac_space=\ *)
-      # `set' does not quote correctly, so add quotes (double-quote
-      # substitution turns \\\\ into \\, and sed turns \\ into \).
-      sed -n \
-       "s/'/'\\\\''/g;
-         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
-      ;;
-    *)
-      # `set' quotes correctly as required by POSIX, so do not add quotes.
-      sed -n \
-       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
-      ;;
-    esac;
-} |
-  sed '
-     t clear
-     : clear
-     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
-     t end
-     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
-     : end' >>confcache
-if diff $cache_file confcache >/dev/null 2>&1; then :; else
-  if test -w $cache_file; then
-    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
-    cat confcache >$cache_file
-  else
-    echo "not updating unwritable cache $cache_file"
-  fi
-fi
-rm -f confcache
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
-# trailing colons and then remove the whole line if VPATH becomes empty
-# (actually we leave an empty line to preserve line numbers).
-if test "x$srcdir" = x.; then
-  ac_vpsub='/^[         ]*VPATH[        ]*=/{
-s/:*\$(srcdir):*/:/;
-s/:*\${srcdir}:*/:/;
-s/:*@srcdir@:*/:/;
-s/^\([^=]*=[    ]*\):*/\1/;
-s/:*$//;
-s/^[^=]*=[      ]*$//;
-}'
-fi
-
-# Transform confdefs.h into DEFS.
-# Protect against shell expansion while executing Makefile rules.
-# Protect against Makefile macro expansion.
-#
-# If the first sed substitution is executed (which looks for macros that
-# take arguments), then we branch to the quote section.  Otherwise,
-# look for a macro that doesn't take arguments.
-cat >confdef2opt.sed <<\_ACEOF
-t clear
-: clear
-s,^[    ]*#[    ]*define[       ][      ]*\([^  (][^    (]*([^)]*)\)[   ]*\(.*\),-D\1=\2,g
-t quote
-s,^[    ]*#[    ]*define[       ][      ]*\([^  ][^     ]*\)[   ]*\(.*\),-D\1=\2,g
-t quote
-d
-: quote
-s,[     `~#$^&*(){}\\|;'"<>?],\\&,g
-s,\[,\\&,g
-s,\],\\&,g
-s,\$,$$,g
-p
-_ACEOF
-# We use echo to avoid assuming a particular line-breaking character.
-# The extra dot is to prevent the shell from consuming trailing
-# line-breaks from the sub-command output.  A line-break within
-# single-quotes doesn't work because, if this script is created in a
-# platform that uses two characters for line-breaks (e.g., DOS), tr
-# would break.
-ac_LF_and_DOT=`echo; echo .`
-DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
-rm -f confdef2opt.sed
-
-
-ac_libobjs=
-ac_ltlibobjs=
-for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
-  # 1. Remove the extension, and $U if already installed.
-  ac_i=`echo "$ac_i" |
-        sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
-  # 2. Add them.
-  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
-  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
-done
-LIBOBJS=$ac_libobjs
-
-LTLIBOBJS=$ac_ltlibobjs
-
-
-
-: ${CONFIG_STATUS=./config.status}
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
-echo "$as_me: creating $CONFIG_STATUS" >&6;}
-cat >$CONFIG_STATUS <<_ACEOF
-#! $SHELL
-# Generated by $as_me.
-# Run this file to recreate the current configuration.
-# Compiler output produced by configure, useful for debugging
-# configure, is in config.log if it exists.
-
-debug=false
-ac_cs_recheck=false
-ac_cs_silent=false
-SHELL=\${CONFIG_SHELL-$SHELL}
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-## --------------------- ##
-## M4sh Initialization.  ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
-  set -o posix
-fi
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
-  as_unset=unset
-else
-  as_unset=false
-fi
-
-
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
-  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
-  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
-  LC_TELEPHONE LC_TIME
-do
-  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
-    eval $as_var=C; export $as_var
-  else
-    $as_unset $as_var
-  fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
-  as_basename=basename
-else
-  as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
-        X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)$' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
-         /^X\/\(\/\/\)$/{ s//\1/; q; }
-         /^X\/\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-
-
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
-fi
-
-
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
-  # Find who we are.  Look in the path if we contain no path at all
-  # relative or not.
-  case $0 in
-    *[\\/]* ) as_myself=$0 ;;
-    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
-       ;;
-  esac
-  # We did not find ourselves, most probably we were run as `sh COMMAND'
-  # in which case we are not to be found in the path.
-  if test "x$as_myself" = x; then
-    as_myself=$0
-  fi
-  if test ! -f "$as_myself"; then
-    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
-echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
-   { (exit 1); exit 1; }; }
-  fi
-  case $CONFIG_SHELL in
-  '')
-    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for as_base in sh bash ksh sh5; do
-        case $as_dir in
-        /*)
-          if ("$as_dir/$as_base" -c '
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
-            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
-            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
-            CONFIG_SHELL=$as_dir/$as_base
-            export CONFIG_SHELL
-            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
-          fi;;
-        esac
-       done
-done
-;;
-  esac
-
-  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
-  # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line before each line; the second 'sed' does the real
-  # work.  The second script uses 'N' to pair each line-number line
-  # with the numbered line, and appends trailing '-' during
-  # substitution so that $LINENO is not a special case at line end.
-  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
-  sed '=' <$as_myself |
-    sed '
-      N
-      s,$,-,
-      : loop
-      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
-      t loop
-      s,-$,,
-      s,^['$as_cr_digits']*\n,,
-    ' >$as_me.lineno &&
-  chmod +x $as_me.lineno ||
-    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
-echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
-   { (exit 1); exit 1; }; }
-
-  # Don't try to exec as it changes $[0], causing all sort of problems
-  # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensible to this).
-  . ./$as_me.lineno
-  # Exit status is that of the last command.
-  exit
-}
-
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
-  *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T='     ' ;;
-  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
-  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
-  # We could just check for DJGPP; but this test a) works b) is more generic
-  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
-  if test -f conf$$.exe; then
-    # Don't use ln at all; we don't have any links
-    as_ln_s='cp -p'
-  else
-    as_ln_s='ln -s'
-  fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s=ln
-else
-  as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.file
-
-if mkdir -p . 2>/dev/null; then
-  as_mkdir_p=:
-else
-  test -d ./-p && rmdir ./-p
-  as_mkdir_p=false
-fi
-
-as_executable_p="test -f"
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS="  $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
-exec 6>&1
-
-# Open the log real soon, to keep \$[0] and so on meaningful, and to
-# report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling.  Logging --version etc. is OK.
-exec 5>>config.log
-{
-  echo
-  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
-} >&5
-cat >&5 <<_CSEOF
-
-This file was extended by $as_me, which was
-generated by GNU Autoconf 2.59.  Invocation command line was
-
-  CONFIG_FILES    = $CONFIG_FILES
-  CONFIG_HEADERS  = $CONFIG_HEADERS
-  CONFIG_LINKS    = $CONFIG_LINKS
-  CONFIG_COMMANDS = $CONFIG_COMMANDS
-  $ $0 $@
-
-_CSEOF
-echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
-echo >&5
-_ACEOF
-
-# Files that config.status was made for.
-if test -n "$ac_config_files"; then
-  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_headers"; then
-  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_links"; then
-  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_commands"; then
-  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
-fi
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-ac_cs_usage="\
-\`$as_me' instantiates files from templates according to the
-current configuration.
-
-Usage: $0 [OPTIONS] [FILE]...
-
-  -h, --help       print this help, then exit
-  -V, --version    print version number, then exit
-  -q, --quiet      do not print progress messages
-  -d, --debug      don't remove temporary files
-      --recheck    update $as_me by reconfiguring in the same conditions
-  --file=FILE[:TEMPLATE]
-                  instantiate the configuration file FILE
-
-Configuration files:
-$config_files
-
-Report bugs to <bug-autoconf@gnu.org>."
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-ac_cs_version="\\
-config.status
-configured by $0, generated by GNU Autoconf 2.59,
-  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
-
-Copyright (C) 2003 Free Software Foundation, Inc.
-This config.status script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it."
-srcdir=$srcdir
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-# If no file are specified by the user, then we need to provide default
-# value.  By we need to know if files were specified by the user.
-ac_need_defaults=:
-while test $# != 0
-do
-  case $1 in
-  --*=*)
-    ac_option=`expr "x$1" : 'x\([^=]*\)='`
-    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
-    ac_shift=:
-    ;;
-  -*)
-    ac_option=$1
-    ac_optarg=$2
-    ac_shift=shift
-    ;;
-  *) # This is not an option, so the user has probably given explicit
-     # arguments.
-     ac_option=$1
-     ac_need_defaults=false;;
-  esac
-
-  case $ac_option in
-  # Handling of the options.
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
-    ac_cs_recheck=: ;;
-  --version | --vers* | -V )
-    echo "$ac_cs_version"; exit 0 ;;
-  --he | --h)
-    # Conflict between --help and --header
-    { { echo "$as_me:$LINENO: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&2;}
-   { (exit 1); exit 1; }; };;
-  --help | --hel | -h )
-    echo "$ac_cs_usage"; exit 0 ;;
-  --debug | --d* | -d )
-    debug=: ;;
-  --file | --fil | --fi | --f )
-    $ac_shift
-    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
-    ac_need_defaults=false;;
-  --header | --heade | --head | --hea )
-    $ac_shift
-    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
-    ac_need_defaults=false;;
-  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-  | -silent | --silent | --silen | --sile | --sil | --si | --s)
-    ac_cs_silent=: ;;
-
-  # This is an error.
-  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2;}
-   { (exit 1); exit 1; }; } ;;
-
-  *) ac_config_targets="$ac_config_targets $1" ;;
-
-  esac
-  shift
-done
-
-ac_configure_extra_args=
-
-if $ac_cs_silent; then
-  exec 6>/dev/null
-  ac_configure_extra_args="$ac_configure_extra_args --silent"
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-if \$ac_cs_recheck; then
-  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
-  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
-fi
-
-_ACEOF
-
-
-
-
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_config_target in $ac_config_targets
-do
-  case "$ac_config_target" in
-  # Handling of arguments.
-  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
-  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
-echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
-   { (exit 1); exit 1; }; };;
-  esac
-done
-
-# If the user did not use the arguments to specify the items to instantiate,
-# then the envvar interface is used.  Set only those that are not.
-# We use the long form for the default assignment because of an extremely
-# bizarre bug on SunOS 4.1.3.
-if $ac_need_defaults; then
-  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
-fi
-
-# Have a temporary directory for convenience.  Make it in the build tree
-# simply because there is no reason to put it here, and in addition,
-# creating and moving files from /tmp can sometimes cause problems.
-# Create a temporary directory, and hook for its removal unless debugging.
-$debug ||
-{
-  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
-  trap '{ (exit 1); exit 1; }' 1 2 13 15
-}
-
-# Create a (secure) tmp directory for tmp files.
-
-{
-  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
-  test -n "$tmp" && test -d "$tmp"
-}  ||
-{
-  tmp=./confstat$$-$RANDOM
-  (umask 077 && mkdir $tmp)
-} ||
-{
-   echo "$me: cannot create a temporary directory in ." >&2
-   { (exit 1); exit 1; }
-}
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-
-#
-# CONFIG_FILES section.
-#
-
-# No need to generate the scripts if there are no CONFIG_FILES.
-# This happens for instance when ./config.status config.h
-if test -n "\$CONFIG_FILES"; then
-  # Protect against being on the right side of a sed subst in config.status.
-  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
-   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
-s,@SHELL@,$SHELL,;t t
-s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
-s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
-s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
-s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
-s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
-s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
-s,@exec_prefix@,$exec_prefix,;t t
-s,@prefix@,$prefix,;t t
-s,@program_transform_name@,$program_transform_name,;t t
-s,@bindir@,$bindir,;t t
-s,@sbindir@,$sbindir,;t t
-s,@libexecdir@,$libexecdir,;t t
-s,@datadir@,$datadir,;t t
-s,@sysconfdir@,$sysconfdir,;t t
-s,@sharedstatedir@,$sharedstatedir,;t t
-s,@localstatedir@,$localstatedir,;t t
-s,@libdir@,$libdir,;t t
-s,@includedir@,$includedir,;t t
-s,@oldincludedir@,$oldincludedir,;t t
-s,@infodir@,$infodir,;t t
-s,@mandir@,$mandir,;t t
-s,@build_alias@,$build_alias,;t t
-s,@host_alias@,$host_alias,;t t
-s,@target_alias@,$target_alias,;t t
-s,@DEFS@,$DEFS,;t t
-s,@ECHO_C@,$ECHO_C,;t t
-s,@ECHO_N@,$ECHO_N,;t t
-s,@ECHO_T@,$ECHO_T,;t t
-s,@LIBS@,$LIBS,;t t
-s,@CC@,$CC,;t t
-s,@CFLAGS@,$CFLAGS,;t t
-s,@LDFLAGS@,$LDFLAGS,;t t
-s,@CPPFLAGS@,$CPPFLAGS,;t t
-s,@ac_ct_CC@,$ac_ct_CC,;t t
-s,@EXEEXT@,$EXEEXT,;t t
-s,@OBJEXT@,$OBJEXT,;t t
-s,@eap_sim_ldflags@,$eap_sim_ldflags,;t t
-s,@eap_sim_cflags@,$eap_sim_cflags,;t t
-s,@targetname@,$targetname,;t t
-s,@LIBOBJS@,$LIBOBJS,;t t
-s,@LTLIBOBJS@,$LTLIBOBJS,;t t
-CEOF
-
-_ACEOF
-
-  cat >>$CONFIG_STATUS <<\_ACEOF
-  # Split the substitutions into bite-sized pieces for seds with
-  # small command number limits, like on Digital OSF/1 and HP-UX.
-  ac_max_sed_lines=48
-  ac_sed_frag=1 # Number of current file.
-  ac_beg=1 # First line for current file.
-  ac_end=$ac_max_sed_lines # Line after last line for current file.
-  ac_more_lines=:
-  ac_sed_cmds=
-  while $ac_more_lines; do
-    if test $ac_beg -gt 1; then
-      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
-    else
-      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
-    fi
-    if test ! -s $tmp/subs.frag; then
-      ac_more_lines=false
-    else
-      # The purpose of the label and of the branching condition is to
-      # speed up the sed processing (if there are no `@' at all, there
-      # is no need to browse any of the substitutions).
-      # These are the two extra sed commands mentioned above.
-      (echo ':t
-  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
-      if test -z "$ac_sed_cmds"; then
-       ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
-      else
-       ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
-      fi
-      ac_sed_frag=`expr $ac_sed_frag + 1`
-      ac_beg=$ac_end
-      ac_end=`expr $ac_end + $ac_max_sed_lines`
-    fi
-  done
-  if test -z "$ac_sed_cmds"; then
-    ac_sed_cmds=cat
-  fi
-fi # test -n "$CONFIG_FILES"
-
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
-  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
-  case $ac_file in
-  - | *:- | *:-:* ) # input from stdin
-       cat >$tmp/stdin
-       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
-       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
-  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
-       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
-  * )   ac_file_in=$ac_file.in ;;
-  esac
-
-  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
-  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$ac_file" : 'X\(//\)[^/]' \| \
-        X"$ac_file" : 'X\(//\)$' \| \
-        X"$ac_file" : 'X\(/\)' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X"$ac_file" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-         /^X\(\/\/\)$/{ s//\1/; q; }
-         /^X\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-  { if $as_mkdir_p; then
-    mkdir -p "$ac_dir"
-  else
-    as_dir="$ac_dir"
-    as_dirs=
-    while test ! -d "$as_dir"; do
-      as_dirs="$as_dir $as_dirs"
-      as_dir=`(dirname "$as_dir") 2>/dev/null ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$as_dir" : 'X\(//\)[^/]' \| \
-        X"$as_dir" : 'X\(//\)$' \| \
-        X"$as_dir" : 'X\(/\)' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X"$as_dir" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-         /^X\(\/\/\)$/{ s//\1/; q; }
-         /^X\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-    done
-    test ! -n "$as_dirs" || mkdir $as_dirs
-  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
-echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
-   { (exit 1); exit 1; }; }; }
-
-  ac_builddir=.
-
-if test "$ac_dir" != .; then
-  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A "../" for each directory in $ac_dir_suffix.
-  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
-  ac_dir_suffix= ac_top_builddir=
-fi
-
-case $srcdir in
-  .)  # No --srcdir option.  We are building in place.
-    ac_srcdir=.
-    if test -z "$ac_top_builddir"; then
-       ac_top_srcdir=.
-    else
-       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
-    fi ;;
-  [\\/]* | ?:[\\/]* )  # Absolute path.
-    ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir ;;
-  *) # Relative path.
-    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
-  case "$ac_dir" in
-  .) ac_abs_builddir=`pwd`;;
-  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
-  *) ac_abs_builddir=`pwd`/"$ac_dir";;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
-  case ${ac_top_builddir}. in
-  .) ac_abs_top_builddir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
-  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
-  case $ac_srcdir in
-  .) ac_abs_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
-  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
-  case $ac_top_srcdir in
-  .) ac_abs_top_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
-  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
-  esac;;
-esac
-
-
-
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
-  # Let's still pretend it is `configure' which instantiates (i.e., don't
-  # use $as_me), people would be surprised to read:
-  #    /* config.h.  Generated by config.status.  */
-  if test x"$ac_file" = x-; then
-    configure_input=
-  else
-    configure_input="$ac_file.  "
-  fi
-  configure_input=$configure_input"Generated from `echo $ac_file_in |
-                                    sed 's,.*/,,'` by configure."
-
-  # First look for the input files in the build tree, otherwise in the
-  # src tree.
-  ac_file_inputs=`IFS=:
-    for f in $ac_file_in; do
-      case $f in
-      -) echo $tmp/stdin ;;
-      [\\/$]*)
-        # Absolute (can't be DOS-style, as IFS=:)
-        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
-   { (exit 1); exit 1; }; }
-        echo "$f";;
-      *) # Relative
-        if test -f "$f"; then
-          # Build tree
-          echo "$f"
-        elif test -f "$srcdir/$f"; then
-          # Source tree
-          echo "$srcdir/$f"
-        else
-          # /dev/null tree
-          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
-   { (exit 1); exit 1; }; }
-        fi;;
-      esac
-    done` || { (exit 1); exit 1; }
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-  sed "$ac_vpsub
-$extrasub
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-:t
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s,@configure_input@,$configure_input,;t t
-s,@srcdir@,$ac_srcdir,;t t
-s,@abs_srcdir@,$ac_abs_srcdir,;t t
-s,@top_srcdir@,$ac_top_srcdir,;t t
-s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
-s,@builddir@,$ac_builddir,;t t
-s,@abs_builddir@,$ac_abs_builddir,;t t
-s,@top_builddir@,$ac_top_builddir,;t t
-s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
-" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
-  rm -f $tmp/stdin
-  if test x"$ac_file" != x-; then
-    mv $tmp/out $ac_file
-  else
-    cat $tmp/out
-    rm -f $tmp/out
-  fi
-
-done
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-{ (exit 0); exit 0; }
-_ACEOF
-chmod +x $CONFIG_STATUS
-ac_clean_files=$ac_clean_files_save
-
-
-# configure is writing to config.log, and then calls config.status.
-# config.status does its own redirection, appending to config.log.
-# Unfortunately, on DOS this fails, as config.log is still kept open
-# by configure, so config.status won't be able to write to it; its
-# output is simply discarded.  So we exec the FD to /dev/null,
-# effectively closing config.log, so it can be properly (re)opened and
-# appended to by config.status.  When coming back to configure, we
-# need to make the FD available again.
-if test "$no_create" != yes; then
-  ac_cs_success=:
-  ac_config_status_args=
-  test "$silent" = yes &&
-    ac_config_status_args="$ac_config_status_args --quiet"
-  exec 5>/dev/null
-  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
-  exec 5>>config.log
-  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
-  # would make configure fail if this is the last instruction.
-  $ac_cs_success || { (exit 1); exit 1; }
-fi
-
diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/configure.in b/src/modules/rlm_eap/types/rlm_eap_sim/configure.in
deleted file mode 100644 (file)
index c5ce37a..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-AC_INIT(rlm_eap_sim.c)
-AC_REVISION($Revision$)
-AC_DEFUN(modname,[rlm_eap_sim])
-
-fail=
-SMART_LIBS=
-SMART_CLFAGS=
-if test x$with_[]modname != xno; then
-
-       AC_PROG_CC
-
-       targetname=modname
-else
-       targetname=
-       echo \*\*\* module modname is disabled.
-fi
-
-if test x"$fail" != x""; then
-       if test x"${enable_strict_dependencies}" = x"yes"; then
-               AC_MSG_ERROR([set --without-]modname[ to disable it explicitly.])
-       else
-               AC_MSG_WARN([silently not building ]modname[.])
-               AC_MSG_WARN([FAILURE: ]modname[ requires: $fail.])
-               if test x"$headersuggestion" != x; then
-                       AC_MSG_WARN([$headersuggestion]) 
-               fi
-               if test x"$libsuggestion" != x; then
-                       AC_MSG_WARN([$libsuggestion]) 
-               fi
-               targetname=""
-       fi
-fi
-
-eap_sim_ldflags=$SMART_LIBS
-eap_sim_cflags=$SMART_CFLAGS
-AC_SUBST(eap_sim_ldflags)
-AC_SUBST(eap_sim_cflags)
-AC_SUBST(targetname)
-AC_OUTPUT(Makefile)
index dcbcf33..168e5e2 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2003  Michael Richardson <mcr@sandelman.ottawa.on.ca>
- * Copyright 2003  The FreeRADIUS server project
+ * Copyright 2003,2006  The FreeRADIUS server project
  *
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -34,7 +37,7 @@
 #include "eap_types.h"
 #include "eap_sim.h"
 
-#include <rad_assert.h>
+#include <freeradius-devel/rad_assert.h>
 
 struct eap_sim_server_state {
        enum eapsim_serverstates state;
@@ -57,7 +60,7 @@ static void add_reply(VALUE_PAIR** vp,
                return;
        }
 
-       memcpy(reply_attr->strvalue, value, len);
+       memcpy(reply_attr->vp_strvalue, value, len);
        reply_attr->length = len;
        pairadd(vp, reply_attr);
 }
@@ -106,7 +109,7 @@ static int eap_sim_sendstart(EAP_HANDLER *handler)
        /* the version list. We support only version 1. */
        newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_VERSION_LIST,
                        PW_TYPE_OCTETS);
-       words = (uint16_t *)newvp->strvalue;
+       words = (uint16_t *)newvp->vp_strvalue;
        newvp->length = 3*sizeof(uint16_t);
        words[0] = htons(1*sizeof(uint16_t));
        words[1] = htons(EAP_SIM_VERSION);
@@ -126,8 +129,8 @@ static int eap_sim_sendstart(EAP_HANDLER *handler)
        newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_FULLAUTH_ID_REQ,
                           PW_TYPE_OCTETS);
        newvp->length = 2;
-       newvp->strvalue[0]=0;
-       newvp->strvalue[0]=1;
+       newvp->vp_strvalue[0]=0;
+       newvp->vp_strvalue[0]=1;
        pairadd(vps, newvp);
 
        /* the SUBTYPE, set to start. */
@@ -156,7 +159,7 @@ static int eap_sim_getchalans(VALUE_PAIR *vps, int chalno,
                       vp->length);
                return 0;
        }
-       memcpy(ess->keys.rand[chalno], vp->strvalue, EAPSIM_RAND_SIZE);
+       memcpy(ess->keys.rand[chalno], vp->vp_strvalue, EAPSIM_RAND_SIZE);
 
        vp = pairfind(vps, ATTRIBUTE_EAP_SIM_SRES1+chalno);
        if(vp == NULL) {
@@ -169,7 +172,7 @@ static int eap_sim_getchalans(VALUE_PAIR *vps, int chalno,
                       vp->length);
                return 0;
        }
-       memcpy(ess->keys.sres[chalno], vp->strvalue, EAPSIM_SRES_SIZE);
+       memcpy(ess->keys.sres[chalno], vp->vp_strvalue, EAPSIM_SRES_SIZE);
 
        vp = pairfind(vps, ATTRIBUTE_EAP_SIM_KC1+chalno);
        if(vp == NULL) {
@@ -182,7 +185,7 @@ static int eap_sim_getchalans(VALUE_PAIR *vps, int chalno,
                       vp->length);
                return 0;
        }
-       memcpy(ess->keys.Kc[chalno], vp->strvalue, EAPSIM_Kc_SIZE);
+       memcpy(ess->keys.Kc[chalno], vp->vp_strvalue, EAPSIM_Kc_SIZE);
 
        return 1;
 }
@@ -229,10 +232,10 @@ static int eap_sim_sendchallenge(EAP_HANDLER *handler)
        /* okay, we got the challenges! Put them into an attribute */
        newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_RAND,
                           PW_TYPE_OCTETS);
-       memset(newvp->strvalue,    0, 2); /* clear reserved bytes */
-       memcpy(newvp->strvalue+2+EAPSIM_RAND_SIZE*0, ess->keys.rand[0], EAPSIM_RAND_SIZE);
-       memcpy(newvp->strvalue+2+EAPSIM_RAND_SIZE*1, ess->keys.rand[1], EAPSIM_RAND_SIZE);
-       memcpy(newvp->strvalue+2+EAPSIM_RAND_SIZE*2, ess->keys.rand[2], EAPSIM_RAND_SIZE);
+       memset(newvp->vp_strvalue,    0, 2); /* clear reserved bytes */
+       memcpy(newvp->vp_strvalue+2+EAPSIM_RAND_SIZE*0, ess->keys.rand[0], EAPSIM_RAND_SIZE);
+       memcpy(newvp->vp_strvalue+2+EAPSIM_RAND_SIZE*1, ess->keys.rand[1], EAPSIM_RAND_SIZE);
+       memcpy(newvp->vp_strvalue+2+EAPSIM_RAND_SIZE*2, ess->keys.rand[2], EAPSIM_RAND_SIZE);
        newvp->length = 2+EAPSIM_RAND_SIZE*3;
        pairadd(outvps, newvp);
 
@@ -261,12 +264,12 @@ static int eap_sim_sendchallenge(EAP_HANDLER *handler)
 
        newvp = paircreate(ATTRIBUTE_EAP_SIM_BASE+PW_EAP_SIM_MAC,
                           PW_TYPE_OCTETS);
-       memcpy(newvp->strvalue, ess->keys.nonce_mt, 16);
+       memcpy(newvp->vp_strvalue, ess->keys.nonce_mt, 16);
        newvp->length = 16;
        pairreplace(outvps, newvp);
 
        newvp = paircreate(ATTRIBUTE_EAP_SIM_KEY, PW_TYPE_OCTETS);
-       memcpy(newvp->strvalue, ess->keys.K_aut, 16);
+       memcpy(newvp->vp_strvalue, ess->keys.K_aut, 16);
        newvp->length = 16;
        pairreplace(outvps, newvp);
 
@@ -448,7 +451,7 @@ static int process_eap_sim_start(EAP_HANDLER *handler, VALUE_PAIR *vps)
                DEBUG2("   EAP-Sim version field is too short.");
                return 0;
        }
-       memcpy(&simversion, selectedversion_vp->strvalue, sizeof(simversion));
+       memcpy(&simversion, selectedversion_vp->vp_strvalue, sizeof(simversion));
        simversion = ntohs(simversion);
        if(simversion != EAP_SIM_VERSION) {
                DEBUG2("   EAP-Sim version %d is unknown.", simversion);
@@ -456,7 +459,7 @@ static int process_eap_sim_start(EAP_HANDLER *handler, VALUE_PAIR *vps)
        }
 
        /* record it for later keying */
-       memcpy(ess->keys.versionselect, selectedversion_vp->strvalue,
+       memcpy(ess->keys.versionselect, selectedversion_vp->vp_strvalue,
               sizeof(ess->keys.versionselect));
 
        /*
@@ -466,7 +469,7 @@ static int process_eap_sim_start(EAP_HANDLER *handler, VALUE_PAIR *vps)
                DEBUG2("   EAP-Sim nonce_mt must be 16 bytes (+2 bytes padding), not %d", nonce_vp->length);
                return 0;
        }
-       memcpy(ess->keys.nonce_mt, nonce_vp->strvalue+2, 16);
+       memcpy(ess->keys.nonce_mt, nonce_vp->vp_strvalue+2, 16);
 
        /* everything looks good, change states */
        eap_sim_stateenter(handler, ess, eapsim_server_challenge);
@@ -625,68 +628,3 @@ EAP_TYPE rlm_eap_sim = {
        eap_sim_authenticate,           /* authentication */
        NULL                            /* XXX detach */
 };
-
-/*
- * $Log$
- * Revision 1.12.4.1  2007-02-15 12:51:38  aland
- *     Handle Client-Error code.  If the client sends us one, we stop
- *     talking EAP-SIM.
- *
- *     This closes #419
- *
- * Revision 1.12  2004/03/19 02:20:35  mcr
- *     increment the EAP-id on each stage of the transaction.
- *
- * Revision 1.11  2004/02/26 19:04:31  aland
- *     perl -i -npe "s/[ \t]+$//g" `find src -name "*.[ch]" -print`
- *
- *     Whitespace changes only, from a fresh checkout.
- *
- *     For bug # 13
- *
- * Revision 1.10  2004/01/30 20:35:33  mcr
- *     capture the RAND/SRES/Kc when we initialize the SIM
- *     rather than later, when they may have changed.
- *
- * Revision 1.9  2004/01/30 19:38:29  mcr
- *     added some debugging of why EAP-sim might not want to
- *     handle the request - lacking RAND1 attribute.
- *
- * Revision 1.8  2003/12/29 01:13:43  mcr
- *     if the un-marshalling fails, then fail the packet.
- *
- * Revision 1.7  2003/11/22 00:21:17  mcr
- *     send the encryption keys to the AccessPoint.
- *
- * Revision 1.6  2003/11/22 00:10:18  mcr
- *     the version list attribute's length of versions is in bytes,
- *     not entries.
- *
- * Revision 1.5  2003/11/21 19:15:51  mcr
- *     rename "SIM-Chal" to "SIM-Rand" to sync with names in official
- *     documentation.
- *
- * Revision 1.4  2003/11/21 19:02:19  mcr
- *     pack the RAND attribute properly - should have 2 bytes
- * reserved.
- *
- * Revision 1.3  2003/11/06 15:45:12  aland
- *     u_int -> uint
- *
- * Revision 1.2  2003/10/31 22:33:45  mcr
- *     fixes for version list length types.
- *     do not include length in hash.
- *     use defines rather than constant sizes.
- *
- * Revision 1.1  2003/10/29 02:49:19  mcr
- *     initial commit of eap-sim
- *
- * Revision 1.3  2003/09/14 00:44:42  mcr
- *     finished trivial challenge state.
- *
- *
- * Local Variables:
- * c-file-style: "linux"
- * End Variables:
- *
- */
index c4183ab..493d850 100644 (file)
@@ -1,15 +1,16 @@
-/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
-/*
+/* config.h.in.  Generated from configure.in by autoheader.  */
 
-acconfig.h - template used by autoheader to create config.h.in
-config.h.in - used by autoconf to create config.h
-config.h - created by autoconf; contains defines generated by autoconf
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
 
-*/
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
 
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
 
-/* Define if you have the <openssl/engine.h> header file.  */
-#undef HAVE_OPENSSL_ENGINE_H
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
 
-/* Define if you have the <openssl/err.h> header file.  */
-#undef HAVE_OPENSSL_ERR_H
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
index 81dd2ec..af2dd39 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.9.4.1 .
+# From configure.in Revision: 1.12 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -875,7 +875,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -2069,11 +2069,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -2112,6 +2107,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 88b62a5..eae6eed 100644 (file)
@@ -4,6 +4,7 @@
 # Version:     $Id$
 #
 
+AC_PREREQ([2.53])
 AC_INIT(rlm_eap_tls.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_eap_tls])
index f88dae0..99ddd3a 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   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 "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #ifdef HAVE_OPENSSL_RAND_H
 #include <openssl/rand.h>
@@ -40,15 +45,15 @@ static CONF_PARSER module_config[] = {
          offsetof(EAP_TLS_CONF, dh_key_length), NULL, "512" },
        { "verify_depth", PW_TYPE_INTEGER,
          offsetof(EAP_TLS_CONF, verify_depth), NULL, "0" },
-       { "CA_path", PW_TYPE_STRING_PTR,
+       { "CA_path", PW_TYPE_FILENAME,
          offsetof(EAP_TLS_CONF, ca_path), NULL, NULL },
        { "pem_file_type", PW_TYPE_BOOLEAN,
          offsetof(EAP_TLS_CONF, file_type), NULL, "yes" },
-       { "private_key_file", PW_TYPE_STRING_PTR,
+       { "private_key_file", PW_TYPE_FILENAME,
          offsetof(EAP_TLS_CONF, private_key_file), NULL, NULL },
-       { "certificate_file", PW_TYPE_STRING_PTR,
+       { "certificate_file", PW_TYPE_FILENAME,
          offsetof(EAP_TLS_CONF, certificate_file), NULL, NULL },
-       { "CA_file", PW_TYPE_STRING_PTR,
+       { "CA_file", PW_TYPE_FILENAME,
          offsetof(EAP_TLS_CONF, ca_file), NULL, NULL },
        { "private_key_password", PW_TYPE_STRING_PTR,
          offsetof(EAP_TLS_CONF, private_key_password), NULL, NULL },
@@ -330,7 +335,6 @@ static SSL_CTX *init_tls_ctx(EAP_TLS_CONF *conf)
                return NULL;
        }
 
-
        /* Load the CAs we trust */
        if (!SSL_CTX_load_verify_locations(ctx, conf->ca_file, conf->ca_path)) {
                radlog(L_ERR, "rlm_eap: SSL error %s", ERR_error_string(ERR_get_error(), NULL));
@@ -338,7 +342,6 @@ static SSL_CTX *init_tls_ctx(EAP_TLS_CONF *conf)
                return NULL;
        }
        SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(conf->ca_file));
-
        if (!(SSL_CTX_use_PrivateKey_file(ctx, conf->private_key_file, type))) {
                radlog(L_ERR, "rlm_eap: SSL error %s", ERR_error_string(ERR_get_error(), NULL));
                radlog(L_ERR, "rlm_eap_tls: Error reading private key file");
@@ -367,13 +370,17 @@ static SSL_CTX *init_tls_ctx(EAP_TLS_CONF *conf)
         *      SSL_OP_SINGLE_DH_USE has an impact on the computer
         *      time needed during negotiation, but it is not very
         *      large.
-        *       
+        */
+       ctx_options |= SSL_OP_SINGLE_DH_USE;
+
+       /*       
         *      SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS to work around issues
         *      in Windows Vista client.
         *      http://www.openssl.org/~bodo/tls-cbc.txt
         *      http://www.nabble.com/(RADIATOR)-Radiator-Version-3.16-released-t2600070.html
         */
-       ctx_options |= SSL_OP_SINGLE_DH_USE | SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
+       ctx_options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
+
        SSL_CTX_set_options(ctx, ctx_options);
 
        /*
@@ -454,18 +461,6 @@ static int eaptls_detach(void *arg)
        conf = inst->conf;
 
        if (conf) {
-               free(conf->dh_file);
-               free(conf->ca_path);
-               free(conf->certificate_file);
-               free(conf->private_key_file);
-               free(conf->private_key_password);
-               free(conf->ca_file);
-               free(conf->random_file);
-
-               free(conf->check_cert_cn);
-               free(conf->cipher_list);
-               free(conf->check_cert_issuer);
-
                memset(conf, 0, sizeof(*conf));
                free(inst->conf);
                inst->conf = NULL;
@@ -563,7 +558,7 @@ static int eaptls_initiate(void *type_arg, EAP_HANDLER *handler)
        eap_tls_t       *inst;
        VALUE_PAIR      *vp;
        int             client_cert = TRUE;
-       int             verify_mode = SSL_VERIFY_NONE;
+       int             verify_mode = 0;
 
        inst = (eap_tls_t *)type_arg;
 
index 52f3ef2..79db023 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   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
  */
 #ifndef _RLM_EAP_TLS_H
 #define _RLM_EAP_TLS_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(rlm_eap_tls_h, "$Id$")
+
 #include "eap_tls.h"
 
-#include "radiusd.h"
-#include "modules.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 /* configured values goes right here */
 typedef struct eap_tls_conf {
index c4183ab..493d850 100644 (file)
@@ -1,15 +1,16 @@
-/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
-/*
+/* config.h.in.  Generated from configure.in by autoheader.  */
 
-acconfig.h - template used by autoheader to create config.h.in
-config.h.in - used by autoconf to create config.h
-config.h - created by autoconf; contains defines generated by autoconf
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
 
-*/
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
 
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
 
-/* Define if you have the <openssl/engine.h> header file.  */
-#undef HAVE_OPENSSL_ENGINE_H
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
 
-/* Define if you have the <openssl/err.h> header file.  */
-#undef HAVE_OPENSSL_ERR_H
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
index 7daf874..7d48a62 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.5.4.1 .
+# From configure.in Revision: 1.8 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -875,7 +875,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -2069,11 +2069,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -2112,6 +2107,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index f233a0b..942acdd 100644 (file)
@@ -4,6 +4,7 @@
 # Version:     $Id$
 #
 
+AC_PREREQ([2.53])
 AC_INIT(rlm_eap_ttls.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_eap_ttls])
index e255037..30ebf85 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
  */
 #ifndef _EAP_TTLS_H
 #define _EAP_TTLS_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(eap_ttls_h, "$Id$")
+
 #include "eap_tls.h"
 
 typedef struct ttls_tunnel_t {
index 7cd8eb7..8b08930 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2003 Alan DeKok <aland@freeradius.org>
+ * Copyright 2006 The FreeRADIUS server project
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 #include "eap_ttls.h"
 
 
@@ -65,7 +69,6 @@ static int eapttls_detach(void *arg)
 {
        rlm_eap_ttls_t *inst = (rlm_eap_ttls_t *) arg;
 
-       if (inst->default_eap_type_name) free(inst->default_eap_type_name);
 
        free(inst);
 
@@ -137,7 +140,7 @@ static void ttls_free(void *p)
 
        if (t->username) {
                DEBUG2("  TTLS: Freeing handler for user %s",
-                      t->username->strvalue);
+                      t->username->vp_strvalue);
        }
 
        pairfree(&t->username);
index d31d73c..bd5d270 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  *   Copyright 2003 Alan DeKok <aland@freeradius.org>
+ *   Copyright 2006 The FreeRADIUS server project
  */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include "eap_ttls.h"
 
 /*
@@ -292,7 +297,7 @@ static VALUE_PAIR *diameter2vp(SSL *ssl,
                   */
                default:
                        vp->length = size;
-                       memcpy(vp->strvalue, data, vp->length);
+                       memcpy(vp->vp_strvalue, data, vp->length);
                        break;
                }
 
@@ -312,8 +317,8 @@ static VALUE_PAIR *diameter2vp(SSL *ssl,
                         *      If the password is exactly 16 octets,
                         *      it won't be zero-terminated.
                         */
-                       vp->strvalue[vp->length] = '\0';
-                       vp->length = strlen(vp->strvalue);
+                       vp->vp_strvalue[vp->length] = '\0';
+                       vp->length = strlen(vp->vp_strvalue);
                        break;
 
                        /*
@@ -354,7 +359,7 @@ static VALUE_PAIR *diameter2vp(SSL *ssl,
                                                      sizeof(challenge));
 
                                for (i = 0; i < vp->length; i++) {
-                                       if (challenge[i] != vp->strvalue[i]) {
+                                       if (challenge[i] != vp->vp_strvalue[i]) {
                                                DEBUG2("  TTLS: Tunneled challenge is incorrect");
                                                pairfree(&first);
                                                return NULL;
@@ -499,7 +504,7 @@ static int vp2diameter(tls_session_t *tls_session, VALUE_PAIR *first)
                case PW_TYPE_STRING:
                case PW_TYPE_OCTETS:
                default:
-                       memcpy(p, vp->strvalue, vp->length);
+                       memcpy(p, vp->vp_strvalue, vp->length);
                        length = vp->length;
                        break;
                }
@@ -996,7 +1001,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
         *      Update other items in the REQUEST data structure.
         */
        fake->username = pairfind(fake->packet->vps, PW_USER_NAME);
-       fake->password = pairfind(fake->packet->vps, PW_PASSWORD);
+       fake->password = pairfind(fake->packet->vps, PW_USER_PASSWORD);
 
        /*
         *      No User-Name, try to create one from stored data.
@@ -1010,22 +1015,22 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                        vp = pairfind(fake->packet->vps, PW_EAP_MESSAGE);
                        if (vp &&
                            (vp->length >= EAP_HEADER_LEN + 2) &&
-                           (vp->strvalue[0] == PW_EAP_RESPONSE) &&
-                           (vp->strvalue[EAP_HEADER_LEN] == PW_EAP_IDENTITY) &&
-                           (vp->strvalue[EAP_HEADER_LEN + 1] != 0)) {
+                           (vp->vp_strvalue[0] == PW_EAP_RESPONSE) &&
+                           (vp->vp_strvalue[EAP_HEADER_LEN] == PW_EAP_IDENTITY) &&
+                           (vp->vp_strvalue[EAP_HEADER_LEN + 1] != 0)) {
                                /*
                                 *      Create & remember a User-Name
                                 */
                                t->username = pairmake("User-Name", "", T_OP_EQ);
                                rad_assert(t->username != NULL);
 
-                               memcpy(t->username->strvalue, vp->strvalue + 5,
+                               memcpy(t->username->vp_strvalue, vp->vp_strvalue + 5,
                                       vp->length - 5);
                                t->username->length = vp->length - 5;
-                               t->username->strvalue[t->username->length] = 0;
+                               t->username->vp_strvalue[t->username->length] = 0;
 
                                DEBUG2("  TTLS: Got tunneled identity of %s",
-                                      t->username->strvalue);
+                                      t->username->vp_strvalue);
 
                                /*
                                 *      If there's a default EAP type,
@@ -1062,7 +1067,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
         */
        if (t->state) {
                DEBUG2("  TTLS: Adding old state with %02x %02x",
-                      t->state->strvalue[0], t->state->strvalue[1]);
+                      t->state->vp_strvalue[0], t->state->vp_strvalue[1]);
                vp = paircopy(t->state);
                if (vp) pairadd(&fake->packet->vps, vp);
        }
@@ -1175,7 +1180,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                vp = pairfind(fake->config_items, PW_PROXY_TO_REALM);
                if (vp) {
                        eap_tunnel_data_t *tunnel;
-                       DEBUG2("  TTLS: Tunneled authentication will be proxied to %s", vp->strvalue);
+                       DEBUG2("  TTLS: Tunneled authentication will be proxied to %s", vp->vp_strvalue);
 
                        /*
                         *      Tell the original request that it's going
index 221545f..7c783cc 100644 (file)
@@ -1,18 +1,52 @@
-/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
-/*
+/* config.h.in.  Generated from configure.in by autoheader.  */
 
-acconfig.h - template used by autoheader to create config.h.in
-config.h.in - used by autoconf to create config.h
-config.h - created by autoconf; contains defines generated by autoconf
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
 
-*/
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
 
-
-/* Define if you have the printf function.  */
+/* Define to 1 if you have the `printf' function. */
 #undef HAVE_PRINTF
 
-/* Define if you have the <stdio.h> header file.  */
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
 #undef HAVE_STDIO_H
 
-/* Define if you have the <stdlib.h> header file.  */
+/* Define to 1 if you have the <stdlib.h> header file. */
 #undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
index 59317ad..e5a101f 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.5 .
+# From configure.in Revision: 1.6 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -938,7 +938,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1284,9 +1284,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
 
 # change 'example'
+ # change 'example'
 
 # change 'example'
+ # change 'example'
 
 if test x$with_rlm_example != xno; then
 
@@ -1858,8 +1858,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1917,8 +1916,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2034,8 +2032,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2089,8 +2086,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2135,8 +2131,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2180,8 +2175,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2494,8 +2488,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2577,8 +2570,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2748,8 +2740,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2812,8 +2803,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2963,8 +2953,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3148,8 +3137,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3997,11 +3985,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -4040,6 +4023,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 947b56d..4765543 100644 (file)
@@ -1,6 +1,7 @@
-AC_INIT(rlm_example.c)  # change 'example'
+AC_PREREQ([2.53])
+AC_INIT(rlm_example.c) # change 'example'
 AC_REVISION($Revision$)
-AC_DEFUN(modname,[rlm_example])  # change 'example'
+AC_DEFUN(modname,[rlm_example]) # change 'example'
 
 if test x$with_[]modname != xno; then
 
index b37ecf6..6a2db8e 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  your name <your address>
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <stdio.h>
 
 #include "other.h"
index 8fd691e..c41a726 100644 (file)
@@ -1,6 +1,11 @@
+/* Copyright 2006 The FreeRADIUS server project */
+
 #ifndef _OTHER_H
 #define _OTHER_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(other_h, "$Id$")
+
 /* define the function */
 
 void other_function(void);
index ebbe968..ea8c9f4 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  your name <your address>
  */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
-
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 /*
  *     Define a structure for our module configuration.
@@ -56,7 +55,7 @@ typedef struct rlm_example_t {
  *     to the strdup'd string into 'config.string'.  This gets around
  *     buffer over-flows.
  */
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
   { "integer", PW_TYPE_INTEGER,    offsetof(rlm_example_t,value), NULL,   "1" },
   { "boolean", PW_TYPE_BOOLEAN,    offsetof(rlm_example_t,boolean), NULL, "no"},
   { "string",  PW_TYPE_STRING_PTR, offsetof(rlm_example_t,string), NULL,  NULL},
@@ -65,21 +64,6 @@ static CONF_PARSER module_config[] = {
   { NULL, -1, 0, NULL, NULL }          /* end the list */
 };
 
-/*
- *     Do any per-module initialization.  e.g. set up connections
- *     to external databases, read configuration files, set up
- *     dictionary entries, etc.
- *
- *     Try to avoid putting too much stuff in here - it's better to
- *     do it in instantiate() where it is not global.
- */
-static int example_init(void)
-{
-       /*
-        *      Everything's OK, return without an error.
-        */
-       return 0;
-}
 
 /*
  *     Do any per-module initialization that is separate to each
@@ -216,9 +200,13 @@ static int example_checksimul(void *instance, REQUEST *request)
   return RLM_MODULE_OK;
 }
 
+
+/*
+ *     Only free memory we allocated.  The strings allocated via
+ *     cf_section_parse() do not need to be freed.
+ */
 static int example_detach(void *instance)
 {
-       free(((struct rlm_example_t *)instance)->string);
        free(instance);
        return 0;
 }
@@ -233,10 +221,11 @@ static int example_detach(void *instance)
  *     is single-threaded.
  */
 module_t rlm_example = {
+       RLM_MODULE_INIT,
        "example",
        RLM_TYPE_THREAD_SAFE,           /* type */
-       example_init,                   /* initialization */
        example_instantiate,            /* instantiation */
+       example_detach,                 /* detach */
        {
                example_authenticate,   /* authentication */
                example_authorize,      /* authorization */
@@ -247,6 +236,4 @@ module_t rlm_example = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       example_detach,                 /* detach */
-       NULL,                           /* destroy */
 };
index 7896a04..9e8517d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * rlm_exe.c
+ * rlm_exec.c
  *
  * Version:    $Id$
  *
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2002  The FreeRADIUS server project
+ * Copyright 2002,2006  The FreeRADIUS server project
  * Copyright 2002  Alan DeKok <aland@ox.org>
  */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
-
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 /*
  *     Define a structure for our module configuration.
@@ -44,7 +43,8 @@ typedef struct rlm_exec_t {
        char    *input;
        char    *output;
        char    *packet_type;
-       int     packet_code;
+       unsigned int    packet_code;
+       int     shell_escape;
 } rlm_exec_t;
 
 /*
@@ -56,7 +56,7 @@ typedef struct rlm_exec_t {
  *     to the strdup'd string into 'config.string'.  This gets around
  *     buffer over-flows.
  */
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
        { "wait", PW_TYPE_BOOLEAN,  offsetof(rlm_exec_t,wait), NULL, "yes" },
        { "program",  PW_TYPE_STRING_PTR,
          offsetof(rlm_exec_t,program), NULL, NULL },
@@ -66,6 +66,7 @@ static CONF_PARSER module_config[] = {
          offsetof(rlm_exec_t,output), NULL, NULL },
        { "packet_type", PW_TYPE_STRING_PTR,
          offsetof(rlm_exec_t,packet_type), NULL, NULL },
+       { "shell_escape", PW_TYPE_BOOLEAN,  offsetof(rlm_exec_t,shell_escape), NULL, "yes" },
        { NULL, -1, 0, NULL, NULL }             /* end the list */
 };
 
@@ -120,8 +121,8 @@ static VALUE_PAIR **decode_string(REQUEST *request, const char *string)
  *     Do xlat of strings.
  */
 static int exec_xlat(void *instance, REQUEST *request,
-                    char *fmt, char *out, int outlen,
-                    RADIUS_ESCAPE_STRING func)
+                    char *fmt, char *out, size_t outlen,
+                    UNUSED RADIUS_ESCAPE_STRING func)
 {
        int             result;
        rlm_exec_t      *inst = instance;
@@ -140,7 +141,7 @@ static int exec_xlat(void *instance, REQUEST *request,
         */
        DEBUG2("rlm_exec (%s): Executing %s", inst->xlat_name, fmt);
        result = radius_exec_program(fmt, request, inst->wait,
-                                    out, outlen, *input_pairs, NULL);
+                                    out, outlen, *input_pairs, NULL, inst->shell_escape);
        DEBUG2("rlm_exec (%s): result %d", inst->xlat_name, result);
        if (result != 0) {
                out[0] = '\0';
@@ -163,14 +164,6 @@ static int exec_detach(void *instance)
                free(inst->xlat_name);
        }
 
-       /*
-        *  Free the strings.
-        */
-       if (inst->program) free(inst->program);
-       if (inst->input) free(inst->input);
-       if (inst->output) free(inst->output);
-       if (inst->packet_type) free(inst->packet_type);
-
        free(inst);
        return 0;
 }
@@ -189,7 +182,7 @@ static int exec_detach(void *instance)
 static int exec_instantiate(CONF_SECTION *conf, void **instance)
 {
        rlm_exec_t      *inst;
-       char            *xlat_name;
+       const char      *xlat_name;
 
        /*
         *      Set up a storage area for instance data
@@ -236,7 +229,7 @@ static int exec_instantiate(CONF_SECTION *conf, void **instance)
         */
        if (inst->wait &&
            (inst->output == NULL)) {
-               radlog(L_INFO, "rlm_exec: Wait=yes but no output defined. Did you mean output=none?");
+               radlog(L_INFO, "rlm_exec: wait=yes but no output defined. Did you mean output=none?");
        }
 
        /*
@@ -331,8 +324,8 @@ static int exec_dispatch(void *instance, REQUEST *request)
         */
        result = radius_exec_program(inst->program, request,
                                     inst->wait, NULL, 0,
-                                    *input_pairs, &answer);
-       if (result != 0) {
+                                    *input_pairs, &answer, inst->shell_escape);
+       if (result < 0) {
                radlog(L_ERR, "rlm_exec (%s): External script failed",
                       inst->xlat_name);
                return RLM_MODULE_FAIL;
@@ -347,11 +340,79 @@ static int exec_dispatch(void *instance, REQUEST *request)
 
        pairfree(&answer);
 
-       return RLM_MODULE_OK;
+       if (result == 0) {
+               return RLM_MODULE_OK;
+       }
+       if (result > RLM_MODULE_NUMCODES) {
+               return RLM_MODULE_FAIL;
+       }
+       return result-1;
 }
 
 
 /*
+ *     First, look for Exec-Program && Exec-Program-Wait.
+ *
+ *     Then, call exec_dispatch.
+ */
+static int exec_postauth(void *instance, REQUEST *request)
+{
+       int result;
+       int exec_wait = 0;
+       VALUE_PAIR *vp, *tmp;
+       rlm_exec_t *inst = (rlm_exec_t *) instance;
+
+       vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM);
+       if (vp) {
+               exec_wait = 0;
+
+       } else if ((vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM_WAIT)) != NULL) {
+               exec_wait = 1;
+       }
+       if (!vp) goto dispatch;
+
+       tmp = NULL;
+       result = radius_exec_program(vp->vp_strvalue, request, exec_wait,
+                                    NULL, 0, request->packet->vps, &tmp,
+                                    inst->shell_escape);
+
+       /*
+        *      Always add the value-pairs to the reply.
+        */
+       pairmove(&request->reply->vps, &tmp);
+       pairfree(&tmp);
+
+       if (result < 0) {
+               /*
+                *      Error. radius_exec_program() returns -1 on
+                *      fork/exec errors.
+                */
+               tmp = pairmake("Reply-Message", "Access denied (external check failed)", T_OP_SET);
+               pairadd(&request->reply->vps, tmp);
+               
+               DEBUG2("Login incorrect (external check failed)");
+
+               request->reply->code = PW_AUTHENTICATION_REJECT;
+               return RLM_MODULE_REJECT;
+       }
+       if (result > 0) {
+               /*
+                *      Reject. radius_exec_program() returns >0
+                *      if the exec'ed program had a non-zero
+                *      exit status.
+                */
+               request->reply->code = PW_AUTHENTICATION_REJECT;
+               DEBUG2("Login incorrect (external check said so)");
+               return RLM_MODULE_REJECT;
+       }
+
+ dispatch:
+       if (!inst->program) return RLM_MODULE_NOOP;
+
+       return exec_dispatch(instance, request);
+}
+
+/*
  *     The module name should be the only globally exported symbol.
  *     That is, everything else should be 'static'.
  *
@@ -361,10 +422,11 @@ static int exec_dispatch(void *instance, REQUEST *request)
  *     is single-threaded.
  */
 module_t rlm_exec = {
+       RLM_MODULE_INIT,
        "exec",                         /* Name */
        RLM_TYPE_THREAD_SAFE,           /* type */
-       NULL,                           /* initialization */
        exec_instantiate,               /* instantiation */
+       exec_detach,                    /* detach */
        {
                exec_dispatch,          /* authentication */
                exec_dispatch,          /* authorization */
@@ -373,8 +435,6 @@ module_t rlm_exec = {
                NULL,                   /* check simul */
                exec_dispatch,          /* pre-proxy */
                exec_dispatch,          /* post-proxy */
-               exec_dispatch           /* post-auth */
+               exec_postauth           /* post-auth */
        },
-       exec_detach,                    /* detach */
-       NULL,                           /* destroy */
 };
diff --git a/src/modules/rlm_expiration/Makefile b/src/modules/rlm_expiration/Makefile
new file mode 100644 (file)
index 0000000..77a5aad
--- /dev/null
@@ -0,0 +1,4 @@
+TARGET  = rlm_expiration
+SRCS    = rlm_expiration.c
+
+include ../rules.mak
diff --git a/src/modules/rlm_expiration/rlm_expiration.c b/src/modules/rlm_expiration/rlm_expiration.c
new file mode 100644 (file)
index 0000000..d5e8a83
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * rlm_expiration.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,2006  The FreeRADIUS server project
+ * Copyright 2004  Kostas Kalevras <kkalev@noc.ntua.gr>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+
+/*
+ *     Define a structure for our module configuration.
+ *
+ *     These variables do not need to be in a structure, but it's
+ *     a lot cleaner to do so, and a pointer to the structure can
+ *     be used as the instance handle.
+ */
+typedef struct rlm_expiration_t {
+       char *msg;              /* The Reply-Message passed back to the user if the account is expired */
+} rlm_expiration_t;
+
+/*
+ *     A mapping of configuration file names to internal variables.
+ *
+ *     Note that the string is dynamically allocated, so it MUST
+ *     be freed.  When the configuration file parse re-reads the string,
+ *     it free's the old one, and strdup's the new one, placing the pointer
+ *     to the strdup'd string into 'config.string'.  This gets around
+ *     buffer over-flows.
+ */
+static const CONF_PARSER module_config[] = {
+  { "reply-message", PW_TYPE_STRING_PTR, offsetof(rlm_expiration_t,msg),
+    NULL, "Password Has Expired\r\n"},
+  { NULL, -1, 0, NULL, NULL }
+};
+
+/*              
+ *      Check if account has expired, and if user may login now.
+ */              
+static int expiration_authorize(void *instance, REQUEST *request)
+{
+       rlm_expiration_t *data = (rlm_expiration_t *)instance;
+       VALUE_PAIR *vp, *check_item = NULL;
+       char msg[MAX_STRING_LEN];
+
+       if ((check_item = pairfind(request->config_items, PW_EXPIRATION)) != NULL){
+               /*
+               *      Has this user's password expired?
+               *
+               *      If so, remove ALL reply attributes,
+               *      and add our own Reply-Message, saying
+               *      why they're being rejected.
+               */
+               DEBUG("rlm_expiration: Checking Expiration time: '%s'",check_item->vp_strvalue);
+               if (((time_t) check_item->lvalue) <= request->timestamp) {
+                       char logstr[MAX_STRING_LEN];
+                       VALUE_PAIR *module_fmsg_vp;
+
+                       DEBUG("rlm_expiration: Account has expired");
+
+                       if (data->msg && data->msg[0]){
+                               if (!radius_xlat(msg, sizeof(msg), data->msg, request, NULL)) {
+                                       radlog(L_ERR, "rlm_expiration: xlat failed.");
+                                       return RLM_MODULE_FAIL;
+                               }
+
+                               vp = pairmake("Reply-Message", msg, T_OP_ADD);
+                               pairfree(&request->reply->vps);
+                               request->reply->vps = vp;
+                       }
+                        snprintf(logstr, sizeof(logstr), "Account has expired [Expiration %s]",check_item->vp_strvalue);
+                        module_fmsg_vp = pairmake("Module-Failure-Message", logstr, T_OP_EQ);
+                        pairadd(&request->packet->vps, module_fmsg_vp);
+
+                       return RLM_MODULE_USERLOCK;
+               }
+               /*
+                *      Else the account hasn't expired, but it may do so
+                *      in the future.  Set Session-Timeout.
+                */
+               vp = pairfind(request->reply->vps, PW_SESSION_TIMEOUT);
+               if (!vp) {
+                       vp = paircreate(PW_SESSION_TIMEOUT, PW_TYPE_INTEGER);
+                       if (!vp) {
+                               radlog(L_ERR|L_CONS, "No memory!");
+                               return RLM_MODULE_FAIL;
+                       }
+                       pairadd(&request->reply->vps, vp);
+                       vp->lvalue = (uint32_t) (((time_t) check_item->lvalue) - request->timestamp);
+
+               } else if (vp->lvalue > ((uint32_t) (((time_t) check_item->lvalue) - request->timestamp))) {
+                       vp->lvalue = (uint32_t) (((time_t) check_item->lvalue) - request->timestamp);
+               }
+       }
+       else
+               return RLM_MODULE_NOOP;
+
+       return RLM_MODULE_OK;
+}
+
+/*
+ *      Compare the expiration date.
+ */
+static int expirecmp(void *instance, REQUEST *req,
+               VALUE_PAIR *request, VALUE_PAIR *check,
+               VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+{
+       time_t now = 0;
+       instance = instance;
+       request = request;      /* shut the compiler up */
+       check_pairs = check_pairs;
+       reply_pairs = reply_pairs;
+
+       now = (req) ? req->timestamp : time(NULL);
+  
+       if (now <= ((time_t) check->lvalue))
+               return 0;
+       return +1;
+}
+
+
+static int expiration_detach(void *instance)
+{
+       rlm_expiration_t *data = (rlm_expiration_t *) instance;
+
+       paircompare_unregister(PW_EXPIRATION, expirecmp);
+       free(instance);
+       return 0;
+}
+
+/*
+ *     Do any per-module initialization that is separate to each
+ *     configured instance of the module.  e.g. set up connections
+ *     to external databases, read configuration files, set up
+ *     dictionary entries, etc.
+ *
+ *     If configuration information is given in the config section
+ *     that must be referenced in later calls, store a handle to it
+ *     in *instance otherwise put a null pointer there.
+ */
+static int expiration_instantiate(CONF_SECTION *conf, void **instance)
+{
+       rlm_expiration_t *data;
+
+       /*
+        *      Set up a storage area for instance data
+        */
+       data = rad_malloc(sizeof(*data));
+       if (!data) {
+               radlog(L_ERR, "rlm_expiration: rad_malloc() failed.");
+               return -1;
+       }
+       memset(data, 0, sizeof(*data));
+
+       /*
+        *      If the configuration parameters can't be parsed, then
+        *      fail.
+        */
+       if (cf_section_parse(conf, data, module_config) < 0) {
+               free(data);
+               radlog(L_ERR, "rlm_expiration: Configuration parsing failed.");
+               return -1;
+       }
+
+       /*
+        * Register the expiration comparison operation.
+        */
+       paircompare_register(PW_EXPIRATION, 0, expirecmp, data);
+
+       *instance = data;
+
+       return 0;
+}
+
+/*
+ *     The module name should be the only globally exported symbol.
+ *     That is, everything else should be 'static'.
+ *
+ *     If the module needs to temporarily modify it's instantiation
+ *     data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
+ *     The server will then take care of ensuring that the module
+ *     is single-threaded.
+ */
+module_t rlm_expiration = {
+       RLM_MODULE_INIT,
+       "expiration",
+       RLM_TYPE_THREAD_SAFE,           /* type */
+       expiration_instantiate,         /* instantiation */
+       expiration_detach,              /* detach */
+       {
+               NULL,                   /* authentication */
+               expiration_authorize,   /* authorization */
+               NULL,                   /* preaccounting */
+               NULL,                   /* accounting */
+               NULL,                   /* checksimul */
+               NULL,                   /* pre-proxy */
+               NULL,                   /* post-proxy */
+               NULL                    /* post-auth */
+       },
+};
index cd78ffa..fc22730 100644 (file)
@@ -5,6 +5,6 @@
 #
 
 TARGET         = rlm_expr
-SRCS           = rlm_expr.c
+SRCS           = rlm_expr.c paircmp.c
 
 include ../rules.mak
diff --git a/src/modules/rlm_expr/paircmp.c b/src/modules/rlm_expr/paircmp.c
new file mode 100644 (file)
index 0000000..4c7e1b0
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * paircmp.c   Valuepair functions for various attributes
+ *
+ * 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 2000,2006  The FreeRADIUS server project
+ * Copyright 2000  Alan DeKok <aland@ox.org>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <freeradius-devel/radiusd.h>
+
+
+/*
+ *     Compare a Connect-Info and a Connect-Rate
+ */
+static int connectcmp(void *instance,
+                     REQUEST *req UNUSED,
+                     VALUE_PAIR *request,
+                     VALUE_PAIR *check,
+                     VALUE_PAIR *check_pairs,
+                     VALUE_PAIR **reply_pairs)
+{
+       int rate;
+
+       instance = instance;
+       check_pairs = check_pairs; /* shut the compiler up */
+       reply_pairs = reply_pairs;
+
+       rate = atoi((char *)request->vp_strvalue);
+       return rate - check->lvalue;
+}
+
+
+/*
+ *     Compare a portno with a range.
+ */
+static int portcmp(void *instance,
+                  REQUEST *req UNUSED, VALUE_PAIR *request, VALUE_PAIR *check,
+       VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+{
+       char buf[MAX_STRING_LEN];
+       char *s, *p;
+       uint32_t lo, hi;
+       uint32_t port = request->lvalue;
+
+       instance = instance;
+       check_pairs = check_pairs; /* shut the compiler up */
+       reply_pairs = reply_pairs;
+
+       if ((strchr((char *)check->vp_strvalue, ',') == NULL) &&
+                       (strchr((char *)check->vp_strvalue, '-') == NULL)) {
+               return (request->lvalue - check->lvalue);
+       }
+
+       /* Same size */
+       strcpy(buf, (char *)check->vp_strvalue);
+       s = strtok(buf, ",");
+
+       while (s != NULL) {
+               if ((p = strchr(s, '-')) != NULL)
+                       p++;
+               else
+                       p = s;
+               lo = strtoul(s, NULL, 10);
+               hi = strtoul(p, NULL, 10);
+               if (lo <= port && port <= hi) {
+                       return 0;
+               }
+               s = strtok(NULL, ",");
+       }
+
+       return -1;
+}
+
+/*
+ *     Compare prefix/suffix.
+ *
+ *     If they compare:
+ *     - if PW_STRIP_USER_NAME is present in check_pairs,
+ *       strip the username of prefix/suffix.
+ *     - if PW_STRIP_USER_NAME is not present in check_pairs,
+ *       add a PW_STRIPPED_USER_NAME to the request.
+ */
+static int presufcmp(void *instance,
+                    REQUEST *req UNUSED,
+                    VALUE_PAIR *request, VALUE_PAIR *check,
+       VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+{
+       VALUE_PAIR *vp;
+       char *name = (char *)request->vp_strvalue;
+       char rest[MAX_STRING_LEN];
+       int len, namelen;
+       int ret = -1;
+
+       instance = instance;
+       reply_pairs = reply_pairs; /* shut the compiler up */
+
+#if 0 /* DEBUG */
+       printf("Comparing %s and %s, check->attr is %d\n",
+               name, check->vp_strvalue, check->attribute);
+#endif
+
+       len = strlen((char *)check->vp_strvalue);
+       switch (check->attribute) {
+               case PW_PREFIX:
+                       ret = strncmp(name, (char *)check->vp_strvalue, len);
+                       if (ret == 0 && rest)
+                               strcpy(rest, name + len);
+                       break;
+               case PW_SUFFIX:
+                       namelen = strlen(name);
+                       if (namelen < len)
+                               break;
+                       ret = strcmp(name + namelen - len,
+                                       (char *)check->vp_strvalue);
+                       if (ret == 0 && rest) {
+                               strlcpy(rest, name, namelen - len + 1);
+                       }
+                       break;
+       }
+       if (ret != 0)
+               return ret;
+
+       /*
+        *      If Strip-User-Name == No, then don't do any more.
+        */
+       vp = pairfind(check_pairs, PW_STRIP_USER_NAME);
+       if (vp && !vp->lvalue) return ret;
+
+       /*
+        *      See where to put the stripped user name.
+        */
+       vp = pairfind(check_pairs, PW_STRIPPED_USER_NAME);
+       if (!vp) {
+               vp = paircreate(PW_STRIPPED_USER_NAME, PW_TYPE_STRING);
+               if (!vp) return ret; /* no memory, do anything? */
+
+               pairadd(&request, vp);
+       }
+
+       strcpy((char *)vp->vp_strvalue, rest);
+       vp->length = strlen(rest);
+
+       return ret;
+}
+
+
+/*
+ *     Matches if there is NO SUCH ATTRIBUTE as the one named
+ *     in check->vp_strvalue.  If there IS such an attribute, it
+ *     doesn't match.
+ *
+ *     This is ugly, and definitely non-optimal.  We should be
+ *     doing the lookup only ONCE, and storing the result
+ *     in check->lvalue...
+ */
+static int attrcmp(void *instance,
+                  REQUEST *req UNUSED,
+                  VALUE_PAIR *request, VALUE_PAIR *check,
+                  VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+{
+       VALUE_PAIR *pair;
+       DICT_ATTR  *dict;
+       int attr;
+
+       instance = instance;
+       check_pairs = check_pairs; /* shut the compiler up */
+       reply_pairs = reply_pairs;
+
+       if (check->lvalue == 0) {
+               dict = dict_attrbyname((char *)check->vp_strvalue);
+               if (dict == NULL) {
+                       return -1;
+               }
+               attr = dict->attr;
+       } else {
+               attr = check->lvalue;
+       }
+
+       /*
+        *      If there's no such attribute, then return MATCH,
+        *      else FAILURE.
+        */
+       pair = pairfind(request, attr);
+       if (pair == NULL) {
+               return 0;
+       }
+
+       return -1;
+}
+
+/*
+ *     Compare the request packet type.
+ */
+static int packetcmp(void *instance UNUSED, REQUEST *req,
+                    VALUE_PAIR *request UNUSED,
+                    VALUE_PAIR *check,
+                    VALUE_PAIR *check_pairs UNUSED,
+                    VALUE_PAIR **reply_pairs UNUSED)
+{
+       if (req->packet->code == check->lvalue) {
+               return 0;
+       }
+
+       return 1;
+}
+
+/*
+ *     Compare the response packet type.
+ */
+static int responsecmp(void *instance UNUSED,
+                      REQUEST *req,
+                      VALUE_PAIR *request UNUSED,
+                      VALUE_PAIR *check,
+                      VALUE_PAIR *check_pairs UNUSED,
+                      VALUE_PAIR **reply_pairs UNUSED)
+{
+       if (req->reply->code == check->lvalue) {
+               return 0;
+       }
+
+       return 1;
+}
+
+/*
+ *     Register server-builtin special attributes.
+ */
+void pair_builtincompare_init(void)
+{
+       paircompare_register(PW_NAS_PORT, -1, portcmp, NULL);
+       paircompare_register(PW_PREFIX, PW_USER_NAME, presufcmp, NULL);
+       paircompare_register(PW_SUFFIX, PW_USER_NAME, presufcmp, NULL);
+       paircompare_register(PW_CONNECT_RATE, PW_CONNECT_INFO, connectcmp, NULL);
+       paircompare_register(PW_NO_SUCH_ATTRIBUTE, 0, attrcmp, NULL);
+       paircompare_register(PW_PACKET_TYPE, 0, packetcmp, NULL);
+       paircompare_register(PW_RESPONSE_PACKET_TYPE, 0, responsecmp, NULL);
+}
+
+void pair_builtincompare_detach(void)
+{
+       paircompare_unregister(PW_NAS_PORT, portcmp);
+       paircompare_unregister(PW_PREFIX, presufcmp);
+       paircompare_unregister(PW_SUFFIX, presufcmp);
+       paircompare_unregister(PW_CONNECT_RATE, connectcmp);
+       paircompare_unregister(PW_NO_SUCH_ATTRIBUTE, attrcmp);
+       paircompare_unregister(PW_PACKET_TYPE, packetcmp);
+       paircompare_unregister(PW_RESPONSE_PACKET_TYPE, responsecmp);
+}
index c6308a6..76d17d6 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2002  The FreeRADIUS server project
+ * Copyright 2002,2006  The FreeRADIUS server project
  * Copyright 2002  Alan DeKok <aland@ox.org>
  */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
-
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 /*
  *     Define a structure for our module configuration.
@@ -74,7 +73,8 @@ static expr_map_t map[] =
 static int get_number(REQUEST *request, const char **string, int *answer)
 {
        int             i, found;
-       uint32_t        result, x;
+       uint32_t        result;
+       int             x;
        const char      *p;
        expr_token_t    this;
 
@@ -280,6 +280,10 @@ static int expr_instantiate(CONF_SECTION *conf, void **instance)
                inst->xlat_name = strdup(xlat_name);
                xlat_register(xlat_name, expr_xlat, inst);
        }
+       /*
+        * Initialize various paircompare functions
+        */
+       pair_builtincompare_init();
        *instance = inst;
 
        return 0;
@@ -293,6 +297,7 @@ static int expr_detach(void *instance)
        rlm_expr_t      *inst = instance;
 
        xlat_unregister(inst->xlat_name, expr_xlat);
+       pair_builtincompare_detach();
        free(inst->xlat_name);
 
        free(inst);
@@ -309,16 +314,15 @@ static int expr_detach(void *instance)
  *     is single-threaded.
  */
 module_t rlm_expr = {
+       RLM_MODULE_INIT,
        "expr",                         /* Name */
        RLM_TYPE_THREAD_SAFE,           /* type */
-       NULL,                           /* initialization */
        expr_instantiate,               /* instantiation */
+       expr_detach,                    /* detach */
        {
                NULL,                   /* authentication */
                NULL,                   /* authorization */
                NULL,                   /* pre-accounting */
                NULL                    /* accounting */
        },
-       expr_detach,                    /* detach */
-       NULL,                           /* destroy */
 };
index abafea0..817f1f8 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Jeff Carneal <jeff@apex.net>
  */
 
-#include        "autoconf.h"
-#include        "libradius.h"
+#include        <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include        <freeradius-devel/autoconf.h>
 
 #include       <sys/socket.h>
 #include       <sys/time.h>
@@ -38,8 +40,8 @@
 #include       <fcntl.h>
 #include       <limits.h>
 
-#include       "radiusd.h"
-#include       "modules.h"
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/modules.h>
 
 struct fastuser_instance {
        char *compat_mode;
@@ -70,12 +72,11 @@ static int fastuser_store(PAIR_LIST **hashtable, PAIR_LIST *entry, int idx);
 static PAIR_LIST *fastuser_find(REQUEST *request, PAIR_LIST *user,
                                                                                                                                const char *username);
 static void fastuser_tablestats(PAIR_LIST **hashtable, int size);
-static int fastuser_passcheck(REQUEST *request, PAIR_LIST *user, const char *name);
 
-static CONF_PARSER module_config[] = {
-       { "usersfile",     PW_TYPE_STRING_PTR,
+static const CONF_PARSER module_config[] = {
+       { "usersfile",     PW_TYPE_FILENAME,
          offsetof(struct fastuser_instance,usersfile), NULL, "${raddbdir}/users_fast" },
-       { "acctusersfile",     PW_TYPE_STRING_PTR,
+       { "acctusersfile",     PW_TYPE_FILENAME,
          offsetof(struct fastuser_instance,acctusersfile), NULL, "${raddbdir}/acct_users" },
        { "hashsize",     PW_TYPE_INTEGER,
          offsetof(struct fastuser_instance,hashsize), NULL, "100000" },
@@ -437,20 +438,9 @@ static PAIR_LIST *fastuser_find(REQUEST *request, PAIR_LIST *user,
         */
        while((cur) && (!userfound)) {
                if((strcmp(cur->name, username)==0) &&
-                               paircmp(request, request->packet->vps, cur->check, &request->reply->vps) == 0) {
-                       /*
-                        * Usercollide means we have to compare check pairs
-                        * AND the password
-                        */
-                       if(mainconfig.do_usercollide) {
-                               if((userfound = fastuser_passcheck(request, cur, username))==0) {
-                                       cur = cur->next;
-                               }
-
-                       } else {
+                               paircompare(request, request->packet->vps, cur->check, &request->reply->vps) == 0) {
                                userfound = 1;
                                DEBUG2("  fastusers: Matched %s at %d", cur->name, cur->lineno);
-                       }
                } else {
                        cur = cur->next;
                }
@@ -498,45 +488,6 @@ static void fastuser_tablestats(PAIR_LIST **hashtable, int size) {
        }
 }
 
-static int fastuser_passcheck(REQUEST *request, PAIR_LIST *user,
-                             const char *name UNUSED)
-{
-       int found=0;
-       VALUE_PAIR      *check_save;
-
-       /*
-        * We check for REJECT specially here or a REJECT
-        * user will never match
-        */
-       check_save = pairfind(user->check, PW_AUTHTYPE);
-       if((check_save) && check_save->lvalue == PW_AUTHTYPE_REJECT)  {
-               DEBUG2("  fastusers(uc):  User '%s' line %d is Auth-Type Reject, but usercollide match",
-                                       user->name, user->lineno);
-               return 1;
-       }
-
-       /* Save the orginal config items */
-       check_save = request->config_items;
-       request->config_items = NULL;
-
-       DEBUG2("  fastusers(uc): Checking %s at %d", user->name, user->lineno);
-
-       /* Copy this users check pairs to the request */
-       request->config_items = paircopy(user->check);
-
-       /* Check the req to see if we matched */
-       if(rad_check_password(request)==0) {
-               DEBUG2("  fastusers(uc): Matched %s at %d", user->name, user->lineno);
-               found = 1;
-       }
-
-       /* Restore check items */
-       pairfree(&request->config_items);
-       request->config_items = check_save;
-
-       return found;
-}
-
 /*
  *     (Re-)read the "users" file into memory.
  */
@@ -608,7 +559,7 @@ static int fastuser_authorize(void *instance, REQUEST *request)
         *      Grab the canonical user name.
         */
        namepair = request->username;
-       name = namepair ? (char *) namepair->strvalue : "NONE";
+       name = namepair ? (char *) namepair->vp_strvalue : "NONE";
 
        /*
         *      Find the entry for the user.
@@ -657,7 +608,7 @@ static int fastuser_authorize(void *instance, REQUEST *request)
 
        curdefault = inst->defaults;
        while(curdefault) {
-               if(paircmp(request, request->packet->vps, curdefault->check,
+               if(paircompare(request, request->packet->vps, curdefault->check,
                                                        &request->reply->vps) == 0) {
                        DEBUG2("  fastusers: Matched %s at %d",
                                                        curdefault->name, curdefault->lineno);
@@ -755,7 +706,7 @@ static int fastuser_preacct(void *instance, REQUEST *request)
        struct fastuser_instance *inst = instance;
 
        namepair = request->username;
-       name = namepair ? (char *) namepair->strvalue : "NONE";
+       name = namepair ? (char *) namepair->vp_strvalue : "NONE";
        request_pairs = request->packet->vps;
        config_pairs = &request->config_items;
 
@@ -767,7 +718,7 @@ static int fastuser_preacct(void *instance, REQUEST *request)
                if (strcmp(name, pl->name) && strcmp(pl->name, "DEFAULT"))
                        continue;
 
-               if (paircmp(request, request_pairs, pl->check, &reply_pairs) == 0) {
+               if (paircompare(request, request_pairs, pl->check, &reply_pairs) == 0) {
                        DEBUG2("  acct_users: Matched %s at %d",
                               pl->name, pl->lineno);
                        found = 1;
@@ -817,13 +768,9 @@ static int fastuser_detach(void *instance)
                }
        }
 
-       free(inst->compat_mode);
        free(inst->hashtable);
        pairlist_free(&inst->defaults);
        pairlist_free(&inst->acctusers);
-       free(inst->usersfile);
-       free(inst->acctusersfile);
-       free(inst);
        return 0;
 }
 
@@ -840,10 +787,11 @@ static int fastuser_accounting(void *instance UNUSED, REQUEST *request UNUSED)
 
 /* globally exported name */
 module_t rlm_fastusers = {
+       RLM_MODULE_INIT,
        "fastusers",
        0,                              /* type: reserved */
-       NULL,                           /* initialization */
        fastuser_instantiate,           /* instantiation */
+       fastuser_detach,                /* detach */
        {
                fastuser_authenticate,  /* authentication */
                fastuser_authorize,     /* authorization */
@@ -854,7 +802,5 @@ module_t rlm_fastusers = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       fastuser_detach,                /* detach */
-       NULL                            /* destroy */
 };
 
index c683327..063e0a4 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2002  The FreeRADIUS server project
+ * Copyright 2002,2006  The FreeRADIUS server project
  * Copyright 2000  Jeff Carneal <jeff@apex.net>
  */
 
-static const char rcsid[] = "$Id$";
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include       "autoconf.h"
-#include       "libradius.h"
+#include       <freeradius-devel/autoconf.h>
 
 #include       <sys/stat.h>
 
@@ -35,25 +35,40 @@ static const char rcsid[] = "$Id$";
 #include       <fcntl.h>
 #include       <limits.h>
 
-#include       "radiusd.h"
-#include       "modules.h"
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/modules.h>
 
 struct file_instance {
        char *compat_mode;
 
+       char *key;
+
        /* autz */
        char *usersfile;
-       PAIR_LIST *users;
+       lrad_hash_table_t *users;
 
        /* preacct */
        char *acctusersfile;
-       PAIR_LIST *acctusers;
+       lrad_hash_table_t *acctusers;
 
        /* pre-proxy */
        char *preproxy_usersfile;
-       PAIR_LIST *preproxy_users;
+       lrad_hash_table_t *preproxy_users;
+
+       /* authenticate */
+       char *auth_usersfile;
+       lrad_hash_table_t *auth_users;
+
+       /* post-proxy */
+       char *postproxy_usersfile;
+       lrad_hash_table_t *postproxy_users;
+
+       /* post-authenticate */
+       char *postauth_usersfile;
+       lrad_hash_table_t *postauth_users;
 };
 
+
 /*
  *     See if a VALUE_PAIR list contains Fall-Through = Yes
  */
@@ -65,22 +80,59 @@ static int fallthrough(VALUE_PAIR *vp)
        return tmp ? tmp->lvalue : 0;
 }
 
-static CONF_PARSER module_config[] = {
-       { "usersfile",     PW_TYPE_STRING_PTR,
-         offsetof(struct file_instance,usersfile), NULL, "${raddbdir}/users" },
-       { "acctusersfile", PW_TYPE_STRING_PTR,
-         offsetof(struct file_instance,acctusersfile), NULL, "${raddbdir}/acct_users" },
-       { "preproxy_usersfile", PW_TYPE_STRING_PTR,
-         offsetof(struct file_instance,preproxy_usersfile), NULL, "${raddbdir}/preproxy_users" },
+static const CONF_PARSER module_config[] = {
+       { "usersfile",     PW_TYPE_FILENAME,
+         offsetof(struct file_instance,usersfile), NULL, NULL },
+       { "acctusersfile", PW_TYPE_FILENAME,
+         offsetof(struct file_instance,acctusersfile), NULL, NULL },
+       { "preproxy_usersfile", PW_TYPE_FILENAME,
+         offsetof(struct file_instance,preproxy_usersfile), NULL, NULL },
+       { "auth_usersfile", PW_TYPE_FILENAME,
+         offsetof(struct file_instance,auth_usersfile), NULL, NULL },
+       { "postproxy_usersfile", PW_TYPE_FILENAME,
+         offsetof(struct file_instance,postproxy_usersfile), NULL, NULL },
+       { "postauth_usersfile", PW_TYPE_FILENAME,
+         offsetof(struct file_instance,postauth_usersfile), NULL, NULL },
        { "compat",        PW_TYPE_STRING_PTR,
          offsetof(struct file_instance,compat_mode), NULL, "cistron" },
+       { "key",           PW_TYPE_STRING_PTR,
+         offsetof(struct file_instance,key), NULL, NULL },
        { NULL, -1, 0, NULL, NULL }
 };
 
-static int getusersfile(const char *filename, PAIR_LIST **pair_list, char *compat_mode_str)
+
+static uint32_t pairlist_hash(const void *data)
+{
+       return lrad_hash_string(((const PAIR_LIST *)data)->name);
+}
+
+static int pairlist_cmp(const void *a, const void *b)
+{
+       return strcmp(((const PAIR_LIST *)a)->name,
+                     ((const PAIR_LIST *)b)->name);
+}
+
+static void my_pairlist_free(void *data)
+{
+       PAIR_LIST *pl = data;
+
+       pairlist_free(&pl);
+}
+
+
+static int getusersfile(const char *filename, lrad_hash_table_t **pht,
+                       char *compat_mode_str)
 {
        int rcode;
        PAIR_LIST *users = NULL;
+       PAIR_LIST *entry, *next;
+       lrad_hash_table_t *ht, *tailht;
+       int order = 0;
+
+       if (!filename) {
+               *pht = NULL;
+               return 0;
+       }
 
        rcode = pairlist_read(filename, &users, 1);
        if (rcode < 0) {
@@ -93,7 +145,6 @@ static int getusersfile(const char *filename, PAIR_LIST **pair_list, char *compa
         */
        if ((debug_flag) ||
            (strcmp(compat_mode_str, "cistron") == 0)) {
-               PAIR_LIST *entry;
                VALUE_PAIR *vp;
                int compat_mode = FALSE;
 
@@ -176,7 +227,6 @@ static int getusersfile(const char *filename, PAIR_LIST **pair_list, char *compa
 
                        } /* end of loop over check items */
 
-
                        /*
                         *      Look for server configuration items
                         *      in the reply list.
@@ -209,11 +259,84 @@ static int getusersfile(const char *filename, PAIR_LIST **pair_list, char *compa
 
        }
 
-       *pair_list = users;
+       ht = lrad_hash_table_create(pairlist_hash, pairlist_cmp,
+                                   my_pairlist_free);
+       if (!ht) {
+               pairlist_free(&users);
+               return -1;
+       }
+
+       tailht = lrad_hash_table_create(pairlist_hash, pairlist_cmp,
+                                       NULL);
+       if (!tailht) {
+               lrad_hash_table_free(ht);
+               pairlist_free(&users);
+               return -1;
+       }
+
+       /*
+        *      Now that we've read it in, put the entries into a hash
+        *      for faster access.
+        */
+       for (entry = users; entry != NULL; entry = next) {
+               PAIR_LIST *tail;
+
+               next = entry->next;
+               entry->next = NULL;
+               entry->order = order++;
+
+               /*
+                *      Insert it into the hash table, and remember
+                *      the tail of the linked list.
+                */
+               tail = lrad_hash_table_finddata(tailht, entry);
+               if (!tail) {
+                       /*
+                        *      Insert it into the head & tail.
+                        */
+                       if (!lrad_hash_table_insert(ht, entry) ||
+                           !lrad_hash_table_insert(tailht, entry)) {
+                               pairlist_free(&next);
+                               lrad_hash_table_free(ht);
+                               lrad_hash_table_free(tailht);
+                               return -1;
+                       }
+               } else {
+                       tail->next = entry;
+                       if (!lrad_hash_table_replace(tailht, entry)) {
+                               pairlist_free(&next);
+                               lrad_hash_table_free(ht);
+                               lrad_hash_table_free(tailht);
+                               return -1;
+                       }
+               }
+       }
+
+       lrad_hash_table_free(tailht);
+       *pht = ht;
+
        return 0;
 }
 
 /*
+ *     Clean up.
+ */
+static int file_detach(void *instance)
+{
+       struct file_instance *inst = instance;
+       lrad_hash_table_free(inst->users);
+       lrad_hash_table_free(inst->acctusers);
+       lrad_hash_table_free(inst->preproxy_users);
+       lrad_hash_table_free(inst->auth_users);
+       lrad_hash_table_free(inst->postproxy_users);
+       lrad_hash_table_free(inst->postauth_users);
+       free(inst);
+       return 0;
+}
+
+
+
+/*
  *     (Re-)read the "users" file into memory.
  */
 static int file_instantiate(CONF_SECTION *conf, void **instance)
@@ -234,20 +357,15 @@ static int file_instantiate(CONF_SECTION *conf, void **instance)
 
        rcode = getusersfile(inst->usersfile, &inst->users, inst->compat_mode);
        if (rcode != 0) {
-               radlog(L_ERR|L_CONS, "Errors reading %s", inst->usersfile);
-               free(inst->usersfile);
-               free(inst->acctusersfile);
-               free(inst);
+         radlog(L_ERR|L_CONS, "Errors reading %s", inst->usersfile);
+               file_detach(inst);
                return -1;
        }
 
        rcode = getusersfile(inst->acctusersfile, &inst->acctusers, inst->compat_mode);
        if (rcode != 0) {
                radlog(L_ERR|L_CONS, "Errors reading %s", inst->acctusersfile);
-               pairlist_free(&inst->users);
-               free(inst->usersfile);
-               free(inst->acctusersfile);
-               free(inst);
+               file_detach(inst);
                return -1;
        }
 
@@ -257,12 +375,28 @@ static int file_instantiate(CONF_SECTION *conf, void **instance)
        rcode = getusersfile(inst->preproxy_usersfile, &inst->preproxy_users, inst->compat_mode);
        if (rcode != 0) {
                radlog(L_ERR|L_CONS, "Errors reading %s", inst->preproxy_usersfile);
-               pairlist_free(&inst->users);
-               pairlist_free(&inst->acctusers);
-               free(inst->usersfile);
-               free(inst->acctusersfile);
-               free(inst->preproxy_usersfile);
-               free(inst);
+               file_detach(inst);
+               return -1;
+       }
+
+       rcode = getusersfile(inst->auth_usersfile, &inst->auth_users, inst->compat_mode);
+       if (rcode != 0) {
+               radlog(L_ERR|L_CONS, "Errors reading %s", inst->auth_usersfile);
+               file_detach(inst);
+               return -1;
+       }
+
+       rcode = getusersfile(inst->postproxy_usersfile, &inst->postproxy_users, inst->compat_mode);
+       if (rcode != 0) {
+               radlog(L_ERR|L_CONS, "Errors reading %s", inst->postproxy_usersfile);
+               file_detach(inst);
+               return -1;
+       }
+
+       rcode = getusersfile(inst->postauth_usersfile, &inst->postauth_users, inst->compat_mode);
+       if (rcode != 0) {
+               radlog(L_ERR|L_CONS, "Errors reading %s", inst->postauth_usersfile);
+               file_detach(inst);
                return -1;
        }
 
@@ -271,176 +405,82 @@ static int file_instantiate(CONF_SECTION *conf, void **instance)
 }
 
 /*
- *     Find the named user in the database.  Create the
- *     set of attribute-value pairs to check and reply with
- *     for this user from the database. The main code only
- *     needs to check the password, the rest is done here.
+ *     Common code called by everything below.
  */
-static int file_authorize(void *instance, REQUEST *request)
+static int file_common(struct file_instance *inst, REQUEST *request,
+                      const char *filename, lrad_hash_table_t *ht,
+                      VALUE_PAIR *request_pairs, VALUE_PAIR **reply_pairs)
 {
-       VALUE_PAIR      *namepair;
-       VALUE_PAIR      *request_pairs;
+       const char      *name, *match;
+       VALUE_PAIR      **config_pairs;
        VALUE_PAIR      *check_tmp;
        VALUE_PAIR      *reply_tmp;
-       PAIR_LIST       *pl;
+       const PAIR_LIST *user_pl, *default_pl;
        int             found = 0;
-       const char      *name;
-       struct file_instance *inst = instance;
-       VALUE_PAIR **check_pairs, **reply_pairs;
-       VALUE_PAIR *check_save;
+       PAIR_LIST       my_pl;
+       char            buffer[256];
 
-       request_pairs = request->packet->vps;
-       check_pairs = &request->config_items;
-       reply_pairs = &request->reply->vps;
+       if (!inst->key) {
+               VALUE_PAIR      *namepair;
 
-       /*
-        *      Grab the canonical user name.
-        */
-       namepair = request->username;
-       name = namepair ? (char *) namepair->strvalue : "NONE";
+               namepair = request->username;
+               name = namepair ? (char *) namepair->vp_strvalue : "NONE";
+       } else {
+               int len;
 
-       /*
-        *      Find the entry for the user.
-        */
-       for(pl = inst->users; pl; pl = pl->next) {
-               /*
-                *      If the current entry is NOT a default,
-                *      AND the name does NOT match the current entry,
-                *      then skip to the next entry.
-                */
-               if ((strcmp(pl->name, "DEFAULT") != 0) &&
-                   (strcmp(name, pl->name) != 0))  {
-                       continue;
-               }
-
-               /*
-                *      If the current request matches against the
-                *      check pairs, then add the reply pairs from the
-                *      entry to the current list of reply pairs.
-                */
-               if ((paircmp(request, request_pairs, pl->check, reply_pairs) == 0)) {
-                       if ((mainconfig.do_usercollide) &&
-                           (strcmp(pl->name, "DEFAULT"))) {
-
-                               /*
-                                * We have to make sure the password
-                                * matches as well
-                                */
-
-                               /* Save the orginal config items */
-                               check_save = paircopy(request->config_items);
-
-                               /* Copy this users check pairs to the request */
-                               check_tmp = paircopy(pl->check);
-                               pairmove(check_pairs, &check_tmp);
-                               pairfree(&check_tmp);
-
-                               DEBUG2("    users: Checking entry %s at line %d", pl->name, pl->lineno);
-                               /* Check the req to see if we matched */
-                               if (rad_check_password(request)==0) {
-                                       DEBUG2("    users: Matched entry %s at line %d", pl->name, pl->lineno);
-
-                                       found = 1;
-
-                                       /* Free our saved config items */
-                                       pairfree(&check_save);
-
-                                       /*
-                                        * Already copied check items, so
-                                        * just copy reply here
-                                        */
-                                       reply_tmp = paircopy(pl->reply);
-                                       pairxlatmove(request, reply_pairs, &reply_tmp);
-                                       pairfree(&reply_tmp);
-
-                               /* We didn't match here */
-                               } else {
-                                       /* Restore check items */
-                                       pairfree(&request->config_items);
-                                       request->config_items = paircopy(check_save);
-                                       check_pairs = &request->config_items;
-                                       continue;
-                               }
-
-                       /* No usercollide */
-                       } else {
-
-                               DEBUG2("    users: Matched entry %s at line %d", pl->name, pl->lineno);
-                               found = 1;
-                               check_tmp = paircopy(pl->check);
-                               reply_tmp = paircopy(pl->reply);
-                               pairxlatmove(request, reply_pairs, &reply_tmp);
-                               pairmove(check_pairs, &check_tmp);
-                               pairfree(&reply_tmp);
-                               pairfree(&check_tmp); /* should be NULL */
-                       }
-                       /*
-                        *      Fallthrough?
-                        */
-                       if (!fallthrough(pl->reply))
-                               break;
-               }
+               len = radius_xlat(buffer, sizeof(buffer), inst->key,
+                                 request, NULL);
+               if (len) name = buffer;
+               else name = "NONE";
        }
 
-       /*
-        *      See if we succeeded.  If we didn't find the user,
-        *      then exit from the module.
-        */
-       if (!found)
-               return RLM_MODULE_NOTFOUND;
+       config_pairs = &request->config_items;
 
-       /*
-        *      Remove server internal parameters.
-        */
-       pairdelete(reply_pairs, PW_FALL_THROUGH);
+       if (!ht) return RLM_MODULE_NOOP;
 
-       return RLM_MODULE_OK;
-}
-
-/*
- *     Pre-Accounting - read the acct_users file for check_items and
- *     config_items. Reply items are Not Recommended(TM) in acct_users,
- *     except for Fallthrough, which should work
- *
- *     This function is mostly a copy of file_authorize
- */
-static int file_preacct(void *instance, REQUEST *request)
-{
-       VALUE_PAIR      *namepair;
-       const char      *name;
-       VALUE_PAIR      *request_pairs;
-       VALUE_PAIR      **config_pairs;
-       VALUE_PAIR      **reply_pairs;
-       VALUE_PAIR      *check_tmp;
-       VALUE_PAIR      *reply_tmp;
-       PAIR_LIST       *pl;
-       int             found = 0;
-       struct file_instance *inst = instance;
-
-       namepair = request->username;
-       name = namepair ? (char *) namepair->strvalue : "NONE";
-       request_pairs = request->packet->vps;
-       config_pairs = &request->config_items;
-       reply_pairs = &request->reply->vps;
+       my_pl.name = name;
+       user_pl = lrad_hash_table_finddata(ht, &my_pl);
+       my_pl.name = "DEFAULT";
+       default_pl = lrad_hash_table_finddata(ht, &my_pl);
 
        /*
         *      Find the entry for the user.
         */
-       for (pl = inst->acctusers; pl; pl = pl->next) {
-
-               if (strcmp(name, pl->name) && strcmp(pl->name, "DEFAULT"))
-                       continue;
+       while (user_pl || default_pl) {
+               const PAIR_LIST *pl;
+
+               if (!default_pl && user_pl) {
+                       pl = user_pl;
+                       match = name;
+                       user_pl = user_pl->next;
+
+               } else if (!user_pl && default_pl) {
+                       pl = default_pl;
+                       match = "DEFAULT";
+                       default_pl = default_pl->next;
+
+               } else if (user_pl->order < default_pl->order) {
+                       pl = user_pl;
+                       match = name;
+                       user_pl = user_pl->next;
+
+               } else {
+                       pl = default_pl;
+                       match = "DEFAULT";
+                       default_pl = default_pl->next;
+               }
 
-               if (paircmp(request, request_pairs, pl->check, reply_pairs) == 0) {
-                       DEBUG2("    acct_users: Matched entry %s at line %d",
-                              pl->name, pl->lineno);
+               if (paircompare(request, request_pairs, pl->check, reply_pairs) == 0) {
+                       DEBUG2("    %s: Matched entry %s at line %d",
+                              filename, match, pl->lineno);
                        found = 1;
                        check_tmp = paircopy(pl->check);
                        reply_tmp = paircopy(pl->reply);
                        pairxlatmove(request, reply_pairs, &reply_tmp);
                        pairmove(config_pairs, &check_tmp);
                        pairfree(&reply_tmp);
-                       pairfree(&check_tmp); /* should be NULL */
+                       pairfree(&check_tmp);
+
                        /*
                         *      Fallthrough?
                         */
@@ -450,137 +490,102 @@ static int file_preacct(void *instance, REQUEST *request)
        }
 
        /*
+        *      Remove server internal parameters.
+        */
+       pairdelete(reply_pairs, PW_FALL_THROUGH);
+
+       /*
         *      See if we succeeded.
         */
        if (!found)
                return RLM_MODULE_NOOP; /* on to the next module */
 
        return RLM_MODULE_OK;
+
 }
 
+
 /*
- *     Pre-proxy - read the preproxy_users file for check_items and
- *     config_items.
- *
- *     This function is mostly a copy of file_authorize
+ *     Find the named user in the database.  Create the
+ *     set of attribute-value pairs to check and reply with
+ *     for this user from the database. The main code only
+ *     needs to check the password, the rest is done here.
  */
-static int file_preproxy(void *instance, REQUEST *request)
+static int file_authorize(void *instance, REQUEST *request)
 {
-       VALUE_PAIR      *namepair;
-       const char      *name;
-       VALUE_PAIR      *request_pairs;
-       VALUE_PAIR      **config_pairs;
-       VALUE_PAIR      **reply_pairs;
-       VALUE_PAIR      *check_tmp;
-       VALUE_PAIR      *reply_tmp;
-       PAIR_LIST       *pl;
-       int             found = 0;
        struct file_instance *inst = instance;
 
-       namepair = request->username;
-       name = namepair ? (char *) namepair->strvalue : "NONE";
-       request_pairs = request->packet->vps;
-       config_pairs = &request->config_items;
-       reply_pairs = &request->proxy->vps;
+       return file_common(inst, request, "users", inst->users,
+                          request->packet->vps, &request->reply->vps);
+}
 
-       /*
-        *      Find the entry for the user.
-        */
-       for (pl = inst->preproxy_users; pl; pl = pl->next) {
 
-               /*
-                *  No match: skip it.
-                */
-               if (strcmp(name, pl->name) && strcmp(pl->name, "DEFAULT"))
-                       continue;
-
-               if (paircmp(request, request_pairs, pl->check, reply_pairs) == 0) {
-                       VALUE_PAIR *vp;
+/*
+ *     Pre-Accounting - read the acct_users file for check_items and
+ *     config_items. Reply items are Not Recommended(TM) in acct_users,
+ *     except for Fallthrough, which should work
+ */
+static int file_preacct(void *instance, REQUEST *request)
+{
+       struct file_instance *inst = instance;
 
-                       DEBUG2("    preproxy_users: Matched entry %s at line %d",
-                              pl->name, pl->lineno);
-                       found = 1;
-                       check_tmp = paircopy(pl->check);
-                       reply_tmp = paircopy(pl->reply);
+       return file_common(inst, request, "acct_users", inst->acctusers,
+                          request->packet->vps, &request->reply->vps);
+}
 
-                       for (vp = reply_tmp; vp != NULL; vp = vp->next) {
-                               /*
-                                *      We've got to xlat the string
-                                *      before moving it over.
-                                */
-                               if (vp->flags.do_xlat) {
-                                       int rcode;
-                                       char buffer[sizeof(vp->strvalue)];
+static int file_preproxy(void *instance, REQUEST *request)
+{
+       struct file_instance *inst = instance;
 
-                                       vp->flags.do_xlat = 0;
-                                       rcode = radius_xlat(buffer, sizeof(buffer),
-                                                           vp->strvalue,
-                                                           request, NULL);
+       return file_common(inst, request, "preproxy_users",
+                          inst->preproxy_users,
+                          request->packet->vps, &request->proxy->vps);
+}
 
-                                       /*
-                                        *      Parse the string into
-                                        *      a new value.
-                                        */
-                                       pairparsevalue(vp, buffer);
-                               }
-                       } /* loop over the things to add to the reply */
+static int file_postproxy(void *instance, REQUEST *request)
+{
+       struct file_instance *inst = instance;
 
-                       pairxlatmove(request, reply_pairs, &reply_tmp);
-                       pairmove(config_pairs, &check_tmp);
-                       pairfree(&reply_tmp);
-                       pairfree(&check_tmp); /* should be NULL */
-                       /*
-                        *      Fallthrough?
-                        */
-                       if (!fallthrough(pl->reply))
-                               break;
-               }
-       }
+       return file_common(inst, request, "postproxy_users",
+                          inst->postproxy_users,
+                          request->proxy_reply->vps, &request->reply->vps);
+}
 
-       /*
-        *      See if we succeeded.
-        */
-       if (!found)
-               return RLM_MODULE_NOOP; /* on to the next module */
+static int file_authenticate(void *instance, REQUEST *request)
+{
+       struct file_instance *inst = instance;
 
-       return RLM_MODULE_OK;
+       return file_common(inst, request, "auth_users",
+                          inst->auth_users,
+                          request->packet->vps, &request->reply->vps);
 }
 
-/*
- *     Clean up.
- */
-static int file_detach(void *instance)
+static int file_postauth(void *instance, REQUEST *request)
 {
        struct file_instance *inst = instance;
-       pairlist_free(&inst->users);
-       pairlist_free(&inst->acctusers);
-       pairlist_free(&inst->preproxy_users);
-       free(inst->usersfile);
-       free(inst->acctusersfile);
-       free(inst->preproxy_usersfile);
-       free(inst->compat_mode);
-       free(inst);
-       return 0;
+
+       return file_common(inst, request, "postauth_users",
+                          inst->postauth_users,
+                          request->packet->vps, &request->reply->vps);
 }
 
 
 /* globally exported name */
 module_t rlm_files = {
+       RLM_MODULE_INIT,
        "files",
        0,                              /* type: reserved */
-       NULL,                           /* initialization */
        file_instantiate,               /* instantiation */
+       file_detach,                    /* detach */
        {
-               NULL,                   /* authentication */
+               file_authenticate,      /* authentication */
                file_authorize,         /* authorization */
                file_preacct,           /* preaccounting */
                NULL,                   /* accounting */
                NULL,                   /* checksimul */
                file_preproxy,          /* pre-proxy */
-               NULL,                   /* post-proxy */
-               NULL                    /* post-auth */
+               file_postproxy,         /* post-proxy */
+               file_postauth           /* post-auth */
        },
-       file_detach,                    /* detach */
-       NULL                            /* destroy */
 };
 
diff --git a/src/modules/rlm_ippool/acconfig.h b/src/modules/rlm_ippool/acconfig.h
deleted file mode 100644 (file)
index 376f75b..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/* do we need GDBM_SYNC */
-#undef NEED_GDBM_SYNC
-
-/* do we have gdbm_fdesc */
-#undef HAVE_GDBM_FDESC
index 18af0c2..32fad9e 100644 (file)
@@ -1,7 +1,22 @@
-/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* do we have gdbm_fdesc */
+#undef HAVE_GDBM_FDESC
 
 /* do we need GDBM_SYNC */
 #undef NEED_GDBM_SYNC
 
-/* do we have gdbm_fdesc */
-#undef HAVE_GDBM_FDESC
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
index f9e4015..d3f1c8d 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.2 .
+# From configure.in Revision: 1.4 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -901,7 +901,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1821,8 +1821,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1880,8 +1879,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1997,8 +1995,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2052,8 +2049,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2098,8 +2094,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2143,8 +2138,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2457,8 +2451,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2481,8 +2474,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" = "x"; then
@@ -2511,8 +2504,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2590,8 +2582,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2614,8 +2605,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" != "x"; then
@@ -2667,8 +2658,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2691,8 +2681,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" = "x"; then
@@ -2721,8 +2711,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2827,8 +2816,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2851,8 +2839,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" != "x"; then
@@ -2907,7 +2895,8 @@ _ACEOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
   $EGREP "found-gdbm-sync" >/dev/null 2>&1; then
 
-                       cat >>confdefs.h <<\_ACEOF
+
+cat >>confdefs.h <<\_ACEOF
 #define NEED_GDBM_SYNC yes
 _ACEOF
 
@@ -2992,8 +2981,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3020,8 +3008,9 @@ echo "${ECHO_T}$ac_cv_func_gdbm_fdesc" >&6
 
        if test "x$ac_cv_func_gdbm_fdesc" = "xyes";
        then
-               cat >>confdefs.h <<\_ACEOF
-#define HAVE_GDBM_FDESC 1
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GDBM_FDESC
 _ACEOF
 
        fi
@@ -3850,11 +3839,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3893,6 +3877,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 5fb931a..a0c9df2 100644 (file)
@@ -1,3 +1,4 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_ippool.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_ippool])
@@ -7,8 +8,8 @@ if test x$with_[]modname != xno; then
        AC_PROG_CC
        AC_PROG_CPP
 
-       AC_SMART_CHECK_INCLUDE(gdbm.h)
-       AC_SMART_CHECK_LIB(gdbm, gdbm_open)
+       FR_SMART_CHECK_INCLUDE(gdbm.h)
+       FR_SMART_CHECK_LIB(gdbm, gdbm_open)
        if test "x$ac_cv_lib_gdbm_gdbm_open" != "xyes"; then
                fail="$fail libgdbm"
        fi
@@ -23,7 +24,7 @@ if test x$with_[]modname != xno; then
        not found.  this version must use sync by default.
 #endif
                        ], [
-                       AC_DEFINE(NEED_GDBM_SYNC, yes) 
+                       AC_DEFINE(NEED_GDBM_SYNC, yes, [do we need GDBM_SYNC]
                        AC_MSG_RESULT(needs it.)
                        ], [
                        AC_MSG_RESULT(SYNCs by default.)
@@ -36,7 +37,7 @@ if test x$with_[]modname != xno; then
        AC_CHECK_FUNC(gdbm_fdesc)
        if test "x$ac_cv_func_gdbm_fdesc" = "xyes";
        then
-               AC_DEFINE(HAVE_GDBM_FDESC)
+               AC_DEFINE(HAVE_GDBM_FDESC, [], [do we have gdbm_fdesc])
        fi
        LIBS=$old_LIBS
 
index 48aceae..e283586 100644 (file)
@@ -15,9 +15,9 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2001  The FreeRADIUS server project
+ * Copyright 2001,2006  The FreeRADIUS server project
  * Copyright 2002  Kostas Kalevras <kkalev@noc.ntua.gr>
  *
  * March 2002, Kostas Kalevras <kkalev@noc.ntua.gr>
  *   to request->timestamp and timeout to %{Session-Timeout:-0}. When we search for a free entry
  *   we check if timeout has expired. If it has then we free the entry. We also add a maximum
  *   timeout configuration directive. If it is non zero then we also use that one to free entries.
+ * Jul 2004, Kostas Kalevras <kkalev@noc.ntua.gr>
+ * - If Pool-Name is set to DEFAULT then always run.
+ * Mar 2005, Kostas Kalevras <kkalev@noc.ntua.gr>
+ * - Make the key an MD5 of a configurable xlated string. This closes Bug #42
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include "config.h"
-#include "autoconf.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <netinet/in.h>
 #endif
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/conffile.h>
+#include "../../include/md5.h"
 
 #include <gdbm.h>
 #include <time.h>
 
 #define MAX_NAS_NAME_SIZE 64
 
-static const char rcsid[] = "$Id$";
-
 /*
  *     Define a structure for our module configuration.
  *
@@ -109,6 +115,7 @@ typedef struct rlm_ippool_t {
        char *session_db;
        char *ip_index;
        char *name;
+       char *key;
        uint32_t range_start;
        uint32_t range_stop;
        uint32_t netmask;
@@ -142,8 +149,7 @@ typedef struct ippool_info {
 } ippool_info;
 
 typedef struct ippool_key {
-       char nas[MAX_NAS_NAME_SIZE];
-       unsigned int port;
+       char key[16];
 } ippool_key;
 
 /*
@@ -155,9 +161,10 @@ typedef struct ippool_key {
  *     to the strdup'd string into 'config.string'.  This gets around
  *     buffer over-flows.
  */
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
   { "session-db", PW_TYPE_STRING_PTR, offsetof(rlm_ippool_t,session_db), NULL, NULL },
   { "ip-index", PW_TYPE_STRING_PTR, offsetof(rlm_ippool_t,ip_index), NULL, NULL },
+  { "key", PW_TYPE_STRING_PTR, offsetof(rlm_ippool_t,key), NULL, "%{NAS-IP-Address} %{NAS-Port}" },
   { "range-start", PW_TYPE_IPADDR, offsetof(rlm_ippool_t,range_start), NULL, "0" },
   { "range-stop", PW_TYPE_IPADDR, offsetof(rlm_ippool_t,range_stop), NULL, "0" },
   { "netmask", PW_TYPE_IPADDR, offsetof(rlm_ippool_t,netmask), NULL, "0" },
@@ -167,7 +174,6 @@ static CONF_PARSER module_config[] = {
   { NULL, -1, 0, NULL, NULL }
 };
 
-
 /*
  *     Do any per-module initialization that is separate to each
  *     configured instance of the module.  e.g. set up connections
@@ -259,7 +265,7 @@ static int ippool_instantiate(CONF_SECTION *conf, void **instance)
                int rcode;
                uint32_t or_result;
                char str[32];
-               const char *nas_init = "NOT_EXIST";
+               char init_str[17];
 
                DEBUG("rlm_ippool: Initializing database");
                for(i=data->range_start,j=~0;i<=data->range_stop;i++,j--){
@@ -276,8 +282,9 @@ static int ippool_instantiate(CONF_SECTION *conf, void **instance)
                                continue;
                        }
 
-                       strcpy(key.nas, nas_init);
-                       key.port = j;
+                       sprintf(init_str,"%016d",j);
+                       DEBUG("rlm_ippool: Initialized bucket: %s",init_str);
+                       memcpy(key.key, init_str,16);
                        key_datum.dptr = (char *) &key;
                        key_datum.dsize = sizeof(ippool_key);
 
@@ -329,14 +336,16 @@ static int ippool_accounting(void *instance, REQUEST *request)
        datum data_datum;
        datum save_datum;
        int acctstatustype = 0;
-       unsigned int port = ~0;
        int rcode;
-       char nas[MAX_NAS_NAME_SIZE];
        ippool_info entry;
        ippool_key key;
        int num = 0;
        VALUE_PAIR *vp;
        char str[32];
+       char key_str[17];
+       char hex_str[35];
+       char xlat_str[MAX_STRING_LEN];
+       MD5_CTX md5_context;
 
 
        if ((vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) != NULL)
@@ -347,22 +356,18 @@ static int ippool_accounting(void *instance, REQUEST *request)
        }
        switch(acctstatustype){
                case PW_STATUS_STOP:
-                       if ((vp = pairfind(request->packet->vps, PW_NAS_PORT)) != NULL)
-                               port = vp->lvalue;
-                       else {
-                               DEBUG("rlm_ippool: Could not find port number in packet. Return NOOP.");
+                       if (!radius_xlat(xlat_str,MAX_STRING_LEN,data->key, request, NULL)){
+                               DEBUG("rlm_ippool: xlat on the 'key' directive failed");
                                return RLM_MODULE_NOOP;
                        }
-                       if ((vp = pairfind(request->packet->vps, PW_NAS_IP_ADDRESS)) != NULL)
-                               strncpy(nas, vp->strvalue, MAX_NAS_NAME_SIZE - 1);
-                       else {
-                               if ((vp = pairfind(request->packet->vps, PW_NAS_IDENTIFIER)) != NULL)
-                                       strncpy(nas, vp->strvalue, MAX_NAS_NAME_SIZE - 1);
-                               else {
-                                       DEBUG("rlm_ippool: Could not find nas information in packet. Return NOOP.");
-                                       return RLM_MODULE_NOOP;
-                               }
-                       }
+                       MD5Init(&md5_context);
+                       MD5Update(&md5_context, xlat_str, strlen(xlat_str));
+                       MD5Final(key_str, &md5_context);
+                       key_str[17] = '\0';
+                       lrad_bin2hex(key_str,hex_str,16);
+                       hex_str[32] = '\0';
+                       DEBUG("rlm_ippool: MD5 on 'key' directive maps to: %s",hex_str);
+                       memcpy(key.key,key_str,16);
                        break;
                default:
                        /* We don't care about any other accounting packet */
@@ -371,10 +376,7 @@ static int ippool_accounting(void *instance, REQUEST *request)
                        return RLM_MODULE_NOOP;
        }
 
-       memset(key.nas,0,MAX_NAS_NAME_SIZE);
-       strncpy(key.nas,nas,MAX_NAS_NAME_SIZE -1 );
-       key.port = port;
-       DEBUG("rlm_ippool: Searching for an entry for nas/port: %s/%u",key.nas,key.port);
+       DEBUG("rlm_ippool: Searching for an entry for key: '%s'",xlat_str);
        key_datum.dptr = (char *) &key;
        key_datum.dsize = sizeof(ippool_key);
 
@@ -387,7 +389,7 @@ static int ippool_accounting(void *instance, REQUEST *request)
                 */
                memcpy(&entry, data_datum.dptr, sizeof(ippool_info));
                free(data_datum.dptr);
-               DEBUG("rlm_ippool: Deallocated entry for ip/port: %s/%u",ip_ntoa(str,entry.ipaddr),port);
+               DEBUG("rlm_ippool: Deallocated entry for ip: %s",ip_ntoa(str,entry.ipaddr));
                entry.active = 0;
                entry.timestamp = 0;
                entry.timeout = 0;
@@ -453,14 +455,12 @@ static int ippool_accounting(void *instance, REQUEST *request)
 static int ippool_postauth(void *instance, REQUEST *request)
 {
        rlm_ippool_t *data = (rlm_ippool_t *) instance;
-       unsigned int port = 0;
        int delete = 0;
        int found = 0;
        int mppp = 0;
        int extra = 0;
        int rcode;
        int num = 0;
-       char nas[MAX_NAS_NAME_SIZE];
        datum key_datum;
        datum nextkey;
        datum data_datum;
@@ -470,6 +470,10 @@ static int ippool_postauth(void *instance, REQUEST *request)
        VALUE_PAIR *vp;
        char *cli = NULL;
        char str[32];
+       char key_str[17];
+       char hex_str[35];
+       char xlat_str[MAX_STRING_LEN];
+       MD5_CTX md5_context;
 
 
        /* quiet the compiler */
@@ -480,49 +484,35 @@ static int ippool_postauth(void *instance, REQUEST *request)
         * run only if they match
         */
        if ((vp = pairfind(request->config_items, PW_POOL_NAME)) != NULL){
-               if (data->name == NULL || strcmp(data->name,vp->strvalue))
+               if (data->name == NULL || (strcmp(data->name,vp->vp_strvalue) && strcmp(vp->vp_strvalue,"DEFAULT")))
                        return RLM_MODULE_NOOP;
        } else {
                DEBUG("rlm_ippool: Could not find Pool-Name attribute.");
                return RLM_MODULE_NOOP;
        }
 
-       /*
-        * Get the nas ip address
-        * If not fail
-        */
-       if ((vp = pairfind(request->packet->vps, PW_NAS_IP_ADDRESS)) != NULL)
-               strncpy(nas, vp->strvalue, MAX_NAS_NAME_SIZE - 1);
-       else{
-               if ((vp = pairfind(request->packet->vps, PW_NAS_IDENTIFIER)) != NULL)
-                       strncpy(nas, vp->strvalue, MAX_NAS_NAME_SIZE - 1);
-               else{
-                       DEBUG("rlm_ippool: Could not find nas information. Return NOOP.");
-                       return RLM_MODULE_NOOP;
-               }
-       }
 
        /*
         * Find the caller id
         */
        if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) != NULL)
-               cli = vp->strvalue;
+               cli = vp->vp_strvalue;
 
-       /*
-        * Find the port
-        * If not fail
-        */
-       if ((vp = pairfind(request->packet->vps, PW_NAS_PORT)) != NULL)
-               port = vp->lvalue;
-       else{
-               DEBUG("rlm_ippool: Could not find nas port information. Return NOOP.");
+
+       if (!radius_xlat(xlat_str,MAX_STRING_LEN,data->key, request, NULL)){
+               DEBUG("rlm_ippool: xlat on the 'key' directive failed");
                return RLM_MODULE_NOOP;
        }
-
-       memset(key.nas,0,MAX_NAS_NAME_SIZE);
-       strncpy(key.nas,nas,MAX_NAS_NAME_SIZE -1 );
-       key.port = port;
-       DEBUG("rlm_ippool: Searching for an entry for nas/port: %s/%u",key.nas,key.port);
+       MD5Init(&md5_context);
+       MD5Update(&md5_context, xlat_str, strlen(xlat_str));
+       MD5Final(key_str, &md5_context);
+       key_str[17] = '\0';
+       lrad_bin2hex(key_str,hex_str,16);
+       hex_str[32] = '\0';
+       DEBUG("rlm_ippool: MD5 on 'key' directive maps to: %s",hex_str);
+       memcpy(key.key,key_str,16);
+
+       DEBUG("rlm_ippool: Searching for an entry for key: '%s'",hex_str);
        key_datum.dptr = (char *) &key;
        key_datum.dsize = sizeof(ippool_key);
 
@@ -537,7 +527,7 @@ static int ippool_postauth(void *instance, REQUEST *request)
                memcpy(&entry, data_datum.dptr, sizeof(ippool_info));
                free(data_datum.dptr);
                if (entry.active){
-                       DEBUG("rlm_ippool: Found a stale entry for ip/port: %s/%u",ip_ntoa(str,entry.ipaddr),port);
+                       DEBUG("rlm_ippool: Found a stale entry for ip: %s",ip_ntoa(str,entry.ipaddr));
                        entry.active = 0;
                        entry.timestamp = 0;
                        entry.timeout = 0;
@@ -627,15 +617,12 @@ static int ippool_postauth(void *instance, REQUEST *request)
                                memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
                                free(data_datum.dptr);
                                /*
-                               * If we find an entry for the same caller-id and nas with active=1
+                               * If we find an entry for the same caller-id with active=1
                                * then we use that for multilink (MPPP) to work properly.
                                */
                                if (strcmp(entry.cli,cli) == 0 && entry.active){
-                                       memcpy(&key,key_datum.dptr,sizeof(ippool_key));
-                                       if (!strcmp(key.nas,nas)){
-                                               mppp = 1;
-                                               break;
-                                       }
+                                       mppp = 1;
+                                       break;
                                }
                        }
                        nextkey = gdbm_nextkey(data->gdbm, key_datum);
@@ -669,7 +656,7 @@ static int ippool_postauth(void *instance, REQUEST *request)
                                         * If we find an entry in the ip index and the number is zero (meaning
                                         * that we haven't allocated the same ip address to another nas/port pair)
                                         * or if we don't find an entry then delete the session entry so
-                                        * that we can change the key (nas/port)
+                                        * that we can change the key
                                         * Else we don't delete the session entry since we haven't yet deallocated the
                                         * corresponding ip address and we continue our search.
                                         */
@@ -718,10 +705,7 @@ static int ippool_postauth(void *instance, REQUEST *request)
                        datum data_datum_tmp;
                        ippool_key key_tmp;
 
-                       memset(key_tmp.nas,0,MAX_NAS_NAME_SIZE);
-                       strncpy(key_tmp.nas,nas,MAX_NAS_NAME_SIZE -1 );
-                       key_tmp.port = port;
-                       DEBUG("rlm_ippool: Searching for an entry for nas/port: %s/%u",key_tmp.nas,key_tmp.port);
+                       memcpy(key_tmp.key,key_str,16);
                        key_datum_tmp.dptr = (char *) &key_tmp;
                        key_datum_tmp.dsize = sizeof(ippool_key);
 
@@ -729,13 +713,13 @@ static int ippool_postauth(void *instance, REQUEST *request)
                        if (data_datum_tmp.dptr != NULL){
 
                                rcode = gdbm_store(data->gdbm, key_datum, data_datum_tmp, GDBM_REPLACE);
+                               free(data_datum_tmp.dptr);
                                if (rcode < 0) {
                                        radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",
                                                data->session_db, gdbm_strerror(gdbm_errno));
                                                pthread_mutex_unlock(&data->op_mutex);
                                        return RLM_MODULE_FAIL;
                                }
-                               free(data_datum_tmp.dptr);
                        }
                }
                else{
@@ -776,13 +760,11 @@ static int ippool_postauth(void *instance, REQUEST *request)
                        entry.extra = 1;
                data_datum.dptr = (char *) &entry;
                data_datum.dsize = sizeof(ippool_info);
-               memset(key.nas,0,MAX_NAS_NAME_SIZE);
-               strncpy(key.nas,nas,MAX_NAS_NAME_SIZE - 1);
-               key.port = port;
+               memcpy(key.key, key_str, 16);
                key_datum.dptr = (char *) &key;
                key_datum.dsize = sizeof(ippool_key);
 
-               DEBUG2("rlm_ippool: Allocating ip to nas/port: %s/%u",key.nas,key.port);
+               DEBUG2("rlm_ippool: Allocating ip to key: '%s'",hex_str);
                rcode = gdbm_store(data->gdbm, key_datum, data_datum, GDBM_REPLACE);
                if (rcode < 0) {
                        radlog(L_ERR, "rlm_ippool: Failed storing data to %s: %s",
@@ -814,14 +796,13 @@ static int ippool_postauth(void *instance, REQUEST *request)
                pthread_mutex_unlock(&data->op_mutex);
 
 
-               DEBUG("rlm_ippool: Allocated ip %s to client on nas %s,port %u",ip_ntoa(str,entry.ipaddr),
-                               key.nas,port);
+               DEBUG("rlm_ippool: Allocated ip %s to client key: %s",ip_ntoa(str,entry.ipaddr),hex_str);
                if ((vp = paircreate(PW_FRAMED_IP_ADDRESS, PW_TYPE_IPADDR)) == NULL) {
                        radlog(L_ERR|L_CONS, "no memory");
                        return RLM_MODULE_FAIL;
                }
                vp->lvalue = entry.ipaddr;
-               ip_ntoa(vp->strvalue, vp->lvalue);
+               ip_ntoa(vp->vp_strvalue, vp->lvalue);
                pairadd(&request->reply->vps, vp);
 
                /*
@@ -833,7 +814,7 @@ static int ippool_postauth(void *instance, REQUEST *request)
                                radlog(L_ERR|L_CONS, "no memory");
                        else {
                                vp->lvalue = ntohl(data->netmask);
-                               ip_ntoa(vp->strvalue, vp->lvalue);
+                               ip_ntoa(vp->vp_strvalue, vp->lvalue);
                                pairadd(&request->reply->vps, vp);
                        }
                }
@@ -854,8 +835,6 @@ static int ippool_detach(void *instance)
 
        gdbm_close(data->gdbm);
        gdbm_close(data->ip);
-       free(data->session_db);
-       free(data->ip_index);
        pthread_mutex_destroy(&data->op_mutex);
 
        free(instance);
@@ -872,10 +851,11 @@ static int ippool_detach(void *instance)
  *     is single-threaded.
  */
 module_t rlm_ippool = {
-       "IPPOOL",
+       RLM_MODULE_INIT,
+       "ippool",
        RLM_TYPE_THREAD_SAFE,           /* type */
-       NULL,                           /* initialization */
        ippool_instantiate,             /* instantiation */
+       ippool_detach,                  /* detach */
        {
                NULL,                   /* authentication */
                NULL,                   /* authorization */
@@ -886,6 +866,4 @@ module_t rlm_ippool = {
                NULL,                   /* post-proxy */
                ippool_postauth         /* post-auth */
        },
-       ippool_detach,                  /* detach */
-       NULL,                           /* destroy */
 };
index e6a1b75..82ed522 100755 (executable)
@@ -15,9 +15,9 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2003  FreeRADIUS Project, http://www.freeradius.org/
+ * Copyright 2003,2006  FreeRADIUS Project, http://www.freeradius.org/
  * Copyright 2003  Edwin Groothuis, edwin@mavetju.org
  * Permission from Edwin Groothuis for release under GPL is archived here:
  * http://lists.cistron.nl/archives/freeradius-devel/2003/09/frm00247.html
  SUCH DAMAGE.
 */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -63,6 +67,9 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include "../../include/md5.h"
+#include <freeradius-devel/missing.h>
+#include <freeradius-devel/libradius.h>
 
 int active=0;
 
@@ -71,6 +78,8 @@ int cflag=0;
 int rflag=0;
 int vflag=0;
 int nflag=0;
+int oflag=0;
+int uflag=0;
 
 typedef struct ippool_info {
     uint32_t        ipaddr;
@@ -81,26 +90,33 @@ typedef struct ippool_info {
 
 
 #define MAX_NAS_NAME_SIZE 64
-typedef struct ippool_key {
+typedef struct old_ippool_key {
     char nas[MAX_NAS_NAME_SIZE];
     unsigned int port;
+} old_ippool_key;
+typedef struct ippool_key {
+    char key[16];
 } ippool_key;
 
 #define MATCH_IP(ip1,ip2) ((ip1)==NULL || strcmp((ip1),(ip2))==0)
 #define MATCH_ACTIVE(info) ((info).active==1 || !aflag)
 
-void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport);
-void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress);
+void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport,int old);
+void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress, int old);
+void tonewformat(char *sessiondbname,char *newsessiondbname);
 void usage(char *argv0);
 
-void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport) {
+void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname, char*NASport, int old) {
     GDBM_FILE sessiondb;
     GDBM_FILE indexdb;
     datum key_datum,data_datum,save_datum;
        datum nextkey;
     ippool_key key;
+    old_ippool_key old_key;
     ippool_info entry;
     struct in_addr ipaddr;
+    char key_str[17];
+    char hex_str[35];
     int num=0;
        int mppp=0;
     int mode=GDBM_WRITER;
@@ -136,11 +152,28 @@ void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname,
 
        /* Basically from rlm_ippool.c */
 
-       memset(key.nas,0,MAX_NAS_NAME_SIZE);
-       strncpy(key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
-       key.port = port;
-       key_datum.dptr = (char *) &key;
-       key_datum.dsize = sizeof(ippool_key);
+       if (old){
+               memset(old_key.nas,0,MAX_NAS_NAME_SIZE);
+               strlcpy(old_key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
+               old_key.port = port;
+               key_datum.dptr = (char *) &old_key;
+               key_datum.dsize = sizeof(old_ippool_key);
+       }
+       else{
+               char md5_input_str[MAX_STRING_LEN];
+               MD5_CTX md5_context;
+
+               snprintf(md5_input_str,MAX_STRING_LEN, "%s %s",NASname,NASport);
+               MD5Init(&md5_context);
+               MD5Update(&md5_context, md5_input_str, strlen(md5_input_str));
+               MD5Final(key_str, &md5_context);
+               memcpy(key.key,key_str,16);
+               lrad_bin2hex(key_str,hex_str,16);
+               hex_str[32] = '\0';
+               key_datum.dptr = (char *) &key;
+               key_datum.dsize = sizeof(ippool_key);
+       }
+               
 
        data_datum = gdbm_fetch(sessiondb, key_datum);
        if (data_datum.dptr != NULL){
@@ -148,8 +181,11 @@ void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname,
                memcpy(&entry,data_datum.dptr, sizeof(ippool_info));
                free(data_datum.dptr);
                if (entry.active){
-                       printf("rlm_ippool_tool: Deleting stale entry for ip/port %s/%u",
+                       if (old)
+                               printf("rlm_ippool_tool: Deleting stale entry for ip/port %s/%u",
                                        ipaddress, port);
+                       else
+                               printf("rlm_ippool_tool: Deleting stale entry for key: '%s'",hex_str);
                        entry.active = 0;
                        save_datum.dptr = key_datum.dptr;
                        save_datum.dsize = key_datum.dsize;
@@ -205,8 +241,14 @@ void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname,
                                * then we use that for multilink (MPPP) to work properly.
                                */
                                if (strcmp(entry.cli,cli) == 0 && entry.active){
-                                       memcpy(&key,key_datum.dptr,sizeof(ippool_key));
-                                       if (!strcmp(key.nas,NASname)){
+                                       if (old){
+                                               memcpy(&old_key,key_datum.dptr,sizeof(ippool_key));
+                                               if (!strcmp(old_key.nas,NASname)){
+                                                       mppp = 1;
+                                                       break;
+                                               }
+                                       }
+                                       else{
                                                mppp = 1;
                                                break;
                                        }
@@ -253,13 +295,20 @@ void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname,
        if (key_datum.dptr){
                if (found && ! mppp){
                        datum key_datum_tmp,data_datum_tmp;
+                       old_ippool_key old_key_tmp;
                        ippool_key key_tmp;
-                       memset(key_tmp.nas,0,MAX_NAS_NAME_SIZE);
-                       strncpy(key_tmp.nas,NASname,MAX_NAS_NAME_SIZE - 1);
-                       key_tmp.port=port;
-                       key_datum_tmp.dptr = (char *) &key_tmp;
-                       key_datum_tmp.dsize = sizeof(ippool_key);
-
+                       if (old){
+                               memset(old_key_tmp.nas,0,MAX_NAS_NAME_SIZE);
+                               strlcpy(old_key_tmp.nas,NASname,MAX_NAS_NAME_SIZE - 1);
+                               old_key_tmp.port=port;
+                               key_datum_tmp.dptr = (char *) &old_key_tmp;
+                               key_datum_tmp.dsize = sizeof(old_ippool_key);
+                       }
+                       else{
+                               memcpy(key_tmp.key,key_str,16);
+                               key_datum_tmp.dptr = (char *) &key_tmp;
+                               key_datum_tmp.dsize = sizeof(ippool_key);
+                       }
                        data_datum_tmp = gdbm_fetch(sessiondb, key_datum_tmp);
                        if (data_datum_tmp.dptr != NULL) {
                                rcode = gdbm_store(sessiondb, key_datum, data_datum_tmp, GDBM_REPLACE);
@@ -278,8 +327,10 @@ void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname,
                        else {
                                if (mppp)
                                        extra = 1;
-//                             if (!mppp)
-//                                     printf("Error in if statements!!!\n");
+#if 0
+                               if (!mppp)
+                                       printf("Error in if statements!!!\n");
+#endif
                        }
                }
                free(key_datum.dptr);
@@ -288,12 +339,21 @@ void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname,
                        entry.extra=1;
                data_datum.dptr = (char *) &entry;
                data_datum.dsize = sizeof(ippool_info);
-               memset(key.nas,0,MAX_NAS_NAME_SIZE);
-               strncpy(key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
-               key.port = port;
-               key_datum.dptr = (char *) &key;
-               key_datum.dsize = sizeof(ippool_key);
-               printf("rlm_ippool_tool: Allocating ip to nas/port: %s/%u\n",key.nas,key.port);
+
+               if (old){
+                       memset(old_key.nas,0,MAX_NAS_NAME_SIZE);
+                       strlcpy(old_key.nas,NASname,MAX_NAS_NAME_SIZE -1 );
+                       old_key.port = port;
+                       key_datum.dptr = (char *) &old_key;
+                       key_datum.dsize = sizeof(old_ippool_key);
+                       printf("rlm_ippool_tool: Allocating ip to nas/port: %s/%u\n",old_key.nas,old_key.port);
+               }
+               else{
+                       memcpy(key.key,key_str,16);
+                       key_datum.dptr = (char *) &key;
+                       key_datum.dsize = sizeof(ippool_key);
+                       printf("rlm_ippool_tool: Allocating ip to key: '%s'\n",hex_str);
+               }
                rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE);
                if (rcode < 0) {
                        printf("rlm_ippool_tool: Failed storing data to %s: %s\n",
@@ -325,22 +385,80 @@ void addip(char *sessiondbname,char *indexdbname,char *ipaddress, char* NASname,
                        return;
                }
 
-               printf("rlm_ippool_tool: Allocated ip %s to client on nas %s,port %u\n",
-                               ipaddress, key.nas,port);
+               if (old)
+                       printf("rlm_ippool_tool: Allocated ip %s to client on nas %s,port %u\n",
+                               ipaddress, old_key.nas,port);
+               else
+                       printf("rlm_ippool_tool: Allocated ip %s to key  '%s'\n",ipaddress,hex_str);
 
        }
     gdbm_close(indexdb);
     gdbm_close(sessiondb);
 }
+void tonewformat(char *sessiondbname,char *newsessiondbname){
+    GDBM_FILE sessiondb;
+    GDBM_FILE newsessiondb;
+    datum key_datum,keynext_datum,data_datum,newkey_datum;
+    old_ippool_key old_key;
+    ippool_key key;
+    char key_str[17];
+    char hex_str[35];
+    int rcode;
+
+    sessiondb=gdbm_open(sessiondbname,512,GDBM_READER,0,NULL);
+    newsessiondb=gdbm_open(newsessiondbname,512,GDBM_NEWDB,0,NULL);
 
-void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress) {
+    if (sessiondb==NULL || newsessiondb==NULL) return;
+
+    memset(key_str,0,17);
+
+    key_datum=gdbm_firstkey(sessiondb);
+    while (key_datum.dptr) {
+       keynext_datum=gdbm_nextkey(sessiondb,key_datum);
+       if (key_datum.dsize==sizeof(struct old_ippool_key)) {
+               char md5_input_str[MAX_STRING_LEN];
+               MD5_CTX md5_context;
+
+               memcpy(&old_key,key_datum.dptr,sizeof(struct old_ippool_key));
+               snprintf(md5_input_str,MAX_STRING_LEN, "%s %d",old_key.nas,old_key.port);
+               MD5Init(&md5_context);
+               MD5Update(&md5_context, md5_input_str, strlen(md5_input_str));
+               MD5Final(key_str, &md5_context);
+               memcpy(key.key,key_str,16);
+               lrad_bin2hex(key_str,hex_str,16);
+               hex_str[32] = '\0';
+               printf("rlm_ippool_tool: Transforming pair nas/port (%s/%d) to md5 '%s'\n",
+                       old_key.nas,old_key.port,hex_str);
+               newkey_datum.dptr = (char *) &key;
+               newkey_datum.dsize = sizeof(ippool_key);
+               data_datum=gdbm_fetch(sessiondb,key_datum);
+               if (data_datum.dptr!=NULL){
+                   rcode=gdbm_store(newsessiondb,newkey_datum,data_datum,GDBM_REPLACE);
+                   if (rcode < 0) {
+                               printf("Failed to update new file %s: %s\n",newsessiondbname,gdbm_strerror(gdbm_errno));
+                               gdbm_close(newsessiondb);
+                               gdbm_close(sessiondb);
+                               return;
+                       }
+               }
+       }
+       key_datum=keynext_datum;
+    }
+    gdbm_close(newsessiondb);
+    gdbm_close(sessiondb);
+}
+
+void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress, int old) {
     GDBM_FILE sessiondb;
     GDBM_FILE indexdb;
     datum key_datum,keynext_datum,data_datum,save_datum;
+    old_ippool_key old_key;
     ippool_key key;
     ippool_info info;
     struct in_addr ipaddr;
     int num;
+    char key_str[17];
+    char hex_str[35];
     char *ip;
     int mode=GDBM_READER;
     int rcode;
@@ -351,11 +469,16 @@ void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress) {
 
     if (sessiondb==NULL || indexdb==NULL) return;
 
+    memset(key_str,0,17);
+
     key_datum=gdbm_firstkey(sessiondb);
     while (key_datum.dptr) {
        keynext_datum=gdbm_nextkey(sessiondb,key_datum);
-       if (key_datum.dsize==sizeof(struct ippool_key)) {
-           memcpy(&key,key_datum.dptr,sizeof(struct ippool_key));
+       if (key_datum.dsize==sizeof(struct ippool_key) || key_datum.dsize==sizeof(struct old_ippool_key)) {
+           if (old)
+                memcpy(&old_key,key_datum.dptr,sizeof(struct old_ippool_key));
+           else
+                memcpy(&key,key_datum.dptr,sizeof(struct ippool_key));
 
            data_datum=gdbm_fetch(sessiondb,key_datum);
            if (data_datum.dptr!=NULL) {
@@ -365,19 +488,27 @@ void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress) {
                ip=inet_ntoa(ipaddr);
 
                if (info.active) active++;
-               if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
-                   printf("NAS:%s port:0x%x - ",key.nas,key.port);
+               if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info)){
+                   if (old)
+                       printf("NAS:%s port:0x%x - ",old_key.nas,old_key.port);
+                   else{
+                       memcpy(key_str,key.key,16);
+                       lrad_bin2hex(key_str,hex_str,16);
+                       hex_str[32] = '\0';
+                       printf("KEY: '%s' - ",hex_str);
+                   }
+               }
                if (!vflag && aflag && info.active && MATCH_IP(ipaddress,ip))
                    printf("%s\n",ip);
                else if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
                    printf("ipaddr:%s active:%d cli:%s",
                        inet_ntoa(ipaddr),info.active,info.cli);
 
-               //
-               // algorythm copied from rlm_ippool.c:
-               // - set active to zero
-               // - set number of sessions to zero
-               //
+               /*
+                * algorythm copied from rlm_ippool.c:
+                * - set active to zero
+                * - set number of sessions to zero
+                */
                if (rflag && MATCH_IP(ipaddress,ip)) {
                    info.active=0;
                        save_datum.dptr = key_datum.dptr;
@@ -425,8 +556,16 @@ void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress) {
                if (vflag && MATCH_IP(ipaddress,ip) && MATCH_ACTIVE(info))
                    printf("\n");
            } else
-               if (vflag && ipaddress==NULL)
-                   printf("NAS:%s port:0x%x\n",key.nas,key.port);
+               if (vflag && ipaddress==NULL){
+                   if (old)
+                       printf("NAS:%s port:0x%x\n",old_key.nas,old_key.port);
+                   else{
+                       memcpy(key_str,key.key,16);
+                       lrad_bin2hex(key_str,hex_str,16);
+                       hex_str[32] = '\0';
+                       printf("KEY: '%s' - ",hex_str);
+                   }
+               }
        }
        key_datum=keynext_datum;
     }
@@ -434,16 +573,19 @@ void viewdb(char *sessiondbname,char *indexdbname,char *ipaddress) {
     gdbm_close(sessiondb);
 }
 
-void usage(char *argv0) {
-    printf("Usage: %s [-a] [-c] [-v] <session-db> <index-db> [ipaddress]\n",argv0);
+void NEVER_RETURNS usage(char *argv0) {
+    printf("Usage: %s [-a] [-c] [-o] [-v] <session-db> <index-db> [ipaddress]\n",argv0);
     printf("-a: print all active entries\n");
     printf("-c: report number of active entries\n");
     printf("-r: remove active entries\n");
     printf("-v: verbose report of all entries\n");
+    printf("-o: Assume old database format (nas/port pair, not md5 output)\n");
     printf("If an ipaddress is specified then that address is used to\n");
     printf("limit the actions or output.\n");
     printf("Usage: %s -n  <session-db> <index-db> <ipaddress> <nasIP> <nasPort>\n",argv0);
     printf("-n: Mark the entry nasIP/nasPort as having ipaddress\n");
+    printf("Usage: %s -u <session-db> <new-session-db>\n",argv0);
+    printf("-u: Update old format database to new.\n");
     exit(0);
 }
 
@@ -451,24 +593,28 @@ int main(int argc,char **argv) {
     int ch;
     char *argv0=argv[0];
 
-    while ((ch=getopt(argc,argv,"acrvn"))!=-1)
+    while ((ch=getopt(argc,argv,"acrvnou"))!=-1)
        switch (ch) {
        case 'a': aflag++;break;
        case 'c': cflag++;break;
        case 'r': rflag++;break;
        case 'v': vflag=1;break;
        case 'n': nflag=1;break;
+       case 'o': oflag=1;break;
+       case 'u': uflag=1;break;
        default: usage(argv0);
        }
     argc -= optind;
     argv += optind;
 
-    if ((argc==2 || argc==3) && !nflag) {
-               viewdb(argv[0],argv[1],argv[2]);
+    if ((argc==2 || argc==3) && !nflag && !uflag) {
+               viewdb(argv[0],argv[1],argv[2],oflag);
                if (cflag) printf("%d\n",active);
        } else
                if (argc==5 && nflag)
-                       addip(argv[0],argv[1],argv[2],argv[3],argv[4]);
+                       addip(argv[0],argv[1],argv[2],argv[3],argv[4],oflag);
+               else if (argc==2 && uflag)
+                       tonewformat(argv[0],argv[1]);
                else
                        usage(argv0);
     return 0;
index 9e71b4a..5c57b01 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.7 .
+# From configure.in Revision: 1.8 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -912,7 +912,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1832,8 +1832,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1891,8 +1890,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2008,8 +2006,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2063,8 +2060,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2109,8 +2105,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2154,8 +2149,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2520,8 +2514,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2544,8 +2537,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" = "x"; then
@@ -2574,8 +2567,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2653,8 +2645,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2677,8 +2668,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" != "x"; then
@@ -2733,8 +2724,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2757,8 +2747,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" = "x"; then
@@ -2787,8 +2777,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2893,8 +2882,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2917,8 +2905,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" != "x"; then
@@ -2974,8 +2962,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2998,8 +2985,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" = "x"; then
@@ -3028,8 +3015,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3134,8 +3120,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3158,8 +3143,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" != "x"; then
@@ -3220,8 +3205,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3244,8 +3228,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" = "x"; then
@@ -3274,8 +3258,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3380,8 +3363,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3404,8 +3386,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" != "x"; then
@@ -3462,8 +3444,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3486,8 +3467,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" = "x"; then
@@ -3516,8 +3497,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3622,8 +3602,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3646,8 +3625,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" != "x"; then
@@ -4501,11 +4480,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -4544,6 +4518,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index a3b82fd..3206a85 100644 (file)
@@ -1,3 +1,4 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_krb5.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_krb5])
@@ -50,16 +51,16 @@ if test x$with_[]modname != xno; then
        )
 
        smart_try_dir=$rlm_krb5_include_dir
-       AC_SMART_CHECK_INCLUDE(krb5.h)
+       FR_SMART_CHECK_INCLUDE(krb5.h)
 
        smart_try_dir=$rlm_krb5_lib_dir
 
-       AC_SMART_CHECK_LIB(k5crypto, krb5_encrypt_data)
+       FR_SMART_CHECK_LIB(k5crypto, krb5_encrypt_data)
        if test "x$ac_cv_lib_k5crypto_krb5_encrypt_data" = "xyes"; then
                krb5libcrypto="-lk5crypto"
        fi
 
-       AC_SMART_CHECK_LIB(crypto, DH_new)
+       FR_SMART_CHECK_LIB(crypto, DH_new)
        if test "x$ac_cv_lib_crypto_DH_new" = "xyes"; then
                krb5libcrypto="-lcrypto"
        fi
@@ -68,12 +69,12 @@ if test x$with_[]modname != xno; then
                AC_MSG_WARN([neither krb5 'k5crypto' nor 'crypto' libraries are found!])
        fi
 
-       AC_SMART_CHECK_LIB(com_err, set_com_err_hook)
+       FR_SMART_CHECK_LIB(com_err, set_com_err_hook)
        if test "x$ac_cv_lib_com_err_set_com_err_hook" != "xyes"; then
                AC_MSG_WARN([the comm_err library isn't found!]) 
        fi
 
-       AC_SMART_CHECK_LIB(krb5, krb5_init_context)
+       FR_SMART_CHECK_LIB(krb5, krb5_init_context)
        if test "x$ac_cv_lib_krb5_krb5_init_context" != "xyes"; then
                fail="$fail krb5"
        fi
index 3ce1e32..1abedae 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Nathan Neulinger <nneul@umr.edu>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
 
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-static const char rcsid[] = "$Id$";
-
-#include       "autoconf.h"
-#include       "libradius.h"
+#include       <freeradius-devel/autoconf.h>
 
 #include       <stdio.h>
 #include       <stdlib.h>
 #include       <string.h>
 
-#include       "radiusd.h"
-#include       "modules.h"
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/modules.h>
 
 /* krb5 includes */
 #include <krb5.h>
@@ -45,7 +44,7 @@ typedef struct rlm_krb5_t {
        krb5_context *context;
 } rlm_krb5_t;
 
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
        { "keytab", PW_TYPE_STRING_PTR,
          offsetof(rlm_krb5_t,keytab), NULL, NULL },
        { "service_principal", PW_TYPE_STRING_PTR,
@@ -75,7 +74,7 @@ static int verify_krb5_tgt(krb5_context context, rlm_krb5_t *instance,
                        *servername = '\0';
                }
 
-               strncpy(service,instance->service_princ,sizeof(service));
+               strlcpy(service,instance->service_princ,sizeof(service));
                service[sizeof(service)-1] = '\0';
 
                if (servername != NULL) {
@@ -93,7 +92,7 @@ static int verify_krb5_tgt(krb5_context context, rlm_krb5_t *instance,
                return RLM_MODULE_REJECT;
        }
 
-       strncpy(phost, krb5_princ_component(c, princ, 1)->data, BUFSIZ);
+       strlcpy(phost, krb5_princ_component(c, princ, 1)->data, BUFSIZ);
        phost[BUFSIZ - 1] = '\0';
 
        /*
@@ -246,7 +245,7 @@ static int krb5_auth(void *instance, REQUEST *request)
         *  Ensure that we're being passed a plain-text password,
         *  and not anything else.
         */
-       if (request->password->attribute != PW_PASSWORD) {
+       if (request->password->attribute != PW_USER_PASSWORD) {
                radlog(L_AUTH, "rlm_krb5: Attribute \"User-Password\" is required for authentication.  Cannot use \"%s\".", request->password->name);
                return RLM_MODULE_INVALID;
        }
@@ -254,8 +253,8 @@ static int krb5_auth(void *instance, REQUEST *request)
        /*
         *      shortcuts
         */
-       user = request->username->strvalue;
-       pass = request->password->strvalue;
+       user = request->username->vp_strvalue;
+       pass = request->password->vp_strvalue;
 
        /* Generate a unique cache_name */
        memset(cache_name, 0, sizeof(cache_name));
@@ -355,7 +354,7 @@ static int krb5_auth(void *instance, REQUEST *request)
         *  Ensure that we're being passed a plain-text password,
         *  and not anything else.
         */
-       if (request->password->attribute != PW_PASSWORD) {
+       if (request->password->attribute != PW_USER_PASSWORD) {
                radlog(L_AUTH, "rlm_krb5: Attribute \"User-Password\" is required for authentication.  Cannot use \"%s\".", request->password->name);
                return RLM_MODULE_INVALID;
        }
@@ -363,8 +362,8 @@ static int krb5_auth(void *instance, REQUEST *request)
        /*
         *      shortcuts
         */
-       user = request->username->strvalue;
-       pass = request->password->strvalue;
+       user = request->username->vp_strvalue;
+       pass = request->password->vp_strvalue;
 
        if ( (r = krb5_parse_name(context, user, &userP)) ) {
                radlog(L_AUTH, "rlm_krb5: [%s] krb5_parse_name failed: %s",
@@ -400,20 +399,19 @@ static int krb5_auth(void *instance, REQUEST *request)
 #endif /* HEIMDAL_KRB5 */
 
 module_t rlm_krb5 = {
-  "Kerberos",
-  RLM_TYPE_THREAD_UNSAFE,      /* type: not thread safe */
-  NULL,                                /* initialize */
-  krb5_instantiate,            /* instantiation */
-  {
-         krb5_auth,            /* authenticate */
-         NULL,                 /* authorize */
-         NULL,                 /* pre-accounting */
-         NULL,                 /* accounting */
-         NULL,                 /* checksimul */
-         NULL,                 /* pre-proxy */
-         NULL,                 /* post-proxy */
-         NULL                  /* post-auth */
-  },
-  krb5_detach,                 /* detach */
-  NULL,                                /* destroy */
+       RLM_MODULE_INIT,
+       "Kerberos",
+       RLM_TYPE_THREAD_UNSAFE, /* type: not thread safe */
+       krb5_instantiate,               /* instantiation */
+       krb5_detach,                    /* detach */
+       {
+               krb5_auth,              /* authenticate */
+               NULL,                   /* authorize */
+               NULL,                   /* pre-accounting */
+               NULL,                   /* accounting */
+               NULL,                   /* checksimul */
+               NULL,                   /* pre-proxy */
+               NULL,                   /* post-proxy */
+               NULL                    /* post-auth */
+       },
 };
index f948915..53aa0ba 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.10.2.4 .
+# From configure.in Revision: 1.15 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -910,7 +910,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1833,8 +1833,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1892,8 +1891,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2009,8 +2007,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2064,8 +2061,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2110,8 +2106,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2155,8 +2150,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2321,8 +2315,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2389,8 +2382,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2467,8 +2459,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2491,8 +2482,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" = "x"; then
@@ -2521,8 +2512,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2627,8 +2617,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2651,8 +2640,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" != "x"; then
@@ -2708,8 +2697,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2732,8 +2720,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" = "x"; then
@@ -2762,8 +2750,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2868,8 +2855,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2892,8 +2878,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" != "x"; then
@@ -2952,8 +2938,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2976,8 +2961,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" = "x"; then
@@ -3006,8 +2991,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3085,8 +3069,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3109,8 +3092,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" != "x"; then
@@ -3195,8 +3178,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3289,8 +3271,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3383,8 +3364,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3449,7 +3429,7 @@ if test "${with_edir+set}" = set; then
   withval="$with_edir"
    case "$withval" in
     yes)
-       SMART_CFLAGS="$SMART_CFLAGS -DNOVELL_UNIVERSAL_PASSWORD -DNOVELL"
+       SMART_CFLAGS="$SMART_CFLAGS -DNOVELL_UNIVERSAL_PASSWORD"
        edir="edir_ldapext.c"
         ;;
     *)
@@ -4274,11 +4254,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -4317,6 +4292,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index a6bfe2f..2465f9d 100644 (file)
@@ -1,3 +1,4 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_ldap.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_ldap])
@@ -7,14 +8,19 @@ SMART_LIBS=
 SMART_CLFAGS=
 if test x$with_[]modname != xno; then
 
+       dnl ############################################################
+       dnl # Check for compiler
+       dnl ############################################################
        AC_PROG_CC
 
-       AC_CHECK_LIB(resolv, inet_aton)
+       dnl ############################################################
+       dnl # Check for command line options
+       dnl ############################################################
 
        dnl extra argument: --with-rlm-ldap-lib-dir
        rlm_ldap_lib_dir=
        AC_ARG_WITH(rlm-ldap-lib-dir,
-       [  --with-rlm-ldap-lib-dir=DIR       Directory for LDAP library files []],
+       [  --with-rlm-ldap-lib-dir=DIR       directory for LDAP library files []],
        [ case "$withval" in
            no)
                AC_MSG_ERROR(Need rlm-ldap-lib-dir)
@@ -28,9 +34,9 @@ if test x$with_[]modname != xno; then
        )
 
        dnl extra argument: --with-rlm-ldap-include-dir
-       rlm_ldap_inc_dir=
+       rlm_ldap_include_dir=
        AC_ARG_WITH(rlm-ldap-include-dir,
-       [  --with-rlm-ldap-include-dir=DIR   Directory for LDAP include files []],
+       [  --with-rlm-ldap-include-dir=DIR   directory for LDAP include files []],
        [ case "$withval" in
            no)
                AC_MSG_ERROR(Need rlm-ldap-include-dir)
@@ -43,57 +49,82 @@ if test x$with_[]modname != xno; then
          esac ]
        )
 
-       smart_try_dir=$rlm_ldap_include_dir
-       AC_SMART_CHECK_INCLUDE(lber.h)
-       AC_SMART_CHECK_INCLUDE(ldap.h)
+       dnl extra argument: --enable-shared --disable-shared
+       AC_ENABLE_SHARED
+
+       dnl OpenLDAP doesn't provide an autoconf test for their libldap,
+       dnl and we can't reasonably check for all the dependancies for
+       dnl every version and every set of options.
+       if test "x$enable_shared" = "xno"; then
+               AC_MSG_WARN(Static linking with libldap will probably result in unresolved symbols.)
+       fi
 
-       AC_SMART_CHECK_LIB(sasl, sasl_encode)
-       AC_SMART_CHECK_LIB(crypto, DH_new)
-       AC_SMART_CHECK_LIB(ssl, SSL_new)
+       dnl extra argument: --with-threads
+       rlm_ldap_with_threads=yes
+       AC_ARG_WITH(threads,
+       [  --with-threads          use threads, if available. (default=yes) ],
+       [ case "$withval" in
+           no)
+               rlm_ldap_with_threads=no
+               ;;
+           *)
+               ;;
+           esac ])
+
+       dnl ############################################################
+       dnl # Check for libraries
+       dnl ############################################################
+
+       dnl pthread stuff is usually in -lpthread
+       dnl or in -lc_r, on *BSD
+       if test "x$rlm_ldap_with_threads" = "xyes"; then
+           AC_CHECK_LIB(pthread, pthread_create,
+                        [ LIBS="-lpthread $LIBS" ],
+                        AC_CHECK_LIB(c_r, pthread_create,
+                                     [ LIBS="-lc_r $LIBS" ],
+                                     [ rlm_ldap_with_threads="no" ]
+                                     )
+                        )
+       fi
 
+       dnl Try only "-lldap_r" or "-lldap"
+       dnl Static linking will probably not work, but nobody ever
+       dnl complained about it.
        smart_try_dir=$rlm_ldap_lib_dir
-       AC_SMART_CHECK_LIB(lber, ber_init)
-        if test "x$ac_cv_lib_lber_ber_init" != "xyes"; then
-         fail="$fail liblber"
-        else
-          if test "x$ac_cv_header_pthread_h" = "xyes"; then
-           AC_SMART_CHECK_LIB(ldap_r, ldap_init)
-            if test "x$ac_cv_lib_ldap_r_ldap_init" != "xyes"; then
-             fail="$fail libldap_r"
-           else
-               libldap=ldap_r
-            fi
-          else
-           AC_SMART_CHECK_LIB(ldap, ldap_init)
-            if test "x$ac_cv_lib_ldap_ldap_init" != "xyes"; then
-             fail="$fail libldap"
-           else
-               libldap=ldap
-           fi
-          fi
-        fi
-
-       if test x"$libldap" != "x"; then
-         AC_SMART_CHECK_LIB("$libldap", ldap_start_tls_s)
-
-         if test "x${ac_cv_lib_ldap_ldap_start_tls_s}${ac_cv_lib_ldap_r_ldap_start_tls_s}" != "x"; then
-            SMART_CFLAGS="$SMART_CFLAGS -DHAVE_LDAP_START_TLS"
-         fi
-      
-         AC_SMART_CHECK_LIB("$libldap", ldap_initialize)
-
-         if test "x${ac_cv_lib_ldap_ldap_initialize}${ac_cv_lib_ldap_r_ldap_initialize}" != "x"; then
-            SMART_CFLAGS="$SMART_CFLAGS -DHAVE_LDAP_INITIALIZE"
-         fi
-      
-         AC_SMART_CHECK_LIB("$libldap", ldap_int_tls_config)
-
-         if test "x${ac_cv_lib_ldap_ldap_int_tls_config}${ac_cv_lib_ldap_r_ldap_int_tls_config}" != "x"; then
-            SMART_CFLAGS="$SMART_CFLAGS -DHAVE_LDAP_INT_TLS_CONFIG"
-         fi
+       if test "x$rlm_ldap_with_threads" = "xyes"; then
+           FR_SMART_CHECK_LIB(ldap_r, ldap_init)
+           if test "x$ac_cv_lib_ldap_r_ldap_init" != "xyes"; then
+               fail="$fail libldap_r"
+           fi
+       else
+           FR_SMART_CHECK_LIB(ldap, ldap_init)
+           if test "x$ac_cv_lib_ldap_ldap_init" != "xyes"; then
+               fail="$fail libldap"
+           fi
+       fi
 
+       dnl ############################################################
+       dnl # Check for header files
+       dnl ############################################################
+
+       smart_try_dir=$rlm_ldap_include_dir
+       FR_SMART_CHECK_INCLUDE(ldap.h)
+       if test "$ac_cv_header_ldap_h" != "yes"; then
+         fail="$fail ldap.h"
        fi
 
+       dnl ############################################################
+       dnl # Check for library functions
+       dnl ############################################################
+
+       if test "x$fail" = "x"; then
+           AC_CHECK_FUNC(ldap_start_tls_s,
+               [ SMART_CFLAGS="$SMART_CFLAGS -DHAVE_LDAP_START_TLS" ])
+           AC_CHECK_FUNC(ldap_initialize,
+               [ SMART_CFLAGS="$SMART_CFLAGS -DHAVE_LDAP_INITIALIZE" ])
+           AC_CHECK_FUNC(ldap_int_tls_config,
+               [ SMART_CFLAGS="$SMART_CFLAGS -DHAVE_LDAP_INT_TLS_CONFIG" ])
+       fi
 
        targetname=modname
 else
@@ -108,10 +139,10 @@ if test x"$fail" != x""; then
                AC_MSG_WARN([silently not building ]modname[.])
                AC_MSG_WARN([FAILURE: ]modname[ requires: $fail.])
                if test x"$headersuggestion" != x; then
-                       AC_MSG_WARN([$headersuggestion]) 
+                       AC_MSG_WARN([$headersuggestion])
                fi
                if test x"$libsuggestion" != x; then
-                       AC_MSG_WARN([$libsuggestion]) 
+                       AC_MSG_WARN([$libsuggestion])
                fi
                targetname=""
        fi
@@ -121,7 +152,7 @@ dnl extra argument: --with-edir
 dnl If using Novell eDirectory, enable UP and Novell specific code
 WITH_EDIRECTORY=no
 AC_ARG_WITH(edir,
-[  --with-edir           Enable Novell eDirectory integration.  (default=no) ],
+[  --with-edir             enable Novell eDirectory integration.  (default=no) ],
 [ case "$withval" in
     yes)
        SMART_CFLAGS="$SMART_CFLAGS -DNOVELL_UNIVERSAL_PASSWORD -DNOVELL"
index 1e4a128..b1e1cd0 100644 (file)
  *
  * To contact Novell about this file by physical or electronic mail, you may
  * find current contact  information at www.novell.com.
+ *
+ * Copyright 2006 The FreeRADIUS Server Project.
  */ 
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <ldap.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <strings.h>
+
 /* NMAS error codes */
 #define NMAS_E_BASE                       (-1600)
 
index aa709cd..fcbdaf8 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * This module is based on LDAP patch to Cistron radiusd by James Golovich
- * <james@wwnet.net>, which in turn was based mostly on a Mysql+Cistron patch
- * from <oyarzun@wilmington.net>
- *
- * 17 Jan 2000,        Adrian Pavlykevych <pam@polynet.lviv.ua>
- *     - OpenLDAP SDK porting, basic TLS support, LDAP authorization,
- *       fault tolerance with multiple LDAP server support
- * 24 May 2000,        Adrian Pavlykevych <pam@polynet.lviv.ua>
- *     - Converting to new configuration file format, futher improvements
- *       in fault tolerance, threaded operation
- * 12 Dec 2000,        Adrian Pavlykevych <pam@polynet.lviv.ua>
- *     - Added preliminary support for multiple instances
- *     - moved all instance configuration into dynamicly allocated structure
- *     - Removed connection maintenance thread and all attempts for multihreading
- *       the module itself. OpenLDAP SDK is not thread safe when used with shared
- *       LDAP connection.
- *     - Added configuration option for defining LDAP attribute of user object,
- *       which controls remote access.
- * 16 Feb 2001, Hannu Laurila <hannu.laurila@japo.fi>
- *     - LDAP<->RADIUS attribute mappings are now read from a file
- *     - Support for generic RADIUS check and reply attribute.
- * Jun 2001, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Fix: check and reply attributes from LDAP _replace_ existing ones
- *     - Added "default_profile" directive, which points to radiusProfile
- *       object, which contains default values for RADIUS users
- *     - Added "profile_attribute" directive, which specifies user object
- *       attribute pointing to radiusProfile object.
- * Nov 2001, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Added support for adding the user password to the check. Based on
- *       the password_header directive rlm_ldap will strip the
- *       password header if needed. This will make support for CHAP much easier.
- *     - Added module messages when we reject a user.
- *     - Added ldap_groupcmp to allow searching for user group membership.
- *     - Added ldap_xlat to allow ldap urls in xlat strings. Something like:
- *       %{ldap:ldap:///dc=company,dc=com?cn?sub?uid=user}
- * Nov 2001, Gordon Tetlow <gordont@gnf.org>
- *     - Do an xlat on the access_group attribute.
- * Dec 2001, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Added ldap caching for the default/regular profiles and group entries.
- *     - Fixed a memory leak in ldap_xlat.
- *     - Removed dict_attrbyname from ldap_pairget. They are not needed.
- *     - Moved the radius_xlat's for filter and basedn in ldap_authenticate() to
- *       the right place.
- *     - Made the module thread safe. We create a connection pool and each thread
- *       will call ldap_get_conn to lock one of the ldap connections and release with
- *       a call to ldap_release_conn when it has finished.
- *     - Request only the user attributes that interest us (radius attributes,regular
- *       profile,user password and access attribute).
- * Mar 2002, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Fixed a bug where the ldap server will kill the idle connections from the ldap
- *       connection pool. We now check if ldap_search returns LDAP_SERVER_DOWN and try to
- *       reconnect if it does. Bug noted by Dan Perik <dan_perik-work@ntm.org.pg>
- * May 2002, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Instead of the Group attribute we now have the Ldap-Group attribute, to avoid
- *       collisions with other modules
- *     - If perform_search fails check the ld != NULL before using it. Based on a bug report
- *       by John <jhogenmiller@pennswoods.net>
- * Jun 2002, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Add the ability to do a paircmp on the check items. Add a compare_check_items boolean
- *       configuration directive which defaults to no. If it is set then we will do a compare
- *     - Add another configuration directive. access_attr_used_for_allow. If it is set to yes
- *       then the access_attr will be used to allow user access. If it is set to no then it will
- *       be used to deny user access.
- *     - Remember to free inst->atts in ldap_detach()
- *     - Add a forgotten ldap_free_urldesc in ldap_xlat()
- *     - Add a variable locked in the LDAP_CONN structure. We use this to avoid deadlocks. The mutex
- *       we are using is of type fast and can deadlock if the same thread tries to relock it. That
- *       could happen in case of calls to xlat.
- *     - When ldap_search returns NO_SUCH_OBJECT don't return fail but notfound
- * Jul 2002, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Fix the logic when we get an LDAP_SERVER_DOWN or we have conn->ld == NULL in perform_search
- *     - Try to minimize the penalty of having the ldap server go down. The comments before
- *       MAX_FAILED_CONNS_* definitions should explain things.
- *     - Check for a number of error codes from ldap_search and log corresponding error messages
- *       We should only reconnect when that can help things.
- *     - In ldap_groupcmp instead of first searching for the group object and then checking user
- *       group membership combine them in one ldap search operation. That should make group
- *       membership checks a lot faster.
- *     - Remember to do ldap_release_conn and ldap_msgfree when we do paircmp and the result is reject
- * Aug 2002, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Add support for group membership attribute inside the user entry in ldap_groupcmp. The attribute
- *       can either contain the name or the DN of the group. Added the groupmembership_attribute
- *       configuration directive
- *     - Move the ldap_{get,release}_conn in ldap_groupcmp so that we hold a connection for the minimum time.
- *     - Now that ldap_groupcmp is complete we really don't need access_group. Removed it.
- *     - Remember to free groupmembership_attribute in ldap_detach
- *     - Don't delete existing generic attributes in ldap_pairget when adding new ones. Since generic attributes
- *       have operators we don't need to try to be cleaver.
- * Sep 2002, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Fix a crash in ldap_pairget when the attribute value is larger than the buffer size
- *       Bug report by Stefan Radovanovici <sra@rtsffm.com>
- *     - If we add a check item then use the == operator. Based on an idea by Allister Maguire <amaguire@gnc.net.nz>
- *     - Only add a failure message for bind as user failed in ldap_authenticate if the result of ldap_connect was
- *       RLM_MODULE_REJECT
- *     - Make tls_mode a configurable option. Patch from John <jhogenmiller@pennswoods.net>
- *     - Allow multiple regular profiles for an entry
- * Oct 2002, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Disable cache after searching for the default profile
- *     - Use the MAX_FAILED_CONNS_* in ldap_authenticate() when calling ldap_connect()
- * Nov 2002, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Set LDAP version to V3 before binding. Now freeradius should work with openldap21
- * Dec 2002, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Set default values for the server and basedn parameters
- * Feb 2003, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Add support for ldap_initialize. That way we can specify the server as an ldap url.
- *       Based on ideas from Derrik Pates <dpates@dsdk12.net>
- * Mar 2003, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Add an ldap_escape_func. Escape the * character from the filter so that we can avoid
- *       the trivial DoS of username=*
- *     - Remove the caching code. It does not exist in openldap21.
- *       Based on a report from Mike Denka <mdenk@whidbey.net>
- * May 2003, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Don't do a double free on the attribute maps. Bug noted by Derrik Pates <dpates@dsdk12.net>
- *     - Apply a patch from Alexander M. Pravking <fduch@antar.bryansk.ru> to do an xlat on the
- *       retrieved attributes.
- * Aug 2003, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - In case of a bad search filter, print out the corresponding filter
- * Sep 2003, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Compile even if we don't have pthread's
- * Oct 2003, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Add a new configuration directive, base_filter which is used for base scope searches
- *       (When searching for the default/regular profiles for example)
- * Nov 2003, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Add a new configuration directive, do_xlat (default: yes). If set we use pairxlatmove
- *       on the radius attributes, else we fall back to the plain old pairadd. That way people
- *       can fall back on the 0.8.1 behaviour without making changes to their ldap database or
- *       gain a little performance by not using pairxlatmove
- * Dec 2003, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - Add a patch from Jon Miner <miner@doit.wisc.edu> to add the ability to configure
- *       various LDAP TLS options
- *     - Only call pairfree if we are using pairxlatmove not for pairadd
- * Mar 2004, Kostas Kalevras <kkalev@noc.ntua.gr>
- *     - If we are passed an empty password log a module failure message not an error message
- * Apr 2004, Kostas Kalveras <kkalev@noc.ntua.gr>
- *     - Add a patch from Tarun Bhushan <tarun.bhushan@macquarie.com> to add a tls_mode boolean
- *       directive so that we can enable TLS connetions even if port is not set to 636
- *     - Add an error message if ldap_initialize() is not available and we are passed a URL like
- *       'server' directive.
- *     - Add a per instance Ldap-Group attribute (of the form <instance>-Ldap-Group) and register
- *       a corresponding ldap_groupcmp function
- *     - Small change to ldap_get_conn to fix problems on some platforms
+ *   Copyright 2004,2006 The FreeRADIUS Server Project.
  */
-static const char rcsid[] = "$Id$";
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include       <sys/types.h>
 #include       <sys/socket.h>
@@ -181,11 +43,10 @@ static const char rcsid[] = "$Id$";
 #include       <unistd.h>
 #include       <pthread.h>
 
-#include        "libradius.h"
-#include       "radiusd.h"
-#include       "conffile.h"
-#include       "modules.h"
-#include       "rad_assert.h"
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/conffile.h>
+#include       <freeradius-devel/modules.h>
+#include       <freeradius-devel/rad_assert.h>
 
 #ifndef HAVE_PTHREAD_H
 /*
@@ -244,11 +105,11 @@ int nmasldap_get_password(
        char     *pwd );
 
 #endif
-
 /* linked list of mappings between RADIUS attributes and LDAP attributes */
 struct TLDAP_RADIUS {
        char*                 attr;
        char*                 radius_attr;
+       LRAD_TOKEN            operator;
        struct TLDAP_RADIUS*  next;
 };
 typedef struct TLDAP_RADIUS TLDAP_RADIUS;
@@ -288,6 +149,7 @@ typedef struct {
        char           *access_attr;
        char           *passwd_hdr;
        char           *passwd_attr;
+       int             auto_header;
        char           *dictionary_mapping;
        char           *groupname_attr;
        char           *groupmemb_filt;
@@ -308,54 +170,144 @@ typedef struct {
        char            *tls_randfile;
        char            *tls_require_cert;
 #ifdef NOVELL
-       int                     edir_account_policy_check;
+       int              edir_account_policy_check;
 #endif
-       int             set_auth_type;
-}               ldap_instance;
+       int              set_auth_type;
+}  ldap_instance;
 
 /* The default setting for TLS Certificate Verification */
 #define TLS_DEFAULT_VERIFY "allow"
 
-static CONF_PARSER module_config[] = {
-       {"server", PW_TYPE_STRING_PTR, offsetof(ldap_instance,server), NULL, "localhost"},
-       {"port", PW_TYPE_INTEGER, offsetof(ldap_instance,port), NULL, "389"},
+static CONF_PARSER tls_config[] = {
+       {"start_tls", PW_TYPE_BOOLEAN,
+        offsetof(ldap_instance,start_tls), NULL, "no"},
+       {"cacertfile", PW_TYPE_FILENAME,
+        offsetof(ldap_instance,tls_cacertfile), NULL, NULL},
+       {"cacertdir", PW_TYPE_FILENAME,
+        offsetof(ldap_instance,tls_cacertdir), NULL, NULL},
+       {"certfile", PW_TYPE_FILENAME,
+        offsetof(ldap_instance,tls_certfile), NULL, NULL},
+       {"keyfile", PW_TYPE_FILENAME,
+        offsetof(ldap_instance,tls_keyfile), NULL, NULL},
+       {"randfile", PW_TYPE_STRING_PTR, /* OK if it changes on HUP */
+        offsetof(ldap_instance,tls_randfile), NULL, NULL},
+       {"require_cert", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,tls_require_cert), NULL, TLS_DEFAULT_VERIFY},
+       { NULL, -1, 0, NULL, NULL }
+};
+
+static const CONF_PARSER module_config[] = {
+       {"server", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,server), NULL, "localhost"},
+       {"port", PW_TYPE_INTEGER,
+        offsetof(ldap_instance,port), NULL, "389"},
+       {"password", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,password), NULL, ""},
+       {"identity", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,login), NULL, ""},
+
+       /*
+        *      Timeouts & stuff.
+        */
        /* wait forever on network activity */
-       {"net_timeout", PW_TYPE_INTEGER, offsetof(ldap_instance,net_timeout.tv_sec), NULL, "10"},
+       {"net_timeout", PW_TYPE_INTEGER,
+        offsetof(ldap_instance,net_timeout.tv_sec), NULL, "10"},
        /* wait forever for search results */
-       {"timeout", PW_TYPE_INTEGER, offsetof(ldap_instance,timeout.tv_sec), NULL, "20"},
+       {"timeout", PW_TYPE_INTEGER,
+        offsetof(ldap_instance,timeout.tv_sec), NULL, "20"},
        /* allow server unlimited time for search (server-side limit) */
-       {"timelimit", PW_TYPE_INTEGER, offsetof(ldap_instance,timelimit), NULL, "20"},
-       {"identity", PW_TYPE_STRING_PTR, offsetof(ldap_instance,login), NULL, ""},
-       {"tls_mode", PW_TYPE_BOOLEAN, offsetof(ldap_instance,tls_mode), NULL, "no"},
-       {"start_tls", PW_TYPE_BOOLEAN, offsetof(ldap_instance,start_tls), NULL, "no"},
-       {"tls_cacertfile", PW_TYPE_STRING_PTR, offsetof(ldap_instance,tls_cacertfile), NULL, NULL},
-       {"tls_cacertdir", PW_TYPE_STRING_PTR, offsetof(ldap_instance,tls_cacertdir), NULL, NULL},
-       {"tls_certfile", PW_TYPE_STRING_PTR, offsetof(ldap_instance,tls_certfile), NULL, NULL},
-       {"tls_keyfile", PW_TYPE_STRING_PTR, offsetof(ldap_instance,tls_keyfile), NULL, NULL},
-       {"tls_randfile", PW_TYPE_STRING_PTR, offsetof(ldap_instance,tls_randfile), NULL, NULL},
-       {"tls_require_cert", PW_TYPE_STRING_PTR, offsetof(ldap_instance,tls_require_cert), NULL, TLS_DEFAULT_VERIFY},
-       {"password", PW_TYPE_STRING_PTR, offsetof(ldap_instance,password), NULL, ""},
-       {"basedn", PW_TYPE_STRING_PTR, offsetof(ldap_instance,basedn), NULL, "o=notexist"},
-       {"filter", PW_TYPE_STRING_PTR, offsetof(ldap_instance,filter), NULL, "(uid=%u)"},
-       {"base_filter", PW_TYPE_STRING_PTR, offsetof(ldap_instance,base_filter), NULL, "(objectclass=radiusprofile)"},
-       {"default_profile", PW_TYPE_STRING_PTR, offsetof(ldap_instance,default_profile), NULL, NULL},
-       {"profile_attribute", PW_TYPE_STRING_PTR, offsetof(ldap_instance,profile_attr), NULL, NULL},
-       {"password_header", PW_TYPE_STRING_PTR, offsetof(ldap_instance,passwd_hdr), NULL, NULL},
-       {"password_attribute", PW_TYPE_STRING_PTR, offsetof(ldap_instance,passwd_attr), NULL, NULL},
+       {"timelimit", PW_TYPE_INTEGER,
+        offsetof(ldap_instance,timelimit), NULL, "20"},
+
+       /*
+        *      TLS configuration  The first few are here for backwards
+        *      compatibility.  The last is the new subsection.
+        */
+       {"tls_mode", PW_TYPE_BOOLEAN,
+        offsetof(ldap_instance,tls_mode), NULL, "no"},
+
+       {"start_tls", PW_TYPE_BOOLEAN,
+        offsetof(ldap_instance,start_tls), NULL, "no"},
+       {"tls_cacertfile", PW_TYPE_FILENAME,
+        offsetof(ldap_instance,tls_cacertfile), NULL, NULL},
+       {"tls_cacertdir", PW_TYPE_FILENAME,
+        offsetof(ldap_instance,tls_cacertdir), NULL, NULL},
+       {"tls_certfile", PW_TYPE_FILENAME,
+        offsetof(ldap_instance,tls_certfile), NULL, NULL},
+       {"tls_keyfile", PW_TYPE_FILENAME,
+        offsetof(ldap_instance,tls_keyfile), NULL, NULL},
+       {"tls_randfile", PW_TYPE_STRING_PTR, /* OK if it changes on HUP */
+        offsetof(ldap_instance,tls_randfile), NULL, NULL},
+       {"tls_require_cert", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,tls_require_cert), NULL, TLS_DEFAULT_VERIFY},
+       { "tls", PW_TYPE_SUBSECTION, 0, NULL, (const void *) tls_config },
+
+       /*
+        *      DN's and filters.
+        */
+       {"basedn", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,basedn), NULL, "o=notexist"},
+       {"filter", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,filter), NULL, "(uid=%u)"},
+       {"base_filter", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,base_filter), NULL, "(objectclass=radiusprofile)"},
+       {"default_profile", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,default_profile), NULL, NULL},
+       {"profile_attribute", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,profile_attr), NULL, NULL},
+
+       /*
+        *      Getting passwords from the database
+        */
+       {"password_header", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,passwd_hdr), NULL, NULL},
+       {"password_attribute", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,passwd_attr), NULL, NULL},
+       {"auto_header", PW_TYPE_BOOLEAN,
+        offsetof(ldap_instance,auto_header), NULL, "no"},
+
+       /*
+        *      Access limitations
+        */
        /* LDAP attribute name that controls remote access */
-       {"access_attr", PW_TYPE_STRING_PTR, offsetof(ldap_instance,access_attr), NULL, NULL},
+       {"access_attr", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,access_attr), NULL, NULL},
+       {"access_attr_used_for_allow", PW_TYPE_BOOLEAN,
+        offsetof(ldap_instance,default_allow), NULL, "yes"},
+
+       /*
+        *      Group checks.  These could probably be done
+        *      via dynamic xlat's.
+        */
+       {"groupname_attribute", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,groupname_attr), NULL, "cn"},
+       {"groupmembership_filter", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,groupmemb_filt), NULL, "(|(&(objectClass=GroupOfNames)(member=%{Ldap-UserDn}))(&(objectClass=GroupOfUniqueNames)(uniquemember=%{Ldap-UserDn})))"},
+       {"groupmembership_attribute", PW_TYPE_STRING_PTR,
+        offsetof(ldap_instance,groupmemb_attr), NULL, NULL},
+
        /* file with mapping between LDAP and RADIUS attributes */
-       {"groupname_attribute", PW_TYPE_STRING_PTR, offsetof(ldap_instance,groupname_attr), NULL, "cn"},
-       {"groupmembership_filter", PW_TYPE_STRING_PTR, offsetof(ldap_instance,groupmemb_filt), NULL, "(|(&(objectClass=GroupOfNames)(member=%{Ldap-UserDn}))(&(objectClass=GroupOfUniqueNames)(uniquemember=%{Ldap-UserDn})))"},
-       {"groupmembership_attribute", PW_TYPE_STRING_PTR, offsetof(ldap_instance,groupmemb_attr), NULL, NULL},
-       {"dictionary_mapping", PW_TYPE_STRING_PTR, offsetof(ldap_instance,dictionary_mapping), NULL, "${confdir}/ldap.attrmap"},
-       {"ldap_debug", PW_TYPE_INTEGER, offsetof(ldap_instance,ldap_debug), NULL, "0x0000"},
-       {"ldap_connections_number", PW_TYPE_INTEGER, offsetof(ldap_instance,num_conns), NULL, "5"},
-       {"compare_check_items", PW_TYPE_BOOLEAN, offsetof(ldap_instance,do_comp), NULL, "no"},
-       {"access_attr_used_for_allow", PW_TYPE_BOOLEAN, offsetof(ldap_instance,default_allow), NULL, "yes"},
-       {"do_xlat", PW_TYPE_BOOLEAN, offsetof(ldap_instance,do_xlat), NULL, "yes"},
+       {"dictionary_mapping", PW_TYPE_FILENAME,
+        offsetof(ldap_instance,dictionary_mapping), NULL, "${confdir}/ldap.attrmap"},
+
+       /*
+        *      Debugging flags to the server
+        */
+       {"ldap_debug", PW_TYPE_INTEGER,
+        offsetof(ldap_instance,ldap_debug), NULL, "0x0000"},
+       {"ldap_connections_number", PW_TYPE_INTEGER,
+        offsetof(ldap_instance,num_conns), NULL, "5"},
+       {"compare_check_items", PW_TYPE_BOOLEAN,
+        offsetof(ldap_instance,do_comp), NULL, "no"},
+       {"do_xlat", PW_TYPE_BOOLEAN,
+        offsetof(ldap_instance,do_xlat), NULL, "yes"},
+
 #ifdef NOVELL
-       {"edir_account_policy_check", PW_TYPE_BOOLEAN, offsetof(ldap_instance,edir_account_policy_check), NULL, "yes"},
+       /*
+        *      Novell magic.
+        */
+       {"edir_account_policy_check", PW_TYPE_BOOLEAN,
+        offsetof(ldap_instance,edir_account_policy_check), NULL, "yes"},
 #endif
 
        {"set_auth_type", PW_TYPE_BOOLEAN, offsetof(ldap_instance,set_auth_type), NULL, "yes"},
@@ -369,7 +321,7 @@ static CONF_PARSER module_config[] = {
 #ifdef FIELDCPY
 static void     fieldcpy(char *, char **);
 #endif
-static VALUE_PAIR *ldap_pairget(LDAP *, LDAPMessage *, TLDAP_RADIUS *,VALUE_PAIR **,char);
+static VALUE_PAIR *ldap_pairget(LDAP *, LDAPMessage *, TLDAP_RADIUS *,VALUE_PAIR **,int);
 static int ldap_groupcmp(void *, REQUEST *, VALUE_PAIR *, VALUE_PAIR *, VALUE_PAIR *, VALUE_PAIR **);
 static int ldap_xlat(void *, REQUEST *, char *, char *, size_t, RADIUS_ESCAPE_STRING);
 static LDAP    *ldap_connect(void *instance, const char *, const char *, int, int *, char **);
@@ -382,7 +334,13 @@ static inline int ldap_get_conn(LDAP_CONN *conns,LDAP_CONN **ret,void *instance)
 
        for(i=0;i<inst->num_conns;i++){
                DEBUG("rlm_ldap: ldap_get_conn: Checking Id: %d",i);
-               if (conns[i].locked == 0 && pthread_mutex_trylock(&(conns[i].mutex)) == 0){
+               if ((pthread_mutex_trylock(&conns[i].mutex) == 0)) {
+                       if (conns[i].locked == 1) {
+                               /* connection is already being used */
+                               pthread_mutex_unlock(&(conns[i].mutex));
+                               continue;
+                       }
+                       /* found an unused connection */
                        *ret = &conns[i];
                        conns[i].locked = 1;
                        DEBUG("rlm_ldap: ldap_get_conn: Got Id: %d",i);
@@ -419,8 +377,7 @@ ldap_instantiate(CONF_SECTION * conf, void **instance)
        int att_map[3] = {0,0,0};
        TLDAP_RADIUS *pair;
        ATTR_FLAGS flags;
-       char *xlat_name;
-       DICT_VALUE *dv;
+       const char *xlat_name;
 
        inst = rad_malloc(sizeof *inst);
        if (!inst) {
@@ -435,7 +392,7 @@ ldap_instantiate(CONF_SECTION * conf, void **instance)
 
        if (inst->server == NULL) {
                radlog(L_ERR, "rlm_ldap: missing 'server' directive.");
-               free(inst);
+               free(inst);     /* FIXME: detach */
                return -1;
        }
        inst->is_url = 0;
@@ -445,7 +402,7 @@ ldap_instantiate(CONF_SECTION * conf, void **instance)
                inst->port = 0;
 #else
                radlog(L_ERR, "rlm_ldap: 'server' directive is in URL form but ldap_initialize() is not available.");
-               free(inst);
+               free(inst);     /* FIXME: detach */
                return -1;
 #endif
        }
@@ -474,19 +431,20 @@ ldap_instantiate(CONF_SECTION * conf, void **instance)
                /*
                 * Allocate room for <instance>-Ldap-Group
                 */
-               group_name = malloc((strlen(xlat_name) + 1 + 11) * sizeof(char));
-               rad_assert(group_name != NULL);
+               group_name = rad_malloc((strlen(xlat_name) + 1 + 11) * sizeof(char));
                sprintf(group_name,"%s-Ldap-Group",xlat_name);
                DEBUG("rlm_ldap: Creating new attribute %s",group_name);
                dict_addattr(group_name, 0, PW_TYPE_STRING, -1, flags);
                dattr = dict_attrbyname(group_name);
                if (dattr == NULL){
                        radlog(L_ERR, "rlm_ldap: Failed to create attribute %s",group_name);
-                       free(inst);
+                       free(group_name);
+                       free(inst);     /* FIXME: detach */
                        return -1;
                }
                DEBUG("rlm_ldap: Registering ldap_groupcmp for %s",group_name);
                paircompare_register(dattr->attr, PW_USER_NAME, ldap_groupcmp, inst);
+               free(group_name);
        }
        else {
                xlat_name = cf_section_name1(conf);
@@ -501,42 +459,48 @@ ldap_instantiate(CONF_SECTION * conf, void **instance)
         *      This automagically catches the case where LDAP is listed
         *      in "authorize", but not "authenticate".
         */
-       dv = dict_valbyname(PW_AUTH_TYPE, xlat_name);
-       if (!dv) {
-               if (inst->set_auth_type) {
+       if (inst->set_auth_type) {
+               DICT_VALUE *dv = dict_valbyname(PW_AUTH_TYPE, xlat_name);
+               if (!dv) {
                        DEBUG2("rlm_ldap: Over-riding set_auth_type, as we're not listed in the \"authenticate\" section.");
+                       inst->set_auth_type = 0;
                }
-         inst->set_auth_type = 0;
-       }
+       } /* else no need to look up the value */
 
 #ifdef NOVELL
        /*
-        * (LDAP_Instance, V1) attribute-value pair in the config items list means
-        * that the 'authorize' method of the instance 'V1' of the LDAP module has
-        * processed this request.
+        *      (LDAP_Instance, V1) attribute-value pair in the config
+        *      items list means that the 'authorize' method of the
+        *      instance 'V1' of the LDAP module has processed this
+        *      request.
         */
        dict_addattr("LDAP-Instance", 0, PW_TYPE_STRING, -1, flags);
+
        /*
-        * ('eDir-APC', '1') in config items list => Do not perform eDirectory account
-        *                                           policy check (APC)
-        * ('eDir-APC', '2') in config items list => Perform eDirectory APC
-        * ('eDir-APC', '3') in config items list => eDirectory APC has been completed
+        *      ('eDir-APC', '1') in config items list
+        *      Do not perform eDirectory account policy check (APC)
+        *                                           
+        *      ('eDir-APC', '2') in config items list
+        *      Perform eDirectory APC
+        *
+        *      ('eDir-APC', '3') in config items list
+        *      eDirectory APC has been completed
         */
        dict_addattr("eDir-APC", 0, PW_TYPE_INTEGER, -1, flags);
 #endif
 
        if (inst->num_conns <= 0){
                radlog(L_ERR, "rlm_ldap: Invalid ldap connections number passed.");
-               free(inst);
+               free(inst);     /* FIXME: detach */
                return -1;
        }
-       inst->conns = (LDAP_CONN *)malloc(sizeof(LDAP_CONN)*inst->num_conns);
+       inst->conns = malloc(sizeof(*(inst->conns))*inst->num_conns);
        if (inst->conns == NULL){
                radlog(L_ERR, "rlm_ldap: Could not allocate memory. Aborting.");
-               free(inst);
+               free(inst);     /* FIXME: detach */
                return -1;
        }
-       for(;i<inst->num_conns;i++){
+       for(i = 0; i < inst->num_conns; i++){
                inst->conns[i].bound = 0;
                inst->conns[i].locked = 0;
                inst->conns[i].failed_conns = 0;
@@ -546,15 +510,16 @@ ldap_instantiate(CONF_SECTION * conf, void **instance)
 
 #ifdef NOVELL
        /*
-        * 'inst->apc_conns' is a separate connection pool to be used for performing
-        * eDirectory account policy check in the 'postauth' method. This avoids
-        * changing the (RADIUS server) credentials associated with the 'inst->conns'
-        * connection pool.
+        *      'inst->apc_conns' is a separate connection pool to be
+        *      used for performing eDirectory account policy check in
+        *      the 'postauth' method. This avoids changing the
+        *      (RADIUS server) credentials associated with the
+        *      'inst->conns' connection pool.
         */
-       inst->apc_conns = (LDAP_CONN *)malloc(sizeof(LDAP_CONN)*inst->num_conns);
+       inst->apc_conns = malloc(sizeof(*(inst->apc_conns))*inst->num_conns);
        if (inst->apc_conns == NULL){
                radlog(L_ERR, "rlm_ldap: Could not allocate memory. Aborting.");
-               free(inst);
+               free(inst);     /* FIXME: detach */
                return -1;
        }
        for(i = 0; i < inst->num_conns; i++){
@@ -569,13 +534,14 @@ ldap_instantiate(CONF_SECTION * conf, void **instance)
        if (read_mappings(inst) != 0) {
                radlog(L_ERR, "rlm_ldap: Reading dictionary mappings from file %s failed",
                       inst->dictionary_mapping);
-               free(inst);
+               free(inst);     /* FIXME: detach */
                return -1;
        }
-       if (inst->check_item_map == NULL && inst->reply_item_map == NULL){
+       if ((inst->check_item_map == NULL) &&
+           (inst->reply_item_map == NULL)) {
                radlog(L_ERR, "rlm_ldap: dictionary mappings file %s did not contain any mappings",
                        inst->dictionary_mapping);
-               free(inst);
+               free(inst);     /* FIXME: detach */
                return -1;
        }
 
@@ -600,7 +566,7 @@ ldap_instantiate(CONF_SECTION * conf, void **instance)
        inst->atts = (char **)malloc(sizeof(char *)*(atts_num + 1));
        if (inst->atts == NULL){
                radlog(L_ERR, "rlm_ldap: Could not allocate memory. Aborting.");
-               free(inst);
+               free(inst);     /* FIXME: detach */
                return -1;
        }
        pair = inst->check_item_map;
@@ -645,9 +611,9 @@ ldap_instantiate(CONF_SECTION * conf, void **instance)
 
 
 /*
- * read_mappings(...) reads a ldap<->radius mappings file to inst->reply_item_map and inst->check_item_map
+ *     read_mappings(...) reads a ldap<->radius mappings file to
+ *     inst->reply_item_map and inst->check_item_map
  */
-
 #define MAX_LINE_LEN 160
 #define GENERIC_ATTRIBUTE_ID "$GENERIC$"
 
@@ -656,9 +622,16 @@ read_mappings(ldap_instance* inst)
 {
        FILE* mapfile;
        char *filename;
-       /* all buffers are of MAX_LINE_LEN so we can use sscanf without being afraid of buffer overflows */
-       char buf[MAX_LINE_LEN], itemType[MAX_LINE_LEN], radiusAttribute[MAX_LINE_LEN], ldapAttribute[MAX_LINE_LEN];
+
+       /*
+        *      All buffers are of MAX_LINE_LEN so we can use sscanf
+        *      without being afraid of buffer overflows
+        */
+       char buf[MAX_LINE_LEN], itemType[MAX_LINE_LEN];
+       char radiusAttribute[MAX_LINE_LEN], ldapAttribute[MAX_LINE_LEN];
        int linenumber;
+       LRAD_TOKEN operator;
+       char opstring[MAX_LINE_LEN];
 
        /* open the mappings file for reading */
 
@@ -671,8 +644,10 @@ read_mappings(ldap_instance* inst)
                return -1; /* error */
        }
 
-       /* read file line by line. Note that if line length exceed MAX_LINE_LEN, line numbers will be mixed up */
-
+       /*
+        *      read file line by line. Note that if line length
+        *      exceeds MAX_LINE_LEN, line numbers will be mixed up
+        */
        linenumber = 0;
 
        while (fgets(buf, sizeof buf, mapfile)!=NULL) {
@@ -690,23 +665,41 @@ read_mappings(ldap_instance* inst)
                if (buf[0] == 0) continue;
 
                /* extract tokens from the string */
-               token_count = sscanf(buf, "%s %s %s", itemType, radiusAttribute, ldapAttribute);
+               token_count = sscanf(buf, "%s %s %s %s",
+                                    itemType, radiusAttribute,
+                                    ldapAttribute, opstring);
 
                if (token_count <= 0) /* no tokens */
                        continue;
 
-               if (token_count != 3) {
-                       radlog(L_ERR, "rlm_ldap: Skipping %s line %i: %s", filename, linenumber, buf);
-                       radlog(L_ERR, "rlm_ldap: Expected 3 tokens "
+               if ((token_count < 3) || (token_count > 4)) {
+                       radlog(L_ERR, "rlm_ldap: Skipping %s line %i: %s",
+                              filename, linenumber, buf);
+                       radlog(L_ERR, "rlm_ldap: Expected 3 to 4 tokens "
                               "(Item type, RADIUS Attribute and LDAP Attribute) but found only %i", token_count);
                        continue;
                }
 
+               if (token_count == 3) {
+                       operator = T_OP_INVALID; /* use defaults */
+               } else {
+                       char *ptr;
+                       
+                       ptr = opstring;
+                       operator = gettoken(&ptr, buf, sizeof(buf));
+                       if ((operator < T_OP_ADD) || (operator > T_OP_CMP_EQ)) {
+                               radlog(L_ERR, "rlm_ldap: file %s: skipping line %i: unknown or invalid operator %s",
+                                      filename, linenumber, opstring);
+                               continue;
+                       }
+               }
+
                /* create new TLDAP_RADIUS list node */
-               pair = rad_malloc(sizeof(TLDAP_RADIUS));
+               pair = rad_malloc(sizeof(*pair));
 
                pair->attr = strdup(ldapAttribute);
                pair->radius_attr = strdup(radiusAttribute);
+               pair->operator = operator;
 
                if ( (pair->attr == NULL) || (pair->radius_attr == NULL) ) {
                        radlog(L_ERR, "rlm_ldap: Out of memory");
@@ -742,9 +735,9 @@ read_mappings(ldap_instance* inst)
        return 0; /* success */
 }
 
-static int
-perform_search(void *instance, LDAP_CONN *conn, char *search_basedn, int scope, char *filter,
-               char **attrs, LDAPMessage ** result)
+static int perform_search(void *instance, LDAP_CONN *conn,
+                         char *search_basedn, int scope, char *filter,
+                         char **attrs, LDAPMessage ** result)
 {
        int             res = RLM_MODULE_OK;
        int             ldap_errno = 0;
@@ -781,8 +774,10 @@ retry:
                conn->bound = 1;
                conn->failed_conns = 0;
        }
-       DEBUG2("rlm_ldap: performing search in %s, with filter %s", search_basedn ? search_basedn : "(null)" , filter);
-       switch (ldap_search_st(conn->ld, search_basedn, scope, filter, attrs, 0, &(inst->timeout), result)) {
+       DEBUG2("rlm_ldap: performing search in %s, with filter %s",
+              search_basedn ? search_basedn : "(null)" , filter);
+       switch (ldap_search_st(conn->ld, search_basedn, scope, filter,
+                              attrs, 0, &(inst->timeout), result)) {
        case LDAP_SUCCESS:
        case LDAP_NO_SUCH_OBJECT:
                break;
@@ -817,12 +812,14 @@ retry:
        case LDAP_UNAVAILABLE:
                /* We don't need to reconnect in these cases so we don't set conn->bound */
                ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
-               radlog(L_ERR, "rlm_ldap: ldap_search() failed: %s", ldap_err2string(ldap_errno));
+               radlog(L_ERR, "rlm_ldap: ldap_search() failed: %s",
+                      ldap_err2string(ldap_errno));
                ldap_msgfree(*result);
                return (RLM_MODULE_FAIL);
        default:
                ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
-               radlog(L_ERR, "rlm_ldap: ldap_search() failed: %s", ldap_err2string(ldap_errno));
+               radlog(L_ERR, "rlm_ldap: ldap_search() failed: %s",
+                      ldap_err2string(ldap_errno));
                conn->bound = 0;
                ldap_msgfree(*result);
                return (RLM_MODULE_FAIL);
@@ -886,11 +883,12 @@ static int ldap_escape_func(char *out, int outlen, const char *in)
 }
 
 /*
- * ldap_groupcmp(). Implement the Ldap-Group == "group" filter
+ *     ldap_groupcmp(). Implement the Ldap-Group == "group" filter
  */
-
-static int ldap_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,
-                VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+static int ldap_groupcmp(void *instance, REQUEST *req,
+                        UNUSED VALUE_PAIR *request, VALUE_PAIR *check,
+                        UNUSED VALUE_PAIR *check_pairs,
+                        UNUSED VALUE_PAIR **reply_pairs)
 {
         char            filter[MAX_FILTER_STR_LEN];
         char            gr_filter[MAX_FILTER_STR_LEN];
@@ -907,11 +905,11 @@ static int ldap_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALU
        VALUE_PAIR      *vp_user_dn;
        VALUE_PAIR      **request_pairs;
 
-       request_pairs = &req->packet->vps;
+       request_pairs = &req->config_items;
 
        DEBUG("rlm_ldap: Entering ldap_groupcmp()");
 
-       if (check->strvalue == NULL || check->length == 0){
+       if (check->vp_strvalue == NULL || check->length == 0){
                 DEBUG("rlm_ldap::ldap_groupcmp: Illegal group name");
                 return 1;
         }
@@ -957,36 +955,41 @@ static int ldap_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALU
                         return 1;
                 }
                ldap_release_conn(conn_id,inst->conns);
+
                 /*
-                * Adding new attribute containing DN for LDAP object associated with
-                * given username
-                */
-                pairadd(request_pairs, pairmake("Ldap-UserDn", user_dn, T_OP_EQ));
+                *      Adding new attribute containing DN for LDAP
+                *      object associated with given username
+                */
+                pairadd(request_pairs, pairmake("Ldap-UserDn", user_dn,
+                                               T_OP_EQ));
                 ldap_memfree(user_dn);
                 ldap_msgfree(result);
         }
 
-        if(!radius_xlat(gr_filter, sizeof(gr_filter), inst->groupmemb_filt, req, ldap_escape_func)){
+        if(!radius_xlat(gr_filter, sizeof(gr_filter),
+                       inst->groupmemb_filt, req, ldap_escape_func)) {
                 DEBUG("rlm_ldap::ldap_groupcmp: unable to create filter.");
                 return 1;
         }
 
-       if (strchr((char *)check->strvalue,',') != NULL) {
+       if (strchr((char *)check->vp_strvalue,',') != NULL) {
                /* This looks like a DN */
                snprintf(filter,sizeof(filter), "%s",gr_filter);
-               snprintf(basedn,sizeof(basedn), "%s",(char *)check->strvalue);
+               snprintf(basedn,sizeof(basedn), "%s",(char *)check->vp_strvalue);
        } else
-               snprintf(filter,sizeof(filter), "(&(%s=%s)%s)",inst->groupname_attr,(char *)check->strvalue,gr_filter);
+               snprintf(filter,sizeof(filter), "(&(%s=%s)%s)",
+                        inst->groupname_attr,
+                        (char *)check->vp_strvalue,gr_filter);
 
-       if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){
+       if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1) {
                radlog(L_ERR, "rlm_ldap: All ldap connections are in use");
                return 1;
        }
 
        if ((res = perform_search(inst, conn, basedn, LDAP_SCOPE_SUBTREE,
-                               filter, attrs, &result)) == RLM_MODULE_OK){
+                               filter, attrs, &result)) == RLM_MODULE_OK) {
                DEBUG("rlm_ldap::ldap_groupcmp: User found in group %s",
-                               (char *)check->strvalue);
+                               (char *)check->vp_strvalue);
                ldap_msgfree(result);
                ldap_release_conn(conn_id,inst->conns);
                return 0;
@@ -1000,11 +1003,12 @@ static int ldap_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALU
        }
 
        if (inst->groupmemb_attr == NULL){
-               /* search returned NOTFOUND and searching for membership
-                * using user object attributes is not specified in config
-                * file
+               /*
+                *      Search returned NOTFOUND and searching for
+                *      membership using user object attributes is not
+                *      specified in config file
                 */
-               DEBUG("rlm_ldap::ldap_groupcmp: Group %s not found or user is not a member.",(char *)check->strvalue);
+               DEBUG("rlm_ldap::ldap_groupcmp: Group %s not found or user is not a member.",(char *)check->vp_strvalue);
                return 1;
        }
 
@@ -1013,8 +1017,9 @@ static int ldap_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALU
                radlog(L_ERR, "rlm_ldap: Add ldap connections are in use");
                return 1;
        }
-       if ((res = perform_search(inst, conn, vp_user_dn->strvalue, LDAP_SCOPE_BASE,
-                                       filter, group_attrs,&result)) != RLM_MODULE_OK){
+       if ((res = perform_search(inst, conn, vp_user_dn->vp_strvalue,
+                                 LDAP_SCOPE_BASE, filter, group_attrs,
+                                 &result)) != RLM_MODULE_OK) {
                DEBUG("rlm_ldap::ldap_groupcmp: Search returned error");
                ldap_release_conn(conn_id, inst->conns);
                return 1;
@@ -1026,22 +1031,23 @@ static int ldap_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALU
                ldap_msgfree(result);
                return 1;
        }
-       if ((vals = ldap_get_values(conn->ld, msg, inst->groupmemb_attr)) != NULL) {
+       if ((vals = ldap_get_values(conn->ld, msg,
+                                   inst->groupmemb_attr)) != NULL) {
                unsigned int i = 0;
                char found = 0;
+
                for (;i < ldap_count_values(vals);i++){
                        if (strchr(vals[i],',') != NULL){
                                /* This looks like a DN */
                                LDAPMessage *gr_result = NULL;
                                snprintf(filter,sizeof(filter), "(%s=%s)",
                                        inst->groupname_attr,
-                                       (char *)check->strvalue);
+                                       (char *)check->vp_strvalue);
                                if ((res = perform_search(inst, conn, vals[i],
                                                LDAP_SCOPE_BASE, filter,
                                                attrs, &gr_result)) != RLM_MODULE_OK){
-                                       if (res != RLM_MODULE_NOTFOUND){
-                                               DEBUG("rlm_ldap::ldap_groupcmp: \
-                                                       Search returned error");
+                                       if (res != RLM_MODULE_NOTFOUND) {
+                                               DEBUG("rlm_ldap::ldap_groupcmp: Search returned error");
                                                ldap_value_free(vals);
                                                ldap_msgfree(result);
                                                ldap_release_conn(conn_id,inst->conns);
@@ -1053,7 +1059,7 @@ static int ldap_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALU
                                        break;
                                }
                        } else {
-                               if (strcmp(vals[i],(char *)check->strvalue) == 0){
+                               if (strcmp(vals[i],(char *)check->vp_strvalue) == 0){
                                        found = 1;
                                        break;
                                }
@@ -1062,9 +1068,8 @@ static int ldap_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALU
                ldap_value_free(vals);
                ldap_msgfree(result);
                if (found == 0){
-                       DEBUG("rlm_ldap::groupcmp: Group %s not found \
-                               or user not a member",
-                               (char *)check->strvalue);
+                       DEBUG("rlm_ldap::groupcmp: Group %s not found or user not a member",
+                               (char *)check->vp_strvalue);
                        ldap_release_conn(conn_id,inst->conns);
                        return 1;
                }
@@ -1075,7 +1080,7 @@ static int ldap_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALU
                        return 1;
        }
 
-       DEBUG("rlm_ldap::ldap_groupcmp: User found in group %s",(char *)check->strvalue);
+       DEBUG("rlm_ldap::ldap_groupcmp: User found in group %s",(char *)check->vp_strvalue);
        ldap_release_conn(conn_id,inst->conns);
 
         return 0;
@@ -1085,9 +1090,8 @@ static int ldap_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALU
  * ldap_xlat()
  * Do an xlat on an LDAP URL
  */
-
-static int ldap_xlat(void *instance, REQUEST *request, char *fmt, char *out,
-                    size_t freespace, RADIUS_ESCAPE_STRING func)
+static int ldap_xlat(void *instance, REQUEST *request, char *fmt,
+                    char *out, size_t freespace, RADIUS_ESCAPE_STRING func)
 {
        char url[MAX_FILTER_STR_LEN];
        int res;
@@ -1113,16 +1117,18 @@ static int ldap_xlat(void *instance, REQUEST *request, char *fmt, char *out,
                radlog (L_ERR, "rlm_ldap: LDAP URL parse failed.\n");
                return 0;
        }
-       if (ldap_url->lud_attrs == NULL || ldap_url->lud_attrs[0] == NULL || \
-               ( ldap_url->lud_attrs[1] != NULL || ( ! strlen(ldap_url->lud_attrs[0]) || \
+       if (ldap_url->lud_attrs == NULL || ldap_url->lud_attrs[0] == NULL ||
+           ( ldap_url->lud_attrs[1] != NULL ||
+             ( ! strlen(ldap_url->lud_attrs[0]) ||
                ! strcmp(ldap_url->lud_attrs[0],"*") ) ) ){
                radlog (L_ERR, "rlm_ldap: Invalid Attribute(s) request.\n");
                ldap_free_urldesc(ldap_url);
                return 0;
        }
        if (ldap_url->lud_host){
-               if (strncmp(inst->server,ldap_url->lud_host,strlen(inst->server)) != 0 || \
-                               ldap_url->lud_port != inst->port){
+               if (strncmp(inst->server,ldap_url->lud_host,
+                           strlen(inst->server)) != 0 ||
+                   ldap_url->lud_port != inst->port) {
                        DEBUG("rlm_ldap: Requested server/port is not known to this module instance.");
                        ldap_free_urldesc(ldap_url);
                        return 0;
@@ -1163,7 +1169,7 @@ static int ldap_xlat(void *instance, REQUEST *request, char *fmt, char *out,
                        return 0;
                }
                DEBUG("rlm_ldap: Adding attribute %s, value: %s",ldap_url->lud_attrs[0],vals[0]);
-               strncpy(out,vals[0],ret);
+               strlcpy(out,vals[0],ret);
                ldap_value_free(vals);
        }
        else
@@ -1179,6 +1185,23 @@ static int ldap_xlat(void *instance, REQUEST *request, char *fmt, char *out,
 }
 
 
+/*
+ *     For auto-header discovery.
+ */
+static const LRAD_NAME_NUMBER header_names[] = {
+       { "{clear}",    PW_CLEARTEXT_PASSWORD },
+       { "{cleartext}", PW_CLEARTEXT_PASSWORD },
+       { "{md5}",      PW_MD5_PASSWORD },
+       { "{smd5}",     PW_SMD5_PASSWORD },
+       { "{crypt}",    PW_CRYPT_PASSWORD },
+       { "{sha}",      PW_SHA_PASSWORD },
+       { "{ssha}",     PW_SSHA_PASSWORD },
+       { "{nt}",       PW_NT_PASSWORD },
+       { "{ns-mta-md5}", PW_NS_MTA_MD5_PASSWORD },
+       { NULL, 0 }
+};
+
+
 /******************************************************************************
  *
  *      Function: rlm_ldap_authorize
@@ -1186,8 +1209,7 @@ static int ldap_xlat(void *instance, REQUEST *request, char *fmt, char *out,
  *      Purpose: Check if user is authorized for remote access
  *
  ******************************************************************************/
-static int
-ldap_authorize(void *instance, REQUEST * request)
+static int ldap_authorize(void *instance, REQUEST * request)
 {
        LDAPMessage     *result = NULL;
        LDAPMessage     *msg = NULL;
@@ -1223,12 +1245,12 @@ ldap_authorize(void *instance, REQUEST * request)
        /*
         * Check for valid input, zero length names not permitted
         */
-       if (request->username->strvalue == 0) {
+       if (request->username->vp_strvalue == 0) {
                radlog(L_ERR, "rlm_ldap: zero length username not permitted\n");
                return RLM_MODULE_INVALID;
        }
        DEBUG("rlm_ldap: performing user authorization for %s",
-              request->username->strvalue);
+              request->username->vp_strvalue);
 
        if (!radius_xlat(filter, sizeof(filter), inst->filter,
                         request, ldap_escape_func)) {
@@ -1272,7 +1294,7 @@ ldap_authorize(void *instance, REQUEST * request)
         * Adding new attribute containing DN for LDAP object associated with
         * given username
         */
-       pairadd(&request->packet->vps, pairmake("Ldap-UserDn", user_dn, T_OP_EQ));
+       pairadd(check_pairs, pairmake("Ldap-UserDn", user_dn, T_OP_EQ));
        ldap_memfree(user_dn);
 
 
@@ -1280,7 +1302,7 @@ ldap_authorize(void *instance, REQUEST * request)
        if (inst->access_attr) {
                if ((vals = ldap_get_values(conn->ld, msg, inst->access_attr)) != NULL) {
                        if (inst->default_allow){
-                               DEBUG("rlm_ldap: checking if remote access for %s is allowed by %s", request->username->strvalue, inst->access_attr);
+                               DEBUG("rlm_ldap: checking if remote access for %s is allowed by %s", request->username->vp_strvalue, inst->access_attr);
                                if (!strncmp(vals[0], "FALSE", 5)) {
                                        DEBUG("rlm_ldap: dialup access disabled");
                                        snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: Access Attribute denies access");
@@ -1325,9 +1347,9 @@ ldap_authorize(void *instance, REQUEST * request)
        if (inst->default_profile || user_profile){
                char *profile = inst->default_profile;
 
-               strNcpy(filter,inst->base_filter,sizeof(filter));
+               strlcpy(filter,inst->base_filter,sizeof(filter));
                if (user_profile)
-                       profile = user_profile->strvalue;
+                       profile = user_profile->vp_strvalue;
                if (profile && strlen(profile)){
                        if ((res = perform_search(instance, conn,
                                profile, LDAP_SCOPE_BASE,
@@ -1366,7 +1388,7 @@ ldap_authorize(void *instance, REQUEST * request)
        if (inst->profile_attr){
                if ((vals = ldap_get_values(conn->ld, msg, inst->profile_attr)) != NULL) {
                        unsigned int i=0;
-                       strNcpy(filter,inst->base_filter,sizeof(filter));
+                       strlcpy(filter,inst->base_filter,sizeof(filter));
                        while(vals[i] != NULL && strlen(vals[i])){
                                if ((res = perform_search(instance, conn,
                                        vals[i], LDAP_SCOPE_BASE,
@@ -1397,50 +1419,82 @@ ldap_authorize(void *instance, REQUEST * request)
                        ldap_value_free(vals);
                }
        }
-       if (inst->passwd_attr && strlen(inst->passwd_attr)){
+       if (inst->passwd_attr && strlen(inst->passwd_attr)) {
 #ifdef NOVELL_UNIVERSAL_PASSWORD
-               if(strcasecmp(inst->passwd_attr,"nspmPassword")!= 0){
+               if (strcasecmp(inst->passwd_attr,"nspmPassword") != 0) {
 #endif
-               VALUE_PAIR *passwd_item;
-
-               if ((passwd_item = pairfind(request->config_items, PW_PASSWORD)) == NULL){
+                       VALUE_PAIR *passwd_item;
                        char **passwd_vals;
-                       char *passwd_val = NULL;
-                       int passwd_len;
-
-                       if ((passwd_vals = ldap_get_values(conn->ld,msg,inst->passwd_attr)) != NULL){
-                               unsigned int i=0;
-                               while(passwd_vals[i] != NULL){
-                                       if (strlen(passwd_vals[i])){
-                                               passwd_val = passwd_vals[i];
-
-                                               if (inst->passwd_hdr && strlen(inst->passwd_hdr)){
-                                                       passwd_val = strstr(passwd_val,inst->passwd_hdr);
-                                                       if (passwd_val != NULL)
-                                                               passwd_val += strlen(inst->passwd_hdr);
-                                                       else
-                                                               DEBUG("rlm_ldap: Password header not found in password %s for user %s", passwd_vals[0],request->username->strvalue);
-                                               }
-                                               if (passwd_val){
-                                                       if ((passwd_item = paircreate(PW_PASSWORD,PW_TYPE_STRING)) == NULL){
-                                                               radlog(L_ERR|L_CONS, "no memory");
-                                                               ldap_value_free(passwd_vals);
-                                                               ldap_msgfree(result);
-                                                               ldap_release_conn(conn_id,inst->conns);
-                                                               return RLM_MODULE_FAIL;
-                                                       }
-                                                       passwd_len = strlen(passwd_val);
-                                                       strncpy(passwd_item->strvalue,passwd_val,MAX_STRING_LEN - 1);
-                                                       passwd_item->length = (passwd_len > (MAX_STRING_LEN - 1)) ? (MAX_STRING_LEN - 1) : passwd_len;
-                                                       pairadd(&request->config_items,passwd_item);
-                                                       DEBUG("rlm_ldap: Added password %s in check items",passwd_item->strvalue);
-                                               }
+                       char *value = NULL;
+                       int i;
+                       
+                       /*
+                        *      Read the password from the DB, and
+                        *      add it to the request.
+                        */
+                       passwd_vals = ldap_get_values(conn->ld,msg,
+                                                     inst->passwd_attr);
+
+                       /*
+                        *      Loop over what we received, and parse it.
+                        */
+                       if (passwd_vals) for (i = 0;
+                                             passwd_vals[i] != NULL;
+                                             i++) {
+                               int attr = PW_USER_PASSWORD;
+                               
+                               if (strlen(passwd_vals[i]) == 0)
+                                       continue;
+                               
+                               value = passwd_vals[i];
+
+                               if (inst->auto_header) {
+                                       char *p;
+                                       char autobuf[16];
+
+                                       p = strchr(value, '}');
+                                       if (!p) continue;
+                                       if ((p - value + 1) >= sizeof(autobuf))
+                                               continue; /* paranoia */
+                                       memcpy(autobuf, value, p - value + 1);
+                                       autobuf[p - value + 1] = '\0';
+                               
+                                       attr = lrad_str2int(header_names,
+                                                           autobuf, 0);
+                                       if (!attr) continue;
+                                       value = p + 1;
+                                       goto create_attr;
+
+                               } else if (inst->passwd_hdr &&
+                                          strlen(inst->passwd_hdr)) {
+                                       if (strncasecmp(value,
+                                                       inst->passwd_hdr,
+                                                       strlen(inst->passwd_hdr)) == 0) {
+                                               value += strlen(inst->passwd_hdr);
+                                       } else {
+                                               DEBUG("rlm_ldap: Password header not found in password %s for user %s", passwd_vals[0], request->username->vp_strvalue);
                                        }
-                                       i++;
                                }
-                               ldap_value_free(passwd_vals);
+                               if (!value) continue;
+                               
+                       create_attr:
+                               passwd_item = paircreate(attr, PW_TYPE_STRING);
+                               if (!passwd_item) {
+                                       radlog(L_ERR|L_CONS, "no memory");
+                                       ldap_value_free(passwd_vals);
+                                       ldap_msgfree(result);
+                                       ldap_release_conn(conn_id,inst->conns);
+                                       return RLM_MODULE_FAIL;
+                               }
+                               strlcpy(passwd_item->vp_strvalue, value,
+                                       sizeof(passwd_item->vp_strvalue));
+                               passwd_item->length = strlen(passwd_item->vp_strvalue);
+                               pairadd(&request->config_items,passwd_item);
+                               DEBUG("rlm_ldap: Added %s = %s in check items",
+                                     passwd_item->name,
+                                     passwd_item->vp_strvalue);
                        }
-               }
+                       ldap_value_free(passwd_vals);
 #ifdef NOVELL_UNIVERSAL_PASSWORD
                }
                else{
@@ -1456,13 +1510,13 @@ ldap_authorize(void *instance, REQUEST * request)
 
                        res = 0;
 
-                       if ((passwd_item = pairfind(request->config_items, PW_PASSWORD)) == NULL){
+                       if ((passwd_item = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD)) == NULL){
                        
                                universal_password = rad_malloc(universal_password_len);
                                memset(universal_password, 0, universal_password_len);
 
-                               vp_user_dn = pairfind(request->packet->vps,PW_LDAP_USERDN);
-                               res = nmasldap_get_password(conn->ld,vp_user_dn->strvalue,&universal_password_len,universal_password);
+                               vp_user_dn = pairfind(request->config_items,PW_LDAP_USERDN);
+                               res = nmasldap_get_password(conn->ld,vp_user_dn->vp_strvalue,&universal_password_len,universal_password);
 
                                if (res == 0){
                                        passwd_val = universal_password;
@@ -1473,11 +1527,11 @@ ldap_authorize(void *instance, REQUEST * request)
                                                if (passwd_val != NULL)
                                                        passwd_val += strlen((char*)inst->passwd_hdr);
                                                else
-                                                       DEBUG("rlm_ldap: Password header not found in password %s for user %s ",passwd_val,request->username->strvalue);
+                                                       DEBUG("rlm_ldap: Password header not found in password %s for user %s ",passwd_val,request->username->vp_strvalue);
                                        }
 
                                        if (passwd_val){
-                                               if ((passwd_item = paircreate(PW_PASSWORD,PW_TYPE_STRING)) == NULL){
+                                               if ((passwd_item = paircreate(PW_CLEARTEXT_PASSWORD,PW_TYPE_STRING)) == NULL){
                                                        radlog(L_ERR, "rlm_ldap: Could not allocate memory. Aborting.");
                                                        ldap_msgfree(result);
                                                        ldap_release_conn(conn_id,inst->conns);
@@ -1487,7 +1541,7 @@ ldap_authorize(void *instance, REQUEST * request)
                                                }
 
                                                passwd_len = strlen(passwd_val);
-                                               strncpy(passwd_item->strvalue,passwd_val,MAX_STRING_LEN - 1);
+                                               strlcpy(passwd_item->vp_strvalue,passwd_val,sizeof(passwd_item->vp_strvalue));
                                                passwd_item->length = (passwd_len > (MAX_STRING_LEN - 1)) ? (MAX_STRING_LEN - 1) : passwd_len;
                                                pairadd(&request->config_items,passwd_item);
 
@@ -1516,8 +1570,8 @@ ldap_authorize(void *instance, REQUEST * request)
                                                                        free(universal_password);
                                                                        return RLM_MODULE_FAIL;
                                                                }
-                                                               strcpy(vp_inst->strvalue, inst->xlat_name);
-                                                               vp_inst->length = strlen(vp_inst->strvalue);
+                                                               strcpy(vp_inst->vp_strvalue, inst->xlat_name);
+                                                               vp_inst->length = strlen(vp_inst->vp_strvalue);
                                                                pairadd(&request->config_items, vp_inst);
 
                                                                /*
@@ -1536,10 +1590,10 @@ ldap_authorize(void *instance, REQUEST * request)
 
                                                                if(!inst->edir_account_policy_check){
                                                                        /* Do nothing */
-                                                                       strcpy(vp_apc->strvalue, "1");
+                                                                       strcpy(vp_apc->vp_strvalue, "1");
                                                                }else{
                                                                        /* Perform eDirectory account-policy check */
-                                                                       strcpy(vp_apc->strvalue, "2");
+                                                                       strcpy(vp_apc->vp_strvalue, "2");
                                                                }
                                                                vp_apc->length = 1;
                                                                pairadd(&request->config_items, vp_apc);
@@ -1547,7 +1601,7 @@ ldap_authorize(void *instance, REQUEST * request)
                                                }
 #endif
 
-                                               DEBUG("rlm_ldap: Added the eDirectory password in check items");
+                                               DEBUG("rlm_ldap: Added the eDirectory password %s in check items as %s",passwd_item->vp_strvalue,passwd_item->name);
                                        }
                                }
                                else {
@@ -1559,7 +1613,6 @@ ldap_authorize(void *instance, REQUEST * request)
                        }
                }                       
 #endif
-
        }
 
 
@@ -1588,7 +1641,7 @@ ldap_authorize(void *instance, REQUEST * request)
                        pairadd(reply_pairs,reply_tmp);
        }
 
-       if (inst->do_comp && paircmp(request,request->packet->vps,*check_pairs,reply_pairs) != 0){
+       if (inst->do_comp && paircompare(request,request->packet->vps,*check_pairs,reply_pairs) != 0){
 #ifdef NOVELL
                /* Don't perform eDirectory APC if RADIUS authorize fails */
                int apc_attr;
@@ -1600,7 +1653,7 @@ ldap_authorize(void *instance, REQUEST * request)
 
                vp_apc = pairfind(request->config_items, apc_attr);
                if(vp_apc)
-                       vp_apc->strvalue[0] = '1';
+                       vp_apc->vp_strvalue[0] = '1';
 #endif
 
                DEBUG("rlm_ldap: Pairs do not match. Rejecting user.");
@@ -1628,7 +1681,7 @@ ldap_authorize(void *instance, REQUEST * request)
        }
 
        DEBUG("rlm_ldap: user %s authorized to use remote access",
-             request->username->strvalue);
+             request->username->vp_strvalue);
        ldap_msgfree(result);
        ldap_release_conn(conn_id,inst->conns);
 
@@ -1642,8 +1695,7 @@ ldap_authorize(void *instance, REQUEST * request)
  *     Purpose: Check the user's password against ldap database
  *
  *****************************************************************************/
-static int
-ldap_authenticate(void *instance, REQUEST * request)
+static int ldap_authenticate(void *instance, REQUEST * request)
 {
        LDAP           *ld_user;
        LDAPMessage    *result, *msg;
@@ -1651,7 +1703,7 @@ ldap_authenticate(void *instance, REQUEST * request)
        char           *user_dn, *attrs[] = {"uid", NULL};
        char            filter[MAX_FILTER_STR_LEN];
        char            basedn[MAX_FILTER_STR_LEN];
-       int             res;
+       int             res;
        VALUE_PAIR     *vp_user_dn;
        VALUE_PAIR      *module_fmsg_vp;
        char            module_fmsg[MAX_STRING_LEN];
@@ -1675,10 +1727,13 @@ ldap_authenticate(void *instance, REQUEST * request)
 
        if (!request->password){
                radlog(L_AUTH, "rlm_ldap: Attribute \"User-Password\" is required for authentication.");
+               DEBUG2("  You seem to have set \"Auth-Type := LDAP\" somewhere.");
+               DEBUG2("  THAT CONFIGURATION IS WRONG.  DELETE IT.");
+               DEBUG2("  YOU ARE PREVENTING THE SERVER FROM WORKING PROPERLY.");
                return RLM_MODULE_INVALID;
        }
 
-       if(request->password->attribute != PW_PASSWORD) {
+       if(request->password->attribute != PW_USER_PASSWORD) {
                radlog(L_AUTH, "rlm_ldap: Attribute \"User-Password\" is required for authentication. Cannot use \"%s\".", request->password->name);
                return RLM_MODULE_INVALID;
        }
@@ -1703,9 +1758,10 @@ ldap_authenticate(void *instance, REQUEST * request)
 
 
        DEBUG("rlm_ldap: login attempt by \"%s\" with password \"%s\"",
-              request->username->strvalue, request->password->strvalue);
+              request->username->vp_strvalue, request->password->vp_strvalue);
 
-       while((vp_user_dn = pairfind(request->packet->vps, PW_LDAP_USERDN)) == NULL) {
+       while ((vp_user_dn = pairfind(request->config_items,
+                                     PW_LDAP_USERDN)) == NULL) {
                if (!radius_xlat(filter, sizeof(filter), inst->filter,
                                request, ldap_escape_func)) {
                        radlog (L_ERR, "rlm_ldap: unable to create filter.\n");
@@ -1743,21 +1799,21 @@ ldap_authenticate(void *instance, REQUEST * request)
                        return RLM_MODULE_FAIL;
                }
                ldap_release_conn(conn_id,inst->conns);
-               pairadd(&request->packet->vps, pairmake("Ldap-UserDn", user_dn, T_OP_EQ));
+               pairadd(&request->config_items, pairmake("Ldap-UserDn", user_dn, T_OP_EQ));
                ldap_memfree(user_dn);
                ldap_msgfree(result);
        }
 
-       user_dn = vp_user_dn->strvalue;
+       user_dn = vp_user_dn->vp_strvalue;
 
        DEBUG("rlm_ldap: user DN: %s", user_dn);
 
 #ifndef NOVELL
-       ld_user = ldap_connect(instance, user_dn, request->password->strvalue,
+       ld_user = ldap_connect(instance, user_dn, request->password->vp_strvalue,
                               1, &res, NULL);
 #else
-
-       ld_user = ldap_connect(instance, user_dn, request->password->strvalue,
+       
+       ld_user = ldap_connect(instance, user_dn, request->password->vp_strvalue,
                        1, &res, &err);
 
        if(err != NULL){
@@ -1776,8 +1832,8 @@ ldap_authenticate(void *instance, REQUEST * request)
                dattr = dict_attrbyname("eDir-APC");
                apc_attr = dattr->attr;
                vp_apc = pairfind(request->config_items, apc_attr);
-               if(vp_apc && vp_apc->strvalue[0] == '2')
-                       vp_apc->strvalue[0] = '3';
+               if(vp_apc && vp_apc->vp_strvalue[0] == '2')
+                       vp_apc->vp_strvalue[0] = '3';
        }
 #endif
 
@@ -1796,7 +1852,7 @@ ldap_authenticate(void *instance, REQUEST * request)
        }
 
        DEBUG("rlm_ldap: user %s authenticated succesfully",
-             request->username->strvalue);
+             request->username->vp_strvalue);
        ldap_unbind_s(ld_user);
        inst->failed_conns = 0;
 
@@ -1812,8 +1868,7 @@ ldap_authenticate(void *instance, REQUEST * request)
  *     to eDirectory.
  *
  *****************************************************************************/
-static int
-ldap_postauth(void *instance, REQUEST * request)
+static int ldap_postauth(void *instance, REQUEST * request)
 {
        int res = RLM_MODULE_FAIL;
        int inst_attr, apc_attr;
@@ -1834,12 +1889,12 @@ ldap_postauth(void *instance, REQUEST * request)
         * Check if the password in the config items list is the user's UP which has
         * been read in the authorize method of this instance of the LDAP module.
         */
-       if((vp_inst == NULL) || strcmp(vp_inst->strvalue, inst->xlat_name))
+       if((vp_inst == NULL) || strcmp(vp_inst->vp_strvalue, inst->xlat_name))
                return RLM_MODULE_NOOP;
 
        vp_apc = pairfind(request->config_items, apc_attr);
 
-       switch(vp_apc->strvalue[0]){
+       switch(vp_apc->vp_strvalue[0]){
                case '1':
                        /* Account policy check not enabled */
                case '3':
@@ -1853,88 +1908,90 @@ ldap_postauth(void *instance, REQUEST * request)
                                VALUE_PAIR *vp_fdn, *vp_pwd;
                                DICT_ATTR *da;
 
-                               if(request->reply->code == PW_AUTHENTICATION_REJECT){
-                                       /* Bind to eDirectory as the RADIUS user with a wrong password. */
-                                       vp_pwd = pairfind(request->config_items, PW_PASSWORD);
-                                       strcpy(password, vp_pwd->strvalue);
-                                       if(strlen(password) > 0){
-                                               if(password[0] != 'a'){
-                                                       password[0] = 'a';
-                                               }else{
-                                                       password[0] = 'b';
-                                               }
-                                       }else{
-                                               strcpy(password, "dummy_password");
-                                       }
-                                       res = RLM_MODULE_REJECT;
-                               }else{
+                               if (request->reply->code == PW_AUTHENTICATION_REJECT) {
+                                 /* Bind to eDirectory as the RADIUS user with a wrong password. */
+                                 vp_pwd = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);
+                                 strcpy(password, vp_pwd->vp_strvalue);
+                                 if (strlen(password) > 0) {
+                                         if (password[0] != 'a') {
+                                                 password[0] = 'a';
+                                         } else {
+                                                 password[0] = 'b';
+                                         }
+                                 } else {
+                                         strcpy(password, "dummy_password");
+                                 }
+                                 res = RLM_MODULE_REJECT;
+                               } else {
                                        /* Bind to eDirectory as the RADIUS user using the user's UP */
-                                       vp_pwd = pairfind(request->config_items, PW_PASSWORD);
-                                       if(vp_pwd == NULL){
+                                       vp_pwd = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);
+                                       if (vp_pwd == NULL) {
                                                DEBUG("rlm_ldap: User's Universal Password not in config items list.");
                                                return RLM_MODULE_FAIL;
                                        }
-                                       strcpy(password, vp_pwd->strvalue);
+                                       strcpy(password, vp_pwd->vp_strvalue);
                                }
 
                                if ((da = dict_attrbyname("Ldap-UserDn")) == NULL) {
                                        DEBUG("rlm_ldap: Attribute for user FDN not found in dictionary. Unable to proceed");
                                        return RLM_MODULE_FAIL;
                                }
-
+                               
                                vp_fdn = pairfind(request->packet->vps, da->attr);
-                               if(vp_fdn == NULL){
+                               if (vp_fdn == NULL) {
                                        DEBUG("rlm_ldap: User's FQDN not in config items list.");
                                        return RLM_MODULE_FAIL;
                                }
-
+                               
                                if ((conn_id = ldap_get_conn(inst->apc_conns, &conn, inst)) == -1){
                                        radlog(L_ERR, "rlm_ldap: All ldap connections are in use");
                                        return RLM_MODULE_FAIL;
                                }
 
                                /*
-                                * If there is an existing LDAP connection to the directory, bind over
-                                * it. Otherwise, establish a new connection.
+                                *      If there is an existing LDAP
+                                *      connection to the directory,
+                                *      bind over it. Otherwise,
+                                *      establish a new connection.
                                 */
-postauth_reconnect:
+                       postauth_reconnect:
                                if (!conn->bound || conn->ld == NULL) {
                                        DEBUG2("rlm_ldap: attempting LDAP reconnection");
                                        if (conn->ld){
                                                DEBUG2("rlm_ldap: closing existing LDAP connection");
                                                ldap_unbind_s(conn->ld);
                                        }
-                                       if ((conn->ld = ldap_connect(instance, (char *)vp_fdn->strvalue, password, 0, &res, &error_msg)) == NULL) {
+                                       if ((conn->ld = ldap_connect(instance, (char *)vp_fdn->vp_strvalue, password, 0, &res, &error_msg)) == NULL) {
                                                radlog(L_ERR, "rlm_ldap: eDirectory account policy check failed.");
-
-                                               if(error_msg != NULL){
+                                               
+                                               if (error_msg != NULL) {
                                                        DEBUG("rlm_ldap: %s", error_msg);
                                                        pairadd(&request->reply->vps, pairmake("Reply-Message", error_msg, T_OP_EQ));
                                                        ldap_memfree((void *)error_msg);
                                                }
-
-                                               vp_apc->strvalue[0] = '3';
+                                               
+                                               vp_apc->vp_strvalue[0] = '3';
                                                ldap_release_conn(conn_id, inst->apc_conns);
                                                return RLM_MODULE_REJECT;
                                        }
                                        conn->bound = 1;
-                               }else if((err = ldap_simple_bind_s(conn->ld, (char *)vp_fdn->strvalue, password)) != LDAP_SUCCESS){
-                                       if(err == LDAP_SERVER_DOWN){
+                               } else if((err = ldap_simple_bind_s(conn->ld, (char *)vp_fdn->vp_strvalue, password)) != LDAP_SUCCESS) {
+                                       if (err == LDAP_SERVER_DOWN) {
                                                conn->bound = 0;
                                                goto postauth_reconnect;
                                        }
                                        DEBUG("rlm_ldap: eDirectory account policy check failed.");
                                        ldap_get_option(conn->ld, LDAP_OPT_ERROR_STRING, &error_msg);
-                                       if(error_msg != NULL){
+                                       if (error_msg != NULL) {
                                                DEBUG("rlm_ldap: %s", error_msg);
                                                pairadd(&request->reply->vps, pairmake("Reply-Message", error_msg, T_OP_EQ));
                                                ldap_memfree((void *)error_msg);
                                        }
-                                       vp_apc->strvalue[0] = '3';
+                                       vp_apc->vp_strvalue[0] = '3';
                                        ldap_release_conn(conn_id, inst->apc_conns);
                                        return RLM_MODULE_REJECT;
                                }
-                               vp_apc->strvalue[0] = '3';
+                               vp_apc->vp_strvalue[0] = '3';
                                ldap_release_conn(conn_id, inst->apc_conns);
                                return RLM_MODULE_OK;
                        }
@@ -1943,8 +2000,8 @@ postauth_reconnect:
 }
 #endif
 
-static LDAP    *
-ldap_connect(void *instance, const char *dn, const char *password, int auth, int *result, char **err)
+static LDAP *ldap_connect(void *instance, const char *dn, const char *password,
+                         int auth, int *result, char **err)
 {
        ldap_instance  *inst = instance;
        LDAP           *ld = NULL;
@@ -1961,8 +2018,7 @@ ldap_connect(void *instance, const char *dn, const char *password, int auth, int
                        return (NULL);
                }
 #endif
-       }
-       else{
+       } else {
                DEBUG("rlm_ldap: (re)connect to %s:%d, authentication %d", inst->server, inst->port, auth);
                if ((ld = ldap_init(inst->server, inst->port)) == NULL) {
                        radlog(L_ERR, "rlm_ldap: ldap_init() failed");
@@ -1970,111 +2026,120 @@ ldap_connect(void *instance, const char *dn, const char *password, int auth, int
                        return (NULL);
                }
        }
-       if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, (void *) &(inst->net_timeout)) != LDAP_OPT_SUCCESS) {
+       if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT,
+                           (void *) &(inst->net_timeout)) != LDAP_OPT_SUCCESS) {
                radlog(L_ERR, "rlm_ldap: Could not set LDAP_OPT_NETWORK_TIMEOUT %ld.%ld", inst->net_timeout.tv_sec, inst->net_timeout.tv_usec);
        }
-       if (ldap_set_option(ld, LDAP_OPT_TIMELIMIT, (void *) &(inst->timelimit)) != LDAP_OPT_SUCCESS) {
+
+       if (ldap_set_option(ld, LDAP_OPT_TIMELIMIT,
+                           (void *) &(inst->timelimit)) != LDAP_OPT_SUCCESS) {
                radlog(L_ERR, "rlm_ldap: Could not set LDAP_OPT_TIMELIMIT %d", inst->timelimit);
        }
+
        if (inst->ldap_debug && ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &(inst->ldap_debug)) != LDAP_OPT_SUCCESS) {
                radlog(L_ERR, "rlm_ldap: Could not set LDAP_OPT_DEBUG_LEVEL %d", inst->ldap_debug);
        }
+
        ldap_version = LDAP_VERSION3;
-       if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldap_version) != LDAP_OPT_SUCCESS) {
+       if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION,
+                           &ldap_version) != LDAP_OPT_SUCCESS) {
                radlog(L_ERR, "rlm_ldap: Could not set LDAP version to V3");
        }
+
 #ifdef HAVE_LDAP_START_TLS
-        if(inst->tls_mode) {
+        if (inst->tls_mode) {
                DEBUG("rlm_ldap: setting TLS mode to %d", inst->tls_mode);
-               if(ldap_set_option(ld, LDAP_OPT_X_TLS,
-                          (void *) &(inst->tls_mode)) != LDAP_OPT_SUCCESS) {
+               if (ldap_set_option(ld, LDAP_OPT_X_TLS,
+                                   (void *) &(inst->tls_mode)) != LDAP_OPT_SUCCESS) {
                        ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
                        radlog(L_ERR, "rlm_ldap: could not set LDAP_OPT_X_TLS option %s", ldap_err2string(ldap_errno));
                }
        }
 
-       if(inst->tls_cacertfile != NULL) {
+       if (inst->tls_cacertfile != NULL) {
                DEBUG("rlm_ldap: setting TLS CACert File to %s", inst->tls_cacertfile);
 
                if ( ldap_set_option( NULL, LDAP_OPT_X_TLS_CACERTFILE,
-                                                         (void *) inst->tls_cacertfile )
-                        != LDAP_OPT_SUCCESS) {
+                                     (void *) inst->tls_cacertfile )
+                    != LDAP_OPT_SUCCESS) {
                        radlog(L_ERR, "rlm_ldap: could not set "
-                                  "LDAP_OPT_X_TLS_CACERTFILE option to %s", inst->tls_cacertfile);
+                              "LDAP_OPT_X_TLS_CACERTFILE option to %s", inst->tls_cacertfile);
                }
        }
-
-       if(inst->tls_cacertdir != NULL) {
+       
+       if (inst->tls_cacertdir != NULL) {
                DEBUG("rlm_ldap: setting TLS CACert Directory to %s", inst->tls_cacertdir);
-
+               
                if ( ldap_set_option( NULL, LDAP_OPT_X_TLS_CACERTDIR,
-                                                         (void *) inst->tls_cacertdir )
-                        != LDAP_OPT_SUCCESS) {
+                                     (void *) inst->tls_cacertdir )
+                    != LDAP_OPT_SUCCESS) {
                        radlog(L_ERR, "rlm_ldap: could not set "
-                                  "LDAP_OPT_X_TLS_CACERTDIR option to %s", inst->tls_cacertdir);
+                              "LDAP_OPT_X_TLS_CACERTDIR option to %s", inst->tls_cacertdir);
                }
        }
 
-       if( strcmp( TLS_DEFAULT_VERIFY, inst->tls_require_cert ) != 0 ) {
+       if (strcmp(TLS_DEFAULT_VERIFY, inst->tls_require_cert ) != 0 ) {
                DEBUG("rlm_ldap: setting TLS Require Cert to %s",
-                         inst->tls_require_cert);
+                     inst->tls_require_cert);
        }
 
 
 #ifdef HAVE_LDAP_INT_TLS_CONFIG
-
-       if ( ldap_int_tls_config( NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
-                                                         (inst->tls_require_cert) )
-                != LDAP_OPT_SUCCESS) {
+       if (ldap_int_tls_config(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
+                               (inst->tls_require_cert)) != LDAP_OPT_SUCCESS) {
                radlog(L_ERR, "rlm_ldap: could not set "
-                          "LDAP_OPT_X_TLS_REQUIRE_CERT option to %s",
-                          inst->tls_require_cert);
+                      "LDAP_OPT_X_TLS_REQUIRE_CERT option to %s",
+                      inst->tls_require_cert);
        }
-
 #endif
 
-       if(inst->tls_certfile != NULL) {
+       if (inst->tls_certfile != NULL) {
                DEBUG("rlm_ldap: setting TLS Cert File to %s", inst->tls_certfile);
 
-               if ( ldap_set_option( NULL, LDAP_OPT_X_TLS_CERTFILE,
-                                                         (void *) inst->tls_certfile )
-                        != LDAP_OPT_SUCCESS) {
+               if (ldap_set_option(NULL, LDAP_OPT_X_TLS_CERTFILE,
+                                   (void *) inst->tls_certfile)
+                   != LDAP_OPT_SUCCESS) {
                        radlog(L_ERR, "rlm_ldap: could not set "
-                                  "LDAP_OPT_X_TLS_CERTFILE option to %s",
-                                  inst->tls_certfile);
+                              "LDAP_OPT_X_TLS_CERTFILE option to %s",
+                              inst->tls_certfile);
                }
        }
-
-       if(inst->tls_keyfile != NULL) {
-               DEBUG("rlm_ldap: setting TLS Key File to %s", inst->tls_keyfile);
-
+       
+       if (inst->tls_keyfile != NULL) {
+               DEBUG("rlm_ldap: setting TLS Key File to %s",
+                     inst->tls_keyfile);
+               
                if ( ldap_set_option( NULL, LDAP_OPT_X_TLS_KEYFILE,
-                                                         (void *) inst->tls_keyfile )
-                        != LDAP_OPT_SUCCESS) {
+                                     (void *) inst->tls_keyfile )
+                    != LDAP_OPT_SUCCESS) {
                        radlog(L_ERR, "rlm_ldap: could not set "
-                                  "LDAP_OPT_X_TLS_KEYFILE option to %s",
-                                  inst->tls_keyfile);
+                              "LDAP_OPT_X_TLS_KEYFILE option to %s",
+                              inst->tls_keyfile);
                }
        }
-
-       if(inst->tls_randfile != NULL) {
-               DEBUG("rlm_ldap: setting TLS Key File to %s", inst->tls_randfile);
-
-               if ( ldap_set_option( NULL, LDAP_OPT_X_TLS_RANDOM_FILE,
-                                                         (void *) inst->tls_randfile )
-                        != LDAP_OPT_SUCCESS) {
+       
+       if (inst->tls_randfile != NULL) {
+               DEBUG("rlm_ldap: setting TLS Key File to %s",
+                     inst->tls_randfile);
+               
+               if (ldap_set_option(NULL, LDAP_OPT_X_TLS_RANDOM_FILE,
+                                   (void *) inst->tls_randfile)
+                   != LDAP_OPT_SUCCESS) {
                        radlog(L_ERR, "rlm_ldap: could not set "
-                                  "LDAP_OPT_X_TLS_RANDOM_FILE option to %s",
-                                  inst->tls_randfile);
+                              "LDAP_OPT_X_TLS_RANDOM_FILE option to %s",
+                              inst->tls_randfile);
                }
        }
+
        if (inst->start_tls) {
                DEBUG("rlm_ldap: starting TLS");
                rc = ldap_start_tls_s(ld, NULL, NULL);
                if (rc != LDAP_SUCCESS) {
                        DEBUG("rlm_ldap: ldap_start_tls_s()");
-                       ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
-                       radlog(L_ERR, "rlm_ldap: could not start TLS %s", ldap_err2string(ldap_errno));
+                       ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER,
+                                       &ldap_errno);
+                       radlog(L_ERR, "rlm_ldap: could not start TLS %s",
+                              ldap_err2string(ldap_errno));
                        *result = RLM_MODULE_FAIL;
                        ldap_unbind_s(ld);
                        return (NULL);
@@ -2083,11 +2148,13 @@ ldap_connect(void *instance, const char *dn, const char *password, int auth, int
 #endif /* HAVE_LDAP_START_TLS */
 
        if (inst->is_url){
-               DEBUG("rlm_ldap: bind as %s/%s to %s", dn, password, inst->server);
-       }
-       else{
-               DEBUG("rlm_ldap: bind as %s/%s to %s:%d", dn, password, inst->server, inst->port);
+               DEBUG("rlm_ldap: bind as %s/%s to %s",
+                     dn, password, inst->server);
+       } else {
+               DEBUG("rlm_ldap: bind as %s/%s to %s:%d",
+                     dn, password, inst->server, inst->port);
        }
+
        msgid = ldap_bind(ld, dn, password,LDAP_AUTH_SIMPLE);
        if (msgid == -1) {
                ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
@@ -2110,7 +2177,7 @@ ldap_connect(void *instance, const char *dn, const char *password, int auth, int
 
        rc = ldap_result(ld, msgid, 1, &(inst->timeout), &res);
 
-       if(rc < 1) {
+       if (rc < 1) {
                DEBUG("rlm_ldap: ldap_result()");
                ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno);
                if(err != NULL){
@@ -2121,13 +2188,14 @@ ldap_connect(void *instance, const char *dn, const char *password, int auth, int
                                dn, inst->server, (rc == 0) ? "timeout" : ldap_err2string(ldap_errno));
                } else {
                        radlog(L_ERR, "rlm_ldap: %s bind to %s:%d failed: %s",
-                               dn, inst->server, inst->port,
+                              dn, inst->server, inst->port,
                                (rc == 0) ? "timeout" : ldap_err2string(ldap_errno));
                }
                *result = RLM_MODULE_FAIL;
                ldap_unbind_s(ld);
                return (NULL);
        }
+
        ldap_errno = ldap_result2error(ld, res, 1);
        switch (ldap_errno) {
        case LDAP_SUCCESS:
@@ -2139,8 +2207,7 @@ ldap_connect(void *instance, const char *dn, const char *password, int auth, int
                if (auth){
                        DEBUG("rlm_ldap: Bind failed with invalid credentials");
                        *result = RLM_MODULE_REJECT;
-               }
-               else {
+               } else {
                        radlog(L_ERR, "rlm_ldap: LDAP login failed: check identity, password settings in ldap section of radiusd.conf");
                        *result = RLM_MODULE_FAIL;
                }
@@ -2150,13 +2217,14 @@ ldap_connect(void *instance, const char *dn, const char *password, int auth, int
                break;
 
        default:
-               if (inst->is_url)
+               if (inst->is_url) {
                        radlog(L_ERR,"rlm_ldap: %s bind to %s failed %s",
                                dn, inst->server, ldap_err2string(ldap_errno));
-               else
+               } else {
                        radlog(L_ERR,"rlm_ldap: %s bind to %s:%d failed %s",
                                dn, inst->server, inst->port,
                                ldap_err2string(ldap_errno));
+               }
                *result = RLM_MODULE_FAIL;
                if(err != NULL){
                        ldap_get_option(ld, LDAP_OPT_ERROR_STRING, err);
@@ -2181,38 +2249,10 @@ ldap_detach(void *instance)
        ldap_instance  *inst = instance;
        TLDAP_RADIUS *pair, *nextpair;
 
-       if (inst->server)
-               free((char *) inst->server);
-       if (inst->login)
-               free((char *) inst->login);
-       if (inst->password)
-               free((char *) inst->password);
-       if (inst->basedn)
-               free((char *) inst->basedn);
-       if (inst->dictionary_mapping)
-               free(inst->dictionary_mapping);
-       if (inst->filter)
-               free((char *) inst->filter);
-       if (inst->base_filter)
-               free((char *) inst->base_filter);
-       if (inst->passwd_hdr)
-               free((char *) inst->passwd_hdr);
-       if (inst->passwd_attr)
-               free((char *) inst->passwd_attr);
-       if (inst->groupname_attr)
-               free((char *) inst->groupname_attr);
-       if (inst->groupmemb_filt)
-               free((char *) inst->groupmemb_filt);
-       if (inst->groupmemb_attr)
-               free((char *) inst->groupmemb_attr);
-       if (inst->access_attr)
-               free((char *) inst->access_attr);
-       if (inst->profile_attr)
-               free((char *) inst->profile_attr);
-       if (inst->conns){
-               int i=0;
-
-               for(;i<inst->num_conns;i++){
+       if (inst->conns) {
+               int i;
+               
+               for (i = 0;i < inst->num_conns; i++) {
                        if (inst->conns[i].ld){
                                ldap_unbind_s(inst->conns[i].ld);
                        }
@@ -2225,7 +2265,7 @@ ldap_detach(void *instance)
        if (inst->apc_conns){ 
                int i;
 
-               for(i = 0; i < inst->num_conns; i++){
+               for (i = 0; i < inst->num_conns; i++) {
                        if (inst->apc_conns[i].ld){
                                ldap_unbind_s(inst->apc_conns[i].ld);
                        }
@@ -2267,6 +2307,7 @@ ldap_detach(void *instance)
        return 0;
 }
 
+
 #ifdef FIELDCPY
 static void
 fieldcpy(char *string, char **uptr)
@@ -2298,16 +2339,42 @@ fieldcpy(char *string, char **uptr)
        return;
 }
 #endif
+
+/*
+ *     Copied from src/lib/token.c
+ */
+static const LRAD_NAME_NUMBER tokens[] = {
+       { "=~", T_OP_REG_EQ,    }, /* order is important! */
+       { "!~", T_OP_REG_NE,    },
+       { "{",  T_LCBRACE,      },
+       { "}",  T_RCBRACE,      },
+       { "(",  T_LBRACE,       },
+       { ")",  T_RBRACE,       },
+       { ",",  T_COMMA,        },
+       { "+=", T_OP_ADD,       },
+       { "-=", T_OP_SUB,       },
+       { ":=", T_OP_SET,       },
+       { "=*", T_OP_CMP_TRUE,  },
+       { "!*", T_OP_CMP_FALSE, },
+       { "==", T_OP_CMP_EQ,    },
+       { "=",  T_OP_EQ,        },
+       { "!=", T_OP_NE,        },
+       { ">=", T_OP_GE,        },
+       { ">",  T_OP_GT,        },
+       { "<=", T_OP_LE,        },
+       { "<",  T_OP_LT,        },
+       { NULL, 0}
+};
+
 /*****************************************************************************
  *     Get RADIUS attributes from LDAP object
  *     ( according to draft-adoba-radius-05.txt
  *       <http://www.ietf.org/internet-drafts/draft-adoba-radius-05.txt> )
  *
  *****************************************************************************/
-
-static VALUE_PAIR *
-ldap_pairget(LDAP * ld, LDAPMessage * entry,
-            TLDAP_RADIUS * item_map, VALUE_PAIR **pairs,char is_check)
+static VALUE_PAIR *ldap_pairget(LDAP *ld, LDAPMessage *entry,
+                               TLDAP_RADIUS *item_map,
+                               VALUE_PAIR **pairs, int is_check)
 {
        char          **vals;
        int             vals_count;
@@ -2375,7 +2442,9 @@ ldap_pairget(LDAP * ld, LDAPMessage * entry,
                                operator = gettoken(&ptr, buf, sizeof(buf));
                                if (operator < T_EQSTART || operator > T_EQEND) {
                                        /* no leading operator found */
-                                       if (is_check)
+                                       if (element->operator != T_OP_INVALID)
+                                               operator = element->operator;
+                                       else if (is_check)
                                                operator = T_OP_CMP_EQ;
                                        else
                                                operator = T_OP_EQ;
@@ -2416,7 +2485,10 @@ ldap_pairget(LDAP * ld, LDAPMessage * entry,
                                        continue;
                                }
 
-                               DEBUG("rlm_ldap: Adding %s as %s, value %s & op=%d", element->attr, element->radius_attr, value, operator);
+                               DEBUG("rlm_ldap: Adding LDAP attribute %s as RADIUS attribute %s %s %s",
+                                     element->attr, element->radius_attr,
+                                     lrad_int2str(tokens, operator, "?"),
+                                     value);
 
                                /*
                                 *      Create the pair.
@@ -2430,8 +2502,8 @@ ldap_pairget(LDAP * ld, LDAPMessage * entry,
                                }
                                if (do_xlat) {
                                        newpair->flags.do_xlat = 1;
-                                       strNcpy(newpair->strvalue, buf,
-                                               sizeof(newpair->strvalue));
+                                       strlcpy(newpair->vp_strvalue, buf,
+                                               sizeof(newpair->vp_strvalue));
                                        newpair->length = 0;
                                }
 
@@ -2451,11 +2523,12 @@ ldap_pairget(LDAP * ld, LDAPMessage * entry,
 }
 
 /* globally exported name */
-module_t        rlm_ldap = {
+module_t rlm_ldap = {
+       RLM_MODULE_INIT,
        "LDAP",
        RLM_TYPE_THREAD_SAFE,   /* type: reserved        */
-       NULL,                   /* initialization        */
        ldap_instantiate,       /* instantiation         */
+       ldap_detach,            /* detach                */
        {
                ldap_authenticate,      /* authentication        */
                ldap_authorize,         /* authorization         */
@@ -2465,11 +2538,9 @@ module_t        rlm_ldap = {
                NULL,                   /* pre-proxy             */
                NULL,                   /* post-proxy            */
 #ifdef NOVELL
-               ldap_postauth                   /* post-auth             */
+               ldap_postauth           /* post-auth             */
 #else
                NULL
 #endif
        },
-       ldap_detach,            /* detach                */
-       NULL,                   /* destroy               */
 };
diff --git a/src/modules/rlm_linelog/Makefile b/src/modules/rlm_linelog/Makefile
new file mode 100755 (executable)
index 0000000..a863f82
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile
+#
+# Version:     $Id$
+#
+
+TARGET         = rlm_linelog
+SRCS           = rlm_linelog.c
+
+include ../rules.mak
diff --git a/src/modules/rlm_linelog/rlm_linelog.c b/src/modules/rlm_linelog/rlm_linelog.c
new file mode 100755 (executable)
index 0000000..b58b969
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * rlm_linelog.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 2004,2006  The FreeRADIUS server project
+ * Copyright 2004  Alan DeKok <aland@freeradius.org>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+
+
+/*
+ *     Define a structure for our module configuration.
+ *
+ *     These variables do not need to be in a structure, but it's
+ *     a lot cleaner to do so, and a pointer to the structure can
+ *     be used as the instance handle.
+ */
+typedef struct rlm_linelog_t {
+       char            *filename;
+       char            *line;
+} rlm_linelog_t;
+
+/*
+ *     A mapping of configuration file names to internal variables.
+ *
+ *     Note that the string is dynamically allocated, so it MUST
+ *     be freed.  When the configuration file parse re-reads the string,
+ *     it free's the old one, and strdup's the new one, placing the pointer
+ *     to the strdup'd string into 'config.string'.  This gets around
+ *     buffer over-flows.
+ */
+static const CONF_PARSER module_config[] = {
+       { "filename",  PW_TYPE_STRING_PTR,
+         offsetof(rlm_linelog_t,filename), NULL,  NULL},
+       { "format",  PW_TYPE_STRING_PTR,
+         offsetof(rlm_linelog_t,line), NULL,  NULL},
+       { NULL, -1, 0, NULL, NULL }             /* end the list */
+};
+
+
+static int linelog_detach(void *instance)
+{
+       rlm_linelog_t *inst = instance;
+
+       
+       free(inst);
+       return 0;
+}
+
+/*
+ *     Instantiate the module.
+ */
+static int linelog_instantiate(CONF_SECTION *conf, void **instance)
+{
+       rlm_linelog_t *inst;
+
+       /*
+        *      Set up a storage area for instance data
+        */
+       inst = rad_malloc(sizeof(*inst));
+       memset(inst, 0, sizeof(*inst));
+
+       /*
+        *      If the configuration parameters can't be parsed, then
+        *      fail.
+        */
+       if (cf_section_parse(conf, inst, module_config) < 0) {
+               linelog_detach(inst);
+               return -1;
+       }
+
+       *instance = inst;
+
+       return 0;
+}
+
+
+/*
+ *     Escape unprintable characters.
+ */
+static int linelog_escape_func(char *out, int outlen, const char *in)
+{
+       int len = 0;
+
+       if (outlen == 0) return 0;
+       if (outlen == 1) {
+               *out = '\0';
+               return 0;
+       }
+
+       while (in[0]) {
+               if (in[0] >= ' ') {
+                       if (in[0] == '\\') {
+                               if (outlen <= 2) break;
+                               outlen--;
+                               *out++ = '\\';
+                               len++;
+                       }
+
+                       outlen--;
+                       if (outlen == 1) break;
+                       *out++ = *in++;
+                       len++;
+                       continue;
+               }
+
+               switch (in[0]) {
+               case '\n':
+                       if (outlen <= 2) break;
+                       *out++ = '\\';
+                       *out++ = 'n';
+                       in++;
+                       len += 2;
+                       break;
+
+               case '\r':
+                       if (outlen <= 2) break;
+                       *out++ = '\\';
+                       *out++ = 'r';
+                       in++;
+                       len += 2;
+                       break;
+
+               default:
+                       if (outlen <= 4) break;
+                       snprintf(out, outlen,  "\\%03o", *in);
+                       in++;
+                       out += 4;
+                       outlen -= 4;
+                       len += 4;
+                       break;
+               }
+       }
+
+       *out = '\0';
+       return len;
+}
+
+static int do_linelog(void *instance, REQUEST *request)
+{
+       int fd;
+       char buffer[4096];
+       char line[1024];
+       rlm_linelog_t *inst;
+
+       inst = (rlm_linelog_t*) instance;
+
+       /*
+        *      FIXME: Check length.
+        */
+       radius_xlat(buffer, sizeof(buffer), inst->filename, request, NULL);
+
+       fd = open(buffer, O_WRONLY | O_APPEND | O_CREAT, 0600);
+       if (fd == -1) {
+               radlog(L_ERR, "rlm_linelog: Failed to open %s: %s",
+                      buffer, strerror(errno));
+               return RLM_MODULE_FAIL;
+       }
+
+       /*
+        *      FIXME: Check length.
+        */
+       radius_xlat(line, sizeof(line) - 1, inst->line, request,
+                   linelog_escape_func);
+       strcat(line, "\n");
+       
+       write(fd, line, strlen(line));
+       close(fd);
+
+       return RLM_MODULE_OK;
+}
+
+
+/*
+ *     Externally visible module definition.
+ */
+module_t rlm_linelog = {
+       RLM_MODULE_INIT,
+       "linelog",
+       RLM_TYPE_THREAD_SAFE,           /* type */
+       linelog_instantiate,            /* instantiation */
+       linelog_detach,                 /* detach */
+       {
+               do_linelog,     /* authentication */
+               do_linelog,     /* authorization */
+               do_linelog,     /* preaccounting */
+               do_linelog,     /* accounting */
+               NULL,           /* checksimul */
+               do_linelog,     /* pre-proxy */
+               do_linelog,     /* post-proxy */
+               do_linelog      /* post-auth */
+       },
+};
diff --git a/src/modules/rlm_logintime/Makefile b/src/modules/rlm_logintime/Makefile
new file mode 100644 (file)
index 0000000..0706c20
--- /dev/null
@@ -0,0 +1,4 @@
+TARGET  = rlm_logintime
+SRCS    = rlm_logintime.c timestr.c
+
+include ../rules.mak
diff --git a/src/modules/rlm_logintime/rlm_logintime.c b/src/modules/rlm_logintime/rlm_logintime.c
new file mode 100644 (file)
index 0000000..dd1a1d1
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * rlm_logintime.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,2006  The FreeRADIUS server project
+ * Copyright 2004  Kostas Kalevras <kkalev@noc.ntua.gr>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+
+/*
+ *     Define a structure for our module configuration.
+ *
+ *     These variables do not need to be in a structure, but it's
+ *     a lot cleaner to do so, and a pointer to the structure can
+ *     be used as the instance handle.
+ */
+typedef struct rlm_logintime_t {
+       char *msg;              /* The Reply-Message passed back to the user 
+                                * if the account is outside allowed timestamp */
+       int min_time;
+} rlm_logintime_t;
+
+/*
+ *     A mapping of configuration file names to internal variables.
+ *
+ *     Note that the string is dynamically allocated, so it MUST
+ *     be freed.  When the configuration file parse re-reads the string,
+ *     it free's the old one, and strdup's the new one, placing the pointer
+ *     to the strdup'd string into 'config.string'.  This gets around
+ *     buffer over-flows.
+ */
+static const CONF_PARSER module_config[] = {
+  { "reply-message", PW_TYPE_STRING_PTR, offsetof(rlm_logintime_t,msg), NULL, 
+       "You are calling outside your allowed timespan\r\n"},
+  { "minimum-timeout", PW_TYPE_INTEGER, offsetof(rlm_logintime_t,min_time), NULL, "60" },
+  { NULL, -1, 0, NULL, NULL }
+};
+
+static int logintime_detach(void *instance);
+
+/*
+ *      Compare the current time to a range.
+ */
+static int timecmp(void *instance,
+               REQUEST *req,
+               VALUE_PAIR *request, VALUE_PAIR *check,
+               VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+{ 
+       instance = instance;
+       request = request;      /* shut the compiler up */
+       check_pairs = check_pairs;
+       reply_pairs = reply_pairs;
+  
+       /*
+        *      If there's a request, use that timestamp.       
+        */
+       if (timestr_match((char *)check->vp_strvalue,
+       req ? req->timestamp : time(NULL)) >= 0)
+               return 0;
+
+       return -1;
+}
+
+
+/*
+ *     Time-Of-Day support
+ */
+static int time_of_day(void *instance,
+                      REQUEST *req,
+                      VALUE_PAIR *request, VALUE_PAIR *check,
+                      VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+{
+       int scan;
+       int hhmmss, when;
+       char *p;
+       struct tm *tm, s_tm;
+
+       instance = instance;
+       request = request;      /* shut the compiler up */
+       check_pairs = check_pairs;
+       reply_pairs = reply_pairs;
+
+       /*
+        *      Must be called with a request pointer.
+        */
+       if (!req) return -1;
+  
+       if (strspn(check->vp_strvalue, "0123456789: ") != strlen(check->vp_strvalue)) {
+               DEBUG("rlm_logintime: Bad Time-Of-Day value \"%s\"",
+                     check->vp_strvalue);
+               return -1;
+       }
+
+       tm = localtime_r(&req->timestamp, &s_tm);
+       hhmmss = (tm->tm_hour * 3600) + (tm->tm_min * 60) + tm->tm_sec;
+
+       /*
+        *      Time of day is a 24-hour clock
+        */
+       p = check->vp_strvalue;
+       scan = atoi(p);
+       p = strchr(p, ':');
+       if ((scan > 23) || !p) {
+               DEBUG("rlm_logintime: Bad Time-Of-Day value \"%s\"",
+                     check->vp_strvalue);
+               return -1;
+       }
+       when = scan * 3600;
+       p++;
+
+       scan = atoi(p);
+       if (scan > 59) {
+               DEBUG("rlm_logintime: Bad Time-Of-Day value \"%s\"",
+                     check->vp_strvalue);
+               return -1;
+       }
+       when += scan * 60;
+
+       p = strchr(p, ':');
+       if (p) {
+               scan = atoi(p + 1);
+               if (scan > 59) {
+                       DEBUG("rlm_logintime: Bad Time-Of-Day value \"%s\"",
+                             check->vp_strvalue);
+                       return -1;
+               }
+               when += scan;
+       }
+
+       fprintf(stderr, "returning %d - %d\n",
+               hhmmss, when);
+       
+       return hhmmss - when;
+}
+
+/*              
+ *      Check if account has expired, and if user may login now.
+ */              
+static int logintime_authorize(void *instance, REQUEST *request)
+{
+       rlm_logintime_t *data = (rlm_logintime_t *)instance;
+       VALUE_PAIR *check_item = NULL;
+       int r;
+
+       if ((check_item = pairfind(request->config_items, PW_LOGIN_TIME)) != NULL) {
+               /*
+                *      Authentication is OK. Now see if this
+                *      user may login at this time of the day.
+                */
+               DEBUG("rlm_logintime: Checking Login-Time: '%s'",check_item->vp_strvalue);
+               r = timestr_match((char *)check_item->vp_strvalue,
+               request->timestamp);
+               if (r == 0) {   /* unlimited */
+                       /*
+                        *      Do nothing: login-time is OK.
+                        */
+
+               /*
+                *      Session-Timeout needs to be at least
+                *      60 seconds, some terminal servers
+                *      ignore smaller values.
+                */
+                       DEBUG("rlm_logintime: timestr returned unlimited");
+               } else if (r < data->min_time) {
+                       char logstr[MAX_STRING_LEN];
+                       VALUE_PAIR *module_fmsg_vp;
+
+                       /*
+                        *      User called outside allowed time interval.
+                        */
+               
+                       DEBUG("rlm_logintime: timestr returned reject");
+                       if (data->msg && data->msg[0]){
+                               char msg[MAX_STRING_LEN];
+                               VALUE_PAIR *tmp;
+
+                               if (!radius_xlat(msg, sizeof(msg), data->msg, request, NULL)) {
+                                       radlog(L_ERR, "rlm_logintime: xlat failed.");
+                                       return RLM_MODULE_FAIL;
+                               }
+                               pairfree(&request->reply->vps);
+                               tmp = pairmake("Reply-Message", msg, T_OP_SET);
+                               request->reply->vps = tmp;
+                       }
+
+                       snprintf(logstr, sizeof(logstr), "Outside allowed timespan (time allowed %s)",
+                       check_item->vp_strvalue);
+                       module_fmsg_vp = pairmake("Module-Failure-Message", logstr, T_OP_EQ);
+                       pairadd(&request->packet->vps, module_fmsg_vp);
+
+                       return RLM_MODULE_REJECT;
+
+               } else if (r > 0) {
+                       VALUE_PAIR *reply_item;
+
+                       /*
+                        *      User is allowed, but set Session-Timeout.
+                        */
+                       DEBUG("rlm_logintime: timestr returned accept");
+                       if ((reply_item = pairfind(request->reply->vps, PW_SESSION_TIMEOUT)) != NULL) {
+                               if (reply_item->lvalue > (unsigned) r)
+                                       reply_item->lvalue = r;
+                       } else {
+                               if ((reply_item = paircreate( PW_SESSION_TIMEOUT, PW_TYPE_INTEGER)) == NULL) {
+                                       radlog(L_ERR|L_CONS, "no memory");
+                                       return RLM_MODULE_FAIL;
+                               }
+                               reply_item->lvalue = r;
+                               pairadd(&request->reply->vps, reply_item);
+                       }
+                       DEBUG("rlm_logintime: Session-Timeout set to: %d",r);
+               }
+       }
+       else
+               return RLM_MODULE_NOOP;
+
+       return RLM_MODULE_OK;
+}
+
+
+/*
+ *     Do any per-module initialization that is separate to each
+ *     configured instance of the module.  e.g. set up connections
+ *     to external databases, read configuration files, set up
+ *     dictionary entries, etc.
+ *
+ *     If configuration information is given in the config section
+ *     that must be referenced in later calls, store a handle to it
+ *     in *instance otherwise put a null pointer there.
+ */
+static int logintime_instantiate(CONF_SECTION *conf, void **instance)
+{
+       rlm_logintime_t *data;
+
+       /*
+        *      Set up a storage area for instance data
+        */
+       data = rad_malloc(sizeof(*data));
+       if (!data) {
+               radlog(L_ERR, "rlm_logintime: rad_malloc() failed.");
+               return -1;
+       }
+       memset(data, 0, sizeof(*data));
+
+       /*
+        *      If the configuration parameters can't be parsed, then
+        *      fail.
+        */
+       if (cf_section_parse(conf, data, module_config) < 0) {
+               free(data);
+               radlog(L_ERR, "rlm_logintime: Configuration parsing failed.");
+               return -1;
+       }
+
+       if (data->min_time == 0){
+               radlog(L_ERR, "rlm_logintime: Minimum timeout should be non zero.");
+               free(data);
+               return -1;
+       }
+
+       /*
+        * Register a Current-Time comparison function
+        */
+       paircompare_register(PW_CURRENT_TIME, 0, timecmp, data);
+       paircompare_register(PW_TIME_OF_DAY, 0, time_of_day, data);
+
+       *instance = data;
+
+       return 0;
+}
+
+static int logintime_detach(void *instance)
+{
+       rlm_logintime_t *data = (rlm_logintime_t *) instance;
+
+       paircompare_unregister(PW_CURRENT_TIME, timecmp);
+       paircompare_unregister(PW_TIME_OF_DAY, time_of_day);
+       free(instance);
+       return 0;
+}
+
+/*
+ *     The module name should be the only globally exported symbol.
+ *     That is, everything else should be 'static'.
+ *
+ *     If the module needs to temporarily modify it's instantiation
+ *     data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
+ *     The server will then take care of ensuring that the module
+ *     is single-threaded.
+ */
+module_t rlm_logintime = {
+       RLM_MODULE_INIT,
+       "logintime",
+       RLM_TYPE_THREAD_SAFE,           /* type */
+       logintime_instantiate,          /* instantiation */
+       logintime_detach,               /* detach */
+       {
+               NULL,                   /* authentication */
+               logintime_authorize,    /* authorization */
+               NULL,                   /* preaccounting */
+               NULL,                   /* accounting */
+               NULL,                   /* checksimul */
+               NULL,                   /* pre-proxy */
+               NULL,                   /* post-proxy */
+               NULL                    /* post-auth */
+       },
+};
similarity index 94%
rename from src/main/timestr.c
rename to src/modules/rlm_logintime/timestr.c
index a1da599..6798798 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
 
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include       "autoconf.h"
-#include       "libradius.h"
+#include       <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 
-#include "radiusd.h"
+#include <freeradius-devel/radiusd.h>
 
 static const char *days[] =
        { "su", "mo", "tu", "we", "th", "fr", "sa", "wk", "any", "al" };
@@ -183,7 +183,7 @@ static int week_fill(char *bitmap, char *tm)
        char *s;
        char tmp[128];
 
-       strncpy(tmp, tm, 128);
+       strlcpy(tmp, tm, 128);
        tmp[127] = 0;
        for (s = tmp; *s; s++)
                if (isupper(*s)) *s = tolower(*s);
index 218fdb7..645abb1 100644 (file)
@@ -15,9 +15,9 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000,2001  The FreeRADIUS server project
+ * Copyright 2000,2001,2006  The FreeRADIUS server project
  */
 
 
 
 /*  MPPE support from Takahiro Wagatsuma <waga@sic.shibaura-it.ac.jp> */
 
-#include       "autoconf.h"
-#include       "libradius.h"
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include       <freeradius-devel/autoconf.h>
 
 #include       <stdio.h>
 #include       <stdlib.h>
 #include       <string.h>
 #include       <ctype.h>
 
-#include       "radiusd.h"
-#include       "modules.h"
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/modules.h>
 
-#include        "md4.h"
-#include        "md5.h"
-#include       "sha1.h"
-#include       "rad_assert.h"
+#include        <freeradius-devel/md5.h>
+#include       <freeradius-devel/rad_assert.h>
 
 #include       "smbdes.h"
 
-static const char rcsid[] = "$Id$";
-
-static const char *letters = "0123456789ABCDEF";
-
-/*
- *     hex2bin converts hexadecimal strings into binary
- */
-static int hex2bin (const char *szHex, unsigned char* szBin, int len)
-{
-       char * c1, * c2;
-       int i;
-
-       for (i = 0; i < len; i++) {
-               if( !(c1 = memchr(letters, toupper((int) szHex[i << 1]), 16)) ||
-                   !(c2 = memchr(letters, toupper((int) szHex[(i << 1) + 1]), 16)))
-                    break;
-                 szBin[i] = ((c1-letters)<<4) + (c2-letters);
-        }
-        return i;
-}
-
-/*
- *     bin2hex creates hexadecimal presentation
- *     of binary data
- */
-static void bin2hex (const unsigned char *szBin, char *szHex, int len)
-{
-       int i;
-       for (i = 0; i < len; i++) {
-               szHex[i<<1] = letters[szBin[i] >> 4];
-               szHex[(i<<1) + 1] = letters[szBin[i] & 0x0F];
-       }
-}
-
-
 /* Allowable account control bits */
 #define ACB_DISABLED   0x0001  /* 1 = User account disabled */
 #define ACB_HOMDIRREQ  0x0002  /* 1 = Home directory required */
@@ -213,12 +178,12 @@ static void ntpwdhash (unsigned char *szHash, const char *szPassword)
  *     implements RFC2759 ChallengeHash()
  *     generates 64 bit challenge
  */
-static void challenge_hash( const char *peer_challenge,
-                           const char *auth_challenge,
-                           const char *user_name, char *challenge )
+static void challenge_hash( const uint8_t *peer_challenge,
+                           const uint8_t *auth_challenge,
+                           const char *user_name, uint8_t *challenge )
 {
        SHA1_CTX Context;
-       unsigned char hash[20];
+       uint8_t hash[20];
 
        SHA1Init(&Context);
        SHA1Update(&Context, peer_challenge, 16);
@@ -234,19 +199,19 @@ static void challenge_hash( const char *peer_challenge,
  *     returns 42-octet response string
  */
 static void auth_response(const char *username,
-                         const unsigned char *nt_hash_hash,
-                         unsigned char *ntresponse,
+                         const uint8_t *nt_hash_hash,
+                         uint8_t *ntresponse,
                          char *peer_challenge, char *auth_challenge,
                          char *response)
 {
        SHA1_CTX Context;
-       const unsigned char magic1[39] =
+       const uint8_t magic1[39] =
        {0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
         0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
         0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
         0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74};
 
-       const unsigned char magic2[41] =
+       const uint8_t magic2[41] =
        {0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
         0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
         0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
@@ -254,7 +219,7 @@ static void auth_response(const char *username,
         0x6E};
 
         char challenge[8];
-       unsigned char digest[20];
+       uint8_t digest[20];
 
        SHA1Init(&Context);
        SHA1Update(&Context, nt_hash_hash, 16);
@@ -277,7 +242,7 @@ static void auth_response(const char *username,
         */
        response[0] = 'S';
        response[1] = '=';
-       bin2hex(digest, response + 2, 20);
+       lrad_bin2hex(digest, response + 2, 20);
 }
 
 
@@ -303,9 +268,9 @@ static int mschap_xlat(void *instance, REQUEST *request,
                       char *fmt, char *out, size_t outlen,
                       RADIUS_ESCAPE_STRING func)
 {
-       int             i, data_len;
+       size_t          i, data_len;
        uint8_t         *data = NULL;
-       uint8_t         buffer[8];
+       uint8_t         buffer[32];
        VALUE_PAIR      *user_name;
        VALUE_PAIR      *chap_challenge, *response;
        rlm_mschap_t    *inst = instance;
@@ -331,8 +296,9 @@ static int mschap_xlat(void *instance, REQUEST *request,
                 *      for MS-CHAPv2
                 */
                if (chap_challenge->length == 8) {
-                       DEBUG2(" mschap1: %02x", chap_challenge->strvalue[0]);
-                       data = chap_challenge->strvalue;
+                       DEBUG2(" mschap1: %02x",
+                              chap_challenge->vp_octets[0]);
+                       data = chap_challenge->vp_octets;
                        data_len = 8;
 
                        /*
@@ -342,7 +308,7 @@ static int mschap_xlat(void *instance, REQUEST *request,
                } else if (chap_challenge->length == 16) {
                        char *username_string;
 
-                       DEBUG2(" mschap2: %02x", chap_challenge->strvalue[0]);
+                       DEBUG2(" mschap2: %02x", chap_challenge->vp_octets[0]);
                        response = pairfind(request->packet->vps,
                                            PW_MSCHAP2_RESPONSE);
                        if (!response) {
@@ -368,15 +334,15 @@ static int mschap_xlat(void *instance, REQUEST *request,
                        /*
                         *      with_ntdomain_hack moved here, too.
                         */
-                       if ((username_string = strchr(user_name->strvalue, '\\')) != NULL) {
+                       if ((username_string = strchr(user_name->vp_strvalue, '\\')) != NULL) {
                                if (inst->with_ntdomain_hack) {
                                        username_string++;
                                } else {
                                        DEBUG2("  rlm_mschap: NT Domain delimeter found, should we have enabled with_ntdomain_hack?");
-                                       username_string = user_name->strvalue;
+                                       username_string = user_name->vp_strvalue;
                                }
                        } else {
-                               username_string = user_name->strvalue;
+                               username_string = user_name->vp_strvalue;
                        }
 
                        /*
@@ -384,8 +350,8 @@ static int mschap_xlat(void *instance, REQUEST *request,
                         *      from the MS-CHAPv2 peer challenge,
                         *      our challenge, and the user name.
                         */
-                       challenge_hash(response->strvalue + 2,
-                                      chap_challenge->strvalue,
+                       challenge_hash(response->vp_octets + 2,
+                                      chap_challenge->vp_octets,
                                       username_string, buffer);
                        data = buffer;
                        data_len = 8;
@@ -413,7 +379,7 @@ static int mschap_xlat(void *instance, REQUEST *request,
                 *      if the second octet says so.
                 */
                if ((response->attribute == PW_MSCHAP_RESPONSE) &&
-                   ((response->strvalue[1] & 0x01) == 0)) {
+                   ((response->vp_octets[1] & 0x01) == 0)) {
                        DEBUG2("  rlm_mschap: No NT-Response in MS-CHAP-Response");
                        return 0;
                }
@@ -423,7 +389,7 @@ static int mschap_xlat(void *instance, REQUEST *request,
                 *      the NT-Response at the same offset, and are
                 *      the same length.
                 */
-               data = response->strvalue + 26;
+               data = response->vp_octets + 26;
                data_len = 24;
                
                /*
@@ -442,11 +408,11 @@ static int mschap_xlat(void *instance, REQUEST *request,
                 *      For MS-CHAPv1, the NT-Response exists only
                 *      if the second octet says so.
                 */
-               if ((response->strvalue[1] & 0x01) != 0) {
+               if ((response->vp_octets[1] & 0x01) != 0) {
                        DEBUG2("  rlm_mschap: No LM-Response in MS-CHAP-Response");
                        return 0;
                }
-               data = response->strvalue + 2;
+               data = response->vp_octets + 2;
                data_len = 24;
 
                /*
@@ -465,17 +431,17 @@ static int mschap_xlat(void *instance, REQUEST *request,
                 *      First check to see if this is a host/ style User-Name
                 *      (a la Kerberos host principal)
                 */
-               if (strncmp(user_name->strvalue, "host/", 5) == 0) {
+               if (strncmp(user_name->vp_strvalue, "host/", 5) == 0) {
                        /*
                         *      If we're getting a User-Name formatted in this way,
                         *      it's likely due to PEAP.  The Windows Domain will be
                         *      the first domain component following the hostname,
                         *      or the machine name itself if only a hostname is supplied
                         */
-                       p = strchr(user_name->strvalue, '.');
+                       p = strchr(user_name->vp_strvalue, '.');
                        if (!p) {
                                DEBUG2("  rlm_mschap: setting NT-Domain to same as machine name");
-                               strNcpy(out, user_name->strvalue + 5, outlen);
+                               strlcpy(out, user_name->vp_strvalue + 5, outlen);
                        } else {
                                p++;    /* skip the period */
                                q = strchr(p, '.');
@@ -484,11 +450,11 @@ static int mschap_xlat(void *instance, REQUEST *request,
                                 * only if another period was found
                                 */
                                if (q) *q = '\0';
-                               strNcpy(out, p, outlen);
+                               strlcpy(out, p, outlen);
                                if (q) *q = '.';
                        }
                } else {
-                       p = strchr(user_name->strvalue, '\\');
+                       p = strchr(user_name->vp_strvalue, '\\');
                        if (!p) {
                                DEBUG2("  rlm_mschap: No NT-Domain was found in the User-Name.");
                                return 0;
@@ -498,7 +464,7 @@ static int mschap_xlat(void *instance, REQUEST *request,
                         *      Hack.  This is simpler than the alternatives.
                         */
                        *p = '\0';
-                       strNcpy(out, user_name->strvalue, outlen);
+                       strlcpy(out, user_name->vp_strvalue, outlen);
                        *p = '\\';
                }
 
@@ -520,7 +486,7 @@ static int mschap_xlat(void *instance, REQUEST *request,
                 *      First check to see if this is a host/ style User-Name
                 *      (a la Kerberos host principal)
                 */
-               if (strncmp(user_name->strvalue, "host/", 5) == 0) {
+               if (strncmp(user_name->vp_strvalue, "host/", 5) == 0) {
                        /*
                         *      If we're getting a User-Name formatted in this way,
                         *      it's likely due to PEAP.  When authenticating this against
@@ -531,26 +497,59 @@ static int mschap_xlat(void *instance, REQUEST *request,
                         *      from that point to the first period into a string and appending
                         *      a $ to the end.
                         */
-                       p = strchr(user_name->strvalue, '.');
+                       p = strchr(user_name->vp_strvalue, '.');
                        /*
                         * use the same hack as above
                         * only if a period was found
                         */
                        if (p) *p = '\0';
-                       snprintf(out, outlen, "%s$", user_name->strvalue + 5);
+                       snprintf(out, outlen, "%s$", user_name->vp_strvalue + 5);
                        if (p) *p = '.';
                } else {
-                       p = strchr(user_name->strvalue, '\\');
+                       p = strchr(user_name->vp_strvalue, '\\');
                        if (p) {
                                p++;    /* skip the backslash */
                        } else {
-                               p = user_name->strvalue; /* use the whole User-Name */
+                               p = user_name->vp_strvalue; /* use the whole User-Name */
                        }
-                       strNcpy(out, p, outlen);
+                       strlcpy(out, p, outlen);
                }
 
                return strlen(out);
 
+               /*
+                * Return the NT-Hash of the passed string
+                */
+       } else if (strncasecmp(fmt, "NT-Hash ", 8) == 0) {
+               char *p;
+
+               p = fmt + 8;    /* 7 is the length of 'NT-Hash' */
+               if ((p == '\0')  || (outlen <= 32))
+                       return 0;
+               DEBUG("rlm_mschap: NT-Hash: %s",p);
+               ntpwdhash(buffer,p);
+
+               lrad_bin2hex(buffer, out, 16);
+               out[32] = '\0';
+               DEBUG("rlm_mschap: NT-Hash: Result: %s",out);
+               return 32;
+
+               /*
+                * Return the LM-Hash of the passed string
+                */
+       } else if (strncasecmp(fmt, "LM-Hash ", 8) == 0) {
+               char *p;
+
+               p = fmt + 8;    /* 7 is the length of 'LM-Hash' */
+               if ((p == '\0') || (outlen <= 32))
+                       return 0;
+                       
+               DEBUG("rlm_mschap: LM-Hash: %s",p);
+               smbdes_lmpwdhash(p,buffer);
+               lrad_bin2hex(buffer, out, 16);
+               out[32] = '\0';
+               DEBUG("rlm_mschap: LM-Hash: Result: %s",out);
+               return 32;
        } else {
                DEBUG2("  rlm_mschap: Unknown expansion string \"%s\"",
                       fmt);
@@ -586,7 +585,7 @@ static int mschap_xlat(void *instance, REQUEST *request,
 }
 
 
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
        /*
         *      Cache the password by default.
         */
@@ -612,8 +611,6 @@ static CONF_PARSER module_config[] = {
  */
 static int mschap_detach(void *instance){
 #define inst ((rlm_mschap_t *)instance)
-       free(inst->passwd_file);
-       free(inst->ntlm_auth);
        if (inst->xlat_name) {
                xlat_unregister(inst->xlat_name, mschap_xlat);
                free(inst->xlat_name);
@@ -658,13 +655,15 @@ static int mschap_instantiate(CONF_SECTION *conf, void **instance)
        /*
         *      Create the dynamic translation.
         */
-       xlat_name = cf_section_name2(conf);
+       if (cf_section_name1(conf))
+               xlat_register(cf_section_name1(conf),mschap_xlat, inst);
+
+       if ((xlat_name = cf_section_name2(conf)) != NULL)
+               xlat_register(xlat_name, mschap_xlat, inst);
        if (xlat_name == NULL)
                xlat_name = cf_section_name1(conf);
-       if (xlat_name){
+       if (xlat_name)
                inst->xlat_name = strdup(xlat_name);
-               xlat_register(xlat_name, mschap_xlat, inst);
-       }
 
        /*
         *      For backwards compatibility
@@ -690,8 +689,8 @@ static void add_reply(VALUE_PAIR** vp, unsigned char ident,
                return;
        }
 
-       reply_attr->strvalue[0] = ident;
-       memcpy(reply_attr->strvalue + 1, value, len);
+       reply_attr->vp_octets[0] = ident;
+       memcpy(reply_attr->vp_octets + 1, value, len);
        reply_attr->length = len + 1;
        pairadd(vp, reply_attr);
 }
@@ -709,7 +708,7 @@ static void mppe_add_reply(VALUE_PAIR **vp,
               return;
        }
 
-       memcpy(reply_attr->strvalue, value, len);
+       memcpy(reply_attr->vp_octets, value, len);
        reply_attr->length = len;
        pairadd(vp, reply_attr);
 }
@@ -767,7 +766,7 @@ static int do_mschap(rlm_mschap_t *inst,
                        return -1;
                }
                
-               smbdes_mschap(password->strvalue, challenge, calculated);
+               smbdes_mschap(password->vp_strvalue, challenge, calculated);
                if (memcmp(response, calculated, 24) != 0) {
                        return -1;
                }
@@ -778,7 +777,7 @@ static int do_mschap(rlm_mschap_t *inst,
                 *      here minimizes work for later.
                 */
                if (password && (password->attribute == PW_NT_PASSWORD)) {
-                       md4_calc(nthashhash, password->strvalue, 16);
+                       md4_calc(nthashhash, password->vp_strvalue, 16);
                } else {
                        memset(nthashhash, 0, 16);
                }
@@ -794,24 +793,9 @@ static int do_mschap(rlm_mschap_t *inst,
                result = radius_exec_program(inst->ntlm_auth, request,
                                             TRUE, /* wait */
                                             buffer, sizeof(buffer),
-                                            NULL, NULL);
+                                            NULL, NULL, 1);
                if (result != 0) {
-                       char *p;
-                       
                        DEBUG2("  rlm_mschap: External script failed.");
-
-                       vp = pairmake("Module-Failure-Message", "", T_OP_EQ);
-                       if (!vp) {
-                               radlog(L_ERR, "No memory");
-                               return -1;
-                       }
-
-                       p = strchr(buffer, '\n');
-                       if (p) *p = '\0';
-                       snprintf(vp->strvalue, sizeof(vp->strvalue), 
-                                "rlm_mschap: %s", buffer);
-                       vp->length = strlen(vp->strvalue);
-                       pairadd(&request->packet->vps, vp);
                        return -1;
                }
 
@@ -838,7 +822,7 @@ static int do_mschap(rlm_mschap_t *inst,
                /*
                 *      Update the NT hash hash, from the NT key.
                 */
-               if (hex2bin(buffer + 8, nthashhash, 16) != 16) {
+               if (lrad_hex2bin(buffer + 8, nthashhash, 16) != 16) {
                        DEBUG2("  rlm_mschap: Invalid output from ntlm_auth: NT_KEY has non-hex values");
                        return -1;
                }
@@ -974,8 +958,7 @@ static void mppe_chap2_gen_keys128(uint8_t *nt_hashhash,uint8_t *response,
 static int mschap_authorize(void * instance, REQUEST *request)
 {
 #define inst ((rlm_mschap_t *)instance)
-       VALUE_PAIR *challenge = NULL;
-       VALUE_PAIR *response = NULL;
+       VALUE_PAIR *challenge = NULL, *response = NULL;
        VALUE_PAIR *vp;
 
        challenge = pairfind(request->packet->vps, PW_MSCHAP_CHALLENGE);
@@ -1020,7 +1003,7 @@ static int mschap_authorize(void * instance, REQUEST *request)
  *
  *     If PW_SMB_ACCOUNT_CTRL is not set to ACB_PWNOTREQ we must have
  *     one of:
- *             PAP:      PW_PASSWORD or
+ *             PAP:      PW_USER_PASSWORD or
  *             MS-CHAP:  PW_MSCHAP_CHALLENGE and PW_MSCHAP_RESPONSE or
  *             MS-CHAP2: PW_MSCHAP_CHALLENGE and PW_MSCHAP2_RESPONSE
  *     In case of password mismatch or locked account we MAY return
@@ -1053,7 +1036,7 @@ static int mschap_authenticate(void * instance, REQUEST *request)
                if (password) {
                        smb_ctrl = pairmake("SMB-Account-CTRL", "0", T_OP_SET);
                        pairadd(&request->config_items, smb_ctrl);
-                       smb_ctrl->lvalue = pdb_decode_acct_ctrl(password->strvalue);
+                       smb_ctrl->lvalue = pdb_decode_acct_ctrl(password->vp_strvalue);
                }
        }
 
@@ -1074,7 +1057,7 @@ static int mschap_authenticate(void * instance, REQUEST *request)
        /*
         *      Decide how to get the passwords.
         */
-       password = pairfind(request->config_items, PW_PASSWORD);
+       password = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);
 
        /*
         *      We need an LM-Password.
@@ -1086,8 +1069,8 @@ static int mschap_authenticate(void * instance, REQUEST *request)
                 */
                if ((lm_password->length == 16) ||
                    ((lm_password->length == 32) &&
-                    (hex2bin(lm_password->strvalue,
-                             lm_password->strvalue, 16) == 16))) {
+                    (lrad_hex2bin(lm_password->vp_strvalue,
+                                  lm_password->vp_strvalue, 16) == 16))) {
                        DEBUG2("  rlm_mschap: Found LM-Password");
                        lm_password->length = 16;
 
@@ -1097,15 +1080,15 @@ static int mschap_authenticate(void * instance, REQUEST *request)
                }
 
        } else if (!password) {
-               DEBUG2("  rlm_mschap: No User-Password configured.  Cannot create LM-Password.");
+               DEBUG2("  rlm_mschap: No Cleartext-Password configured.  Cannot create LM-Password.");
 
-       } else {                /* there is a configured User-Password */
+       } else {                /* there is a configured Cleartext-Password */
                lm_password = pairmake("LM-Password", "", T_OP_EQ);
                if (!lm_password) {
                        radlog(L_ERR, "No memory");
                } else {
-                       smbdes_lmpwdhash(password->strvalue,
-                                      lm_password->strvalue);
+                       smbdes_lmpwdhash(password->vp_strvalue,
+                                      lm_password->vp_strvalue);
                        lm_password->length = 16;
                        pairadd(&request->config_items, lm_password);
                }
@@ -1118,8 +1101,8 @@ static int mschap_authenticate(void * instance, REQUEST *request)
        if (nt_password) {
                if ((nt_password->length == 16) ||
                    ((nt_password->length == 32) &&
-                    (hex2bin(nt_password->strvalue,
-                             nt_password->strvalue, 16) == 16))) {
+                    (lrad_hex2bin(nt_password->vp_strvalue,
+                                  nt_password->vp_strvalue, 16) == 16))) {
                        DEBUG2("  rlm_mschap: Found NT-Password");
                        nt_password->length = 16;
 
@@ -1128,15 +1111,16 @@ static int mschap_authenticate(void * instance, REQUEST *request)
                        nt_password = NULL;
                }
        } else if (!password) {
-               DEBUG2("  rlm_mschap: No User-Password configured.  Cannot create NT-Password.");
+               DEBUG2("  rlm_mschap: No Cleartext-Password configured.  Cannot create NT-Password.");
 
-       } else {                /* there is a configured User-Password */
+       } else {                /* there is a configured Cleartext-Password */
                nt_password = pairmake("NT-Password", "", T_OP_EQ);
                if (!nt_password) {
                        radlog(L_ERR, "No memory");
                        return RLM_MODULE_FAIL;
                } else {
-                       ntpwdhash(nt_password->strvalue, password->strvalue);
+                       ntpwdhash(nt_password->vp_strvalue,
+                                 password->vp_strvalue);
                        nt_password->length = 16;
                        pairadd(&request->config_items, nt_password);
                }
@@ -1179,7 +1163,7 @@ static int mschap_authenticate(void * instance, REQUEST *request)
                 *      We are doing MS-CHAP.  Calculate the MS-CHAP
                 *      response
                 */
-               if (response->strvalue[1] & 0x01) {
+               if (response->vp_octets[1] & 0x01) {
                        DEBUG2("  rlm_mschap: Told to do MS-CHAPv1 with NT-Password");
                        password = nt_password;
                        offset = 26;
@@ -1192,10 +1176,10 @@ static int mschap_authenticate(void * instance, REQUEST *request)
                /*
                 *      Do the MS-CHAP authentication.
                 */
-               if (do_mschap(inst, request, password, challenge->strvalue,
-                             response->strvalue + offset, nthashhash) < 0) {
+               if (do_mschap(inst, request, password, challenge->vp_octets,
+                             response->vp_octets + offset, nthashhash) < 0) {
                        DEBUG2("  rlm_mschap: MS-CHAP-Response is incorrect.");
-                       add_reply(&request->reply->vps, *response->strvalue,
+                       add_reply(&request->reply->vps, *response->vp_octets,
                                  "MS-CHAP-Error", "E=691 R=1", 9);
                        return RLM_MODULE_REJECT;
                }
@@ -1234,15 +1218,15 @@ static int mschap_authenticate(void * instance, REQUEST *request)
                /*
                 *      with_ntdomain_hack moved here
                 */
-               if ((username_string = strchr(username->strvalue, '\\')) != NULL) {
+               if ((username_string = strchr(username->vp_strvalue, '\\')) != NULL) {
                        if (inst->with_ntdomain_hack) {
                                username_string++;
                        } else {
                                DEBUG2("  rlm_mschap: NT Domain delimeter found, should we have enabled with_ntdomain_hack?");
-                               username_string = username->strvalue;
+                               username_string = username->vp_strvalue;
                        }
                } else {
-                       username_string = username->strvalue;
+                       username_string = username->vp_strvalue;
                }
 
                /*
@@ -1252,8 +1236,8 @@ static int mschap_authenticate(void * instance, REQUEST *request)
                 *      MS-CHAPv2 takes some additional data to create an
                 *      MS-CHAPv1 challenge, and then does MS-CHAPv1.
                 */
-               challenge_hash(response->strvalue + 2, /* peer challenge */
-                              challenge->strvalue, /* our challenge */
+               challenge_hash(response->vp_octets + 2, /* peer challenge */
+                              challenge->vp_octets, /* our challenge */
                               username_string, /* user name */
                               mschapv1_challenge); /* resulting challenge */
                
@@ -1261,9 +1245,9 @@ static int mschap_authenticate(void * instance, REQUEST *request)
                       username_string);
 
                if (do_mschap(inst, request, nt_password, mschapv1_challenge,
-                             response->strvalue + 26, nthashhash) < 0) {
+                             response->vp_octets + 26, nthashhash) < 0) {
                        DEBUG2("  rlm_mschap: FAILED: MS-CHAP2-Response is incorrect");
-                       add_reply(&request->reply->vps, *response->strvalue,
+                       add_reply(&request->reply->vps, *response->vp_octets,
                                  "MS-CHAP-Error", "E=691 R=1", 9);
                        return RLM_MODULE_REJECT;
                }
@@ -1276,11 +1260,11 @@ static int mschap_authenticate(void * instance, REQUEST *request)
 
                auth_response(username_string, /* without the domain */
                              nthashhash, /* nt-hash-hash */
-                             response->strvalue + 26, /* peer response */
-                             response->strvalue + 2, /* peer challenge */
-                             challenge->strvalue, /* our challenge */
+                             response->vp_octets + 26, /* peer response */
+                             response->vp_octets + 2, /* peer challenge */
+                             challenge->vp_octets, /* our challenge */
                              msch2resp); /* calculated MPPE key */
-               add_reply( &request->reply->vps, *response->strvalue,
+               add_reply( &request->reply->vps, *response->vp_octets,
                           "MS-CHAP2-Success", msch2resp, 42);
                chap = 2;
 
@@ -1304,7 +1288,7 @@ static int mschap_authenticate(void * instance, REQUEST *request)
                if (((smb_ctrl->lvalue & ACB_DISABLED) != 0) ||
                    ((smb_ctrl->lvalue & ACB_NORMAL) == 0)) {
                        DEBUG2("  rlm_mschap: SMB-Account-Ctrl says that the account is disabled, or is not a normal account.");
-                       add_reply( &request->reply->vps, *response->strvalue,
+                       add_reply( &request->reply->vps, *response->vp_octets,
                                   "MS-CHAP-Error", "E=691 R=1", 9);
                        return RLM_MODULE_NOTFOUND;
                }
@@ -1314,7 +1298,7 @@ static int mschap_authenticate(void * instance, REQUEST *request)
                 */
                if ((smb_ctrl->lvalue & ACB_AUTOLOCK) != 0) {
                        DEBUG2("  rlm_mschap: SMB-Account-Ctrl says that the account is locked out.");
-                       add_reply( &request->reply->vps, *response->strvalue,
+                       add_reply( &request->reply->vps, *response->vp_octets,
                                   "MS-CHAP-Error", "E=647 R=0", 9);
                        return RLM_MODULE_USERLOCK;
                }
@@ -1329,7 +1313,7 @@ static int mschap_authenticate(void * instance, REQUEST *request)
                        DEBUG2("rlm_mschap: adding MS-CHAPv1 MPPE keys");
                        memset(mppe_sendkey, 0, 32);
                        if (lm_password) {
-                               memcpy(mppe_sendkey, lm_password->strvalue, 8);
+                               memcpy(mppe_sendkey, lm_password->vp_octets, 8);
                        }
 
                        /*
@@ -1352,7 +1336,7 @@ static int mschap_authenticate(void * instance, REQUEST *request)
                } else if (chap == 2) {
                        DEBUG2("rlm_mschap: adding MS-CHAPv2 MPPE keys");
                        mppe_chap2_gen_keys128(nthashhash,
-                                              response->strvalue + 26,
+                                              response->vp_octets + 26,
                                               mppe_sendkey, mppe_recvkey);
                        
                        mppe_add_reply(&request->reply->vps,
@@ -1381,20 +1365,19 @@ static int mschap_authenticate(void * instance, REQUEST *request)
 }
 
 module_t rlm_mschap = {
-  "MS-CHAP",
-  RLM_TYPE_THREAD_SAFE,                /* type */
-  NULL,                                /* initialize */
-  mschap_instantiate,          /* instantiation */
-  {
-         mschap_authenticate,  /* authenticate */
-         mschap_authorize,     /* authorize */
-         NULL,                 /* pre-accounting */
-         NULL,                 /* accounting */
-         NULL,                 /* checksimul */
-         NULL,                 /* pre-proxy */
-         NULL,                 /* post-proxy */
-         NULL                  /* post-auth */
-  },
-  mschap_detach,               /* detach */
-  NULL,                                /* destroy */
+       RLM_MODULE_INIT,
+       "MS-CHAP",
+       RLM_TYPE_THREAD_SAFE,           /* type */
+       mschap_instantiate,             /* instantiation */
+       mschap_detach,          /* detach */
+       {
+               mschap_authenticate,    /* authenticate */
+               mschap_authorize,       /* authorize */
+               NULL,                   /* pre-accounting */
+               NULL,                   /* accounting */
+               NULL,                   /* checksimul */
+               NULL,                   /* pre-proxy */
+               NULL,                   /* post-proxy */
+               NULL                    /* post-auth */
+       },
 };
index 1031467..b7614fe 100644 (file)
@@ -19,6 +19,8 @@
    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+   Copyright 2006 The FreeRADIUS server project
 */
 
 
    should confirm it for yourself (and maybe let me know if you come
    up with a different answer to the one above)
 */
-#include "libradius.h"
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <string.h>
 #include <ctype.h>
 
index 63f1adc..ba1d4bc 100644 (file)
@@ -1,6 +1,11 @@
+/* Copyright 2006 The FreeRADIUS server project */
+
 #ifndef _SMBDES_H
 #define _SMBDES_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(smbdes_h, "$Id$")
+
 void smbdes_lmpwdhash(const unsigned char *password,unsigned char *lmhash);
 void smbdes_mschap(const unsigned char *win_password,
                 const unsigned char *challenge, unsigned char *response);
index 601a580..90150f9 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2002  3APA3A for FreeRADIUS project
+   Copyright 2006  The FreeRADIUS server project
  */
 
-#include       "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include       <freeradius-devel/autoconf.h>
 #include        <stdio.h>
 #include        <stdlib.h>
 #include        <string.h>
 #include        <ctype.h>
 
-#include        "md4.h"
+#include        <freeradius-devel/md4.h>
 
 #include       "smbdes.h"
 
diff --git a/src/modules/rlm_ns_mta_md5/Makefile b/src/modules/rlm_ns_mta_md5/Makefile
deleted file mode 100644 (file)
index bda32e0..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-TARGET = rlm_ns_mta_md5
-SRCS   = rlm_ns_mta_md5.c
-
-include ../rules.mak
diff --git a/src/modules/rlm_ns_mta_md5/rlm_ns_mta_md5.c b/src/modules/rlm_ns_mta_md5/rlm_ns_mta_md5.c
deleted file mode 100644 (file)
index 53831b9..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * rlm_ns_mta_md5.c    Functions to authenticate using NS-MTA-MD5 passwords.
- *             Taken from the hacks for qmail located at nrg4u.com
- *             by Andre Oppermann.
- *
- *             NS-MTA-MD5 passwords are 64 byte strings, the first
- *             32 bytes being the password hash and the last 32 bytes
- *             the salt.  The clear text password and the salt are MD5
- *             hashed[1].  If the resulting hash concatenated with the salt
- *             are equivalent to the original NS-MTA-MD5 password the
- *             password is correct.
- *
- *             [1] Read the source for details.
- *
- *             bob Auth-Type := NS-MTA-MD5, NS-MTA-MD5-Password := "f8b4eac9f051a61eebe266f9c29a193626d8eb25c2598c55c8874260b24eb435"
- *                 Reply-Message = "NS-MTA-MD5 is working!"
- *             password = "testpass".
- *
- *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Copyright 2000  The FreeRADIUS server project
- * Copyright 2000  Andre Oppermann
- */
-
-
-static const char rcsid[] = "$Id$";
-
-#include "autoconf.h"
-#include "libradius.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "radiusd.h"
-#include "modules.h"
-#include "md5.h"
-
-#define HASH_LEN 100
-
-static const char *ns_mta_hextab = "0123456789abcdef";
-
-/*
- *  Smaller & faster than snprintf("%x");
- */
-static void ns_mta_hexify(char *buffer, char *str, int len)
-{
-  char *pch = str;
-  char ch;
-  int i;
-
-  for(i = 0;i < len; i ++) {
-    ch = pch[i];
-    buffer[2*i] = ns_mta_hextab[(ch>>4) & 15];
-    buffer[2*i + 1] = ns_mta_hextab[ch & 15];
-  }
-  return;
-}
-
-/*
- *     Do the hash.
- */
-static char *ns_mta_hash_alg(char *buffer, const char *salt, const char *passwd)
-{
-  MD5_CTX context;
-  char saltstr[2048];
-  unsigned char digest[16];
-
-  snprintf(saltstr, sizeof(saltstr), "%s%c%s%c%s",salt, 89, passwd, 247, salt);
-
-  MD5Init(&context);
-  MD5Update(&context,(unsigned char *)saltstr,strlen(saltstr));
-  MD5Final(digest,&context);
-  ns_mta_hexify(buffer,(char*)digest,16);
-  buffer[32] = '\0';
-  return(buffer);
-}
-
-/*
- *  Take the clear
- */
-static int ns_mta_md5_pass(const char *clear, const char *encrypted)
-{
-  char hashed[HASH_LEN];
-  char salt[33];
-
-  if (!(strlen(encrypted) == 64)) {
-    DEBUG2("NS-MTA-MD5 hash not 64 bytes");
-    return -1;
-  }
-
-  memcpy(salt, &encrypted[32], 32);
-  salt[32] = 0;
-  ns_mta_hash_alg(hashed, salt, clear);
-  memcpy(&hashed[32], salt, 33);
-
-  if (strcasecmp(hashed,encrypted) == 0) {
-    return 0;
-  }
-
-  return -1;
-}
-
-/*
- *  Validate User-Name / Passwd
- */
-static int module_auth(void *instance, REQUEST *request)
-{
-       VALUE_PAIR *md5_password;
-
-       /*
-        *      We can only authenticate user requests which HAVE
-        *      a User-Password attribute.
-        */
-       if (!request->password) {
-               radlog(L_AUTH, "rlm_ns_mta_md5: Attribute \"User-Password\" is required for authentication.");
-               return RLM_MODULE_INVALID;
-       }
-
-       /*
-        *  Ensure that we're being passed a plain-text password,
-        *  and not anything else.
-        */
-       if (request->password->attribute != PW_PASSWORD) {
-               radlog(L_AUTH, "rlm_ns_mta_md5: Attribute \"User-Password\" is required for authentication.  Cannot use \"%s\".", request->password->name);
-               return RLM_MODULE_INVALID;
-       }
-
-       /*
-        *  Find the MD5 encrypted password
-        */
-       md5_password = pairfind(request->config_items, PW_NS_MTA_MD5_PASSWORD);
-       if (!md5_password) {
-               radlog(L_AUTH, "rlm_ns_mta_md5: Cannot find NS-MTA-MD5-Password attribute.");
-               return RLM_MODULE_INVALID;
-       }
-
-       /*
-        *  Check their password against the encrypted one.
-        */
-       if (ns_mta_md5_pass(request->password->strvalue,
-                           md5_password->strvalue) < 0) {
-               return RLM_MODULE_REJECT;
-       }
-
-       return RLM_MODULE_OK;
-}
-
-module_t rlm_ns_mta_md5 = {
-  "NS-MTA-MD5",
-  0,                           /* type: reserved */
-  NULL,                                /* initialize */
-  NULL,                                /* instantiation */
-  {
-         module_auth,          /* authenticate */
-         NULL,                 /* authorize */
-         NULL,                 /* pre-accounting */
-         NULL,                 /* accounting */
-         NULL,                 /* checksimul */
-         NULL,                 /* pre-proxy */
-         NULL,                 /* post-proxy */
-         NULL                  /* post-auth */
-  },
-  NULL,                                /* detach */
-  NULL,                                /* destroy */
-};
index ca728dd..75e923e 100644 (file)
@@ -23,7 +23,7 @@
 TARGET         = @targetname@
 SRCS           = otp_rlm.c otp_radstate.c otp_pwe.c otp_pw_valid.c
 SRCS          += otp_util.c otp_mppe.c
-HEADERS        = extern.h otp_pw_valid.h otp_mppe.h ident.h
+HEADERS        = extern.h otp_pw_valid.h otp_mppe.h
 RLM_CFLAGS     = @otp_cflags@ $(OPENSSL_INCLUDE)
 RLM_LIBS       = @otp_ldflags@ $(OPENSSL_LIBS)
 
index 74a87c4..3a6231b 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.1.2.5 .
+# From configure.in Revision: 1.4 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
index 4dcd5f6..5fad0cb 100644 (file)
 #ifndef EXTERN_H
 #define EXTERN_H
 
-#include "ident.h"
+#include <freeradius-devel/ident.h>
 RCSIDH(extern_h, "$Id$")
 
-#include <autoconf.h>
-#include <radiusd.h>
-#include <modules.h>
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 #include <sys/types.h>
 #include <pthread.h>
index defe016..fe2b029 100644 (file)
@@ -21,8 +21,8 @@
 #ifndef OTP_H
 #define OTP_H
 
-#include "ident.h"
-RCSIDH(otp_h, "$Id$");
+#include <freeradius-devel/ident.h>
+RCSIDH(otp_h, "$Id$")
 
 #include <sys/types.h>
 
index 112edb4..f4199f6 100644 (file)
  * Copyright 2005,2006 TRI-D Systems, Inc.
  */
 
-#include "ident.h"
+#include <freeradius-devel/ident.h>
 RCSID("$Id$")
 
 /* avoid inclusion of these FR headers which conflict w/ OpenSSL */
 #define _LRAD_MD4_H
 #define _LRAD_SHA1_H
 
-#include <rad_assert.h>
+#include <freeradius-devel/rad_assert.h>
 
 #include "extern.h"
 #include "otp.h"
@@ -178,7 +178,7 @@ otp_mppe(REQUEST *request, otp_pwe_t pwe, const otp_option_t *opt,
       /*                    0x  (ID) ( ASCII("S="ASCII(auth_md))) */
       char auth_octet_string[2 + 2 + (2 * sizeof(auth_md_string))];
 
-      char *username = request->username->strvalue;
+      char *username = request->username->vp_strvalue;
       int username_len = request->username->length;
 
       /* "Magic server to client signing constant" */
@@ -215,14 +215,14 @@ otp_mppe(REQUEST *request, otp_pwe_t pwe, const otp_option_t *opt,
       /* MD1 */
       SHA1_Init(&ctx);
       SHA1_Update(&ctx, password_md_md, MD4_DIGEST_LENGTH);
-      SHA1_Update(&ctx, rvp->strvalue + 26, 24);
+      SHA1_Update(&ctx, rvp->vp_strvalue + 26, 24);
       SHA1_Update(&ctx, magic1, sizeof(magic1));
       SHA1_Final(md1, &ctx);
 
       /* MD2 */
       SHA1_Init(&ctx);
-      SHA1_Update(&ctx, rvp->strvalue + 2, 16);
-      SHA1_Update(&ctx, cvp->strvalue, 16);
+      SHA1_Update(&ctx, rvp->vp_strvalue + 2, 16);
+      SHA1_Update(&ctx, cvp->vp_strvalue, 16);
       SHA1_Update(&ctx, username, username_len);
       SHA1_Final(md2, &ctx);
 
@@ -242,7 +242,7 @@ otp_mppe(REQUEST *request, otp_pwe_t pwe, const otp_option_t *opt,
       /* And then octet conversion.  Ugh! */
       auth_octet_string[0] = '0';
       auth_octet_string[1] = 'x';
-      (void) sprintf(&auth_octet_string[2], "%02X", rvp->strvalue[0]);
+      (void) sprintf(&auth_octet_string[2], "%02X", rvp->vp_strvalue[0]);
       for (i = 0; i < sizeof(auth_md_string) - 1; ++i)
         (void) sprintf(&auth_octet_string[i * 2 +4], "%02X", auth_md_string[i]);
 
@@ -357,7 +357,7 @@ otp_mppe(REQUEST *request, otp_pwe_t pwe, const otp_option_t *opt,
       /* Generate the master session key. */
       SHA1_Init(&ctx);
       SHA1_Update(&ctx, password_md_md, MD4_DIGEST_LENGTH);
-      SHA1_Update(&ctx, rvp->strvalue + 26, 24);
+      SHA1_Update(&ctx, rvp->vp_strvalue + 26, 24);
       SHA1_Update(&ctx, Magic1, sizeof(Magic1));
       SHA1_Final(sha_md, &ctx);
       (void) memcpy(MasterKey, sha_md, 16);
index 2b55535..e1f8452 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef OTP_MPPE_H
 #define OTP_MPPE_H
 
-#include "ident.h"
+#include <freeradius-devel/ident.h>
 RCSIDH(otp_mppe_h, "$Id$")
 
 /* Some hardcoding here ... because not all types have #defines */
index ba6709e..a036231 100644 (file)
  * Copyright 2006 TRI-D Systems, Inc.
  */
 
-#include "ident.h"
+#include <freeradius-devel/ident.h>
 RCSID("$Id$")
 
-#include "autoconf.h"
-#include "radiusd.h"
-#include "modules.h"
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 #include "extern.h"
 #include "otp.h"
@@ -80,7 +80,7 @@ otp_pw_valid(REQUEST *request, int pwe, const char *challenge,
   otp_request_t        otp_request;
   otp_reply_t  otp_reply;
   VALUE_PAIR   *cvp, *rvp;
-  char         *username = request->username->strvalue;
+  char         *username = request->username->vp_strvalue;
   int          rc;
 
   if (request->username->length > OTP_MAX_USERNAME_LEN) {
@@ -108,7 +108,7 @@ otp_pw_valid(REQUEST *request, int pwe, const char *challenge,
       (void) radlog(L_AUTH, "rlm_otp: passcode for [%s] too long", username);
       return RLM_MODULE_REJECT;
     }
-    (void) strcpy(otp_request.pwe.passcode, rvp->strvalue);
+    (void) strcpy(otp_request.pwe.passcode, rvp->vp_strvalue);
     break;
 
   case PWE_CHAP:
@@ -122,9 +122,9 @@ otp_pw_valid(REQUEST *request, int pwe, const char *challenge,
                     username);
       return RLM_MODULE_INVALID;
     }
-    (void) memcpy(otp_request.pwe.challenge, cvp->strvalue, cvp->length);
+    (void) memcpy(otp_request.pwe.challenge, cvp->vp_strvalue, cvp->length);
     otp_request.pwe.clen = cvp->length;
-    (void) memcpy(otp_request.pwe.response, rvp->strvalue, rvp->length);
+    (void) memcpy(otp_request.pwe.response, rvp->vp_strvalue, rvp->length);
     otp_request.pwe.rlen = rvp->length;
     break;
 
@@ -139,9 +139,9 @@ otp_pw_valid(REQUEST *request, int pwe, const char *challenge,
                     username);
       return RLM_MODULE_INVALID;
     }
-    (void) memcpy(otp_request.pwe.challenge, cvp->strvalue, cvp->length);
+    (void) memcpy(otp_request.pwe.challenge, cvp->vp_strvalue, cvp->length);
     otp_request.pwe.clen = cvp->length;
-    (void) memcpy(otp_request.pwe.response, rvp->strvalue, rvp->length);
+    (void) memcpy(otp_request.pwe.response, rvp->vp_strvalue, rvp->length);
     otp_request.pwe.rlen = rvp->length;
     break;
 
@@ -156,9 +156,9 @@ otp_pw_valid(REQUEST *request, int pwe, const char *challenge,
                     username);
       return RLM_MODULE_INVALID;
     }
-    (void) memcpy(otp_request.pwe.challenge, cvp->strvalue, cvp->length);
+    (void) memcpy(otp_request.pwe.challenge, cvp->vp_strvalue, cvp->length);
     otp_request.pwe.clen = cvp->length;
-    (void) memcpy(otp_request.pwe.response, rvp->strvalue, rvp->length);
+    (void) memcpy(otp_request.pwe.response, rvp->vp_strvalue, rvp->length);
     otp_request.pwe.rlen = rvp->length;
     break;
   } /* switch (otp_request.pwe.pwe) */
index ab8dc63..0d9ba6b 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef OTP_PW_VALID_H
 #define OTP_PW_VALID_H
 
-#include "ident.h"
+#include <freeradius-devel/ident.h>
 RCSIDH(otp_pw_valid_h, "$Id$")
 
 #include <pthread.h>
index f0c9b99..0227918 100644 (file)
  * is not sufficient for X9.9 use.
  */
 
-#include "ident.h"
+#include <freeradius-devel/ident.h>
 RCSID("$Id$")
 
 /* avoid inclusion of these FR headers which conflict w/ OpenSSL */
 #define _LRAD_MD4_H
 #define _LRAD_SHA1_H
-#include <rad_assert.h>
-#include <autoconf.h>
-#include <radiusd.h>
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/radiusd.h>
 
 #include "extern.h"
 
index ad96bf8..6b8f632 100644 (file)
@@ -19,7 +19,7 @@
  * Copyright 2005,2006 TRI-D Systems, Inc.
  */
 
-#include "ident.h"
+#include <freeradius-devel/ident.h>
 RCSID("$Id$")
 
 /* avoid inclusion of these FR headers which conflict w/ OpenSSL */
index 058ddea..a487d8a 100644 (file)
  * Copyright 2005,2006 TRI-D Systems, Inc.
  */
 
-#include "ident.h"
+#include <freeradius-devel/ident.h>
 RCSID("$Id$")
 
-#include <autoconf.h>
-#include <radiusd.h>
-#include <modules.h>
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 #include "extern.h"
 #include "otp.h"
@@ -192,7 +192,7 @@ otp_authorize(void *instance, REQUEST *request)
     auth_type_found = 0;
     if ((vp = pairfind(request->config_items, PW_AUTHTYPE)) != NULL) {
       auth_type_found = 1;
-      if (strcmp(vp->strvalue, inst->name))
+      if (strcmp(vp->vp_strvalue, inst->name))
         return RLM_MODULE_NOOP;
     }
   }
@@ -306,7 +306,7 @@ otp_authenticate(void *instance, REQUEST *request)
                   __func__);
     return RLM_MODULE_INVALID;
   }
-  username = request->username->strvalue;
+  username = request->username->vp_strvalue;
 
   if ((pwe = otp_pwe_present(request)) == 0) {
     (void) radlog(L_AUTH, "rlm_otp: %s: Attribute \"User-Password\" "
@@ -343,7 +343,7 @@ otp_authenticate(void *instance, REQUEST *request)
      */
 
     /* ASCII decode; this is why OTP_MAX_RADSTATE_LEN has +1 */
-    (void) memcpy(rad_state, vp->strvalue, vp->length);
+    (void) memcpy(rad_state, vp->vp_strvalue, vp->length);
     rad_state[e_length] = '\0';
     if (otp_a2x(rad_state, raw_state) == -1) {
       (void) radlog(L_AUTH, "rlm_otp: %s: bad radstate for [%s]: not hex",
@@ -364,7 +364,7 @@ otp_authenticate(void *instance, REQUEST *request)
       return RLM_MODULE_FAIL;
     }
     /* compare generated state against returned state to verify hmac */
-    if (memcmp(state, vp->strvalue, vp->length)) {
+    if (memcmp(state, vp->vp_strvalue, vp->length)) {
       (void) radlog(L_AUTH, "rlm_otp: %s: bad radstate for [%s]: hmac",
                     __func__, username);
       return RLM_MODULE_REJECT;
@@ -396,8 +396,6 @@ otp_detach(void *instance)
 {
   otp_option_t *inst = (otp_option_t *) instance;
 
-  free(inst->otpd_rp);
-  free(inst->chal_prompt);
   free(instance);
   /*
    * Only the main thread instantiates and detaches instances,
@@ -417,10 +415,11 @@ otp_detach(void *instance)
  *     is single-threaded.
  */
 module_t rlm_otp = {
+  RLM_MODULE_INIT,
   "otp",
   RLM_TYPE_THREAD_SAFE,                /* type */
-  NULL,
   otp_instantiate,             /* instantiation */
+  otp_detach,                  /* detach */
   {
     otp_authenticate,          /* authentication */
     otp_authorize,             /* authorization */
@@ -431,6 +430,4 @@ module_t rlm_otp = {
     NULL,                      /* post-proxy */
     NULL                       /* post-auth */
   },
-  otp_detach,                  /* detach */
-  NULL,
 };
index 45f6c8e..4c596fb 100644 (file)
@@ -19,7 +19,7 @@
  * Copyright 2005,2006 TRI-D Systems, Inc.
  */
 
-#include "ident.h"
+#include <freeradius-devel/ident.h>
 RCSID("$Id$")
 
 #include "extern.h"
index 5500f7e..69ae66b 100644 (file)
@@ -1,15 +1,52 @@
-/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
-/*
+/* config.h.in.  Generated from configure.in by autoheader.  */
 
-acconfig.h - template used by autoheader to create config.h.in
-config.h.in - used by autoconf to create config.h
-config.h - created by autoconf; contains defines generated by autoconf
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
 
-*/
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
 
-
-/* Define if you have the <pam/pam_appl.h> header file.  */
+/* Define to 1 if you have the <pam/pam_appl.h> header file. */
 #undef HAVE_PAM_PAM_APPL_H
 
-/* Define if you have the <security/pam_appl.h> header file.  */
+/* Define to 1 if you have the <security/pam_appl.h> header file. */
 #undef HAVE_SECURITY_PAM_APPL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
index 5c9f47d..454059f 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.5 .
+# From configure.in Revision: 1.6 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -938,7 +938,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1858,8 +1858,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1917,8 +1916,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2034,8 +2032,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2089,8 +2086,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2135,8 +2131,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2180,8 +2175,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2494,8 +2488,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2565,8 +2558,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2647,8 +2639,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2818,8 +2809,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2890,8 +2880,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3820,11 +3809,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3863,6 +3847,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 3633f17..3b773e1 100644 (file)
@@ -1,3 +1,4 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_pam.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_pam])
index 016622f..1e7a289 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 1997  Jeph Blaize <jblaize@kiva.net>
  * Copyright 1999  miguel a.l. paraz <map@iphil.net>
  */
 
-#include       "autoconf.h"
-#include       "libradius.h"
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include       <freeradius-devel/autoconf.h>
 
 #include       "config.h"
 
 #include       <syslog.h>
 #endif
 
-#include       "radiusd.h"
-#include       "modules.h"
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/modules.h>
 
 typedef struct rlm_pam_t {
        const char *pam_auth_name;
 } rlm_pam_t;
 
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
        { "pam_auth",    PW_TYPE_STRING_PTR, offsetof(rlm_pam_t,pam_auth_name),
          NULL, "radiusd" },
        { NULL, -1, 0, NULL, NULL }
@@ -92,7 +94,6 @@ static int pam_detach(void *instance)
 {
        rlm_pam_t *data = (rlm_pam_t *) instance;
 
-       free((char *) data->pam_auth_name);
         free((char *) data);
        return 0;
 }
@@ -262,7 +263,7 @@ static int pam_auth(void *instance, REQUEST *request)
         *  Ensure that we're being passed a plain-text password,
         *  and not anything else.
         */
-       if (request->password->attribute != PW_PASSWORD) {
+       if (request->password->attribute != PW_USER_PASSWORD) {
                radlog(L_AUTH, "rlm_pam: Attribute \"User-Password\" is required for authentication.  Cannot use \"%s\".", request->password->name);
                return RLM_MODULE_INVALID;
        }
@@ -272,15 +273,15 @@ static int pam_auth(void *instance, REQUEST *request)
         *      for backwards compatibility.
         */
        pair = pairfind(request->config_items, PAM_AUTH_ATTR);
-       if (pair) pam_auth_string = (char *)pair->strvalue;
+       if (pair) pam_auth_string = (char *)pair->vp_strvalue;
 
-       r = pam_pass((char *)request->username->strvalue,
-                    (char *)request->password->strvalue,
+       r = pam_pass((char *)request->username->vp_strvalue,
+                    (char *)request->password->vp_strvalue,
                     pam_auth_string);
 
 #ifdef HAVE_SYSLOG_H
        if (!strcmp(radlog_dir, "syslog")) {
-               openlog(progname, LOG_PID, syslog_facility);
+               openlog(progname, LOG_PID, mainconfig.syslog_facility);
        }
 #endif
 
@@ -291,21 +292,20 @@ static int pam_auth(void *instance, REQUEST *request)
 }
 
 module_t rlm_pam = {
-  "Pam",
-  RLM_TYPE_THREAD_UNSAFE,      /* The PAM libraries are not thread-safe */
-  NULL,                                /* initialize */
-  pam_instantiate,             /* instantiation */
-  {
-         pam_auth,             /* authenticate */
-         NULL,                 /* authorize */
-         NULL,                 /* pre-accounting */
-         NULL,                 /* accounting */
-         NULL,                 /* checksimul */
-         NULL,                 /* pre-proxy */
-         NULL,                 /* post-proxy */
-         NULL                  /* post-auth */
-  },
-  pam_detach,                  /* detach */
-  NULL,                                /* destroy */
+       RLM_MODULE_INIT,
+       "pam",
+       RLM_TYPE_THREAD_UNSAFE, /* The PAM libraries are not thread-safe */
+       pam_instantiate,                /* instantiation */     
+       pam_detach,                     /* detach */
+       {
+               pam_auth,               /* authenticate */
+               NULL,                   /* authorize */
+               NULL,                   /* pre-accounting */
+               NULL,                   /* accounting */
+               NULL,                   /* checksimul */
+               NULL,                   /* pre-proxy */
+               NULL,                   /* post-proxy */
+               NULL                    /* post-auth */
+       },
 };
 
index 754b0ea..504df4d 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2001  The FreeRADIUS server project
+ * Copyright 2001,2006  The FreeRADIUS server project
  * Copyright 2001  Kostas Kalevras <kkalev@noc.ntua.gr>
  */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <ctype.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 #include "../../include/md5.h"
 #include "../../include/sha1.h"
 
@@ -49,8 +51,6 @@
 #define PAP_MAX_ENC            9
 
 
-static const char rcsid[] = "$Id$";
-
 /*
  *      Define a structure for our module configuration.
  *
@@ -75,10 +75,10 @@ typedef struct rlm_pap_t {
  *      to the strdup'd string into 'config.string'.  This gets around
  *      buffer over-flows.
  */
-static CONF_PARSER module_config[] = {
-  { "encryption_scheme", PW_TYPE_STRING_PTR, offsetof(rlm_pap_t,scheme), NULL, "crypt" },
+static const CONF_PARSER module_config[] = {
+       { "encryption_scheme", PW_TYPE_STRING_PTR, offsetof(rlm_pap_t,scheme), NULL, "auto" },
        { "auto_header", PW_TYPE_BOOLEAN, offsetof(rlm_pap_t,auto_header), NULL, "no" },
-  { NULL, -1, 0, NULL, NULL }
+       { NULL, -1, 0, NULL, NULL }
 };
 
 static const LRAD_NAME_NUMBER schemes[] = {
@@ -117,7 +117,6 @@ static int pap_detach(void *instance)
 {
        rlm_pap_t *inst = (rlm_pap_t *) instance;
 
-       free((char *)inst->scheme);
        free(inst);
 
        return 0;
@@ -142,10 +141,9 @@ static int pap_instantiate(CONF_SECTION *conf, void **instance)
          *      fail.
          */
         if (cf_section_parse(conf, inst, module_config) < 0) {
-                pap_detach(inst);
+               pap_detach(inst);
                 return -1;
         }
-
        if (inst->scheme == NULL || strlen(inst->scheme) == 0){
                radlog(L_ERR, "rlm_pap: No scheme defined");
                pap_detach(inst);
@@ -208,7 +206,7 @@ static int base64_decode (const char *src, uint8_t *dst)
 {
        int length, equals;
        int i, num;
-       uint8_t last[3];
+       char last[3];
 
        length = equals = 0;
        while (src[length] && src[length] != '=') length++;
@@ -246,10 +244,10 @@ static void normify(VALUE_PAIR *vp, int min_length)
         *      Hex encoding.
         */
        if (vp->length >= (2 * min_length)) {
-               decoded = lrad_hex2bin(vp->strvalue, buffer, vp->length >> 1);
+               decoded = lrad_hex2bin(vp->vp_octets, buffer, vp->length >> 1);
                if (decoded == (vp->length >> 1)) {
                        DEBUG2("rlm_pap: Normalizing %s from hex encoding", vp->name);
-                       memcpy(vp->strvalue, buffer, decoded);
+                       memcpy(vp->vp_octets, buffer, decoded);
                        vp->length = decoded;
                        return;
                }
@@ -260,10 +258,10 @@ static void normify(VALUE_PAIR *vp, int min_length)
         *      and we want to avoid division...
         */
        if ((vp->length * 3) >= ((min_length * 4))) {
-               decoded = base64_decode(vp->strvalue, buffer);
+               decoded = base64_decode(vp->vp_octets, buffer);
                if (decoded >= min_length) {
                        DEBUG2("rlm_pap: Normalizing %s from base64 encoding", vp->name);
-                       memcpy(vp->strvalue, buffer, decoded);
+                       memcpy(vp->vp_octets, buffer, decoded);
                        vp->length = decoded;
                        return;
                }
@@ -286,23 +284,20 @@ static int pap_authorize(void *instance, REQUEST *request)
        rlm_pap_t *inst = instance;
        int auth_type = FALSE;
        int found_pw = FALSE;
-       int user_pw = FALSE;
        VALUE_PAIR *vp, *next;
-       VALUE_PAIR *cleartext_pw = NULL;
 
        for (vp = request->config_items; vp != NULL; vp = next) {
                next = vp->next;
 
                switch (vp->attribute) {
                case PW_USER_PASSWORD: /* deprecated */
-                       user_pw = TRUE;
                        found_pw = TRUE;
 
                        /*
                         *      Look for '{foo}', and use them
                         */
                        if (!inst->auto_header ||
-                           (vp->strvalue[0] != '{')) {
+                           (vp->vp_strvalue[0] != '{')) {
                                break;
                        }
                        /* FALL-THROUGH */
@@ -315,7 +310,7 @@ static int pap_authorize(void *instance, REQUEST *request)
                        VALUE_PAIR *new_vp;
                        
                        found_pw = TRUE;
-                       q = vp->strvalue;
+                       q = vp->vp_strvalue;
                        p = strchr(q + 1, '}');
                        if (!p) {
                                /*
@@ -341,8 +336,8 @@ static int pap_authorize(void *instance, REQUEST *request)
                        new_vp = paircreate(attr, PW_TYPE_STRING);
                        if (!new_vp) break; /* OOM */
                        
-                       strcpy(new_vp->strvalue, p + 1);/* bounds OK */
-                       new_vp->length = strlen(new_vp->strvalue);
+                       strcpy(new_vp->vp_strvalue, p + 1);/* bounds OK */
+                       new_vp->length = strlen(new_vp->vp_strvalue);
                        pairadd(&request->config_items, new_vp);
 
                        /*
@@ -356,8 +351,6 @@ static int pap_authorize(void *instance, REQUEST *request)
                        break;
 
                case PW_CLEARTEXT_PASSWORD:
-                       cleartext_pw = vp;
-
                case PW_CRYPT_PASSWORD:
                case PW_NS_MTA_MD5_PASSWORD:
                        found_pw = TRUE;
@@ -383,9 +376,10 @@ static int pap_authorize(void *instance, REQUEST *request)
                         */
                case PW_PROXY_TO_REALM:
                {
-                       REALM *realm = realm_find(vp->strvalue, 0);
+                       REALM *realm = realm_find(vp->vp_strvalue, 0);
                        if (realm &&
-                           (realm->ipaddr != htonl(INADDR_NONE))) {
+                           (realm->ipaddr.af == AF_INET) &&
+                           (realm->ipaddr.ipaddr.ip4addr.s_addr != htonl(INADDR_NONE))) {
                                return RLM_MODULE_NOOP;
                        }
                        break;
@@ -419,19 +413,6 @@ static int pap_authorize(void *instance, REQUEST *request)
        }
 
        /*
-        *      For backwards compatibility with all of the other
-        *      modules, copy Cleartext-Password to User-Password
-        */
-       if (cleartext_pw && !user_pw) {
-               vp = paircreate(PW_USER_PASSWORD, PW_TYPE_STRING);
-               if (!vp) return RLM_MODULE_FAIL;
-
-               memcpy(vp, cleartext_pw, sizeof(*vp));
-               vp->next = NULL;
-               pairadd(&request->config_items, vp);
-       }
-
-       /*
         *      Don't touch existing Auth-Types.
         */
        if (auth_type) {
@@ -506,13 +487,13 @@ static int pap_authenticate(void *instance, REQUEST *request)
        }
 
        DEBUG("rlm_pap: login attempt with password %s",
-             request->password->strvalue);
+             request->password->vp_strvalue);
 
        /*
         *      First, auto-detect passwords, by attribute in the
         *      config items.
         */
-       if ((inst->sch == PAP_ENC_AUTO) || inst->auto_header) {
+       if (inst->sch == PAP_ENC_AUTO) {
                for (vp = request->config_items; vp != NULL; vp = vp->next) {
                        switch (vp->attribute) {
                        case PW_USER_PASSWORD: /* deprecated */
@@ -567,7 +548,6 @@ static int pap_authenticate(void *instance, REQUEST *request)
                        vp = pairfind(request->config_items, PW_USER_PASSWORD);
                        if (!vp) goto fail;
                }
-               scheme = inst->sch;
        }
 
        /*
@@ -576,9 +556,9 @@ static int pap_authenticate(void *instance, REQUEST *request)
        switch (scheme) {
        case PAP_ENC_CLEAR:
        do_clear:
-               DEBUG("rlm_pap: Using clear text password \"%s\".", vp->strvalue);
-               if (strcmp((char *) vp->strvalue,
-                          (char *) request->password->strvalue) != 0){
+               DEBUG("rlm_pap: Using clear text password.");
+               if (strcmp((char *) vp->vp_strvalue,
+                          (char *) request->password->vp_strvalue) != 0){
                        snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: CLEAR TEXT password check failed");
                        goto make_msg;
                }
@@ -590,8 +570,8 @@ static int pap_authenticate(void *instance, REQUEST *request)
        case PAP_ENC_CRYPT:
        do_crypt:
                DEBUG("rlm_pap: Using CRYPT encryption.");
-               if (lrad_crypt_check((char *) request->password->strvalue,
-                                    (char *) vp->strvalue) != 0) {
+               if (lrad_crypt_check((char *) request->password->vp_strvalue,
+                                    (char *) vp->vp_strvalue) != 0) {
                        snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: CRYPT password check failed");
                        goto make_msg;
                }
@@ -610,10 +590,10 @@ static int pap_authenticate(void *instance, REQUEST *request)
                }
                
                MD5Init(&md5_context);
-               MD5Update(&md5_context, request->password->strvalue,
+               MD5Update(&md5_context, request->password->vp_strvalue,
                          request->password->length);
                MD5Final(digest, &md5_context);
-               if (memcmp(digest, vp->strvalue, vp->length) != 0) {
+               if (memcmp(digest, vp->vp_octets, vp->length) != 0) {
                        snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: MD5 password check failed");
                        goto make_msg;
                }
@@ -632,15 +612,15 @@ static int pap_authenticate(void *instance, REQUEST *request)
                }
                
                MD5Init(&md5_context);
-               MD5Update(&md5_context, request->password->strvalue,
+               MD5Update(&md5_context, request->password->vp_strvalue,
                          request->password->length);
-               MD5Update(&md5_context, &vp->strvalue[16], vp->length - 16);
+               MD5Update(&md5_context, &vp->vp_octets[16], vp->length - 16);
                MD5Final(digest, &md5_context);
 
                /*
                 *      Compare only the MD5 hash results, not the salt.
                 */
-               if (memcmp(digest, vp->strvalue, 16) != 0) {
+               if (memcmp(digest, vp->vp_octets, 16) != 0) {
                        snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: SMD5 password check failed");
                        goto make_msg;
                }
@@ -659,10 +639,10 @@ static int pap_authenticate(void *instance, REQUEST *request)
                }
                
                SHA1Init(&sha1_context);
-               SHA1Update(&sha1_context, request->password->strvalue,
+               SHA1Update(&sha1_context, request->password->vp_strvalue,
                           request->password->length);
                SHA1Final(digest,&sha1_context);
-               if (memcmp(digest, vp->strvalue, vp->length) != 0) {
+               if (memcmp(digest, vp->vp_octets, vp->length) != 0) {
                        snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: SHA1 password check failed");
                        goto make_msg;
                }
@@ -682,11 +662,11 @@ static int pap_authenticate(void *instance, REQUEST *request)
 
                
                SHA1Init(&sha1_context);
-               SHA1Update(&sha1_context, request->password->strvalue,
+               SHA1Update(&sha1_context, request->password->vp_strvalue,
                           request->password->length);
-               SHA1Update(&sha1_context, &vp->strvalue[20], vp->length - 20);
+               SHA1Update(&sha1_context, &vp->vp_octets[20], vp->length - 20);
                SHA1Final(digest,&sha1_context);
-               if (memcmp(digest, vp->strvalue, 20) != 0) {
+               if (memcmp(digest, vp->vp_octets, 20) != 0) {
                        snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: SSHA password check failed");
                        goto make_msg;
                }
@@ -705,14 +685,14 @@ static int pap_authenticate(void *instance, REQUEST *request)
                }
                
                sprintf(buff2,"%%{mschap:NT-Hash %s}",
-                       request->password->strvalue);
+                       request->password->vp_strvalue);
                if (!radius_xlat(digest,sizeof(digest),buff2,request,NULL)){
                        DEBUG("rlm_pap: mschap xlat failed");
                        snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: mschap xlat failed");
                        goto make_msg;
                }
                if ((lrad_hex2bin(digest, digest, 16) != vp->length) ||
-                   (memcmp(digest, vp->strvalue, vp->length) != 0)) {
+                   (memcmp(digest, vp->vp_octets, vp->length) != 0)) {
                        snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: NT password check failed");
                        goto make_msg;
                }
@@ -730,14 +710,14 @@ static int pap_authenticate(void *instance, REQUEST *request)
                        goto make_msg;
                }
                sprintf(buff2,"%%{mschap:LM-Hash %s}",
-                       request->password->strvalue);
+                       request->password->vp_strvalue);
                if (!radius_xlat(digest,sizeof(digest),buff2,request,NULL)){
                        DEBUG("rlm_pap: mschap xlat failed");
                        snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: mschap xlat failed");
                        goto make_msg;
                }
                if ((lrad_hex2bin(digest, digest, 16) != vp->length) ||
-                   (memcmp(digest, vp->strvalue, vp->length) != 0)) {
+                   (memcmp(digest, vp->vp_octets, vp->length) != 0)) {
                        snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: LM password check failed");
                make_msg:
                        DEBUG("rlm_pap: Passwords don't match");
@@ -762,7 +742,7 @@ static int pap_authenticate(void *instance, REQUEST *request)
                /*
                 *      Sanity check the value of NS-MTA-MD5-Password
                 */
-               if (lrad_hex2bin(vp->strvalue, buff, 32) != 16) {
+               if (lrad_hex2bin(vp->vp_octets, buff, 32) != 16) {
                        DEBUG("rlm_pap: Configured NS-MTA-MD5-Password has invalid value");
                        snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: Configured NS-MTA-MD5-Password has invalid value");
                        goto make_msg;
@@ -773,7 +753,7 @@ static int pap_authenticate(void *instance, REQUEST *request)
                 *
                 *      This really: sizeof(buff) - 2 - 2*32 - strlen(passwd)
                 */
-               if (strlen(request->password->strvalue) >= (sizeof(buff2) - 2 - 2 * 32)) {
+               if (strlen(request->password->vp_strvalue) >= (sizeof(buff2) - 2 - 2 * 32)) {
                        DEBUG("rlm_pap: Configured password is too long");
                        snprintf(module_fmsg,sizeof(module_fmsg),"rlm_pap: password is too long");
                        goto make_msg;
@@ -785,13 +765,13 @@ static int pap_authenticate(void *instance, REQUEST *request)
                {
                        char *p = buff2;
 
-                       memcpy(p, &vp->strvalue[32], 32);
+                       memcpy(p, &vp->vp_octets[32], 32);
                        p += 32;
                        *(p++) = 89;
-                       strcpy(p, request->password->strvalue);
+                       strcpy(p, request->password->vp_strvalue);
                        p += strlen(p);
                        *(p++) = 247;
-                       memcpy(p, &vp->strvalue[32], 32);
+                       memcpy(p, &vp->vp_octets[32], 32);
                        p += 32;
 
                        MD5Init(&md5_context);
@@ -823,13 +803,14 @@ static int pap_authenticate(void *instance, REQUEST *request)
  *     is single-threaded.
  */
 module_t rlm_pap = {
+       RLM_MODULE_INIT,
        "PAP",
        0,                              /* type */
-       NULL,                           /* initialization */
        pap_instantiate,                /* instantiation */
+       pap_detach,                     /* detach */
        {
                pap_authenticate,       /* authentication */
-               pap_authorize,          /* authorization */
+               pap_authorize,          /* authorization */
                NULL,                   /* preaccounting */
                NULL,                   /* accounting */
                NULL,                   /* checksimul */
@@ -837,6 +818,4 @@ module_t rlm_pap = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       pap_detach,                     /* detach */
-       NULL,                           /* destroy */
 };
index d55656f..4969d4d 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-/*#include "autoconf.h"
-#include "libradius.h"*/
-#include "radiusd.h"
-#include "modules.h"
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 
 struct mypasswd {
@@ -44,7 +46,7 @@ struct hashtable {
        struct mypasswd *last_found;
        char buffer[1024];
        FILE *fp;
-       char *delimiter;
+       char delimiter;
 };
 
 
@@ -77,10 +79,11 @@ static struct mypasswd * mypasswd_malloc(const char* buffer, int nfields, int* l
 }
 
 static int string_to_entry(const char* string, int nfields, char delimiter,
-       struct mypasswd *passwd, int bufferlen)
+       struct mypasswd *passwd, size_t bufferlen)
 {
        char *str;
-       int len, i, fn=0;
+       size_t len, i;
+       int fn=0;
        char *data_beg;
 
 
@@ -90,7 +93,8 @@ static int string_to_entry(const char* string, int nfields, char delimiter,
        if(!len) return 0;
        if (string[len-1] == '\r') len--;
        if(!len) return 0;
-       if (!len || !passwd || bufferlen < (len + nfields * sizeof (char*) + nfields * sizeof (char) + sizeof (struct mypasswd) + 1) ) return 0;
+       if (!len || !passwd ||
+           bufferlen < (len + nfields * sizeof (char*) + nfields * sizeof (char) + sizeof (struct mypasswd) + 1) ) return 0;
        passwd->next = NULL;
        data_beg=(char *)passwd + sizeof(struct mypasswd);
        str = data_beg + nfields * sizeof (char) + nfields * sizeof (char*);
@@ -132,12 +136,19 @@ static unsigned int hash(const unsigned char * username, unsigned int tablesize)
 static void release_hash_table(struct hashtable * ht){
        int i;
 
-       if (!ht) return;
-       for (i=0; i<ht->tablesize; i++)
+       if (ht == NULL) return;
+       for (i = 0; i < ht->tablesize; i++)
                if (ht->table[i])
                        destroy_password(ht->table[i]);
-       if (ht->table) free(ht->table);
-       if (ht->fp) fclose(ht->fp);
+       if (ht->table) {
+               free(ht->table);
+               ht->table = NULL;
+       }
+       if (ht->fp) {
+               fclose(ht->fp);
+               ht->fp = NULL;
+       }
+       ht->tablesize = 0;
 }
 
 static void release_ht(struct hashtable * ht){
@@ -148,12 +159,12 @@ static void release_ht(struct hashtable * ht){
 }
 
 static struct hashtable * build_hash_table (const char * file, int nfields,
-       int keyfield, int islist, int tablesize, int ignorenis, char delimiter)
+       int keyfield, int islist, int tablesize, int ignorenis, char delimiter)
 {
 #define passwd ((struct mypasswd *) ht->buffer)
        char buffer[1024];
        struct hashtable* ht;
-       int len;
+       size_t len;
        unsigned int h;
        struct mypasswd *hashentry, *hashentry1;
        char *list;
@@ -175,8 +186,8 @@ static struct hashtable * build_hash_table (const char * file, int nfields,
        ht->keyfield = keyfield;
        ht->islist = islist;
        ht->ignorenis = ignorenis;
-       if (delimiter && *delimiter) ht->delimiter = delimiter;
-       else ht->delimiter = ":";
+       if (delimiter) ht->delimiter = delimiter;
+       else ht->delimiter = ':';
        if(!tablesize) return ht;
        if(!(ht->fp = fopen(file,"r"))) return NULL;
        memset(ht->buffer, 0, 1024);
@@ -194,10 +205,9 @@ static struct hashtable * build_hash_table (const char * file, int nfields,
                if(*buffer && *buffer!='\n' && (!ignorenis || (*buffer != '+' && *buffer != '-')) ){
                        if(!(hashentry = mypasswd_malloc(buffer, nfields, &len))){
                                release_hash_table(ht);
-                               ht->tablesize = 0;
                                return ht;
                        }
-                       len = string_to_entry(buffer, nfields, *ht->delimiter, hashentry, len);
+                       len = string_to_entry(buffer, nfields, ht->delimiter, hashentry, len);
                        if(!hashentry->field[keyfield] || *hashentry->field[keyfield] == '\0') {
                                free(hashentry);
                                continue;
@@ -219,7 +229,6 @@ static struct hashtable * build_hash_table (const char * file, int nfields,
                                        else nextlist = 0;
                                        if(!(hashentry1 = mypasswd_malloc("", nfields, &len))){
                                                release_hash_table(ht);
-                                               ht->tablesize = 0;
                                                return ht;
                                        }
                                        for (i=0; i<nfields; i++) hashentry1->field[i] = hashentry->field[i];
@@ -257,10 +266,10 @@ static struct mypasswd * get_next(char *name, struct hashtable *ht)
                }
                return NULL;
        }
-       printf("try to find in file\n");
+       /*      printf("try to find in file\n"); */
        if (!ht->fp) return NULL;
        while (fgets(buffer, 1024,ht->fp)) {
-               if(*buffer && *buffer!='\n' && (len = string_to_entry(buffer, ht->nfields, *ht->delimiter, passwd, sizeof(ht->buffer)-1)) &&
+               if(*buffer && *buffer!='\n' && (len = string_to_entry(buffer, ht->nfields, ht->delimiter, passwd, sizeof(ht->buffer)-1)) &&
                        (!ht->ignorenis || (*buffer !='-' && *buffer != '+') ) ){
                        if(!ht->islist) {
                                if(!strcmp(passwd->field[ht->keyfield], name))
@@ -340,7 +349,6 @@ struct passwd_instance {
        struct mypasswd *pwdfmt;
        char *filename;
        char *format;
-       char *authtype;
        char * delimiter;
        int allowmultiple;
        int ignorenislike;
@@ -353,13 +361,11 @@ struct passwd_instance {
        int ignoreempty;
 };
 
-static CONF_PARSER module_config[] = {
-       { "filename",   PW_TYPE_STRING_PTR,
+static const CONF_PARSER module_config[] = {
+       { "filename",   PW_TYPE_FILENAME,
           offsetof(struct passwd_instance, filename), NULL,  NULL },
        { "format",   PW_TYPE_STRING_PTR,
           offsetof(struct passwd_instance, format), NULL,  NULL },
-       { "authtype",   PW_TYPE_STRING_PTR,
-          offsetof(struct passwd_instance, authtype), NULL,  NULL },
        { "delimiter",   PW_TYPE_STRING_PTR,
           offsetof(struct passwd_instance, delimiter), NULL,  ":" },
        { "ignorenislike",   PW_TYPE_BOOLEAN,
@@ -431,7 +437,7 @@ static int passwd_instantiate(CONF_SECTION *conf, void **instance)
                radlog(L_ERR, "rlm_passwd: no field market as key in format: %s", inst->format);
                return -1;
        }
-       if (! (inst->ht = build_hash_table (inst->filename, nfields, keyfield, listable, inst->hashsize, inst->ignorenislike, inst->delimiter)) ){
+       if (! (inst->ht = build_hash_table (inst->filename, nfields, keyfield, listable, inst->hashsize, inst->ignorenislike, *inst->delimiter)) ){
                radlog(L_ERR, "rlm_passwd: can't build hashtable from passwd file");
                return -1;
        }
@@ -470,7 +476,7 @@ static int passwd_instantiate(CONF_SECTION *conf, void **instance)
        inst->nfields = nfields;
        inst->keyfield = keyfield;
        inst->listable = listable;
-       radlog(L_INFO, "rlm_passwd: nfields: %d keyfield %d(%s) listable: %s", nfields, keyfield, inst->pwdfmt->field[keyfield], listable?"yes":"no");
+       DEBUG("rlm_passwd: nfields: %d keyfield %d(%s) listable: %s", nfields, keyfield, inst->pwdfmt->field[keyfield], listable?"yes":"no");
        return 0;
 
 #undef inst
@@ -479,10 +485,6 @@ static int passwd_instantiate(CONF_SECTION *conf, void **instance)
 static int passwd_detach (void *instance) {
 #define inst ((struct passwd_instance *)instance)
        if(inst->ht) release_ht(inst->ht);
-        if (inst->filename != NULL)    free(inst->filename);
-        if (inst->format != NULL)      free(inst->format);
-        if (inst->authtype != NULL )   free(inst->authtype);
-        if (inst->delimiter != NULL)   free(inst->delimiter);
        free(instance);
        return 0;
 #undef inst
@@ -528,7 +530,7 @@ static int passwd_authorize(void *instance, REQUEST *request)
                                name = buffer;
                                break;
                        default:
-                               name = key->strvalue;
+                               name = key->vp_strvalue;
                }
                if (! (pw = get_pw_nam(name, inst->ht)) ) {
                        continue;
@@ -544,27 +546,17 @@ static int passwd_authorize(void *instance, REQUEST *request)
        if(!found) {
                return RLM_MODULE_NOTFOUND;
        }
-       if (inst->authtype &&
-           (key = pairmake ("Auth-Type", inst->authtype, T_OP_EQ))) {
-               radlog(L_INFO, "rlm_passwd: Adding \"Auth-Type = %s\"",
-                      inst->authtype);
-               /*
-                *      Don't call pairadd.  pairmove doesn't
-                *      over-write existing attributes.
-                */
-               pairmove(&request->config_items, &key);
-               pairfree(&key); /* pairmove may have NOT moved it */
-       }
        return RLM_MODULE_OK;
 
 #undef inst
 }
 
 module_t rlm_passwd = {
+       RLM_MODULE_INIT,
        "passwd",
        RLM_TYPE_THREAD_SAFE,           /* type */
-       NULL,                           /* initialize */
        passwd_instantiate,             /* instantiation */
+       passwd_detach,                  /* detach */
        {
                NULL,                   /* authentication */
                passwd_authorize,       /* authorization */
@@ -575,7 +567,5 @@ module_t rlm_passwd = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       passwd_detach,                  /* detach */
-       NULL                            /* destroy */
 };
 #endif /* TEST */
index ca00d8e..493d850 100644 (file)
@@ -1,9 +1,16 @@
-/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
-/*
+/* config.h.in.  Generated from configure.in by autoheader.  */
 
-acconfig.h - template used by autoheader to create config.h.in
-config.h.in - used by autoconf to create config.h
-config.h - created by autoconf; contains defines generated by autoconf
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
 
-*/
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
 
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
index 857224b..84fd96c 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.1.10.1 .
+# From configure.in Revision: 1.2 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -901,7 +901,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1821,8 +1821,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1880,8 +1879,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1997,8 +1995,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2052,8 +2049,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2098,8 +2094,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2143,8 +2138,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2459,7 +2453,7 @@ fi
            fail=$fail" perl"
        else
           old_CFLAGS=$CFLAGS
-          CFLAGS="$CFLAGS `perl -MExtUtils::Embed -e ccopts; perl -MConfig -e 'print $Config{cppflags}'`"
+          CFLAGS="$CFLAGS `perl -MExtUtils::Embed -e ccopts`"
 
          smart_try_dir=
 
@@ -2501,8 +2495,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2525,8 +2518,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" = "x"; then
@@ -2555,8 +2548,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2634,8 +2626,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2658,8 +2649,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" != "x"; then
@@ -2674,7 +2665,7 @@ echo "${ECHO_T}no" >&6
 fi
 
          if test "x$ac_cv_header_EXTERN_h" = "xyes"; then
-               perl_cflags="`perl -MExtUtils::Embed -e ccopts; perl -MConfig -e 'print $Config{cppflags}'`"
+               perl_cflags='`perl -MExtUtils::Embed -e ccopts`'
          else
                fail="$fail EXTERN.h"
                targetname=
@@ -2718,8 +2709,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2742,8 +2732,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" = "x"; then
@@ -2772,8 +2762,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2851,8 +2840,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2875,8 +2863,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" != "x"; then
@@ -2891,7 +2879,7 @@ echo "${ECHO_T}no" >&6
 fi
 
          if test "x$ac_cv_header_perl_h" = "xyes"; then
-               perl_cflags="`perl -MExtUtils::Embed -e ccopts; perl -MConfig -e 'print $Config{cppflags}'`"
+               perl_cflags='`perl -MExtUtils::Embed -e ccopts`'
          else
                fail="$fail perl.h"
                targetname=
@@ -3719,11 +3707,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3762,6 +3745,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 0172a57..7fa50e5 100644 (file)
@@ -1,3 +1,4 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_perl.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_perl])
@@ -16,20 +17,20 @@ if test x$with_[]modname != xno; then
            fail=$fail" perl"
        else
           old_CFLAGS=$CFLAGS
-          CFLAGS="$CFLAGS `perl -MExtUtils::Embed -e ccopts; perl -MConfig -e 'print $Config{cppflags}'`"
+          CFLAGS="$CFLAGS `perl -MExtUtils::Embed -e ccopts`"
 
          smart_try_dir=
-         AC_SMART_CHECK_INCLUDE(EXTERN.h)
+         FR_SMART_CHECK_INCLUDE(EXTERN.h)
          if test "x$ac_cv_header_EXTERN_h" = "xyes"; then
-               perl_cflags="`perl -MExtUtils::Embed -e ccopts; perl -MConfig -e 'print $Config{cppflags}'`"
+               perl_cflags='`perl -MExtUtils::Embed -e ccopts`'
          else
                fail="$fail EXTERN.h"
                targetname=
          fi
 
-         AC_SMART_CHECK_INCLUDE(perl.h, [#include <EXTERN.h>])
+         FR_SMART_CHECK_INCLUDE(perl.h, [#include <EXTERN.h>])
          if test "x$ac_cv_header_perl_h" = "xyes"; then
-               perl_cflags="`perl -MExtUtils::Embed -e ccopts; perl -MConfig -e 'print $Config{cppflags}'`"
+               perl_cflags='`perl -MExtUtils::Embed -e ccopts`'
          else
                fail="$fail perl.h"
                targetname=
index 96d5fd2..8418f04 100644 (file)
@@ -11,7 +11,7 @@
 # 
 #  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 #  
 #  Copyright 2002  The FreeRADIUS server project
 #  Copyright 2002  Boian Jordanov <bjordanov@orbitel.bg>
index 17bcd93..3fd351e 100644 (file)
@@ -1,4 +1,4 @@
-/*
+ /*
  * rlm_perl.c
  *
  * Version:    $Id$
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2002  The FreeRADIUS server project
+ * Copyright 2002,2006  The FreeRADIUS server project
  * Copyright 2002  Boian Jordanov <bjordanov@orbitel.bg>
  */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 #ifdef DEBUG
 #undef DEBUG
@@ -50,8 +51,6 @@
 extern char **environ;
 #endif
 
-static const char rcsid[] = "$Id$";
-
 #ifdef USE_ITHREADS
 
 /*
@@ -127,7 +126,7 @@ typedef struct perl_inst {
  *     buffer over-flows.
  */
 static const CONF_PARSER module_config[] = {
-       { "module",  PW_TYPE_STRING_PTR,
+       { "module",  PW_TYPE_FILENAME,
          offsetof(PERL_INST,module), NULL,  "module"},
        { "func_authorize", PW_TYPE_STRING_PTR,
          offsetof(PERL_INST,func_authorize), NULL, "authorize"},
@@ -170,13 +169,13 @@ EXTERN_C void boot_DynaLoader(pTHX_ CV* cv);
  *     We clone it for every instance if we have perl
  *     with -Duseithreads compiled in
  */
-static PerlInterpreter *interp;
+static PerlInterpreter *interp = NULL;
 
 static const CONF_PARSER pool_conf[] = {
        { "max_clones", PW_TYPE_INTEGER, offsetof(PERL_POOL, max_clones), NULL,         "32"},
-       { "start_clones",PW_TYPE_INTEGER, offsetof(PERL_POOL, start_clones), NULL,              "5"},
-       { "min_spare_clones",PW_TYPE_INTEGER, offsetof(PERL_POOL, min_spare_clones),NULL,       "3"},
-       { "max_spare_clones",PW_TYPE_INTEGER, offsetof(PERL_POOL,max_spare_clones),NULL,        "3"},
+       { "start_clones",PW_TYPE_INTEGER, offsetof(PERL_POOL, start_clones), NULL,              "32"},
+       { "min_spare_clones",PW_TYPE_INTEGER, offsetof(PERL_POOL, min_spare_clones),NULL,       "0"},
+       { "max_spare_clones",PW_TYPE_INTEGER, offsetof(PERL_POOL,max_spare_clones),NULL,        "32"},
        { "cleanup_delay",PW_TYPE_INTEGER, offsetof(PERL_POOL,cleanup_delay),NULL,              "5"},
        { "max_request_per_clone",PW_TYPE_INTEGER, offsetof(PERL_POOL,max_request_per_clone),NULL,      "0"},
        { NULL, -1, 0, NULL, NULL }             /* end the list */
@@ -257,7 +256,7 @@ static void rlm_perl_close_handles(void **handles)
 static PerlInterpreter *rlm_perl_clone(PerlInterpreter *perl)
 {
        PerlInterpreter *clone;
-       UV      clone_flags = 0;
+       UV clone_flags = 0;
 
        PERL_SET_CONTEXT(perl);
 
@@ -554,6 +553,7 @@ static int init_pool (CONF_SECTION *conf, PERL_INST *inst) {
        int t;
        PERL_POOL       *pool;
 
+
        pool = rad_malloc(sizeof(PERL_POOL));
        memset(pool,0,sizeof(PERL_POOL));
 
@@ -580,20 +580,6 @@ static int init_pool (CONF_SECTION *conf, PERL_INST *inst) {
        return 1;
 }
 #endif
-/*
- *     Do any per-module initialization.  e.g. set up connections
- *     to external databases, read configuration files, set up
- *     dictionary entries, etc.
- *
- *     Try to avoid putting too much stuff in here - it's better to
- *     do it in instantiate() where it is not global.
- *     I use one global interpetator to make things more fastest for
- *     Threading env I clone new perl from this interp.
- */
-static int perl_init(void)
-{
-       return 0;
-}
 
 static void xs_init(pTHX)
 {
@@ -693,7 +679,7 @@ static int perl_xlat(void *instance, REQUEST *request, char *fmt, char * out,
                POPs ;
        } else if (count > 0) {
                tmp = POPp;
-               strNcpy(out,tmp,freespace);
+               strlcpy(out, tmp, freespace);
                ret = strlen(out);
 
                radlog(L_DBG,"rlm_perl: Len is %d , out is %s freespace is %d",
@@ -730,12 +716,14 @@ static int perl_instantiate(CONF_SECTION *conf, void **instance)
        PERL_INST       *inst = (PERL_INST *) instance;
        HV              *rad_reply_hv;
        HV              *rad_check_hv;
+       HV              *rad_config_hv;
        HV              *rad_request_hv;
        HV              *rad_request_proxy_hv;
        HV              *rad_request_proxy_reply_hv;
        AV              *end_AV;
 
-       char *embed[4], *xlat_name;
+       char *embed[4];
+       const char *xlat_name;
        int exitstatus = 0, argc=0;
 
        /*
@@ -773,7 +761,7 @@ static int perl_instantiate(CONF_SECTION *conf, void **instance)
                radlog(L_DBG, "rlm_perl: No memory for allocating new perl !");
                return (-1);
        }
-
+               
        perl_construct(inst->perl);
        PL_perl_destruct_level = 2;
 
@@ -812,12 +800,14 @@ static int perl_instantiate(CONF_SECTION *conf, void **instance)
 
        rad_reply_hv = newHV();
        rad_check_hv = newHV();
+       rad_config_hv = newHV();
        rad_request_hv = newHV();
        rad_request_proxy_hv = newHV();
        rad_request_proxy_reply_hv = newHV();
 
        rad_reply_hv = get_hv("RAD_REPLY",1);
         rad_check_hv = get_hv("RAD_CHECK",1);
+       rad_config_hv = get_hv("RAD_CONFIG",1);
         rad_request_hv = get_hv("RAD_REQUEST",1);
        rad_request_proxy_hv = get_hv("RAD_REQUEST_PROXY",1);
        rad_request_proxy_reply_hv = get_hv("RAD_REQUEST_PROXY_REPLY",1);
@@ -926,6 +916,7 @@ static int get_hv_content(HV *my_hv, VALUE_PAIR **vp)
        I32             key_len, len, i, j;
        int             ret=0;
 
+       *vp = NULL;
        for (i = hv_iterinit(my_hv); i > 0; i--) {
                res_sv = hv_iternextsv(my_hv,&key,&key_len);
                if (SvROK(res_sv) && (SvTYPE(SvRV(res_sv)) == SVt_PVAV)) {
@@ -956,6 +947,7 @@ static int rlmperl_call(void *instance, REQUEST *request, char *function_name)
 
        HV              *rad_reply_hv;
        HV              *rad_check_hv;
+       HV              *rad_config_hv;
        HV              *rad_request_hv;
        HV              *rad_request_proxy_hv;
        HV              *rad_request_proxy_reply_hv;
@@ -993,6 +985,7 @@ static int rlmperl_call(void *instance, REQUEST *request, char *function_name)
 
        rad_reply_hv = get_hv("RAD_REPLY",1);
        rad_check_hv = get_hv("RAD_CHECK",1);
+       rad_config_hv = get_hv("RAD_CONFIG",1);
        rad_request_hv = get_hv("RAD_REQUEST",1);
        rad_request_proxy_hv = get_hv("RAD_REQUEST_PROXY",1);
        rad_request_proxy_reply_hv = get_hv("RAD_REQUEST_PROXY_REPLY",1);
@@ -1001,6 +994,7 @@ static int rlmperl_call(void *instance, REQUEST *request, char *function_name)
        perl_store_vps(request->reply->vps, rad_reply_hv);
        perl_store_vps(request->config_items, rad_check_hv);
        perl_store_vps(request->packet->vps, rad_request_hv);
+       perl_store_vps(request->config_items, rad_config_hv);
        
        if (request->proxy != NULL) {
                perl_store_vps(request->proxy->vps, rad_request_proxy_hv);
@@ -1014,9 +1008,6 @@ static int rlmperl_call(void *instance, REQUEST *request, char *function_name)
                hv_undef(rad_request_proxy_reply_hv);
        }       
        
-       vp = NULL;
-
-
        PUSHMARK(SP);
        /*
        * This way %RAD_xx can be pushed onto stack as sub parameters.
@@ -1048,23 +1039,51 @@ static int rlmperl_call(void *instance, REQUEST *request, char *function_name)
        PUTBACK;
        FREETMPS;
        LEAVE;
+       
+       vp = NULL;
+       if ((get_hv_content(rad_request_hv, &vp)) > 0 ) {
+               pairfree(&request->packet->vps);
+               request->packet->vps = vp;
+               vp = NULL;
 
+               /*
+                *      Update cached copies
+                */
+               request->username = pairfind(request->packet->vps,
+                                            PW_USER_NAME);
+               request->password = pairfind(request->packet->vps,
+                                            PW_USER_PASSWORD);
+               if (!request->password)
+                       request->password = pairfind(request->packet->vps,
+                                                    PW_CHAP_PASSWORD);
+       }
 
        if ((get_hv_content(rad_reply_hv, &vp)) > 0 ) {
-               pairmove(&request->reply->vps, &vp);
-               pairfree(&vp);
+               pairfree(&request->reply->vps);
+               request->reply->vps = vp;
+               vp = NULL;
        }
 
        if ((get_hv_content(rad_check_hv, &vp)) > 0 ) {
-               pairmove(&request->config_items, &vp);
-               pairfree(&vp);
+               pairfree(&request->config_items);
+               request->config_items = vp;
+               vp = NULL;
        }
        
-       if ((get_hv_content(rad_request_proxy_reply_hv, &vp)) > 0 && request->proxy_reply != NULL) {
+       if (request->proxy &&
+           (get_hv_content(rad_request_proxy_hv, &vp) > 0)) {
+               pairfree(&request->proxy->vps);
+               request->proxy->vps = vp;
+               vp = NULL;
+       }
+
+       if (request->proxy_reply &&
+           (get_hv_content(rad_request_proxy_reply_hv, &vp) > 0)) {
                pairfree(&request->proxy_reply->vps);
-               pairmove(&request->proxy_reply->vps, &vp);
-               pairfree(&vp);
+               request->proxy_reply->vps = vp;
+               vp = NULL;
        }
+
        }
 #ifdef USE_ITHREADS
        pool_release(handle,instance);
@@ -1184,7 +1203,7 @@ static int perl_post_auth(void *instance, REQUEST *request)
 static int perl_detach(void *instance)
 {
        PERL_INST       *inst = (PERL_INST *) instance;
-       int             exitstatus=0,count=0;
+       int             exitstatus = 0, count = 0;
 
 #ifdef USE_ITHREADS
        POOL_HANDLE     *handle, *tmp, *tmp2;
@@ -1270,15 +1289,6 @@ static int perl_detach(void *instance)
        xlat_unregister(inst->xlat_name, perl_xlat);
        free(inst->xlat_name);
 
-       if (inst->func_authorize) free(inst->func_authorize);
-       if (inst->func_authenticate) free(inst->func_authenticate);
-       if (inst->func_accounting) free(inst->func_accounting);
-       if (inst->func_preacct) free(inst->func_preacct);
-       if (inst->func_checksimul) free(inst->func_checksimul);
-       if (inst->func_pre_proxy) free(inst->func_pre_proxy);
-       if (inst->func_post_proxy) free(inst->func_post_proxy);
-       if (inst->func_post_auth) free(inst->func_post_auth);
-       if (inst->func_detach) free(inst->func_detach);
 
 #ifdef USE_ITHREADS
        free(inst->perl_pool->head);
@@ -1304,24 +1314,23 @@ static int perl_detach(void *instance)
  *     is single-threaded.
  */
 module_t rlm_perl = {
+       RLM_MODULE_INIT,
        "perl",                         /* Name */
 #ifdef USE_ITHREADS
        RLM_TYPE_THREAD_SAFE,           /* type */
 #else
        RLM_TYPE_THREAD_UNSAFE,
 #endif
-       perl_init,                      /* initialization */
        perl_instantiate,               /* instantiation */
+       perl_detach,                    /* detach */
        {
-               perl_authenticate,
-               perl_authorize,
-               perl_preacct,
-               perl_accounting,
+               perl_authenticate,      /* authenticate */
+               perl_authorize,         /* authorize */
+               perl_preacct,           /* preacct */
+               perl_accounting,        /* accounting */
                perl_checksimul,        /* check simul */
-               perl_pre_proxy,  /* pre-proxy */
+               perl_pre_proxy,         /* pre-proxy */
                perl_post_proxy,        /* post-proxy */
-               perl_post_auth    /* post-auth */
+               perl_post_auth          /* post-auth */
        },
-       perl_detach,                    /* detach */
-       NULL,                           /* destroy */
 };
diff --git a/src/modules/rlm_policy/Makefile b/src/modules/rlm_policy/Makefile
new file mode 100644 (file)
index 0000000..808d84a
--- /dev/null
@@ -0,0 +1,15 @@
+#
+# Makefile
+#
+# Version:     $Id$
+#
+
+TARGET         = rlm_policy
+SRCS           = rlm_policy.c parse.c evaluate.c
+HEADERS                = rlm_policy.h
+RLM_CFLAGS     =
+RLM_LIBS       =
+
+include ../rules.mak
+
+$(LT_OBJS): $(HEADERS)
diff --git a/src/modules/rlm_policy/evaluate.c b/src/modules/rlm_policy/evaluate.c
new file mode 100644 (file)
index 0000000..ca355de
--- /dev/null
@@ -0,0 +1,1106 @@
+/*
+ * evaluate.c          Evaluate a policy language
+ *
+ * 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 2004  Alan DeKok <aland@ox.org>
+ * Copyright 2006  The FreeRADIUS server project
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include "rlm_policy.h"
+
+#ifdef HAVE_REGEX_H
+#include <regex.h>
+#endif
+
+#define debug_evaluate if (0) printf
+
+/*
+ *     Print stuff we've parsed
+ */
+static void policy_print(const policy_item_t *item, int indent)
+{
+       if (!item) {
+               if (indent) printf("%*s", indent, " ");
+               printf("[NULL]\n");
+               return;
+       }
+       
+       while (item) {
+               switch (item->type) {
+               case POLICY_TYPE_BAD:
+                       if (indent) printf("%*s", indent, " ");
+                       printf("[BAD STATEMENT]");
+                       break;
+                       
+               case POLICY_TYPE_PRINT:
+                       if (indent) printf("%*s", indent, " ");
+                       {
+                               const policy_print_t *this;
+
+                               this = (const policy_print_t *) item;
+                               
+                               if (this->rhs_type == POLICY_LEX_BARE_WORD) {
+                                       printf("print %s\n", this->rhs);
+                               } else {
+                                       printf("print \"%s\"\n", this->rhs);
+                               }
+                       }
+                       break;
+                       
+               case POLICY_TYPE_ASSIGNMENT:
+                       {
+                               const policy_assignment_t *assign;
+                               
+                               assign = (const policy_assignment_t *) item;
+                               if (indent) printf("%*s", indent, " ");
+
+                               printf("\t%s %s ", assign->lhs,
+                                      lrad_int2str(rlm_policy_tokens,
+                                                   assign->assign, "?"));
+                               if (assign->rhs_type == POLICY_LEX_BARE_WORD) {
+                                       printf("%s\n", assign->rhs);
+                               } else {
+                                       /*
+                                        *      FIXME: escape "
+                                        */
+                                       printf("\"%s\"\n", assign->rhs);
+                               }
+                       }
+                       break;
+
+               case POLICY_TYPE_CONDITIONAL: /* no indentation here */
+                       {
+                               const policy_condition_t *condition;
+
+                               condition = (const policy_condition_t *) item;
+
+                               printf("(");
+
+                               /*
+                                *      Nested conditions.
+                                */
+                               if (condition->compare == POLICY_LEX_L_BRACKET) {
+                                       policy_print(condition->child, indent);
+                                       printf(")");
+                                       break;
+                               }
+
+                               if (condition->compare == POLICY_LEX_L_NOT) {
+                                       printf("!");
+                                       policy_print(condition->child, indent);
+                                       printf(")");
+                                       break;
+                               }
+
+                               if (condition->compare == POLICY_LEX_CMP_TRUE) {
+                                       printf("%s)", condition->lhs);
+                                       break;
+                               }
+
+                               if (condition->lhs_type == POLICY_LEX_FUNCTION) {
+                                       printf("%s()", condition->lhs);
+                               } else {
+                                       /*
+                                        *      FIXME: escape ",
+                                        *      and move all of this logic
+                                        *      to a function.
+                                        */
+                                       printf("\"%s\"", condition->lhs);
+                               }
+
+                               /*
+                                *      We always print this condition.
+                                */
+                               printf(" %s ", lrad_int2str(rlm_policy_tokens,
+                                                           condition->compare,
+                                                           "?"));
+                               if (condition->rhs_type == POLICY_LEX_BARE_WORD) {
+                                       printf("%s", condition->rhs);
+                               } else {
+                                       /*
+                                        *      FIXME: escape ",
+                                        *      and move all of this logic
+                                        *      to a function.
+                                        */
+                                       printf("\"%s\"", condition->rhs);
+                               }
+                               printf(")");
+                               
+                               if ((condition->child_condition != POLICY_LEX_BAD) &&
+                                   (condition->child_condition != POLICY_LEX_BARE_WORD)) {
+                                       printf(" %s ", lrad_int2str(rlm_policy_tokens, condition->child_condition, "?"));
+                                       policy_print(condition->child, indent);
+                               }
+                       }
+                       break;
+
+               case POLICY_TYPE_IF:
+                       {
+                               const policy_if_t *statement;
+
+                               statement = (const policy_if_t *) item;
+
+                               if (indent) printf("%*s", indent, " ");
+                               printf("if ");
+                               policy_print(statement->condition, indent);
+                               printf(" {\n");
+                               policy_print(statement->if_true, indent + 1);
+                               if (indent) printf("%*s", indent, " ");
+                               if (statement->if_false) {
+                                       printf("} else ");
+                                       if (statement->if_false->type == POLICY_TYPE_ASSIGNMENT) {
+                                               printf(" { ");
+                                               policy_print(statement->if_false, indent + 1);
+                                               if (indent) printf("%*s", indent, " ");
+                                               printf(" }");
+                                       } else {
+                                               policy_print(statement->if_false, indent + 1);
+                                       }
+                               } else {
+                                       printf("}\n");
+                               }
+                       }
+                       break;
+
+               case POLICY_TYPE_ATTRIBUTE_LIST:
+                       {
+                               const policy_attributes_t *this;
+
+                               this = (const policy_attributes_t *) item;
+
+                               if (indent) printf("%*s", indent, " ");
+                               printf("%s %s {\n",
+                                      lrad_int2str(policy_reserved_words,
+                                                   this->where, "?"),
+                                      lrad_int2str(rlm_policy_tokens,
+                                                   this->how, "?"));
+                               policy_print(this->attributes, indent + 1);
+                               if (indent) printf("%*s", indent, " ");
+                               printf("}\n");
+                       }
+                       break;
+
+               case POLICY_TYPE_NAMED_POLICY:
+                       {
+                               const policy_named_t *this;
+
+                               this = (const policy_named_t *) item;
+                               if (indent) printf("%*s", indent, " ");
+                               printf("policy %s {\n", this->name);
+                               policy_print(this->policy, indent + 1);
+                               if (indent) printf("%*s", indent, " ");
+                               printf("}\n");
+                       }
+                       break;
+
+               case POLICY_TYPE_CALL:
+                       {
+                               const policy_call_t *this;
+
+                               this = (const policy_call_t *) item;
+                               if (indent) printf("%*s", indent, " ");
+                               printf("call %s\n", this->name);
+                       }
+                       break;
+
+               case POLICY_TYPE_RETURN:
+                       {
+                               const policy_return_t *this;
+
+                               this = (const policy_return_t *) item;
+                               if (indent) printf("%*s", indent, " ");
+                               printf("return %s\n",
+                                      lrad_int2str(policy_return_codes,
+                                                   this->rcode, "???"));
+                       }
+                       break;
+
+               case POLICY_TYPE_MODULE:
+                       {
+                               const policy_module_t *this;
+
+                               this = (const policy_module_t *) item;
+                               if (indent) printf("%*s", indent, " ");
+                               printf("module %s <stuff>\n",
+                                      lrad_int2str(policy_component_names,
+                                                   this->component, "???"));
+                       }
+                       break;
+
+               default:
+                       if (indent) printf("%*s", indent, " ");
+                       printf("[HUH?]\n");
+                       break;
+                       
+               }
+
+               item = item->next;
+       }
+}
+
+
+void rlm_policy_print(const policy_item_t *item)
+{
+       printf("----------------------------------------------------------\n");
+       policy_print(item, 0);
+       printf("----------------------------------------------------------\n");
+}
+
+/*
+ *     Internal stack of things to do.  This lets us have function
+ *     calls...
+ *
+ *     Yes, we should learn lex, yacc, etc.
+ */
+#define POLICY_MAX_STACK 16
+typedef struct policy_state_t {
+       rlm_policy_t    *inst;
+       REQUEST         *request; /* so it's not passed on the C stack */
+       int             rcode;  /* for functions, etc. */
+       int             component; /* for calling other modules */
+       int             depth;
+       const policy_item_t *stack[POLICY_MAX_STACK];
+} policy_state_t;
+
+
+static int policy_evaluate_name(policy_state_t *state, const char *name);
+
+/*
+ *     Push an item onto the state.
+ */
+static int policy_stack_push(policy_state_t *state, const policy_item_t *item)
+{
+       rad_assert(state->depth >= 0);
+
+       /*
+        *      Asked to push nothing.  Don't push it.
+        */
+       if (!item) return 1;
+
+       /*
+        *      State is full.  Die.
+        */
+       if (state->depth >= POLICY_MAX_STACK) {
+               return 0;
+       }
+
+       /*
+        *      Walk back up the stack, looking for previous ocurrances
+        *      of this name.  If found, we have infinite recursion,
+        *      which we stop dead in the water!
+        *
+        *      This isn't strictly necessary right now, as we look up
+        *      policies by name when they're first referenced.  This
+        *      means that ALL references are backwards (to the start
+        *      of the file), which means that there are no circular
+        *      references.
+        */
+       if (item->type == POLICY_TYPE_NAMED_POLICY) {
+               int i;
+
+               for (i = 0; i < state->depth; i++) {
+                       /*
+                        *      Check for circular references, by seeing
+                        *      if the function is already on the stack.
+                        *
+                        *      Hmmm... do we want to do this for any type?
+                        */
+                       if (state->stack[i] == item) {
+                               debug_evaluate("Circular call to policy %s\n",
+                                              ((const policy_named_t *) item)->name);
+                               return 0;
+                       }
+               }
+       }
+
+       debug_evaluate("push %d %p\n", state->depth, item);
+
+       state->stack[state->depth] = item;
+       state->depth++;         /* points to unused entry */
+
+       return 1;
+}
+
+
+/*
+ *     Pop an item from the state.
+ */
+static int policy_stack_pop(policy_state_t *state, const policy_item_t **pitem)
+{
+       rad_assert(pitem != NULL);
+       rad_assert(state->depth >= 0);
+
+ redo:
+       if (state->depth == 0) {
+               *pitem = NULL;
+               return 0;
+       }
+
+       *pitem = state->stack[state->depth - 1];
+
+       /*
+        *      Named policies are on the stack for catching recursion.
+        */
+       if ((*pitem)->type == POLICY_TYPE_NAMED_POLICY) {
+               state->depth--;
+               goto redo;
+       }
+
+       /*
+        *      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);
+       } else {
+               state->depth--;         /* points to unused entry */
+               debug_evaluate("pop %d %p\n", state->depth, *pitem);
+       }
+
+       return 1;
+}
+
+
+/*
+ *     Evaluate a print statement
+ */
+static int evaluate_print(policy_state_t *state, const policy_item_t *item)
+{
+       const policy_print_t *this;
+
+       this = (const policy_print_t *) item;
+
+       if (this->rhs_type == POLICY_LEX_BARE_WORD) {
+               printf("%s\n", this->rhs);
+       } else {
+               char buffer[1024];
+
+               radius_xlat(buffer, sizeof(buffer), this->rhs,
+                           state->request, NULL);
+               printf("%s", buffer);
+       }
+
+       /*
+        *      Doesn't change state->rcode
+        */
+
+       return 1;
+}
+
+/*
+ *     Return a VALUE_PAIR, given an attribute name.
+ *
+ *     FIXME: Have it return the N'th one, too, like
+ *     doc/variables.txt?
+ *
+ *     The amount of duplicated code is getting annoying...
+ */
+static VALUE_PAIR *find_vp(REQUEST *request, const char *name)
+{
+       const char *p;
+       const DICT_ATTR *dattr;
+       VALUE_PAIR *vps;
+
+       p = name;
+       vps = request->packet->vps;;
+
+       /*
+        *      FIXME: use names from reserved word list?
+        */
+       if (strncasecmp(name, "request:", 8) == 0) {
+               p += 8;
+       } else if (strncasecmp(name, "reply:", 6) == 0) {
+               p += 6;
+               vps = request->reply->vps;
+       } else if (strncasecmp(name, "proxy-request:", 14) == 0) {
+               p += 14;
+               if (request->proxy) {
+                       vps = request->proxy->vps;
+               }
+       } else if (strncasecmp(name, "proxy-reply:", 12) == 0) {
+               p += 12;
+               if (request->proxy_reply) {
+                       vps = request->proxy_reply->vps;
+               }
+       } else if (strncasecmp(name, "control:", 8) == 0) {
+               p += 8;
+               vps = request->config_items;
+       } /* else it must be a bare attribute name */
+
+       if (!vps) {
+               return NULL;
+       }
+
+       dattr = dict_attrbyname(p);
+       if (!dattr) {
+               fprintf(stderr, "No such attribute %s\n", p);
+               return NULL;    /* no such attribute */
+       }
+
+       return pairfind(vps, dattr->attr);
+}
+
+
+/*
+ *     Evaluate an assignment
+ *
+ *     Not really used much...
+ */
+static int evaluate_assignment(policy_state_t *state, const policy_item_t *item)
+{
+       const policy_assignment_t *this;
+#if 0
+       const DICT_ATTR *dattr;
+#endif
+
+       this = (const policy_assignment_t *) item;
+
+       rad_assert(this->lhs != NULL);
+       rad_assert(this->rhs != NULL);
+
+#if 0
+       dattr = dict_attrbyname(this->lhs);
+       if (!dattr) {
+               fprintf(stderr, "HUH?\n");
+               return 0;
+       }
+#endif
+
+       return 1;
+}
+
+
+/*
+ *     Evaluate a condition
+ */
+static int evaluate_condition(policy_state_t *state, const policy_item_t *item)
+{
+       int rcode;
+       const policy_condition_t *this;
+       VALUE_PAIR *vp = NULL;
+       const char *data = NULL;
+       int compare;
+#ifdef HAVE_REGEX_H
+       regex_t reg;
+#endif
+       char buffer[256];
+       char lhs_buffer[2048];
+
+       this = (const policy_condition_t *) item;
+
+ redo:
+       /*
+        *      FIXME: Don't always do this...
+        */
+       if (this->compare != POLICY_LEX_L_BRACKET) {
+               if (this->lhs_type == POLICY_LEX_FUNCTION) {
+                       /*
+                        *      We can't call evaluate_call here,
+                        *      because that just pushes stuff onto
+                        *      the stack, and we want to actually
+                        *      evaluate all of it...
+                        */
+                       rcode = policy_evaluate_name(state, this->lhs);
+                       data = lrad_int2str(policy_return_codes, rcode, "???");
+                       strlcpy(lhs_buffer, data, sizeof(lhs_buffer)); /* FIXME: yuck */
+               } else if (this->lhs_type == POLICY_LEX_DOUBLE_QUOTED_STRING) {
+                       if (radius_xlat(lhs_buffer, sizeof(lhs_buffer), this->lhs,
+                                       state->request, NULL) > 0) {
+                               data = lhs_buffer;
+                       }
+               }
+       }
+       
+       switch (this->compare) {
+       case POLICY_LEX_L_BRACKET: /* nested brackets are a special case */
+               rcode = evaluate_condition(state, this->child);
+               break;
+
+       case POLICY_LEX_L_NOT:
+               rcode = evaluate_condition(state, this->child);
+               rcode = (rcode == FALSE); /* reverse sense of test */
+               break;
+
+       case POLICY_LEX_CMP_FALSE: /* non-existence */
+               if (this->lhs_type == POLICY_LEX_BARE_WORD) {
+                       vp = find_vp(state->request, this->lhs);
+                       rcode = (vp == NULL);
+               } else {
+                       rcode = (data == NULL);
+               }
+               break;
+
+       case POLICY_LEX_CMP_TRUE: /* existence */
+               if (this->lhs_type == POLICY_LEX_BARE_WORD) {
+                       vp = find_vp(state->request, this->lhs);
+                       rcode = (vp != NULL);
+               } else {
+                       rcode = (data != NULL);
+               }
+               break;
+
+       default:                /* process other comparisons */
+               if ((this->compare != POLICY_LEX_CMP_EQUALS) &&
+#ifdef HAVE_REGEX_H
+                   (this->compare != POLICY_LEX_RX_EQUALS) &&
+                   (this->compare != POLICY_LEX_RX_NOT_EQUALS) &&
+#endif
+                   (this->compare != POLICY_LEX_LT) &&
+                   (this->compare != POLICY_LEX_GT) &&
+                   (this->compare != POLICY_LEX_LE) &&
+                   (this->compare != POLICY_LEX_GE) &&
+                   (this->compare != POLICY_LEX_CMP_NOT_EQUALS)) {
+                       fprintf(stderr, "%d: bad comparison\n",
+                               this->item.lineno);
+                       return FALSE;
+               }
+
+               if (this->lhs_type == POLICY_LEX_BARE_WORD) {
+                       VALUE_PAIR *myvp;
+
+                       vp = find_vp(state->request, this->lhs);
+
+                       /*
+                        *      A op B always returns FALSE if A doesn't
+                        *      exist.
+                        */
+                       if (!vp) return FALSE; /* not in the request */
+
+                       /*
+                        *      FIXME: Move sanity checks to
+                        *      post-parse code, so we don't do
+                        *      it on every packet.
+                        */
+                       vp_prints_value(buffer, sizeof(buffer), vp, 0);
+                       myvp = pairmake(vp->name, this->rhs, T_OP_EQ);
+                       data = buffer;
+
+                       /*
+                        *      FIXME: What to do about comparisons
+                        *      where vp doesn't exist?  Right now,
+                        *      "simplepaircmp" returns -1, which is
+                        *      probably a bad idea.  it should
+                        *      instead take an operator, a pointer to
+                        *      the comparison result, and return
+                        *      "true/false" for "comparions
+                        *      succeeded/failed", which are different
+                        *      error codes than "comparison is less
+                        *      than, equal to, or greater than zero".
+                        */
+                       compare = simplepaircmp(state->request,
+                                               vp, myvp);
+                       pairfree(&myvp);
+                       
+               } else {
+                       /*
+                        *      FIXME: Do something for RHS type?
+                        */
+                       printf("CMP %s %s\n", lhs_buffer, this->rhs);
+                       compare = strcmp(lhs_buffer, this->rhs);
+               }
+
+               debug_evaluate("CONDITION COMPARE %d\n", compare);
+               
+               switch (this->compare) {
+               case POLICY_LEX_CMP_EQUALS:
+                       rcode = (compare == 0);
+                       break;
+                       
+               case POLICY_LEX_CMP_NOT_EQUALS:
+                       rcode = (compare != 0);
+                       break;
+                       
+               case POLICY_LEX_LT:
+                       rcode = (compare < 0);
+                       break;
+                       
+               case POLICY_LEX_GT:
+                       rcode = (compare > 0);
+                       break;
+                       
+               case POLICY_LEX_LE:
+                       rcode =(compare <= 0);
+                       break;
+                       
+               case POLICY_LEX_GE:
+                       rcode = (compare >= 0);
+                       break;
+                       
+#ifdef HAVE_REGEX_H
+               case POLICY_LEX_RX_EQUALS:
+               { /* FIXME: copied from src/main/valuepair.c */
+                       int i;
+                       regmatch_t rxmatch[REQUEST_MAX_REGEX + 1];
+                       
+                       /*
+                        *      Include substring matches.
+                        */
+                       if (regcomp(&reg, this->rhs,
+                                   REG_EXTENDED) != 0) {
+                               return FALSE;
+                       }
+                       rad_assert(data != NULL);
+                       rcode = regexec(&reg, data,
+                                       REQUEST_MAX_REGEX + 1,
+                                       rxmatch, 0);
+                       rcode = (rcode == 0);
+                       regfree(&reg);
+                       
+                       /*
+                        *      Add %{0}, %{1}, etc.
+                        */
+                       for (i = 0; i <= REQUEST_MAX_REGEX; i++) {
+                               char *p;
+                               char rxbuffer[256];
+                               
+                               /*
+                                *      Didn't match: delete old
+                                *      match, if it existed.
+                                */
+                               if (!rcode ||
+                                   (rxmatch[i].rm_so == -1)) {
+                                       p = request_data_get(state->request, state->request,
+                                                            REQUEST_DATA_REGEX | i);
+                                       if (p) {
+                                               free(p);
+                                               continue;
+                                       }
+                                               
+                                       /*
+                                        *      No previous match
+                                        *      to delete, stop.
+                                        */
+                                       break;
+                               }
+                               
+                               /*
+                                *      Copy substring into buffer.
+                                */
+                               memcpy(rxbuffer,
+                                      data + rxmatch[i].rm_so,
+                                      rxmatch[i].rm_eo - rxmatch[i].rm_so);
+                               rxbuffer[rxmatch[i].rm_eo - rxmatch[i].rm_so] = '\0';
+                               
+                               /*
+                                *      Copy substring, and add it to
+                                *      the request.
+                                *
+                                *      Note that we don't check
+                                *      for out of memory, which is
+                                *      the only error we can get...
+                                */
+                               p = strdup(rxbuffer);
+                               request_data_add(state->request,
+                                                state->request,
+                                                REQUEST_DATA_REGEX | i,
+                                                p, free);
+                       }
+                       
+               }
+               break;
+               
+               case POLICY_LEX_RX_NOT_EQUALS:
+                       regcomp(&reg, this->rhs, REG_EXTENDED|REG_NOSUB);
+                       rad_assert(data != NULL);
+                       rcode = regexec(&reg, data,
+                                       0, NULL, 0);
+                       rcode = (rcode != 0);
+                       regfree(&reg);
+                               break;
+#endif /* HAVE_REGEX_H */
+               default:
+                       rcode = FALSE;
+                       break;
+               } /* switch over comparison operators */
+               break;          /* default from first switch over compare */
+       }
+
+       /*
+        *      No trailing &&, ||
+        */
+       switch (this->child_condition) {
+       default:
+               return rcode;
+
+       case POLICY_LEX_L_AND:
+               if (!rcode) return rcode; /* FALSE && x == FALSE */
+               break;
+
+       case POLICY_LEX_L_OR:
+               if (rcode) return rcode; /* TRUE && x == TRUE */
+               break;
+       }
+
+       /*
+        *      Tail recursion.
+        */
+       this = (const policy_condition_t *) this->child;
+       goto redo;
+
+       return 1;               /* should never reach here */
+}
+
+
+/*
+ *     Evaluate an 'if' statement
+ */
+static int evaluate_if(policy_state_t *state, const policy_item_t *item)
+{
+       int rcode;
+       const policy_if_t *this;
+
+       this = (const policy_if_t *) item;
+
+       /*
+        *      evaluate_condition calls itself recursively.
+        *      We should probably allocate a new state, instead.
+        */
+       rcode = evaluate_condition(state, this->condition);
+       debug_evaluate("IF condition returned %s\n",
+              rcode ? "true" : "false");
+       if (rcode) {
+               rcode = policy_stack_push(state, this->if_true);
+               if (!rcode) return rcode;
+       } else if (this->if_false) {
+               rcode = policy_stack_push(state, this->if_false);
+               if (!rcode) return rcode;
+       }
+
+       /*
+        *      'if' can fail, if the block it's processing fails.
+        */
+       return 1;;
+}
+
+
+/*
+ *     Make a VALUE_PAIR from a policy_assignment_t*
+ *
+ *     The assignment operator has to be '='.
+ */
+static VALUE_PAIR *assign2vp(REQUEST *request,
+                            const policy_assignment_t *assign)
+{
+       VALUE_PAIR *vp;
+       LRAD_TOKEN operator = T_OP_EQ;
+       const char *value = assign->rhs;
+       char buffer[2048];
+
+       if ((assign->rhs_type == POLICY_LEX_DOUBLE_QUOTED_STRING) &&
+           (strchr(assign->rhs, '%') != NULL)) {
+               radius_xlat(buffer, sizeof(buffer), assign->rhs,
+                           request, NULL);
+               value = buffer;
+       }
+
+       /*
+        *      This is crappy.. fix it.
+        */
+       switch (assign->assign) {
+       case POLICY_LEX_ASSIGN:
+               operator = T_OP_EQ;
+               break;
+
+       case POLICY_LEX_SET_EQUALS:
+               operator = T_OP_SET;
+               break;
+       
+       case POLICY_LEX_PLUS_EQUALS:
+               operator = T_OP_ADD;
+               break;
+       
+       default:
+               fprintf(stderr, "Expected '=' for operator, not '%s' at line %d\n",
+                       lrad_int2str(rlm_policy_tokens,
+                                    assign->assign, "?"),
+                       assign->item.lineno);
+               return NULL;
+       }
+       
+       vp = pairmake(assign->lhs, value, operator);
+       if (!vp) {
+               fprintf(stderr, "SHIT: %s %s\n", value, librad_errstr);
+       }
+
+       return vp;
+}
+
+
+/*
+ *     Evaluate a 'packet .= {attrs}' statement
+ */
+static int evaluate_attr_list(policy_state_t *state, const policy_item_t *item)
+{
+       const policy_attributes_t *this;
+       VALUE_PAIR **vps = NULL;
+       VALUE_PAIR *vp, *head, **tail;
+       const policy_item_t *attr;
+
+       this = (const policy_attributes_t *) item;
+
+       switch (this->where) {
+       case POLICY_RESERVED_CONTROL:
+               vps = &(state->request->config_items);
+               break;
+
+       case POLICY_RESERVED_REQUEST:
+               vps = &(state->request->packet->vps);
+               break;
+
+       case POLICY_RESERVED_REPLY:
+               vps = &(state->request->reply->vps);
+               break;
+
+       case POLICY_RESERVED_PROXY_REQUEST:
+               if (!state->request->proxy) return 0; /* FIXME: print error */
+               vps = &(state->request->proxy->vps);
+               break;
+
+       case POLICY_RESERVED_PROXY_REPLY:
+               if (!state->request->proxy_reply) return 0; /* FIXME: print error */
+               vps = &(state->request->proxy_reply->vps);
+               break;
+
+       default:
+               return 0;
+       }
+
+       head = NULL;
+       tail = &head;
+
+       for (attr = this->attributes; attr != NULL; attr = attr->next) {
+               if (attr->type != POLICY_TYPE_ASSIGNMENT) {
+                       fprintf(stderr, "bad assignment in attribute list at line %d\n", attr->lineno);
+                       pairfree(&head);
+                       return 0;
+               }
+
+               vp = assign2vp(state->request, (const policy_assignment_t *) attr);
+               if (!vp) {
+                       fprintf(stderr, "Failed to allocate VP\n");
+                       pairfree(&head);
+                       return 0;
+               }
+               *tail = vp;
+               tail = &(vp->next);
+       }
+
+       switch (this->how) {
+       case POLICY_LEX_SET_EQUALS: /* dangerous: removes all previous things! */
+               pairfree(vps);
+               *vps = head;
+               break;
+
+       case POLICY_LEX_ASSIGN: /* 'union' */
+               pairmove(vps, &head);
+               pairfree(&head);
+               break;
+
+       case POLICY_LEX_CONCAT_EQUALS:
+               pairadd(vps, head);
+               break;
+
+       default:
+               fprintf(stderr, "HUH?\n");
+               pairfree(&head);
+               return 0;
+       }
+
+       state->rcode = RLM_MODULE_UPDATED; /* we did stuff */
+
+       return 1;
+}
+
+
+/*
+ *     Evaluate a reference call to a module.
+ */
+static int evaluate_call(policy_state_t *state, const policy_item_t *item)
+{
+       int rcode;
+       const policy_call_t *this;
+       const policy_named_t *policy;
+
+       this = (const policy_call_t *) item;
+
+       policy = rlm_policy_find(state->inst->policies, this->name);
+       if (!policy) return 0;  /* not found... */
+       
+       DEBUG2("rlm_policy: Evaluating policy %s", this->name);
+       
+       rad_assert(policy->policy->type != POLICY_TYPE_BAD);
+       rad_assert(policy->policy->type < POLICY_TYPE_NUM_TYPES);
+
+       /*
+        *      Push the name of the function onto the stack,
+        *      so that we can catch recursive calls.
+        *
+        *      The "pop" function will skip over it when it sees it.
+        */
+       rcode = policy_stack_push(state, (const policy_item_t *) policy);
+       if (!rcode) {
+               return rcode;
+       }
+
+       /*
+        *      Push it onto the stack.  Other code will take care of
+        *      calling it.
+        */
+       rcode = policy_stack_push(state, policy->policy);
+       if (!rcode) {
+               return rcode;
+       }
+
+       return 1;
+}
+
+
+/*
+ *     Evaluate a return statement
+ */
+static int evaluate_return(policy_state_t *state, const policy_item_t *item)
+{
+       const policy_return_t *this;
+
+       this = (const policy_return_t *) item;
+       state->rcode = this->rcode;
+       
+       return 1;               /* we succeeded */
+}
+
+
+/*
+ *     Evaluate a module statement
+ */
+static int evaluate_module(policy_state_t *state, const policy_item_t *item)
+{
+       const policy_module_t *this;
+
+       this = (const policy_module_t *) item;
+
+       /*
+        *      Just to be paranoid.  Maybe we want to loosen this
+        *      restriction in the future?
+        */
+       if (this->component != state->component) {
+               DEBUG2("rlm_policy: Cannot mix & match components");
+               return 0;
+       }
+
+       DEBUG2("rlm_policy: begin nested call");
+       state->rcode = modcall(this->component, this->mc, state->request);
+       DEBUG2("rlm_policy: end nested call");
+       
+       return 1;               /* we succeeded */
+}
+
+
+/*
+ *     State machine stuff.
+ */
+typedef int (*policy_evaluate_type_t)(policy_state_t *, const policy_item_t *);
+
+
+/*
+ *     MUST be kept in sync with policy_type_t
+ */
+static policy_evaluate_type_t evaluate_functions[POLICY_TYPE_NUM_TYPES] = {
+       NULL,                   /* POLICY_TYPE_BAD */
+       evaluate_if,
+       evaluate_condition,
+       evaluate_assignment,
+       evaluate_attr_list,
+       evaluate_print,
+       NULL,                   /* define a named policy.. */
+       evaluate_call,
+       evaluate_return,
+       evaluate_module
+};
+
+
+/*
+ *     Evaluate a policy, keyed by name.
+ */
+static int policy_evaluate_name(policy_state_t *state, const char *name)
+{
+       int rcode;
+       const policy_item_t *this;
+       policy_named_t mypolicy, *policy;
+       
+       mypolicy.name = name;
+       policy = rbtree_finddata(state->inst->policies, &mypolicy);
+       if (!policy) return RLM_MODULE_FAIL;
+       
+       DEBUG2("rlm_policy: Evaluating policy %s", name);
+       
+       rad_assert(policy->item.type != POLICY_TYPE_BAD);
+       rad_assert(policy->item.type < POLICY_TYPE_NUM_TYPES);
+       
+       rcode = policy_stack_push(state, policy->policy);
+       if (!rcode) {
+               return RLM_MODULE_FAIL;
+       }
+
+       /*
+        *      FIXME: Look for magic keywords like "return",
+        *      where the packet gets accepted/rejected/whatever
+        */
+       while (policy_stack_pop(state, &this)) {
+               rad_assert(this != NULL);
+               rad_assert(this->type != POLICY_TYPE_BAD);
+               rad_assert(this->type < POLICY_TYPE_NUM_TYPES);
+               
+               debug_evaluate("Evaluating at line %d\n",
+                              this->lineno);
+               rcode = (*evaluate_functions[this->type])(state,
+                                                         this);
+               if (!rcode) {
+                       return RLM_MODULE_FAIL;
+               }
+       } /* loop until the stack is empty */
+
+       return state->rcode;
+}
+
+
+/*
+ *     Evaluate, which is pretty close to print, but we look at what
+ *     we're printing.
+ */
+int rlm_policy_evaluate(rlm_policy_t *inst, REQUEST *request, const char *name)
+{
+       int rcode;
+       policy_state_t *state;
+
+       state = rad_malloc(sizeof(*state));
+       memset(state, 0, sizeof(*state));
+       state->request = request;
+       state->inst = inst;
+       state->rcode = RLM_MODULE_OK;
+       state->component = lrad_str2int(policy_component_names, name,
+                                       RLM_COMPONENT_COUNT);
+
+       rcode = policy_evaluate_name(state, name);
+
+       free(state);
+
+       return rcode;           /* evaluated OK. */
+}
diff --git a/src/modules/rlm_policy/parse.c b/src/modules/rlm_policy/parse.c
new file mode 100644 (file)
index 0000000..2d2406a
--- /dev/null
@@ -0,0 +1,1618 @@
+/*
+ * parse.c             Parse a policy language
+ *
+ * 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 2004  Alan DeKok <aland@ox.org>
+ * Copyright 2006  The FreeRADIUS server project
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include "rlm_policy.h"
+
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#endif
+
+#include <freeradius-devel/modules.h>
+
+const LRAD_NAME_NUMBER policy_return_codes[] = {
+       { "reject", RLM_MODULE_REJECT },
+       { "fail", RLM_MODULE_FAIL },
+       { "ok", RLM_MODULE_OK },
+       { "handled", RLM_MODULE_HANDLED },
+       { "invalid", RLM_MODULE_INVALID },
+       { "userlock", RLM_MODULE_USERLOCK },
+       { "notfound", RLM_MODULE_NOTFOUND },
+       { "noop", RLM_MODULE_NOOP },
+       { "updated", RLM_MODULE_UPDATED },
+       { NULL, RLM_MODULE_NUMCODES }
+};
+
+/*
+ *     Explanations of what the lexical tokens are.
+ */
+static const LRAD_NAME_NUMBER policy_explanations[] = {
+       { "invalid input", POLICY_LEX_BAD },
+       { "end of file", POLICY_LEX_EOF },
+       { "end of line", POLICY_LEX_EOL },
+       { "whitespace", POLICY_LEX_WHITESPACE },
+       { "hash mark", POLICY_LEX_HASH },
+       { "left bracket", POLICY_LEX_L_BRACKET },
+       { "right bracket", POLICY_LEX_R_BRACKET },
+       { "{", POLICY_LEX_LC_BRACKET },
+       { "}", POLICY_LEX_RC_BRACKET },
+       { "comma", POLICY_LEX_COMMA },
+       { "logical AND", POLICY_LEX_L_AND },
+       { "logical OR", POLICY_LEX_L_OR },
+       { "AND", POLICY_LEX_AND },
+       { "OR", POLICY_LEX_OR },
+       { "logical NOT", POLICY_LEX_L_NOT },
+       { "assignment", POLICY_LEX_ASSIGN },
+       { "comparison", POLICY_LEX_CMP_EQUALS },
+       { "comparison", POLICY_LEX_CMP_NOT_EQUALS },
+       { "comparison", POLICY_LEX_LT },
+       { "comparison", POLICY_LEX_GT },
+       { "comparison", POLICY_LEX_LE },
+       { "comparison", POLICY_LEX_GT },
+       { "comparison", POLICY_LEX_RX_EQUALS },
+       { "comparison", POLICY_LEX_RX_NOT_EQUALS },
+       { "double quoted string", POLICY_LEX_DOUBLE_QUOTED_STRING },
+       { "single quoted string", POLICY_LEX_SINGLE_QUOTED_STRING },
+       { "back quoted string", POLICY_LEX_BACK_QUOTED_STRING },
+       { "bare word", POLICY_LEX_BARE_WORD },
+
+       { NULL, -1 }
+};
+
+
+const LRAD_NAME_NUMBER rlm_policy_tokens[] = {
+       { "EOF", POLICY_LEX_EOF },
+       { "#", POLICY_LEX_HASH },
+       { "(", POLICY_LEX_L_BRACKET },
+       { ")", POLICY_LEX_R_BRACKET },
+       { "{", POLICY_LEX_LC_BRACKET },
+       { "}", POLICY_LEX_RC_BRACKET },
+       { ",", POLICY_LEX_COMMA },
+       { "&&", POLICY_LEX_L_AND },
+       { "||", POLICY_LEX_L_OR },
+       { "&", POLICY_LEX_AND },
+       { "|", POLICY_LEX_OR },
+       { "!", POLICY_LEX_L_NOT },
+       { "=", POLICY_LEX_ASSIGN },
+       { "==", POLICY_LEX_CMP_EQUALS },
+       { "!=", POLICY_LEX_CMP_NOT_EQUALS },
+       { "=*", POLICY_LEX_CMP_TRUE },
+       { "!*", POLICY_LEX_CMP_FALSE },
+       { "<", POLICY_LEX_LT },
+       { ">", POLICY_LEX_GT },
+       { "<=", POLICY_LEX_LE },
+       { ">=", POLICY_LEX_GT },
+       { "=~", POLICY_LEX_RX_EQUALS },
+       { "!~", POLICY_LEX_RX_NOT_EQUALS },
+       { ".=", POLICY_LEX_CONCAT_EQUALS },
+       { ":=", POLICY_LEX_SET_EQUALS },
+       { "double quoted string", POLICY_LEX_DOUBLE_QUOTED_STRING },
+       { "single quoted string", POLICY_LEX_SINGLE_QUOTED_STRING },
+       { "back quoted string", POLICY_LEX_BACK_QUOTED_STRING },
+       { "bare word", POLICY_LEX_BARE_WORD },
+
+       { NULL, -1 }
+};
+
+
+/*
+ *     Hand-coded lexical analysis of a string.
+ *     Handed input string, updates token, possible a decoded
+ *     string in buffer, and returns the pointer to the next token.
+ *
+ *     Lexical tokens cannot cross a string boundary.
+ */
+static const char *policy_lex_string(const char *input,
+                                    policy_lex_t *token,
+                                    char *buffer, size_t buflen)
+{
+       rad_assert(input != NULL);
+
+       if (buffer) *buffer = '\0';
+       
+       switch (*input) {
+       case '\0':
+               *token = POLICY_LEX_EOL;
+               return NULL;    /* nothing more to do */
+               
+       case ' ':
+       case '\t':
+       case '\r':
+       case '\n':
+               /*
+                *      Skip over all of the whitespace in one swell foop.
+                */
+               *token = POLICY_LEX_WHITESPACE;
+               while ((*input == ' ') || (*input == '\t') ||
+                      (*input == '\r') || (*input == '\n')) input++;
+               return input;   /* point to next non-whitespace character */
+               
+       case '#':               /* ignore everything to the end of the line */
+               *token = POLICY_LEX_EOL;
+               return NULL;
+
+       case '(':
+               *token = POLICY_LEX_L_BRACKET;
+               return input + 1;
+               
+       case ')':
+               *token = POLICY_LEX_R_BRACKET;
+               return input + 1;
+               
+       case '{':
+               *token = POLICY_LEX_LC_BRACKET;
+               return input + 1;
+               
+       case '}':
+               *token = POLICY_LEX_RC_BRACKET;
+               return input + 1;
+               
+       case ',':
+               *token = POLICY_LEX_COMMA;
+               return input + 1;
+
+       case '+':
+               switch (input[1]) {
+               case '=':
+                       *token = POLICY_LEX_PLUS_EQUALS;
+                       input++;
+                       break;
+
+               default:
+                       *token = POLICY_LEX_PLUS;
+                       break;
+               }
+               return input + 1;
+
+       case '-':
+               switch (input[1]) {
+               case '=':
+                       *token = POLICY_LEX_MINUS_EQUALS;
+                       input++;
+                       break;
+
+               default:
+                       *token = POLICY_LEX_MINUS;
+                       break;
+               }
+               return input + 1;
+
+       case '.':
+               if (input[1] == '=') {
+                       *token = POLICY_LEX_CONCAT_EQUALS;
+                       return input + 2;
+               }
+               *token = POLICY_LEX_BAD;
+               return input + 1;
+
+       case ':':
+               if (input[1] == '=') {
+                       *token = POLICY_LEX_SET_EQUALS;
+                       return input + 2;
+               }
+               *token = POLICY_LEX_BAD;
+               return input + 1;
+
+       case '&':
+               switch (input[1]) {
+               case '&':
+                       *token = POLICY_LEX_L_AND;
+                       input++;
+                       break;
+
+               case '=':
+                       *token = POLICY_LEX_AND_EQUALS;
+                       input++;
+                       break;
+
+               default:
+                       *token = POLICY_LEX_AND;
+               }
+               return input + 1;
+               
+       case '|':
+               switch (input[1]) {
+               case '|':
+                       *token = POLICY_LEX_L_OR;
+                       input++;
+                       break;
+
+               case '=':
+                       *token = POLICY_LEX_OR_EQUALS;
+                       input++;
+                       break;
+
+               default:
+                       *token = POLICY_LEX_OR;
+               }
+               return input + 1;
+               
+       case '!':
+               switch (input[1]) {
+               case '=':
+                       input++;
+                       *token = POLICY_LEX_CMP_NOT_EQUALS;
+                       break;
+
+               case '~':
+                       input++;
+                       *token = POLICY_LEX_RX_NOT_EQUALS;
+                       break;
+
+               case '*':
+                       input++;
+                       *token = POLICY_LEX_CMP_FALSE;
+                       break;
+
+               default:
+                       *token = POLICY_LEX_L_NOT;
+               }
+               return input + 1;
+               
+       case '=':
+               switch (input[1]) {
+               case '=':
+                       input++;
+                       *token = POLICY_LEX_CMP_EQUALS;
+                       break;
+
+               case '~':
+                       input++;
+                       *token = POLICY_LEX_RX_EQUALS;
+                       break;
+
+               case '*':
+                       input++;
+                       *token = POLICY_LEX_CMP_TRUE;
+                       break;
+
+               default:
+                       *token = POLICY_LEX_ASSIGN;
+               }
+               return input + 1;
+               
+       case '<':
+               if (input[1] == '=') {
+                       input++;
+                       *token = POLICY_LEX_LE;
+               } else {
+                       *token = POLICY_LEX_LT;
+               }
+               return input + 1;
+               
+       case '>':
+               if (input[1] == '=') {
+                       input++;
+                       *token = POLICY_LEX_GE;
+               } else {
+                       *token = POLICY_LEX_GT;
+               }
+               return input + 1;
+
+       case '"':
+               if (buflen < 2) {
+                       *token = POLICY_LEX_BAD;
+                       return input + 1;
+               }
+               
+               input++;
+               while (*input != '"') {
+                       /*
+                        *      Strings can't pass EOL.
+                        */
+                       if (!*input) {
+                               return POLICY_LEX_BAD;
+                       }
+
+                       /*
+                        *      FIXME: Embedded quotes?
+                        */
+                       *(buffer++) = *(input++);
+                       buflen--;
+                       
+                       /*
+                        *      FIXME: Print more warnings?
+                        */
+                       if (buflen == 1) {
+                               break;
+                       }
+               }
+               *buffer = '\0';
+               
+               *token = POLICY_LEX_DOUBLE_QUOTED_STRING;
+               return input + 1; /* skip trailing '"' */
+
+       default:                /* bare word */
+               break;
+       }
+
+       /*
+        *      It's a bare word, with nowhere to put it.  Die.
+        */
+       if (!buffer) {
+               *token = POLICY_LEX_BAD;
+               return input + 1;
+       }
+       
+       /*
+        *      Getting one character is stupid.
+        */
+       if (buflen < 2) {
+               *token = POLICY_LEX_BAD;
+               return input + 1;
+       }
+       
+       /*
+        *      Bare words are [-a-zA-Z0-9.]+
+        */
+       while (*input) {
+               if (!(((*input >= '0') && (*input <= '9')) ||
+                     ((*input >= 'a') && (*input <= 'z')) ||
+                     ((*input >= 'A') && (*input <= 'Z')) ||
+                     (*input == '-') || (*input == '.') ||
+                     (*input == ':') || (*input == '_'))) {
+                       break;
+               }
+               *(buffer++) = *(input++);
+               buflen--;
+               
+               /*
+                *      FIXME: Print more warnings?
+                */
+               if (buflen == 1) {
+                       break;
+               }
+       }
+       *buffer = '\0';
+       
+       *token = POLICY_LEX_BARE_WORD;
+       return input;
+}
+
+
+/*
+ *     We want to lexically analyze a file, so we need a wrapper
+ *     around the lexical analysis of strings.
+ */
+typedef struct policy_lex_file_t {
+       FILE            *fp;
+       const char      *parse;
+       const char      *filename;
+       int             lineno;
+       int             debug;
+       rbtree_t        *policies;
+       policy_lex_t    token;
+       char            buffer[1024];
+} policy_lex_file_t;
+
+
+#define POLICY_LEX_FLAG_RETURN_EOL  (1 << 0)
+#define POLICY_LEX_FLAG_PEEK        (1 << 1)
+#define POLICY_LEX_FLAG_PRINT_TOKEN (1 << 2)
+
+#define debug_tokens if (lexer->debug & POLICY_DEBUG_PRINT_TOKENS) printf
+
+
+/*
+ *     Function to return a token saying what it read, and possibly
+ *     a buffer of the quoted string or bare word.
+ */
+static policy_lex_t policy_lex_file(policy_lex_file_t *lexer,
+                                   int flags,
+                                   char *mystring, size_t mystringlen)
+{
+       policy_lex_t token = POLICY_LEX_BARE_WORD; /* to prime it */
+
+       if (lexer->debug & POLICY_DEBUG_PRINT_TOKENS) {
+               flags |= POLICY_LEX_FLAG_PRINT_TOKEN;
+       }
+
+       if (!lexer->fp) {
+               return POLICY_LEX_EOF;
+       }
+
+       /*
+        *      Starting off, the buffer needs to be primed.
+        */
+       if (!lexer->parse) {
+               lexer->parse = fgets(lexer->buffer,
+                                    sizeof(lexer->buffer),
+                                    lexer->fp);
+               
+               if (!lexer->parse) {
+                       return POLICY_LEX_EOF;
+               }
+
+               lexer->lineno = 1;
+       } /* buffer is primed, read stuff */
+
+       if (lexer->token != POLICY_LEX_BAD) {
+               token = lexer->token;
+               lexer->token = POLICY_LEX_BAD;
+               return token;
+       }
+
+       /*
+        *      Ignore whitespace, and keep filling the buffer
+        */
+       while (lexer->parse) {
+               const char *next;
+
+               next = policy_lex_string(lexer->parse, &token,
+                                        mystring, mystringlen);
+               switch (token) {
+               case POLICY_LEX_WHITESPACE: /* skip whitespace */
+                       lexer->parse = next;
+                       continue;
+
+               case POLICY_LEX_EOL: /* read another line */
+                       lexer->parse = fgets(lexer->buffer,
+                                            sizeof(lexer->buffer),
+                                            lexer->fp);
+                       lexer->lineno++;
+                       if (flags & POLICY_LEX_FLAG_RETURN_EOL) {
+                               return POLICY_LEX_EOL;
+                       }
+                       break;  /* read another token */
+
+               default:        /* return the token */
+                       if (!(flags & POLICY_LEX_FLAG_PEEK)) {
+                               lexer->parse = next;
+                       }
+                       if (flags & POLICY_LEX_FLAG_PRINT_TOKEN) {
+                               debug_tokens("[%s token %s] ",
+                                            (flags & POLICY_LEX_FLAG_PEEK) ? "peek " : "",
+                                            lrad_int2str(rlm_policy_tokens,
+                                                         token, "?"));
+                       }
+                       return token;
+                       break;
+               }
+       } /* loop until EOF */
+
+       /*
+        *      Close it for the user.
+        */
+       fclose(lexer->fp);
+       lexer->fp = NULL;
+
+       return POLICY_LEX_EOF;
+}
+
+
+/*
+ *     Push a token back onto the input.
+ *
+ *     FIXME: Push words, too?
+ */
+static int policy_lex_push_token(policy_lex_file_t *lexer,
+                                policy_lex_t token)
+{
+       if (lexer->token != POLICY_LEX_BAD) {
+               rad_assert(0 == 1);
+               return 0;
+       }
+
+       lexer->token = token;
+       return 1;
+}
+
+
+/*
+ *     Forward declarations.
+ */
+static int parse_block(policy_lex_file_t *lexer, policy_item_t **tail);
+
+
+/*
+ *     Map reserved words to tokens, and vice versa.
+ */
+const LRAD_NAME_NUMBER policy_reserved_words[] = {
+       { "if", POLICY_RESERVED_IF },
+       { "else", POLICY_RESERVED_ELSE },
+       { "debug", POLICY_RESERVED_DEBUG },
+       { "print", POLICY_RESERVED_PRINT },
+       { "policy", POLICY_RESERVED_POLICY },
+       { "control", POLICY_RESERVED_CONTROL },
+       { "request", POLICY_RESERVED_REQUEST },
+       { "reply", POLICY_RESERVED_REPLY },
+       { "proxy-request", POLICY_RESERVED_PROXY_REQUEST },
+       { "proxy-reply", POLICY_RESERVED_PROXY_REPLY },
+       { "include", POLICY_RESERVED_INCLUDE },
+       { "return", POLICY_RESERVED_RETURN },
+       { "module", POLICY_RESERVED_MODULE },
+       { NULL, POLICY_RESERVED_UNKNOWN }
+};
+
+
+/*
+ *     Simplifies some later coding
+ */
+static int policy_lex_str2int(policy_lex_file_t *lexer,
+                             const LRAD_NAME_NUMBER *table, int default_value)
+{
+       policy_lex_t token;
+       char buffer[256];
+
+       token = policy_lex_file(lexer, 0, buffer, sizeof(buffer));
+       if (token != POLICY_LEX_BARE_WORD) {
+               fprintf(stderr, "%s[%d]: Unexpected token\n",
+                       lexer->filename, lexer->lineno);
+               return default_value;
+       }
+
+       return lrad_str2int(table, buffer, default_value);
+}
+
+
+/*
+ *     print foo
+ *     print "foo"
+ */
+static int parse_print(policy_lex_file_t *lexer, policy_item_t **tail)
+{
+       policy_lex_t token;
+       char mystring[1024];
+       policy_print_t *this;
+
+       debug_tokens("[PRINT] ");
+
+       this = rad_malloc(sizeof(*this));
+       memset(this, 0, sizeof(*this));
+
+       this->item.type = POLICY_TYPE_PRINT;
+       this->item.lineno = lexer->lineno;
+
+       token = policy_lex_file(lexer, 0, mystring, sizeof(mystring));
+       if ((token != POLICY_LEX_BARE_WORD) &&
+           (token != POLICY_LEX_DOUBLE_QUOTED_STRING)) {
+               fprintf(stderr, "%s[%d]: Bad print command\n",
+                       lexer->filename, lexer->lineno);
+               return 0;
+       }
+
+       this->rhs_type = token;
+       this->rhs = strdup(mystring);
+
+       *tail = (policy_item_t *) this;
+       
+       return 1;
+}
+
+
+/*
+ * (foo == bar), with nested conditionals.
+ */
+static int parse_condition(policy_lex_file_t *lexer, policy_item_t **tail)
+{
+       int rcode;
+       policy_lex_t token, compare;
+       char lhs[256], rhs[256];
+       policy_condition_t *this;
+
+       token = policy_lex_file(lexer, 0, lhs, sizeof(lhs));
+       if (token != POLICY_LEX_L_BRACKET) {
+               fprintf(stderr, "%s[%d]: Expected '(', got \"%s\"\n",
+                       lexer->filename, lexer->lineno,
+                       lrad_int2str(rlm_policy_tokens, token, lhs));
+               return 0;
+       }
+
+       this = rad_malloc(sizeof(*this));
+       memset(this, 0, sizeof(*this));
+
+       this->item.type = POLICY_TYPE_CONDITIONAL;
+       this->item.lineno = lexer->lineno;
+
+       token = policy_lex_file(lexer, 0, lhs, sizeof(lhs));
+       switch (token) {
+       case POLICY_LEX_L_BRACKET:
+               if (!policy_lex_push_token(lexer, token)) {
+                       rlm_policy_free_item((policy_item_t *) this);
+                       return 0;
+               }
+               
+               this->compare = POLICY_LEX_L_BRACKET;
+               this->child_condition = POLICY_LEX_L_BRACKET;
+               rcode = parse_condition(lexer, &(this->child));
+               if (!rcode) {
+                       rlm_policy_free_item((policy_item_t *) this);
+                       return rcode;
+               }
+               break;
+
+       case POLICY_LEX_L_NOT:
+               this->compare = POLICY_LEX_L_NOT;
+               debug_tokens("[NOT] ");
+
+               /*
+                *      FIXME: allow !foo, !foo=bar, etc.
+                *
+                *      Maybe we should learn how to use lex && yacc?
+                */
+
+               rcode = parse_condition(lexer, &(this->child));
+               if (!rcode) {
+                       rlm_policy_free_item((policy_item_t *) this);
+                       return rcode;
+               }
+               break;
+
+       case POLICY_LEX_BARE_WORD:
+               this->lhs_type = token;
+               token = policy_lex_file(lexer, POLICY_LEX_FLAG_PEEK, NULL, 0);
+               if (token == POLICY_LEX_L_BRACKET) {
+                       debug_tokens("[IF-CALL %s] ", lhs);
+
+                       /*
+                        *      Function call.
+                        */
+                       if (rlm_policy_find(lexer->policies, lhs) == NULL) {
+                               fprintf(stderr, "%s[%d]: Undefined function \"%s\"\n",
+                                       lexer->filename, lexer->lineno,
+                                       lhs);
+                               rlm_policy_free_item((policy_item_t *) this);
+                               return 0;
+                               
+                       }
+                       
+                       /*
+                        *      this->lhs set up below, after "check"
+                        */
+                       this->lhs_type = POLICY_LEX_FUNCTION;
+
+                       /*
+                        *      Copied from parse_call
+                        */
+                       token = policy_lex_file(lexer, 0, NULL, 0);
+                       if (token != POLICY_LEX_L_BRACKET) {
+                               fprintf(stderr, "%s[%d]: Expected left bracket, got \"%s\"\n",
+                                       lexer->filename, lexer->lineno,
+                                       lrad_int2str(rlm_policy_tokens, token, "?"));
+                               return 0;
+                       }
+                       
+                       token = policy_lex_file(lexer, 0, NULL, 0);
+                       if (token != POLICY_LEX_R_BRACKET) {
+                               fprintf(stderr, "%s[%d]: Expected right bracket, got \"%s\"\n",
+                                       lexer->filename, lexer->lineno,
+                                       lrad_int2str(rlm_policy_tokens, token, "?"));
+                               return 0;
+                       }
+               } /* else it's a comparison? */
+               goto check;
+
+       case POLICY_LEX_DOUBLE_QUOTED_STRING:
+               this->lhs_type = token;
+
+               /*
+                *      Got word.  May just be test for existence.
+                */
+       check:
+               token = policy_lex_file(lexer, POLICY_LEX_FLAG_PEEK, NULL, 0);
+               if (token == POLICY_LEX_R_BRACKET) {
+                       debug_tokens("[TEST %s] ", lhs);
+                       this->lhs = strdup(lhs);
+                       this->compare = POLICY_LEX_CMP_TRUE;
+                       break;
+               }
+
+               compare = policy_lex_file(lexer, 0, rhs, sizeof(rhs));
+               switch (compare) {
+               case POLICY_LEX_CMP_EQUALS:
+               case POLICY_LEX_CMP_NOT_EQUALS:
+               case POLICY_LEX_RX_EQUALS:
+               case POLICY_LEX_RX_NOT_EQUALS:
+               case POLICY_LEX_CMP_TRUE:
+               case POLICY_LEX_CMP_FALSE:
+               case POLICY_LEX_LT:
+               case POLICY_LEX_GT:
+               case POLICY_LEX_LE:
+               case POLICY_LEX_GE:
+                       break;
+
+               default:
+                       fprintf(stderr, "%s[%d]: Invalid operator \"%s\"\n",
+                               lexer->filename, lexer->lineno,
+                               lrad_int2str(rlm_policy_tokens, compare, rhs));
+                       rlm_policy_free_item((policy_item_t *) this);
+                       return 0;
+               }
+
+               token = policy_lex_file(lexer, 0, rhs, sizeof(rhs));
+               if ((token != POLICY_LEX_BARE_WORD) &&
+                   (token != POLICY_LEX_DOUBLE_QUOTED_STRING)) {
+                       fprintf(stderr, "%s[%d]: Unexpected rhs token\n",
+                               lexer->filename, lexer->lineno);
+                       rlm_policy_free_item((policy_item_t *) this);
+                       return 0;
+               }
+               debug_tokens("[COMPARE (%s %s %s)] ",
+                      lhs, lrad_int2str(rlm_policy_tokens, compare, "?"), rhs);
+               this->lhs = strdup(lhs);
+               this->compare = compare;
+               this->rhs_type = token;
+               this->rhs = strdup(rhs);
+               break;
+
+       default:
+               fprintf(stderr, "%s[%d]: Unexpected lhs token\n",
+                       lexer->filename, lexer->lineno);
+               rlm_policy_free_item((policy_item_t *) this);
+               return 0;
+       }
+
+       token = policy_lex_file(lexer, 0, NULL, 0);
+       if (token != POLICY_LEX_R_BRACKET) {
+               fprintf(stderr, "%s[%d]: Expected ')', got \"%s\"\n",
+                       lexer->filename, lexer->lineno,
+                       lrad_int2str(rlm_policy_tokens, token, "?"));
+               rlm_policy_free_item((policy_item_t *) this);
+               return 0;
+       }
+
+       /*
+        *      After the end of condition, we MAY have && or ||
+        */
+       token = policy_lex_file(lexer, POLICY_LEX_FLAG_PEEK, NULL, 0);
+       if ((token == POLICY_LEX_L_AND) || (token == POLICY_LEX_L_OR)) {
+               token = policy_lex_file(lexer, 0, NULL, 0); /* skip over it */
+               debug_tokens("[%s] ",
+                      lrad_int2str(rlm_policy_tokens, token, "?"));
+               this->child_condition = token;
+               rcode = parse_condition(lexer, &(this->child));
+               if (!rcode) {
+                       rlm_policy_free_item((policy_item_t *) this);
+                       return 0;
+               }
+       }
+
+       *tail = (policy_item_t *) this;
+
+       return 1;
+}
+
+
+/*
+ *     if (...) {...}
+ *     if (...) {...} else {...}
+ *     if (...) {...} else if ...
+ */
+static int parse_if(policy_lex_file_t *lexer, policy_item_t **tail)
+{
+       int rcode;
+       policy_lex_t token;
+       char mystring[256];
+       policy_if_t *this;
+
+       debug_tokens("[IF] ");
+
+       this = rad_malloc(sizeof(*this));
+       memset(this, 0, sizeof(*this));
+
+       this->item.type = POLICY_TYPE_IF;
+       this->item.lineno = lexer->lineno;
+
+       rcode = parse_condition(lexer, &(this->condition));
+       if (!rcode) {
+               rlm_policy_free_item((policy_item_t *) this);
+               return rcode;
+       }
+
+       rcode = parse_block(lexer, &(this->if_true));
+       if (!rcode) {
+               rlm_policy_free_item((policy_item_t *) this);
+               return rcode;
+       }
+
+       token = policy_lex_file(lexer, POLICY_LEX_FLAG_PEEK,
+                               mystring, sizeof(mystring));
+       if ((token == POLICY_LEX_BARE_WORD) &&
+           (lrad_str2int(policy_reserved_words, mystring,
+                         POLICY_RESERVED_UNKNOWN) == POLICY_RESERVED_ELSE)) {
+               debug_tokens("[ELSE] ");
+               token = policy_lex_file(lexer, 0, mystring, sizeof(mystring));
+
+               token = policy_lex_file(lexer, POLICY_LEX_FLAG_PEEK,
+                                       mystring, sizeof(mystring));
+               if ((token == POLICY_LEX_BARE_WORD) &&
+                   (lrad_str2int(policy_reserved_words, mystring,
+                                 POLICY_RESERVED_UNKNOWN) == POLICY_RESERVED_IF)) {
+                       token = policy_lex_file(lexer, 0,
+                                               mystring, sizeof(mystring));
+                       rcode = parse_if(lexer, &(this->if_false));
+               } else {
+                       rcode = parse_block(lexer, &(this->if_false));
+               }
+               if (!rcode) {
+                       rlm_policy_free_item((policy_item_t *) this);
+                       return rcode;
+               }
+       }
+
+       debug_tokens("\n");
+
+       /*
+        *      Empty "if" condition, don't even bother remembering
+        *      it.
+        */
+       if (!this->if_true && !this->if_false) {
+               debug_tokens("Discarding empty \"if\" statement at line %d\n",
+                            this->item.lineno);
+               rlm_policy_free_item((policy_item_t *) this);
+               return 1;
+       }
+
+       *tail = (policy_item_t *) this;
+       
+       return 1;
+}
+
+
+/*
+ *     Parse a reference to a named policy "foo()"
+ */
+static int parse_call(policy_lex_file_t *lexer, policy_item_t **tail,
+                     const char *name)
+{
+       policy_lex_t token;
+       policy_call_t *this;
+
+       debug_tokens("[CALL] ");
+
+       token = policy_lex_file(lexer, 0, NULL, 0);
+       if (token != POLICY_LEX_L_BRACKET) {
+               fprintf(stderr, "%s[%d]: Expected left bracket, got \"%s\"\n",
+                       lexer->filename, lexer->lineno,
+                       lrad_int2str(rlm_policy_tokens, token, "?"));
+               return 0;
+       }
+
+       token = policy_lex_file(lexer, 0, NULL, 0);
+       if (token != POLICY_LEX_R_BRACKET) {
+               fprintf(stderr, "%s[%d]: Expected right bracket, got \"%s\"\n",
+                       lexer->filename, lexer->lineno,
+                       lrad_int2str(rlm_policy_tokens, token, "?"));
+               return 0;
+       }
+
+       this = rad_malloc(sizeof(*this));
+       memset(this, 0, sizeof(*this));
+
+       this->item.type = POLICY_TYPE_CALL;
+       this->item.lineno = lexer->lineno;
+
+       this->name = strdup(name);
+
+       *tail = (policy_item_t *) this;
+
+       return 1;
+}
+
+
+/*
+ *     Edit/update/replace an attribute list
+ */
+static int parse_attribute_block(policy_lex_file_t *lexer,
+                                policy_item_t **tail,
+                                policy_reserved_word_t where)
+{
+       policy_lex_t token;
+       policy_attributes_t *this;
+       char buffer[32];
+       
+       token = policy_lex_file(lexer, 0, buffer, sizeof(buffer));
+       switch (token) {
+       case POLICY_LEX_ASSIGN:
+       case POLICY_LEX_SET_EQUALS:
+       case POLICY_LEX_CONCAT_EQUALS:
+               break;
+
+       default:
+               fprintf(stderr, "%s[%d]: Unexpected token %s\n",
+                       lexer->filename, lexer->lineno,
+                       lrad_int2str(rlm_policy_tokens, token, "?"));
+               return 0;       /* unknown */
+       }
+       
+       this = rad_malloc(sizeof(*this));
+       memset(this, 0, sizeof(*this));
+
+       this->item.type = POLICY_TYPE_ATTRIBUTE_LIST;
+       this->item.lineno = lexer->lineno;
+       this->where = where;
+       this->how = token;
+
+       if (!parse_block(lexer, &(this->attributes))) {
+               rlm_policy_free_item((policy_item_t *) this);
+               return 0;
+       }
+
+       *tail = (policy_item_t *) this;
+       return 1;
+}
+
+
+/*
+ *     Parse a return statement.
+ */
+static int parse_return(policy_lex_file_t *lexer, policy_item_t **tail)
+{
+       int rcode;
+       policy_lex_t token;
+       policy_return_t *this;
+
+       rcode = policy_lex_str2int(lexer, policy_return_codes,
+                                  RLM_MODULE_NUMCODES);
+       if (rcode == RLM_MODULE_NUMCODES) {
+               fprintf(stderr, "%s[%d]: Invalid return code\n",
+                       lexer->filename, lexer->lineno);
+               return 0;
+       }
+
+       /*
+        *      Look for more sutff
+        */
+       token = policy_lex_file(lexer, POLICY_LEX_FLAG_PEEK,
+                               NULL, sizeof(0));
+       if (token != POLICY_LEX_RC_BRACKET) {
+               fprintf(stderr, "%s[%d]: return statement must be the last statement in a policy.\n",
+                       lexer->filename, lexer->lineno);
+               return 0;
+       }
+
+       this = rad_malloc(sizeof(*this));
+       memset(this, 0, sizeof(*this));
+
+       this->item.type = POLICY_TYPE_RETURN;
+       this->item.lineno = lexer->lineno;
+       this->rcode = rcode;
+
+       *tail = (policy_item_t *) this;
+
+       return 1;
+}
+
+
+const LRAD_NAME_NUMBER policy_component_names[] = {
+       { "authenticate", RLM_COMPONENT_AUTH },
+       { "authorize", RLM_COMPONENT_AUTZ },
+       { "preacct", RLM_COMPONENT_PREACCT },
+       { "accounting", RLM_COMPONENT_ACCT },
+       { "session", RLM_COMPONENT_SESS },
+       { "pre-proxy", RLM_COMPONENT_PRE_PROXY },
+       { "post-proxy", RLM_COMPONENT_POST_PROXY },
+       { "post-auth", RLM_COMPONENT_POST_AUTH },
+       { NULL, RLM_COMPONENT_COUNT }
+};
+
+/*
+ *     Parse a module statement.
+ */
+static int parse_module(policy_lex_file_t *lexer, policy_item_t **tail)
+{
+       int component;
+       policy_lex_t token;
+       policy_module_t *this;
+       char *p;
+       const char *section_name;
+       char filename[1024];
+       char buffer[2048];
+       CONF_SECTION *cs, *subcs;
+       modcallable *mc;
+
+       /*
+        *      And the filename
+        */
+       token = policy_lex_file(lexer, 0, filename, sizeof(filename));
+       if (token != POLICY_LEX_DOUBLE_QUOTED_STRING) {
+               fprintf(stderr, "%s[%d]: Expected filename, got \"%s\"\n",
+                       lexer->filename, lexer->lineno,
+                       lrad_int2str(rlm_policy_tokens, token, "?"));
+               return 0;
+       }
+
+       /*
+        *      See if we're including all of the files in a subdirectory.
+        */
+       strlcpy(buffer, lexer->filename, sizeof(buffer));
+       p = strrchr(buffer, '/');
+       if (p) {
+               strlcpy(p + 1, filename, sizeof(buffer) - 1 - (p - buffer));
+       } else {
+               snprintf(buffer, sizeof(buffer), "%s/%s",
+                        radius_dir, filename);
+       }
+       
+       /*
+        *      Include section calling a module.
+        */
+       debug_tokens("including module section from file %s\n", buffer);
+       cs = cf_file_read(buffer);
+       if (!cs) {
+               return 0;       /* it prints out error messages */
+       }
+
+       /*
+        *      The outer section is called "main", and can be ignored.
+        *      It should be a section, so there should be a subsection.
+        */
+       subcs = cf_subsection_find_next(cs, NULL, NULL);
+       if (!subcs) {
+               fprintf(stderr, "%s[%d]: Expected section containing modules\n",
+                       lexer->filename, lexer->lineno);
+               cf_section_free(&cs);
+               return 0;
+       }
+
+       section_name = cf_section_name1(subcs);
+       rad_assert(section_name != NULL);
+       component = lrad_str2int(policy_component_names, section_name,
+                                RLM_COMPONENT_COUNT);
+       if (component == RLM_COMPONENT_COUNT) {
+               fprintf(stderr, "%s[%d]: Invalid section name \"%s\"\n",
+                       lexer->filename, lexer->lineno, section_name);
+               cf_section_free(&cs);
+               return 0;
+       }
+
+       /*
+        *      Compile the module entry.
+        */
+       mc = compile_modgroup(component, subcs, buffer);
+       if (!mc) {
+               cf_section_free(&cs);
+               return 0;       /* more often results in calling exit... */
+       }
+
+       this = rad_malloc(sizeof(*this));
+       memset(this, 0, sizeof(*this));
+
+       this->item.type = POLICY_TYPE_MODULE;
+       this->item.lineno = lexer->lineno;
+       this->component = component;
+       this->cs = cs;
+       this->mc = mc;
+
+       *tail = (policy_item_t *) this;
+
+       return 1;
+}
+
+
+/*
+ *     Parse one statement.  'foo = bar', or 'if (...) {...}', or '{...}',
+ *     and so on.
+ */
+static int parse_statement(policy_lex_file_t *lexer, policy_item_t **tail)
+{
+       int rcode;
+       policy_reserved_word_t reserved;
+       policy_lex_t token, assign;
+       char lhs[256], rhs[256];
+       policy_assignment_t *this;
+
+       /*
+        *      See what kind of token we have.
+        */
+       token = policy_lex_file(lexer, 0, lhs, sizeof(lhs));
+       switch (token) {
+       case POLICY_LEX_LC_BRACKET:
+               rcode = parse_block(lexer, tail);
+               if (!rcode) {
+                       return 0;
+               }
+               break;
+
+       case POLICY_LEX_BARE_WORD:
+               reserved = lrad_str2int(policy_reserved_words,
+                                       lhs,
+                                       POLICY_RESERVED_UNKNOWN);
+               switch (reserved) {
+               case POLICY_RESERVED_IF:
+                       if (parse_if(lexer, tail)) {
+                               return 1;
+                       }
+                       return 0;
+                       break;
+                       
+               case POLICY_RESERVED_CONTROL:
+               case POLICY_RESERVED_REQUEST:
+               case POLICY_RESERVED_REPLY:
+               case POLICY_RESERVED_PROXY_REQUEST:
+               case POLICY_RESERVED_PROXY_REPLY:
+                       if (parse_attribute_block(lexer, tail,
+                                                 reserved))
+                               return 1;
+                       return 0;
+                       break;
+                       
+               case POLICY_RESERVED_PRINT:
+                       if (parse_print(lexer, tail)) {
+                               return 1;
+                       }
+                       return 0;
+                       break;
+                       
+               case POLICY_RESERVED_RETURN:
+                       if (parse_return(lexer, tail)) {
+                               return 1;
+                       }
+                       return 0;
+                       break;
+                       
+               case POLICY_RESERVED_MODULE:
+                       if (parse_module(lexer, tail)) {
+                               return 1;
+                       }
+                       return 0;
+                       break;
+
+               case POLICY_RESERVED_UNKNOWN: /* wasn't a reserved word */
+                       /*
+                        *      Is a named policy, parse the reference to it.
+                        */
+                       if (rlm_policy_find(lexer->policies, lhs) != NULL) {
+                               if (!parse_call(lexer, tail, lhs)) {
+                                       return 0;
+                               }
+                               return 1;
+                       }
+
+                       {
+                               const DICT_ATTR *dattr;
+                               
+                               /*
+                                *      Bare words MUST be dictionary attributes
+                                */
+                               
+                               dattr = dict_attrbyname(lhs);
+                               if (!dattr) {
+                                       fprintf(stderr, "%s[%d]: Expected attribute name, got \"%s\"\n",
+                                               lexer->filename, lexer->lineno, lhs);
+                                       return 0;
+                               }
+                               debug_tokens("%s[%d]: Got attribute %s\n",
+                                            lexer->filename, lexer->lineno,
+                                            lhs);
+                       }
+                       break;
+                       
+               default:
+                       fprintf(stderr, "%s[%d]: Unexpected reserved word \"%s\"\n",
+                               lexer->filename, lexer->lineno, lhs);
+                       return 0;
+               } /* switch over reserved words */
+               break;
+               
+               /*
+                *      Return from nested blocks.
+                */
+       case POLICY_LEX_RC_BRACKET:
+               policy_lex_push_token(lexer, token);
+               return 2;       /* magic */
+
+       case POLICY_LEX_EOF:    /* nothing more to do */
+               return 3;
+
+       default:
+               fprintf(stderr, "%s[%d]: Unexpected %s\n",
+                       lexer->filename, lexer->lineno,
+                       lrad_int2str(policy_explanations,
+                                    token, "string"));
+               break;
+       }
+
+       /*
+        *      Parse a bare statement.
+        */
+       assign = policy_lex_file(lexer, 0, rhs, sizeof(rhs));
+       switch (assign) {
+       case POLICY_LEX_ASSIGN:
+       case POLICY_LEX_SET_EQUALS:
+       case POLICY_LEX_AND_EQUALS:
+       case POLICY_LEX_OR_EQUALS:
+       case POLICY_LEX_PLUS_EQUALS:
+               break;
+
+       default:
+               fprintf(stderr, "%s[%d]: Unexpected assign %s\n",
+                       lexer->filename, lexer->lineno,
+                       lrad_int2str(policy_explanations,
+                                    assign, "string"));
+               return 0;
+       }
+
+       this = rad_malloc(sizeof(*this));
+       memset(this, 0, sizeof(*this));
+
+       this->item.type = POLICY_TYPE_ASSIGNMENT;
+       this->item.lineno = lexer->lineno;
+
+       token = policy_lex_file(lexer, 0, rhs, sizeof(rhs));
+       if ((token != POLICY_LEX_BARE_WORD) &&
+           (token != POLICY_LEX_DOUBLE_QUOTED_STRING)) {
+               fprintf(stderr, "%s[%d]: Unexpected rhs %s\n",
+                       lexer->filename, lexer->lineno,
+                       lrad_int2str(policy_explanations,
+                                    token, "string"));
+               rlm_policy_free_item((policy_item_t *) this);
+               return 0;
+       }
+       this->rhs_type = token;
+       this->rhs = strdup(rhs);
+
+       token = policy_lex_file(lexer, POLICY_LEX_FLAG_RETURN_EOL,
+                               rhs, sizeof(rhs));
+       if (token != POLICY_LEX_EOL) {
+               fprintf(stderr, "%s[%d]: Expected EOL\n",
+                       lexer->filename, lexer->lineno);
+               rlm_policy_free_item((policy_item_t *) this);
+               return 0;
+       }
+       debug_tokens("[ASSIGN %s %s %s]\n",
+              lhs, lrad_int2str(rlm_policy_tokens, assign, "?"), rhs);
+
+       /*
+        *      Fill in the assignment struct
+        */
+       this->lhs = strdup(lhs);
+       this->assign = assign;
+
+       *tail = (policy_item_t *) this;
+
+       return 1;
+}
+
+
+/*
+ *     Parse block of statements.  The block has already been checked
+ *     to begin with a '{'.
+ */
+static int parse_block(policy_lex_file_t *lexer, policy_item_t **tail)
+{
+       int rcode;
+       policy_lex_t token;
+
+       debug_tokens("[BLOCK] ");
+
+       token = policy_lex_file(lexer, 0, NULL, 0);
+       if (token != POLICY_LEX_LC_BRACKET) {
+               fprintf(stderr, "%s[%d]: Expected '{'\n",
+                       lexer->filename, lexer->lineno);
+               return 0;
+       }
+
+       rcode = 0;
+       while ((rcode = parse_statement(lexer, tail)) != 0) {
+               if (rcode == 2) {
+                       token = policy_lex_file(lexer, 0, NULL, 0);
+                       if (token != POLICY_LEX_RC_BRACKET) {
+                               fprintf(stderr, "%s[%d]: Expected '}'\n",
+                                       lexer->filename, lexer->lineno);
+                               return 0;
+                       }
+                       return 1;
+               }
+               rad_assert(*tail != NULL);
+               /* parse_statement must fill this in */
+               while (*tail) tail = &((*tail)->next);
+       }
+       debug_tokens("\n");
+
+       /*
+        *      Parse statement failed.
+        */
+       return 0;
+}
+
+
+/*
+ *     Parse debugging statements
+ */
+static int parse_debug(policy_lex_file_t *lexer)
+{
+       int rcode = 0;
+       policy_lex_t token;
+       char buffer[32];
+
+       token = policy_lex_file(lexer, 0, buffer, sizeof(buffer));
+       if (token != POLICY_LEX_BARE_WORD) {
+               fprintf(stderr, "%s[%d]: Bad debug command\n",
+                       lexer->filename, lexer->lineno);
+               return 0;
+       }
+
+       if (strcasecmp(buffer, "none") == 0) {
+               lexer->debug = POLICY_DEBUG_NONE;
+               rcode = 1;
+
+       } else if (strcasecmp(buffer, "peek") == 0) {
+               lexer->debug |= POLICY_DEBUG_PEEK;
+               rcode = 1;
+
+       } else if (strcasecmp(buffer, "print_tokens") == 0) {
+               lexer->debug |= POLICY_DEBUG_PRINT_TOKENS;
+               rcode = 1;
+
+       } else if (strcasecmp(buffer, "print_policy") == 0) {
+               lexer->debug |= POLICY_DEBUG_PRINT_POLICY;
+               rcode = 1;
+
+       } else if (strcasecmp(buffer, "evaluate") == 0) {
+               lexer->debug |= POLICY_DEBUG_EVALUATE;
+               rcode = 1;
+       }
+
+       if (rcode) {
+               token = policy_lex_file(lexer, POLICY_LEX_FLAG_RETURN_EOL,
+                                       NULL, 0);
+               if (token != POLICY_LEX_EOL) {
+                       fprintf(stderr, "%s[%d]: Expected EOL\n",
+                               lexer->filename, lexer->lineno);
+                       return 0;
+               }
+       } else {
+               fprintf(stderr, "%s[%d]: Bad debug command \"%s\"\n",
+                       lexer->filename, lexer->lineno, buffer);
+               return 0;
+       }
+
+       return 1;
+}
+
+
+/*
+ *     Parse a named policy "policy foo {...}"
+ */
+static int parse_named_policy(policy_lex_file_t *lexer)
+{
+       int rcode;
+       policy_lex_t token;
+       char mystring[256];
+       policy_named_t *this;
+       DICT_ATTR *dattr;
+
+       debug_tokens("[POLICY] ");
+
+       this = rad_malloc(sizeof(*this));
+       memset(this, 0, sizeof(*this));
+
+       this->item.type = POLICY_TYPE_NAMED_POLICY;
+       this->item.lineno = lexer->lineno;
+
+       token = policy_lex_file(lexer, 0, mystring, sizeof(mystring));
+       if (token != POLICY_LEX_BARE_WORD) {
+               fprintf(stderr, "%s[%d]: Expected policy name, got \"%s\"\n",
+                       lexer->filename, lexer->lineno,
+                       lrad_int2str(rlm_policy_tokens, token, "?"));
+               rlm_policy_free_item((policy_item_t *) this);
+               return 0;
+       }
+
+       dattr = dict_attrbyname(mystring);
+       if (dattr) {
+               fprintf(stderr, "%s[%d]: Invalid policy name \"%s\": it is already defined as a dictionary attribute\n",
+                       lexer->filename, lexer->lineno, mystring);
+               rlm_policy_free_item((policy_item_t *) this);
+               return 0;
+       }
+
+       this->name = strdup(mystring);
+       rcode = parse_block(lexer, &(this->policy));
+       if (!rcode) {
+               rlm_policy_free_item((policy_item_t *) this);
+               return rcode;
+       }
+
+       /*
+        *      And insert it into the tree of policies.
+        *
+        *      For now, policy names aren't scoped, they're global.
+        */
+       if (!rlm_policy_insert(lexer->policies, this)) {
+               fprintf(stderr, "Failed to insert policy \"%s\"\n", this->name);
+               rlm_policy_free_item((policy_item_t *) this);
+               return 0;
+       }
+
+       /*
+        *      Do NOT add it into the list of parsed expressions!
+        *      The above insertion will take care of freeing it if
+        *      anything goes wrong...
+        */
+       return 1;
+}
+
+
+/*
+ *     Parse an "include filename" statement
+ *
+ *     FIXME: Tie this file into the CONF_SECTION for HUP handling!
+ */
+static int parse_include(policy_lex_file_t *lexer)
+{
+       char *p;
+       policy_lex_t token;
+       char filename[1024];
+       char buffer[2048];
+
+       token = policy_lex_file(lexer, 0, filename, sizeof(filename));
+       if (token != POLICY_LEX_DOUBLE_QUOTED_STRING) {
+               fprintf(stderr, "%s[%d]: Expected filename, got \"%s\"\n",
+                       lexer->filename, lexer->lineno,
+                       lrad_int2str(rlm_policy_tokens, token, "?"));
+               return 0;
+       }
+
+       /*
+        *      See if we're including all of the files in a subdirectory.
+        */
+       strlcpy(buffer, lexer->filename, sizeof(buffer));
+       p = strrchr(buffer, '/');
+       if (p) {
+               strlcpy(p + 1, filename, sizeof(buffer) - 1 - (p - buffer));
+
+#ifdef HAVE_DIRENT_H   
+               p = strrchr(p + 1, '/');
+               if (p && !p[1]) {
+                       DIR             *dir;
+                       struct dirent   *dp;
+                       
+                       p++;
+
+                       dir = opendir(buffer);
+                       if (!dir) {
+                               fprintf(stderr, "%s[%d]: Error opening %s:%s\n",
+                                       lexer->filename, lexer->lineno,
+                                       buffer, strerror(errno));
+                               return 0;
+                       }
+                       
+                       /*
+                        *      Read the directory, ignoring "." files.
+                        */
+                       while ((dp = readdir(dir)) != NULL) {
+                               struct stat buf;
+
+                               if (dp->d_name[0] == '.') continue;
+                               if (strchr(dp->d_name, '~') != NULL) continue;
+
+                               strlcpy(p, dp->d_name,
+                                       sizeof(buffer) - (p - buffer));
+
+                               if ((stat(buffer, &buf) != 0) ||
+                                   S_ISDIR(buf.st_mode)) continue;
+
+                               debug_tokens("\nincluding file %s\n", buffer);
+                               if (!rlm_policy_parse(lexer->policies, buffer)) {
+                                       closedir(dir);
+                                       return 0;
+                               }
+                       }
+                       closedir(dir);
+                       return 1;
+               } /* else it must have been a normalx file */
+#endif
+       } else {
+               snprintf(buffer, sizeof(buffer), "%s/%s",
+                        radius_dir, filename);
+       }
+       
+       /*
+        *      Handle one include file.
+        */
+       debug_tokens("\nincluding file %s\n", buffer);
+       if (!rlm_policy_parse(lexer->policies, buffer)) {
+               return 0;
+       }
+
+       return 1;
+}
+
+
+/*
+ *     Parse data from a file into a policy language.
+ */
+int rlm_policy_parse(rbtree_t *policies, const char *filename)
+{
+       FILE *fp;
+       policy_lex_t token;
+       policy_lex_file_t mylexer, *lexer = NULL;
+       char buffer[32];
+
+       fp = fopen(filename, "r");
+       if (!fp) {
+               fprintf(stderr, "Failed to open %s: %s\n",
+                       filename, strerror(errno));
+               return 0;
+       }
+
+       lexer = &mylexer;
+       memset(lexer, 0, sizeof(*lexer));
+       lexer->filename = filename;
+       lexer->fp = fp;
+       lexer->token = POLICY_LEX_BAD;
+       lexer->parse = NULL;    /* initial input */
+       lexer->policies = policies;
+
+       do {
+               int reserved;
+
+               token = policy_lex_file(lexer, 0, buffer, sizeof(buffer));
+               switch (token) {
+               case POLICY_LEX_BARE_WORD:
+                       reserved = lrad_str2int(policy_reserved_words,
+                                               buffer,
+                                               POLICY_RESERVED_UNKNOWN);
+                       switch (reserved) {
+                       case POLICY_RESERVED_POLICY:
+                               if (!parse_named_policy(lexer)) {
+                                       return 0;
+                               }
+                               break;
+                               
+                       case POLICY_RESERVED_INCLUDE:
+                               if (!parse_include(lexer)) {
+                                       return 0;
+                               }
+                               break;
+                               
+                       case POLICY_RESERVED_DEBUG:
+                               if (!parse_debug(lexer)) {
+                                       return 0;
+                               }
+                               break;
+                       
+                       default:
+                               fprintf(stderr, "%s[%d]: Unexpected word \"%s\"\n",
+                                       lexer->filename, lexer->lineno,
+                                       buffer);
+                               return 0;
+                               break;
+                       } /* switch over reserved words */
+
+               case POLICY_LEX_EOF:
+                       break;
+
+               default:
+                       fprintf(stderr, "%s[%d]: Illegal input\n",
+                               lexer->filename, lexer->lineno);
+                       return 0;
+               }
+
+               fflush(stdout);
+       } while (token != POLICY_LEX_EOF);
+
+
+       debug_tokens("--------------------------------------------------\n");
+
+       return 1;
+}
+
diff --git a/src/modules/rlm_policy/rlm_policy.c b/src/modules/rlm_policy/rlm_policy.c
new file mode 100644 (file)
index 0000000..fb6cb94
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * rlm_policy.c                Implements a policy language
+ *
+ * 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 2004  Alan DeKok <aland@ox.org>
+ * Copyright 2006  The FreeRADIUS server project
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include "rlm_policy.h"
+
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/conffile.h>
+
+/*
+ *     A mapping of configuration file names to internal variables.
+ *
+ *     Note that the string is dynamically allocated, so it MUST
+ *     be freed.  When the configuration file parse re-reads the string,
+ *     it free's the old one, and strdup's the new one, placing the pointer
+ *     to the strdup'd string into 'config.string'.  This gets around
+ *     buffer over-flows.
+ */
+static const CONF_PARSER module_config[] = {
+  { "filename",  PW_TYPE_FILENAME,
+    offsetof(rlm_policy_t,filename), NULL,  NULL},
+
+  { NULL, -1, 0, NULL, NULL }          /* end the list */
+};
+
+
+/*
+ *     Callbacks for red-black trees.
+ */
+static int policyname_cmp(const void *a, const void *b)
+{
+       return strcmp(((const policy_named_t *)a)->name,
+                     ((const policy_named_t *)b)->name);
+}
+
+
+/*
+ *     Detach a policy.
+ */
+static int policy_detach(void *instance)
+{
+       rlm_policy_t *inst = instance;
+
+       if (inst->policies) rbtree_free(inst->policies);
+       free(instance);
+       return 0;
+}
+
+/*
+ *     Do any per-module initialization that is separate to each
+ *     configured instance of the module.  e.g. set up connections
+ *     to external databases, read configuration files, set up
+ *     dictionary entries, etc.
+ *
+ *     If configuration information is given in the config section
+ *     that must be referenced in later calls, store a handle to it
+ *     in *instance otherwise put a null pointer there.
+ */
+static int policy_instantiate(CONF_SECTION *conf, void **instance)
+{
+       rlm_policy_t *inst;
+
+       /*
+        *      Set up a storage area for instance data
+        */
+       inst = rad_malloc(sizeof(*inst));
+       if (!inst) {
+               return -1;
+       }
+       memset(inst, 0, sizeof(*inst));
+
+       /*
+        *      If the configuration parameters can't be parsed, then
+        *      fail.
+        */
+       if (cf_section_parse(conf, inst, module_config) < 0) {
+               policy_detach(inst);
+               return -1;
+       }
+
+       inst->policies = rbtree_create(policyname_cmp, rlm_policy_free_item, 0);
+       if (!inst->policies) {
+               policy_detach(inst);
+               return -1;
+       }
+
+       /*
+        *      Parse the policy from the file.
+        */
+       if (!rlm_policy_parse(inst->policies, inst->filename)) {
+               policy_detach(inst);
+               return -1;
+       }
+
+       *instance = inst;
+
+       return 0;
+}
+
+
+/*
+ *     Insert a named policy into a list.
+ */
+int rlm_policy_insert(rbtree_t *head, policy_named_t *policy)
+{
+       if (!rbtree_insert(head, policy)) {
+               rlm_policy_free_item((policy_item_t *) policy);
+               return 0;
+       }
+
+       return 1;
+}
+
+
+/*
+ *     Find a named policy
+ */
+policy_named_t *rlm_policy_find(rbtree_t *head, const char *name)
+{
+       policy_named_t mypolicy;
+
+       mypolicy.name = name;
+
+       return rbtree_finddata(head, &mypolicy);
+}
+
+
+/*
+ *     Find the named user in this modules database.  Create the set
+ *     of attribute-value pairs to check and reply with for this user
+ *     from the database. The authentication code only needs to check
+ *     the password, the rest is done here.
+ */
+static int policy_authorize(void *instance, REQUEST *request)
+{
+       return rlm_policy_evaluate((rlm_policy_t *) instance, request,
+                                  "authorize");
+}
+
+
+static int policy_preacct(void *instance, REQUEST *request)
+{
+       return rlm_policy_evaluate((rlm_policy_t *) instance, request,
+                                  "preacct");
+}
+
+static int policy_accounting(void *instance, REQUEST *request)
+{
+       return rlm_policy_evaluate((rlm_policy_t *) instance, request,
+                                  "accounting");
+}
+
+static int policy_post_auth(void *instance, REQUEST *request)
+{
+       return rlm_policy_evaluate((rlm_policy_t *) instance, request,
+                                  "post-auth");
+}
+
+static int policy_pre_proxy(void *instance, REQUEST *request)
+{
+       return rlm_policy_evaluate((rlm_policy_t *) instance, request,
+                                  "pre-proxy");
+}
+
+static int policy_post_proxy(void *instance, REQUEST *request)
+{
+       return rlm_policy_evaluate((rlm_policy_t *) instance, request,
+                                  "post-proxy");
+}
+
+/*
+ *     The "free" functions are here, for no particular reason.
+ */
+void rlm_policy_free_item(policy_item_t *item)
+{
+       while (item) {
+               policy_item_t *next = item->next;
+
+               switch (item->type) {
+               default:
+               case POLICY_TYPE_BAD:
+                       break;
+                       
+               case POLICY_TYPE_ASSIGNMENT:
+                       {
+                               policy_assignment_t *this;
+                               
+                               this = (policy_assignment_t *) item;
+                               if (this->lhs) free(this->lhs);
+                               if (this->rhs) free(this->rhs);
+                       }
+                       break;
+                       
+               case POLICY_TYPE_CONDITIONAL:
+                       {
+                               policy_condition_t *this;
+                               
+                               this = (policy_condition_t *) item;
+                               if (this->lhs) free(this->lhs);
+                               if (this->rhs) free(this->rhs);
+
+                               if (this->child) {
+                                       rlm_policy_free_item(this->child);
+                                       this->child = NULL;
+                               }
+                       }
+                       break;
+                       
+               case POLICY_TYPE_IF:
+                       {
+                               policy_if_t *this;
+                               
+                               this = (policy_if_t *) item;
+                               if (this->condition) {
+                                       rlm_policy_free_item(this->condition);
+                                       this->condition = NULL;
+                               }
+                               if (this->if_true) {
+                                       rlm_policy_free_item(this->if_true);
+                                       this->if_true = NULL;
+                               }
+                               if (this->if_false) {
+                                       rlm_policy_free_item(this->if_false);
+                                       this->if_false = NULL;
+                               }
+                       }
+                       break;
+
+               case POLICY_TYPE_ATTRIBUTE_LIST:
+                       {
+                               policy_attributes_t *this;
+                               
+                               this = (policy_attributes_t *) item;
+                               rlm_policy_free_item(this->attributes);
+                       }
+                       break;
+
+               case POLICY_TYPE_NAMED_POLICY:
+                       {
+                               policy_named_t *this;
+                               
+                               this = (policy_named_t *) item;
+                               rad_assert(this->name != NULL);
+                               free(this->name);
+                               rlm_policy_free_item(this->policy);
+                       }
+                       break;
+
+               case POLICY_TYPE_CALL:
+                       {
+                               policy_call_t *this;
+                               
+                               this = (policy_call_t *) item;
+                               if (this->name) free(this->name);
+                       }
+                       break;
+                       
+               case POLICY_TYPE_RETURN:
+                       break;  /* do nothing */
+
+               case POLICY_TYPE_MODULE:
+                       {
+                               policy_module_t *this;
+                               
+                               this = (policy_module_t *) item;
+                               if (this->cs) cf_section_free(&this->cs);
+                               if (this->mc) modcallable_free(&this->mc);
+                       }
+                       break;
+               } /* switch over type */
+               item->next = NULL; /* for debugging & sanity checks */
+               item->type = POLICY_TYPE_BAD;
+               free(item);
+
+               item = next;
+       }
+}
+
+
+/*
+ *     The module name should be the only globally exported symbol.
+ *     That is, everything else should be 'static'.
+ *
+ *     If the module needs to temporarily modify it's instantiation
+ *     data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
+ *     The server will then take care of ensuring that the module
+ *     is single-threaded.
+ */
+module_t rlm_policy = {
+       RLM_MODULE_INIT,
+       "policy",
+       RLM_TYPE_THREAD_SAFE,           /* type */
+       policy_instantiate,             /* instantiation */
+       policy_detach,                  /* detach */
+       {
+               NULL,                   /* authentication */
+               policy_authorize,       /* authorization */
+               policy_preacct,         /* preaccounting */
+               policy_accounting,      /* accounting */
+               NULL,                   /* checksimul */
+               policy_pre_proxy,       /* pre-proxy */
+               policy_post_proxy,      /* post-proxy */
+               policy_post_auth        /* post-auth */
+       },
+};
diff --git a/src/modules/rlm_policy/rlm_policy.h b/src/modules/rlm_policy/rlm_policy.h
new file mode 100644 (file)
index 0000000..9b77597
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * rlm_policy.h    Header file for policy module
+ *
+ * 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 2004  Alan DeKok <aland@freeradius.org>
+ * Copyright 2006  The FreeRADIUS server project
+ */
+#ifndef _RLM_POLICY_H
+#define _RLM_POLICY_H
+
+#include <freeradius-devel/ident.h>
+RCSIDH(rlm_policy_h, "$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/modcall.h>
+
+#include <freeradius-devel/rad_assert.h>
+
+/*
+ *     Internal lexer.
+ */
+typedef enum policy_lex_t {
+       POLICY_LEX_BAD = 0,
+       POLICY_LEX_EOF,         /* end of the file/input */
+       POLICY_LEX_EOL,         /* end of the line */
+       POLICY_LEX_WHITESPACE,
+       POLICY_LEX_HASH,
+       POLICY_LEX_L_BRACKET,
+       POLICY_LEX_R_BRACKET,
+       POLICY_LEX_LC_BRACKET,  /* left curly bracket */
+       POLICY_LEX_RC_BRACKET,  /* right curly bracket */
+       POLICY_LEX_COMMA,
+       POLICY_LEX_L_AND,       /* logical AND */
+       POLICY_LEX_L_OR,        /* logical OR */
+       POLICY_LEX_AND,         /* bit-wise AND */
+       POLICY_LEX_OR,          /* bit-wise OR */
+       POLICY_LEX_L_NOT,
+       POLICY_LEX_PLUS,        /* + */
+       POLICY_LEX_MINUS,       /* - */
+       POLICY_LEX_ASSIGN,      /* = */
+       POLICY_LEX_CMP_EQUALS,
+       POLICY_LEX_CMP_NOT_EQUALS,
+       POLICY_LEX_CMP_TRUE,
+       POLICY_LEX_CMP_FALSE,
+       POLICY_LEX_LT,
+       POLICY_LEX_GT,
+       POLICY_LEX_LE,
+       POLICY_LEX_GE,
+       POLICY_LEX_RX_EQUALS,
+       POLICY_LEX_RX_NOT_EQUALS,
+       POLICY_LEX_SET_EQUALS,  /* := */
+       POLICY_LEX_AND_EQUALS,  /* &= */
+       POLICY_LEX_OR_EQUALS,   /* |= */
+       POLICY_LEX_PLUS_EQUALS, /* += */
+       POLICY_LEX_MINUS_EQUALS, /* -= */
+       POLICY_LEX_CONCAT_EQUALS, /* .= */
+       POLICY_LEX_VARIABLE,    /* %{foo} */
+       POLICY_LEX_FUNCTION,    /* Hmmm... */
+       POLICY_LEX_DOUBLE_QUOTED_STRING,
+       POLICY_LEX_SINGLE_QUOTED_STRING,
+       POLICY_LEX_BACK_QUOTED_STRING,
+       POLICY_LEX_BARE_WORD
+} policy_lex_t;
+
+typedef enum policy_type_t {
+       POLICY_TYPE_BAD = 0,
+       POLICY_TYPE_IF,
+       POLICY_TYPE_CONDITIONAL,
+       POLICY_TYPE_ASSIGNMENT,
+       POLICY_TYPE_ATTRIBUTE_LIST,
+       POLICY_TYPE_PRINT,
+       POLICY_TYPE_NAMED_POLICY,
+       POLICY_TYPE_CALL,
+       POLICY_TYPE_RETURN,
+       POLICY_TYPE_MODULE,
+       POLICY_TYPE_NUM_TYPES
+} policy_type_t;
+
+
+/*
+ *     For our policy language, we want to have some reserved words.
+ */
+typedef enum policy_reserved_word_t {
+       POLICY_RESERVED_UNKNOWN = 0,
+       POLICY_RESERVED_CONTROL,
+       POLICY_RESERVED_REQUEST,
+       POLICY_RESERVED_REPLY,
+       POLICY_RESERVED_PROXY_REQUEST,
+       POLICY_RESERVED_PROXY_REPLY,
+       POLICY_RESERVED_IF,
+       POLICY_RESERVED_ELSE,
+       POLICY_RESERVED_DEBUG,
+       POLICY_RESERVED_PRINT,
+       POLICY_RESERVED_POLICY,
+       POLICY_RESERVED_INCLUDE,
+       POLICY_RESERVED_RETURN,
+       POLICY_RESERVED_MODULE,
+       POLICY_RESERVED_NUM_WORDS
+} policy_reserved_word_t;
+
+
+#define POLICY_DEBUG_NONE           0
+#define POLICY_DEBUG_PEEK           (1 << 0)
+#define        POLICY_DEBUG_PRINT_TOKENS   (1 << 1)
+#define        POLICY_DEBUG_PRINT_POLICY   (1 << 2)
+#define        POLICY_DEBUG_EVALUATE       (1 << 3)
+
+/*
+ *     A policy item
+ */
+typedef struct policy_item_t {
+       struct policy_item_t    *next;
+       policy_type_t           type;
+       int                     lineno;
+} policy_item_t;
+
+
+/*
+ *     A list of attributes to add/replace/whatever in a packet.
+ */
+typedef struct policy_print_t {
+       policy_item_t           item;
+       policy_lex_t            rhs_type;
+       const char              *rhs;
+} policy_print_t;
+
+
+/*
+ *     A list of attributes to add/replace/whatever in a packet.
+ */
+typedef struct policy_attributes_t {
+       policy_item_t           item;
+       policy_reserved_word_t  where; /* where to do it */
+       policy_lex_t            how; /* how to do */
+       policy_item_t           *attributes; /* things to do */
+       /* FIXME: VALUE_PAIR *vps; */
+} policy_attributes_t;
+
+
+/*
+ *     Holds a named policy
+ */
+typedef struct policy_named_t {
+       policy_item_t   item;
+       const char      *name;
+       policy_item_t   *policy;
+} policy_named_t;
+
+
+/*
+ *     Reference to a named policy
+ */
+typedef struct policy_call_t {
+       policy_item_t   item;
+       const char      *name;
+} policy_call_t;
+
+
+/*
+ *     Hold a return code
+ */
+typedef struct policy_return_t {
+       policy_item_t   item;
+       int             rcode;
+} policy_return_t;
+
+
+/*
+ *     Holds an assignment.
+ */
+typedef struct policy_assignment_t {
+       policy_item_t   item;
+       char            *lhs;
+       policy_lex_t    assign; /* operator for the assignment */
+       policy_lex_t    rhs_type;
+       char            *rhs;
+} policy_assignment_t;
+
+
+/*
+ *     Condition
+ */
+typedef struct policy_condition_t {
+       policy_item_t   item;
+
+       policy_lex_t    lhs_type;
+       char            *lhs;
+       policy_lex_t    compare;
+       policy_lex_t    rhs_type; /* bare word, quoted string, etc. */
+       char            *rhs;
+
+       policy_lex_t    child_condition;
+       policy_item_t   *child;
+} policy_condition_t;
+
+
+/*
+ *     Holds an "if" statement.  The "else" may be a block, or another "if"
+ */
+typedef struct policy_if_t {
+       policy_item_t           item;
+       policy_item_t           *condition;
+       policy_item_t           *if_true;
+       policy_item_t           *if_false;      /* assignment, or other 'if' */
+} policy_if_t;
+
+
+/*
+ *     Holds a reference to calling other modules... wild.
+ */
+typedef struct policy_module_t {
+       policy_item_t   item;
+       int             component; /* authorize, authenticate, etc. */
+       CONF_SECTION    *cs;
+       modcallable     *mc;
+} policy_module_t;
+
+
+/*
+ *     Define a structure for our module configuration.
+ *
+ *     These variables do not need to be in a structure, but it's
+ *     a lot cleaner to do so, and a pointer to the structure can
+ *     be used as the instance handle.
+ */
+typedef struct rlm_policy_t {
+       char            *filename;
+       rbtree_t        *policies;
+} rlm_policy_t;
+
+
+/*
+ *     Functions.
+ */
+extern const LRAD_NAME_NUMBER rlm_policy_tokens[];
+extern const LRAD_NAME_NUMBER policy_reserved_words[];
+extern const LRAD_NAME_NUMBER policy_return_codes[];
+extern const LRAD_NAME_NUMBER policy_component_names[];
+
+extern int rlm_policy_insert(rbtree_t *head, policy_named_t *policy);
+extern policy_named_t *rlm_policy_find(rbtree_t *head, const char *name);
+
+extern int rlm_policy_parse(rbtree_t *policies, const char *filename);
+extern void rlm_policy_free_item(policy_item_t *item);
+extern void rlm_policy_print(const policy_item_t *item);
+extern int rlm_policy_evaluate(rlm_policy_t *inst, REQUEST *request,
+                              const char *name);
+
+#endif /* _RLM_POLICY_H */
index b55729e..8f081d9 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
 
-static const char rcsid[] = "$Id$";
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include       "autoconf.h"
-#include       "libradius.h"
+#include       <freeradius-devel/autoconf.h>
 
 #include       <sys/stat.h>
 
@@ -35,8 +35,9 @@ static const char rcsid[] = "$Id$";
 #include       <string.h>
 #include       <ctype.h>
 
-#include       "radiusd.h"
-#include       "modules.h"
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/modules.h>
+#include       <freeradius-devel/rad_assert.h>
 
 typedef struct rlm_preprocess_t {
        char            *huntgroup_file;
@@ -51,11 +52,11 @@ typedef struct rlm_preprocess_t {
        int             with_alvarion_vsa_hack;
 } rlm_preprocess_t;
 
-static CONF_PARSER module_config[] = {
-       { "huntgroups",                 PW_TYPE_STRING_PTR,
+static const CONF_PARSER module_config[] = {
+       { "huntgroups",                 PW_TYPE_FILENAME,
          offsetof(rlm_preprocess_t,huntgroup_file), NULL,
          "${raddbdir}/huntgroups" },
-       { "hints",                      PW_TYPE_STRING_PTR,
+       { "hints",                      PW_TYPE_FILENAME,
          offsetof(rlm_preprocess_t,hints_file), NULL,
          "${raddbdir}/hints" },
        { "with_ascend_hack",           PW_TYPE_BOOLEAN,
@@ -126,7 +127,7 @@ static void cisco_vsa_hack(VALUE_PAIR *vp)
                /*
                 *  No weird packing.  Ignore it.
                 */
-               ptr = strchr(vp->strvalue, '='); /* find an '=' */
+               ptr = strchr(vp->vp_strvalue, '='); /* find an '=' */
                if (!ptr) continue;
 
                /*
@@ -144,7 +145,7 @@ static void cisco_vsa_hack(VALUE_PAIR *vp)
                        char *p;
                        DICT_ATTR       *dattr;
 
-                       p = vp->strvalue;
+                       p = vp->vp_strvalue;
                        gettoken(&p, newattr, sizeof(newattr));
 
                        if (((dattr = dict_attrbyname(newattr)) != NULL) &&
@@ -165,10 +166,10 @@ static void cisco_vsa_hack(VALUE_PAIR *vp)
                         *      value field, we use only the value on
                         *      the right side of the '=' character.
                         */
-                       strNcpy(newattr, ptr + 1, sizeof(newattr));
-                       strNcpy((char *)vp->strvalue, newattr,
-                               sizeof(vp->strvalue));
-                       vp->length = strlen((char *)vp->strvalue);
+                       strlcpy(newattr, ptr + 1, sizeof(newattr));
+                       strlcpy((char *)vp->vp_strvalue, newattr,
+                               sizeof(vp->vp_strvalue));
+                       vp->length = strlen((char *)vp->vp_strvalue);
                }
        }
 }
@@ -223,10 +224,10 @@ static void rad_mangle(rlm_preprocess_t *data, REQUEST *request)
                 *
                 *      FIXME: should we handle this as a REALM ?
                 */
-               if ((ptr = strchr(namepair->strvalue, '\\')) != NULL) {
-                       strNcpy(newname, ptr + 1, sizeof(newname));
+               if ((ptr = strchr(namepair->vp_strvalue, '\\')) != NULL) {
+                       strlcpy(newname, ptr + 1, sizeof(newname));
                        /* Same size */
-                       strcpy(namepair->strvalue, newname);
+                       strcpy(namepair->vp_strvalue, newname);
                        namepair->length = strlen(newname);
                }
        }
@@ -242,12 +243,12 @@ static void rad_mangle(rlm_preprocess_t *data, REQUEST *request)
                 *
                 *      Reported by Lucas Heise <root@laonet.net>
                 */
-               if ((strlen((char *)namepair->strvalue) > 10) &&
-                   (namepair->strvalue[10] == '/')) {
-                       for (ptr = (char *)namepair->strvalue + 11; *ptr; ptr++)
+               if ((strlen((char *)namepair->vp_strvalue) > 10) &&
+                   (namepair->vp_strvalue[10] == '/')) {
+                       for (ptr = (char *)namepair->vp_strvalue + 11; *ptr; ptr++)
                                *(ptr - 1) = *ptr;
                        *(ptr - 1) = 0;
-                       namepair->length = strlen((char *)namepair->strvalue);
+                       namepair->length = strlen((char *)namepair->vp_strvalue);
                }
        }
 
@@ -283,7 +284,7 @@ static int hunt_paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check)
                tmp = check_item->next;
                check_item->next = NULL;
 
-               result = paircmp(req, request, check_item, NULL);
+               result = paircompare(req, request, check_item, NULL);
 
                check_item->next = tmp;
                check_item = check_item->next;
@@ -316,7 +317,7 @@ static int hints_setup(PAIR_LIST *hints, REQUEST *request)
        if ((tmp = pairfind(request_pairs, PW_USER_NAME)) == NULL)
                name = NULL;
        else
-               name = (char *)tmp->strvalue;
+               name = (char *)tmp->vp_strvalue;
 
        if (name == NULL || name[0] == 0)
                /*
@@ -326,9 +327,9 @@ static int hints_setup(PAIR_LIST *hints, REQUEST *request)
 
        for (i = hints; i; i = i->next) {
                /*
-                *      Use "paircmp", which is a little more general...
+                *      Use "paircompare", which is a little more general...
                 */
-               if (paircmp(request, request_pairs, i->check, NULL) == 0) {
+               if (paircompare(request, request_pairs, i->check, NULL) == 0) {
                        DEBUG2("  hints: Matched %s at %d",
                               i->name, i->lineno);
                        break;
@@ -371,7 +372,7 @@ static int huntgroup_access(REQUEST *request,
                /*
                 *      See if this entry matches.
                 */
-               if (paircmp(request, request_pairs, i->check, NULL) != 0)
+               if (paircompare(request, request_pairs, i->check, NULL) != 0)
                        continue;
 
                /*
@@ -394,9 +395,9 @@ static int huntgroup_access(REQUEST *request,
                                        r = RLM_MODULE_FAIL;
                                }
 
-                               strNcpy(vp->strvalue, i->name,
-                                       sizeof(vp->strvalue));
-                               vp->length = strlen(vp->strvalue);
+                               strlcpy(vp->vp_strvalue, i->name,
+                                       sizeof(vp->vp_strvalue));
+                               vp->length = strlen(vp->vp_strvalue);
 
                                pairadd(&request_pairs, vp);
                        }
@@ -416,37 +417,41 @@ static int add_nas_attr(REQUEST *request)
 {
        VALUE_PAIR *nas;
 
-       nas = pairfind(request->packet->vps, PW_NAS_IP_ADDRESS);
-       if (!nas) {
-               nas = paircreate(PW_NAS_IP_ADDRESS, PW_TYPE_IPADDR);
+       switch (request->packet->src_ipaddr.af) {
+       case AF_INET:
+               nas = pairfind(request->packet->vps, PW_NAS_IP_ADDRESS);
                if (!nas) {
-                       radlog(L_ERR, "No memory");
-                       return -1;
+                       nas = paircreate(PW_NAS_IP_ADDRESS, PW_TYPE_IPADDR);
+                       if (!nas) {
+                               radlog(L_ERR, "No memory");
+                               return -1;
+                       }
+                       nas->lvalue = request->packet->src_ipaddr.ipaddr.ip4addr.s_addr;
+                       pairadd(&request->packet->vps, nas);
                }
-               nas->lvalue = request->packet->src_ipaddr;
-               ip_hostname(nas->strvalue, sizeof(nas->strvalue), nas->lvalue);
-               pairadd(&request->packet->vps, nas);
-       }
+               break;
 
-       /*
-        *      Add in a Client-IP-Address, to tell the user
-        *      the source IP of the request.  That is, the client,
-        *
-        *      Note that this MAY BE different from the NAS-IP-Address,
-        *      especially if the request is being proxied.
-        *
-        *      Note also that this is a server configuration item,
-        *      and will NOT make it to any packets being sent from
-        *      the server.
-        */
-       nas = paircreate(PW_CLIENT_IP_ADDRESS, PW_TYPE_IPADDR);
-       if (!nas) {
-         radlog(L_ERR, "No memory");
-         return -1;
+       case AF_INET6:
+               nas = pairfind(request->packet->vps, PW_NAS_IPV6_ADDRESS);
+               if (!nas) {
+                       nas = paircreate(PW_NAS_IPV6_ADDRESS, PW_TYPE_IPV6ADDR);
+                       if (!nas) {
+                               radlog(L_ERR, "No memory");
+                               return -1;
+                       }
+                       
+                       memcpy(nas->vp_strvalue,
+                              &request->packet->src_ipaddr.ipaddr,
+                              sizeof(request->packet->src_ipaddr.ipaddr));
+                       pairadd(&request->packet->vps, nas);
+               }
+               break;
+
+       default:
+               radlog(L_ERR, "Unknown address family for packet");
+               return -1;
        }
-       nas->lvalue = request->packet->src_ipaddr;
-       ip_hostname(nas->strvalue, sizeof(nas->strvalue), nas->lvalue);
-       pairadd(&request->packet->vps, nas);
+
        return 0;
 }
 
@@ -509,7 +514,6 @@ static int preprocess_instantiate(CONF_SECTION *conf, void **instance)
  */
 static int preprocess_authorize(void *instance, REQUEST *request)
 {
-       char buf[1024];
        int r;
        rlm_preprocess_t *data = (rlm_preprocess_t *) instance;
 
@@ -572,14 +576,15 @@ static int preprocess_authorize(void *instance, REQUEST *request)
                        return RLM_MODULE_FAIL;
                }
                vp->length = AUTH_VECTOR_LEN;
-               memcpy(vp->strvalue, request->packet->vector, AUTH_VECTOR_LEN);
+               memcpy(vp->vp_strvalue, request->packet->vector, AUTH_VECTOR_LEN);
                pairadd(&request->packet->vps, vp);
        }
 
        if ((r = huntgroup_access(request, data->huntgroups,
                             request->packet->vps)) != RLM_MODULE_OK) {
+               char buf[1024];
                radlog(L_AUTH, "No huntgroup access: [%s] (%s)",
-                      request->username ? request->username->strvalue : "<No User-Name>",
+                      request->username ? request->username->vp_strvalue : "<NO User-Name>",
                       auth_name(buf, sizeof(buf), request, 1));
                return r;
        }
@@ -626,6 +631,15 @@ static int preprocess_preaccounting(void *instance, REQUEST *request)
 
        r = hints_setup(data->hints, request);
 
+       if ((r = huntgroup_access(request, data->huntgroups,
+                            request->packet->vps)) != RLM_MODULE_OK) {
+               char buf[1024];
+               radlog(L_INFO, "No huntgroup access: [%s] (%s)",
+                      request->username ? request->username->vp_strvalue : "<NO User-Name>",
+                      auth_name(buf, sizeof(buf), request, 1));
+               return r;
+       }
+
        return r;
 }
 
@@ -639,19 +653,18 @@ static int preprocess_detach(void *instance)
        pairlist_free(&(data->huntgroups));
        pairlist_free(&(data->hints));
 
-       free(data->huntgroup_file);
-       free(data->hints_file);
        free(data);
 
        return 0;
 }
 
 /* globally exported name */
-module_t rlm_preprocess = {
+module_t rlm_preprocess = {    
+       RLM_MODULE_INIT,
        "preprocess",
        0,                      /* type: reserved */
-       NULL,                   /* initialization */
        preprocess_instantiate, /* instantiation */
+       preprocess_detach,      /* detach */
        {
                NULL,                   /* authentication */
                preprocess_authorize,   /* authorization */
@@ -662,7 +675,5 @@ module_t rlm_preprocess = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       preprocess_detach,      /* detach */
-       NULL,                   /* destroy */
 };
 
diff --git a/src/modules/rlm_protocol_filter/Makefile b/src/modules/rlm_protocol_filter/Makefile
new file mode 100755 (executable)
index 0000000..9d08409
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Makefile
+#
+# Version:     $Id$
+#
+
+TARGET         = rlm_protocol_filter
+SRCS           = rlm_protocol_filter.c
+
+include ../rules.mak
diff --git a/src/modules/rlm_protocol_filter/rlm_protocol_filter.c b/src/modules/rlm_protocol_filter/rlm_protocol_filter.c
new file mode 100755 (executable)
index 0000000..d5828ab
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * rlm_protocol_filter.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 2004  Cladju Consulting, Inc. <aland@cladju.com>
+ * Copyright 2006  The FreeRADIUS server project
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+
+static const char rcsid[] = "$Id$";
+
+/*
+ *     Define a structure for our module configuration.
+ *
+ */
+typedef struct rlm_protocol_filter_t {
+       char            *filename;
+       char            *key;
+       CONF_SECTION    *cs;
+} rlm_protocol_filter_t;
+
+/*
+ *     A mapping of configuration file names to internal variables.
+ *
+ *     Note that the string is dynamically allocated, so it MUST
+ *     be freed.  When the configuration file parse re-reads the string,
+ *     it free's the old one, and strdup's the new one, placing the pointer
+ *     to the strdup'd string into 'config.string'.  This gets around
+ *     buffer over-flows.
+ */
+static const CONF_PARSER module_config[] = {
+       { "filename",  PW_TYPE_FILENAME,
+         offsetof(rlm_protocol_filter_t,filename), NULL,
+         "${raddbdir}/protocol_filter.conf"},
+
+       { "key",  PW_TYPE_STRING_PTR,
+         offsetof(rlm_protocol_filter_t,key), NULL, "%{Realm:-DEFAULT}"},
+       
+       { NULL, -1, 0, NULL, NULL }             /* end the list */
+};
+
+static int filter_detach(void *instance)
+{
+       rlm_protocol_filter_t *inst = instance;
+
+       if (inst->cs) cf_section_free(&(inst->cs));
+
+       free(instance);
+       return 0;
+}
+
+
+/*
+ *     Do any per-module initialization that is separate to each
+ *     configured instance of the module.  e.g. set up connections
+ *     to external databases, read configuration files, set up
+ *     dictionary entries, etc.
+ *
+ *     If configuration information is given in the config section
+ *     that must be referenced in later calls, store a handle to it
+ *     in *instance otherwise put a null pointer there.
+ */
+static int filter_instantiate(CONF_SECTION *conf, void **instance)
+{
+       rlm_protocol_filter_t *inst;
+
+       /*
+        *      Set up a storage area for instance data
+        */
+       inst = rad_malloc(sizeof(*inst));
+       if (!inst) {
+               return -1;
+       }
+       memset(inst, 0, sizeof(*inst));
+
+       /*
+        *      If the configuration parameters can't be parsed, then
+        *      fail.
+        */
+       if (cf_section_parse(conf, inst, module_config) < 0) {
+               filter_detach(inst);
+               return -1;
+       }
+
+       inst->cs = conf_read("rlm_protocol_filter", 0,
+                            inst->filename, NULL);
+       if (!inst->cs) {
+               filter_detach(inst);
+               return -1;
+       }
+
+       *instance = inst;
+
+       return 0;
+}
+
+
+/*
+ *     Return permission.
+ */
+static int str2sense(const char *str)
+{
+       if (strcasecmp(str, "permit") == 0) return 1;
+       if (strcasecmp(str, "deny") == 0) return 0;
+
+       return -1;
+}
+
+/*
+ *     Apply a subsection to a request.
+ *     Returns permit/deny/error.
+ */
+static int apply_subsection(rlm_protocol_filter_t *inst, REQUEST *request,
+                           CONF_SECTION *cs, const char *name)
+{
+       int sense;
+       CONF_PAIR *cp;
+       const char *value;
+       char keybuf[256];
+       
+       DEBUG2("  rlm_protocol_filter: Found subsection %s", name);
+       
+       cp = cf_pair_find(cs, "key");
+       if (!cp) {
+               radlog(L_ERR, "rlm_protocol_filter: %s[%d]: No key defined in subsection %s",
+                      inst->filename, cf_section_lineno(cs), name);
+               return RLM_MODULE_FAIL;
+       }
+       
+       radius_xlat(keybuf, sizeof(keybuf),
+                   cf_pair_value(cp), request, NULL);
+       if (!*keybuf) {
+               DEBUG2("  rlm_protocol_filter: %s[%d]: subsection %s, key is empty, doing nothing.",
+                      inst->filename, cf_section_lineno(cs), name);
+               return RLM_MODULE_NOOP;
+       }
+
+       DEBUG2("  rlm_protocol_filter: %s[%d]: subsection %s, using key %s",
+              inst->filename, cf_section_lineno(cs), name, keybuf);
+                       
+       /*
+        *      And repeat some of the above code.
+        */
+       cp = cf_pair_find(cs, keybuf);
+       if (!cp) {
+               CONF_SECTION *subcs;
+
+               /*
+                *      Maybe it has a subsection, too.
+                */
+               subcs = cf_section_sub_find(cs, keybuf);
+               if (subcs) {
+                       return apply_subsection(inst, request, subcs, keybuf);
+               } /* it was a subsection */
+
+
+
+               DEBUG2("  rlm_protocol_filter: %s[%d]: subsection %s, rule not found, doing nothing.",
+                      inst->filename, cf_section_lineno(cs), name);
+               return RLM_MODULE_NOOP;
+       }
+       
+       value = cf_pair_value(cp);
+       sense = str2sense(value);
+       if (sense < 0) {
+               radlog(L_ERR, "rlm_protocol_filter: %s[%d]: Unknwn directive %s",
+                      inst->filename, cf_pair_lineno(cp), value);
+               return RLM_MODULE_FAIL;
+       }
+       
+       if (!sense) return RLM_MODULE_REJECT;
+
+       return RLM_MODULE_OK;
+}
+
+
+/*
+ *     Authorize the user.
+ */
+static int filter_authorize(void *instance, REQUEST *request)
+{
+       int sense;
+       VALUE_PAIR *vp;
+       CONF_SECTION *cs;
+       CONF_PAIR *cp;
+       char keybuf[1024];
+       rlm_protocol_filter_t *inst = instance;
+
+       radius_xlat(keybuf, sizeof(keybuf), inst->key, request, NULL);
+       if (!*keybuf) {
+               DEBUG2("  rlm_protocol_filter: key is empty");
+               return RLM_MODULE_NOOP;
+       }
+       DEBUG2("  rlm_protocol_filter: Using key %s", keybuf);
+
+       cs = cf_section_sub_find(inst->cs, keybuf);
+       if (!cs) {
+               DEBUG2("  rlm_protocol_filter: No such key in %s", inst->filename);
+               return RLM_MODULE_NOTFOUND;
+       }
+
+       /*
+        *      Walk through the list of attributes, seeing if they're
+        *      permitted/denied.
+        */
+       for (vp = request->packet->vps; vp != NULL; vp = vp->next) {
+               const char *value;
+               CONF_SECTION *subcs;
+
+               cp = cf_pair_find(cs, vp->name);
+               if (cp) {
+                       value = cf_pair_value(cp);
+
+                       sense = str2sense(value);
+                       if (sense < 0) {
+                               radlog(L_ERR, "rlm_protocol_filter %s[%d]: Unknown directive %s",
+                                      inst->filename,
+                                      cf_pair_lineno(cp),
+                                      value);
+                               return RLM_MODULE_FAIL;
+                       }
+
+                       if (!sense) return RLM_MODULE_REJECT;
+                       continue; /* was permitted */
+               } /* else no pair was found */
+
+               /*
+                *      Maybe it has a subsection
+                */
+               subcs = cf_section_sub_find(cs, vp->name);
+               if (subcs) {
+                       sense = apply_subsection(inst, request, subcs, vp->name);
+                       if ((sense == RLM_MODULE_OK) ||
+                           (sense == RLM_MODULE_NOOP)) {
+                               continue;
+                       }
+
+                       return sense;
+               } /* it was a subsection */
+
+               /*
+                *      Not found, must be "permit"
+                */
+       }
+
+       return RLM_MODULE_OK;
+}
+
+
+/*
+ *     The module name should be the only globally exported symbol.
+ *     That is, everything else should be 'static'.
+ *
+ *     If the module needs to temporarily modify it's instantiation
+ *     data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
+ *     The server will then take care of ensuring that the module
+ *     is single-threaded.
+ */
+module_t rlm_protocol_filter = {
+       RLM_MODULE_INIT,
+       "protocol_filter",
+       RLM_TYPE_THREAD_SAFE,           /* type */
+       filter_instantiate,             /* instantiation */
+       filter_detach,                  /* detach */
+       {
+               NULL,                   /* authentication */
+               filter_authorize,       /* authorization */
+               NULL,                   /* preaccounting */
+               NULL,                   /* accounting */
+               NULL,                   /* checksimul */
+               NULL,                   /* pre-proxy */
+               NULL,                   /* post-proxy */
+               NULL                    /* post-auth */
+       },
+};
index aa96770..eb0df8f 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.7 .
+# From configure.in Revision: 1.8 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -907,7 +907,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1827,8 +1827,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1886,8 +1885,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2003,8 +2001,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2058,8 +2055,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2104,8 +2100,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2149,8 +2144,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2571,8 +2565,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2595,8 +2588,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" = "x"; then
@@ -2625,8 +2618,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2704,8 +2696,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2728,8 +2719,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" != "x"; then
@@ -2793,8 +2784,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2817,8 +2807,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" = "x"; then
@@ -2847,8 +2837,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2953,8 +2942,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2977,8 +2965,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" != "x"; then
@@ -3837,11 +3825,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3880,6 +3863,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 1e688e8..fc27948 100644 (file)
@@ -1,3 +1,4 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_python.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_python])
@@ -68,7 +69,7 @@ if test x$with_[]modname != xno; then
                old_CFLAGS=$CFLAGS
                CFLAGS="$CFLAGS $PY_CFLAGS"
                smart_try_dir=$PY_INC_DIR
-               AC_SMART_CHECK_INCLUDE(Python.h)
+               FR_SMART_CHECK_INCLUDE(Python.h)
                CFLAGS=$old_CFLAGS
 
                if test "x$ac_cv_header_Python_h" = "xyes"; then
@@ -81,7 +82,7 @@ if test x$with_[]modname != xno; then
                old_LIBS=$LIBS
                LIBS="$LIBS $PY_LIB_LOC $PY_EXTRA_LIBS -lm"
                smart_try_dir=$PY_LIB_DIR
-               AC_SMART_CHECK_LIB(python${PY_VERSION}, Py_Initialize)
+               FR_SMART_CHECK_LIB(python${PY_VERSION}, Py_Initialize)
                LIBS=$old_LIBS
 
                eval t=\${ac_cv_lib_${sm_lib_safe}_${sm_func_safe}}
index 51567b6..aae1c83 100644 (file)
@@ -1,3 +1,4 @@
+#! /usr/bin/env python
 #
 # Example Python module for prepaid usage using MySQL
 
 # 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 #
 # Copyright 2002 Miguel A.L. Paraz <mparaz@mparaz.com>
 # Copyright 2002 Imperium Technology, Inc.
+#
+# $Id$
 
 import radiusd
 import MySQLdb
index 08fe100..08a1aa0 100644 (file)
@@ -1,3 +1,4 @@
+#! /usr/bin/env python
 #
 # Definitions for RADIUS programs
 #
@@ -6,6 +7,8 @@
 # This should only be used when testing modules.
 # Inside freeradius, the 'radiusd' Python module is created by the C module
 # and the definitions are automatically created.
+#
+# $Id$
 
 # from modules.h
 
index 2e24af5..3db91f0 100644 (file)
@@ -1,6 +1,9 @@
+#! /usr/bin/env python
 #
 # Python module test
 # Miguel A.L. Paraz <mparaz@mparaz.com>
+#
+# $Id$
 
 import radiusd
 
index 2a74554..1880465 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2002  Miguel A.L. Paraz <mparaz@mparaz.com>
  * Copyright 2002  Imperium Technology, Inc.
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <Python.h>
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
-
-#define Pyx_BLOCK_THREADS       {PyGILState_STATE __gstate = PyGILState_Ensure();
-#define Pyx_UNBLOCK_THREADS     PyGILState_Release(__gstate);}
-
-
-
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/conffile.h>
 
 /*
  *     Define a structure for our module configuration.
@@ -47,43 +42,55 @@ static const char rcsid[] = "$Id$";
  *     a lot cleaner to do so, and a pointer to the structure can
  *     be used as the instance handle.
  */
-
-struct rlm_python_t {
-        char    *mod_instantiate;
-        char    *mod_authorize;
-        char    *mod_authenticate;
-        char    *mod_preacct;
-        char    *mod_accounting;
-        char    *mod_checksimul;
-        char    *mod_detach;
-
-        /* Names of functions */
-        char    *func_instantiate;
-        char    *func_authorize;
-        char    *func_authenticate;
-        char    *func_preacct;
-        char    *func_accounting;
-        char    *func_checksimul;
-        char    *func_detach;
-
-        PyObject *pModule_instantiate;
-        PyObject *pModule_authorize;
-        PyObject *pModule_authenticate;
-        PyObject *pModule_preacct;
-        PyObject *pModule_accounting;
-        PyObject *pModule_checksimul;
-        PyObject *pModule_detach;
-
-        /* Functions */
-        PyObject *pFunc_instantiate;
-        PyObject *pFunc_authorize;
-        PyObject *pFunc_authenticate;
-        PyObject *pFunc_preacct;
-        PyObject *pFunc_accounting;
-        PyObject *pFunc_checksimul;
-        PyObject *pFunc_detach;
-};
-
+typedef struct rlm_python_t {
+    /* Config section */
+
+    /* Names of modules */
+    char
+        *mod_instantiate,
+        *mod_authorize,
+       *mod_authenticate,
+       *mod_preacct,
+       *mod_accounting,
+       *mod_checksimul,
+       *mod_detach,
+
+    /* Names of functions */
+        *func_instantiate,
+        *func_authorize,
+       *func_authenticate,
+       *func_preacct,
+       *func_accounting,
+       *func_checksimul,
+       *func_detach;
+
+
+    /* End Config section */
+
+
+    /* Python objects for modules */
+    PyObject
+        *pModule_builtin,
+        *pModule_instantiate,
+        *pModule_authorize,
+       *pModule_authenticate,
+       *pModule_preacct,
+       *pModule_accounting,
+       *pModule_checksimul,
+       *pModule_detach,
+
+
+       /* Functions */
+
+       *pFunc_instantiate,
+       *pFunc_authorize,
+       *pFunc_authenticate,
+       *pFunc_preacct,
+       *pFunc_accounting,
+       *pFunc_checksimul,
+       *pFunc_detach;
+
+} rlm_python_t;
 
 /*
  *     A mapping of configuration file names to internal variables.
@@ -94,80 +101,52 @@ struct rlm_python_t {
  *     to the strdup'd string into 'config.string'.  This gets around
  *     buffer over-flows.
  */
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
   { "mod_instantiate",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, mod_instantiate), NULL,  NULL},
+    offsetof(rlm_python_t, mod_instantiate), NULL,  NULL},
   { "func_instantiate",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, func_instantiate), NULL,  NULL},
+    offsetof(rlm_python_t, func_instantiate), NULL,  NULL},
 
   { "mod_authorize",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, mod_authorize), NULL,  NULL},
+    offsetof(rlm_python_t, mod_authorize), NULL,  NULL},
   { "func_authorize",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, func_authorize), NULL,  NULL},
+    offsetof(rlm_python_t, func_authorize), NULL,  NULL},
 
   { "mod_authenticate",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, mod_authenticate), NULL,  NULL},
+    offsetof(rlm_python_t, mod_authenticate), NULL,  NULL},
   { "func_authenticate",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, func_authenticate), NULL,  NULL},
+    offsetof(rlm_python_t, func_authenticate), NULL,  NULL},
 
   { "mod_preacct",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, mod_preacct), NULL,  NULL},
+    offsetof(rlm_python_t, mod_preacct), NULL,  NULL},
   { "func_preacct",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, func_preacct), NULL,  NULL},
+    offsetof(rlm_python_t, func_preacct), NULL,  NULL},
 
   { "mod_accounting",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, mod_accounting), NULL,  NULL},
+    offsetof(rlm_python_t, mod_accounting), NULL,  NULL},
   { "func_accounting",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, func_accounting), NULL,  NULL},
+    offsetof(rlm_python_t, func_accounting), NULL,  NULL},
 
   { "mod_checksimul",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, mod_checksimul), NULL,  NULL},
+    offsetof(rlm_python_t, mod_checksimul), NULL,  NULL},
   { "func_checksimul",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, func_checksimul), NULL,  NULL},
+    offsetof(rlm_python_t, func_checksimul), NULL,  NULL},
 
   { "mod_detach",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, mod_detach), NULL,  NULL},
+    offsetof(rlm_python_t, mod_detach), NULL,  NULL},
   { "func_detach",  PW_TYPE_STRING_PTR,
-    offsetof(struct rlm_python_t, func_detach), NULL,  NULL},
+    offsetof(rlm_python_t, func_detach), NULL,  NULL},
 
 
   { NULL, -1, 0, NULL, NULL }          /* end the list */
 };
 
-static struct {
-        const char*     name;
-        int             value;
-} radiusd_constants[] = {
-        { "L_DBG",              L_DBG                   },
-        { "L_AUTH",             L_AUTH                  },
-        { "L_INFO",             L_INFO                  },
-        { "L_ERR",              L_ERR                   },
-        { "L_PROXY",            L_PROXY                 },
-        { "L_CONS",             L_CONS                  },
-        { "RLM_MODULE_REJECT",  RLM_MODULE_REJECT       },
-        { "RLM_MODULE_FAIL",    RLM_MODULE_FAIL         },
-        { "RLM_MODULE_OK",      RLM_MODULE_OK           },
-        { "RLM_MODULE_HANDLED", RLM_MODULE_HANDLED      },
-        { "RLM_MODULE_INVALID", RLM_MODULE_INVALID      },
-        { "RLM_MODULE_USERLOCK",RLM_MODULE_USERLOCK     },
-        { "RLM_MODULE_NOTFOUND",RLM_MODULE_NOTFOUND     },
-        { "RLM_MODULE_NOOP",    RLM_MODULE_NOOP         },
-        { "RLM_MODULE_UPDATED", RLM_MODULE_UPDATED      },
-        { "RLM_MODULE_NUMCODES",RLM_MODULE_NUMCODES     },
-        { NULL, 0 },
-};
-
-
-/* Let assume that radiusd module is only one since we have only one intepreter */
-
-static PyObject *radiusd_module = NULL;
-
 /*
  * radiusd Python functions
  */
 
 /* radlog wrapper */
-static PyObject *python_radlog(const PyObject *module, PyObject *args) {
+static PyObject *radlog_py(const PyObject *self, PyObject *args) {
     int status;
     char *msg;
 
@@ -175,332 +154,389 @@ static PyObject *python_radlog(const PyObject *module, PyObject *args) {
        return NULL;
     }
 
-    radlog(status, "%s", msg);
-    Py_INCREF(Py_None);
-
+    radlog(status, msg);
     return Py_None;
 }
 
 static PyMethodDef radiusd_methods[] = {
-    {"radlog", (PyCFunction) &python_radlog, METH_VARARGS, "freeradius radlog()."},
+    {"radlog", (PyCFunction)radlog_py, METH_VARARGS, "freeradius radlog()."},
     {NULL, NULL, 0, NULL}
 };
 
-static void python_error() {
-    PyObject        *pType = NULL;
-    PyObject        *pValue = NULL;
-    PyObject        *pTraceback = NULL;
-    PyObject        *pStr1 = NULL;
-    PyObject        *pStr2 = NULL;
 
-    Pyx_BLOCK_THREADS
+/* Extract string representation of Python error. */
+static void python_error(void) {
+    PyObject *pType, *pValue, *pTraceback, *pStr1, *pStr2;
 
     PyErr_Fetch(&pType, &pValue, &pTraceback);
-    if (pType == NULL || pValue == NULL)
-        goto failed;
-    if ((pStr1 = PyObject_Str(pType)) == NULL || (pStr2 = PyObject_Str(pValue)) == NULL)
-        goto failed;
-    radlog(L_ERR, "rlm_python:EXCEPT:%s: %s", PyString_AsString(pStr1), PyString_AsString(pStr2));
-
-failed:
-    Py_XDECREF(pStr1);
-    Py_XDECREF(pStr2);
-    Py_XDECREF(pType);
-    Py_XDECREF(pValue);
-    Py_XDECREF(pTraceback);
-
-    Pyx_UNBLOCK_THREADS
+    pStr1 = PyObject_Str(pType);
+    pStr2 = PyObject_Str(pValue);
+
+    radlog(L_ERR, "%s: %s\n",
+          PyString_AsString(pStr1), PyString_AsString(pStr2));
 }
 
-static int python_init()
+/* Tuple to value pair conversion */
+static void add_vp_tuple(VALUE_PAIR **vpp, PyObject *pValue,
+                        const char *function_name) {
+    int i, outertuplesize;
+    VALUE_PAIR *vp;
+
+    /* If the Python function gave us None for the tuple, then just return. */
+    if (pValue == Py_None) {
+       return;
+    }
+
+    if (!PyTuple_Check(pValue)) {
+       radlog(L_ERR, "%s: non-tuple passed", function_name);
+    }
+
+    /* Get the tuple size. */
+    outertuplesize = PyTuple_Size(pValue);
+
+    for (i = 0; i < outertuplesize; i++) {
+       PyObject *pTupleElement = PyTuple_GetItem(pValue, i);
+
+       if ((pTupleElement != NULL) &&
+           (PyTuple_Check(pTupleElement))) {
+
+           /* Check if it's a pair */
+           int tuplesize;
+
+           if ((tuplesize = PyTuple_Size(pTupleElement)) != 2) {
+               radlog(L_ERR, "%s: tuple element %d is a tuple "
+                      " of size %d. must be 2\n", function_name,
+                      i, tuplesize);
+           }
+           else {
+               PyObject *pString1, *pString2;
+
+               pString1 = PyTuple_GetItem(pTupleElement, 0);
+               pString2 = PyTuple_GetItem(pTupleElement, 1);
+
+               /* xxx PyString_Check does not compile here */
+               if  ((pString1 != NULL) &&
+                    (pString2 != NULL) &&
+                    PyObject_TypeCheck(pString1,&PyString_Type) &&
+                    PyObject_TypeCheck(pString2,&PyString_Type)) {
+
+
+                   const char *s1, *s2;
+
+                   /* pairmake() will convert and find any
+                    * errors in the pair.
+                    */
+
+                   s1 = PyString_AsString(pString1);
+                   s2 = PyString_AsString(pString2);
+
+                   if ((s1 != NULL) && (s2 != NULL)) {
+                       radlog(L_DBG, "%s: %s = %s ",
+                              function_name, s1, s2);
+
+                       /* xxx Might need to support other T_OP */
+                       vp = pairmake(s1, s2, T_OP_EQ);
+                       if (vp != NULL) {
+                           pairadd(vpp, vp);
+                           radlog(L_DBG, "%s: s1, s2 OK\n",
+                                  function_name);
+                       }
+                       else {
+                           radlog(L_DBG, "%s: s1, s2 FAILED\n",
+                                  function_name);
+                       }
+                   }
+                   else {
+                       radlog(L_ERR, "%s: string conv failed\n",
+                              function_name);
+                   }
+
+               }
+               else {
+                   radlog(L_ERR, "%s: tuple element %d must be "
+                          "(string, string)", function_name, i);
+               }
+           }
+       }
+       else {
+           radlog(L_ERR, "%s: tuple element %d is not a tuple\n",
+                  function_name, i);
+       }
+    }
+
+}
+
+/* This is the core Python function that the others wrap around.
+ * Pass the value-pair print strings in a tuple.
+ * xxx We're not checking the errors. If we have errors, what do we do?
+ */
+
+static int python_function(REQUEST *request,
+                          PyObject *pFunc, const char *function_name)
 {
-    int i;
+#define BUF_SIZE 1024
 
-    Py_SetProgramName("radiusd");
+    char buf[BUF_SIZE];                /* same size as vp_print buffer */
 
-    Py_Initialize();
+    VALUE_PAIR *vp;
 
-    PyEval_InitThreads(); // This also grabs a lock
+    PyObject *pValue, *pValuePairContainer, **pValueHolder, **pValueHolderPtr;
+    int i, n_tuple, return_value;
 
-    if ((radiusd_module = Py_InitModule3("radiusd", radiusd_methods, "FreeRADIUS Module.")) == NULL)
-        goto failed;
+    /* Return with "OK, continue" if the function is not defined. */
+    if (pFunc == NULL) {
+       return RLM_MODULE_OK;
+    }
 
-    for (i = 0; radiusd_constants[i].name; i++)
-        if ((PyModule_AddIntConstant(radiusd_module, radiusd_constants[i].name, radiusd_constants[i].value)) < 0)
-            goto failed;
+    /* Default return value is "OK, continue" */
+    return_value = RLM_MODULE_OK;
+
+    /* We will pass a tuple containing (name, value) tuples
+     * We can safely use the Python function to build up a tuple,
+     * since the tuple is not used elsewhere.
+     *
+     * Determine the size of our tuple by walking through the packet.
+     * If request is NULL, pass None.
+     */
+    n_tuple = 0;
+
+    if (request != NULL) {
+       for (vp = request->packet->vps; vp; vp = vp->next) {
+           n_tuple++;
+       }
+    }
 
-    PyEval_ReleaseLock(); // Drop lock grabbed by InitThreads
+    /* Create the tuple and a holder for the pointers, so that we can
+     * decref more efficiently later without the overhead of reading
+     * the tuple.
+     *
+     * We use malloc() instead of the Python memory allocator since we
+     * are not embedded.
+     */
 
-    radlog(L_DBG, "python_init done");
+    if (NULL == (pValueHolder = pValueHolderPtr =
+                malloc(sizeof(PyObject *) * n_tuple))) {
 
-    return 0;
+       radlog(L_ERR, "%s: malloc of %d bytes failed\n",
+              function_name, sizeof(PyObject *) * n_tuple);
 
-failed:
-    python_error();
-    Py_Finalize();
-    return -1;
-}
+       return -1;
+    }
 
-static int python_destroy() {
-    Pyx_BLOCK_THREADS
-    Py_XDECREF(radiusd_module);
-    Py_Finalize();
-    Pyx_UNBLOCK_THREADS
+    if (n_tuple == 0) {
+       pValuePairContainer = Py_None;
+    }
+    else {
+       pValuePairContainer = PyTuple_New(n_tuple);
 
-    return 0;
-}
+       i = 0;
+       for (vp = request->packet->vps; vp; vp = vp->next) {
+           PyObject *pValuePair, *pString1, *pString2;
 
-static void python_vptuple(VALUE_PAIR **vpp, PyObject *pValue, const char *funcname) {
-        int             i;
-        int             tuplesize;
-        VALUE_PAIR      *vp;
-
-        /* If the Python function gave us None for the tuple, then just return. */
-        if (pValue == Py_None)
-                return;
-
-        if (!PyTuple_CheckExact(pValue)) {
-                radlog(L_ERR, "rlm_python:%s: non-tuple passed", funcname);
-                return;
-        }
-        /* Get the tuple tuplesize. */
-        tuplesize = PyTuple_GET_SIZE(pValue);
-        for (i = 0; i < tuplesize; i++) {
-                PyObject *pTupleElement = PyTuple_GET_ITEM(pValue, i);
-                PyObject *pStr1;
-                PyObject *pStr2;
-                int pairsize;
-                const char *s1;
-                const char *s2;
-
-                if (!PyTuple_CheckExact(pTupleElement)) {
-                        radlog(L_ERR, "rlm_python:%s: tuple element %d is not a tuple", funcname, i);
-                        continue;
-                }
-                /* Check if it's a pair */
-                if ((pairsize = PyTuple_GET_SIZE(pTupleElement)) != 2) {
-                        radlog(L_ERR, "rlm_python:%s: tuple element %d is a tuple of size %d. Must be 2", funcname, i, pairsize);
-                        continue;
-                }
-                pStr1 = PyTuple_GET_ITEM(pTupleElement, 0);
-                pStr2 = PyTuple_GET_ITEM(pTupleElement, 1);
-                if ((!PyString_CheckExact(pStr1)) || (!PyString_CheckExact(pStr2))) {
-                        radlog(L_ERR, "rlm_python:%s: tuple element %d must be as (str, str)", funcname, i);
-                        continue;
-                }
-                s1 = PyString_AsString(pStr1);
-                s2 = PyString_AsString(pStr2);
-                /* xxx Might need to support other T_OP */
-                vp = pairmake(s1, s2, T_OP_EQ);
-                if (vp != NULL) {
-                        pairadd(vpp, vp);
-                        radlog(L_DBG, "rlm_python:%s: '%s' = '%s'", funcname, s1, s2);
-                } else {
-                        radlog(L_DBG, "rlm_python:%s: Failed: '%s' = '%s'", funcname, s1, s2);
-                }
-        }
-}
+           /* The inside tuple has two only: */
+           pValuePair = PyTuple_New(2);
 
+           /* The name. logic from vp_prints, lib/print.c */
+           if (vp->flags.has_tag) {
+               snprintf(buf, BUF_SIZE, "%s:%d", vp->name, vp->flags.tag);
+           }
+           else {
+               strcpy(buf, vp->name);
+           }
 
-/* This is the core Python function that the others wrap around.
- * Pass the value-pair print strings in a tuple.
- * xxx We're not checking the errors. If we have errors, what do we do?
- */
+           pString1 = PyString_FromString(buf);
+           PyTuple_SetItem(pValuePair, 0, pString1);
+
+
+           /* The value. Use delimiter - don't know what that means */
+           vp_prints_value(buf, sizeof(buf), vp, 1);
+           pString2 = PyString_FromString(buf);
+           PyTuple_SetItem(pValuePair, 1, pString2);
+
+           /* Put the tuple inside the container */
+           PyTuple_SetItem(pValuePairContainer, i++, pValuePair);
+
+           /* Store the pointer in our malloc() storage */
+           *pValueHolderPtr++ = pValuePair;
+       }
+    }
+
+
+    /* Call Python function.
+     */
+
+    if (pFunc && PyCallable_Check(pFunc)) {
+       PyObject *pArgs;
+
+       /* call the function with a singleton tuple containing the
+        * container tuple.
+        */
+
+       if ((pArgs = PyTuple_New(1)) == NULL) {
+           radlog(L_ERR, "%s: could not create tuple", function_name);
+           return -1;
+       }
+       if ((PyTuple_SetItem(pArgs, 0, pValuePairContainer)) != 0) {
+           radlog(L_ERR, "%s: could not set tuple item", function_name);
+           return -1;
+       }
+
+       if ((pValue = PyObject_CallObject(pFunc, pArgs)) == NULL) {
+           radlog(L_ERR, "%s: function call failed", function_name);
+           python_error();
+           return -1;
+       }
+
+       /* The function returns either:
+        *  1. tuple containing the integer return value,
+        *  then the integer reply code (or None to not set),
+        *  then the string tuples to build the reply with.
+        *     (returnvalue, (p1, s1), (p2, s2))
+        *
+        *  2. the function return value alone
+        *
+        *  3. None - default return value is set
+        *
+        * xxx This code is messy!
+        */
+
+       if (PyTuple_Check(pValue)) {
+           PyObject *pTupleInt;
+
+           if (PyTuple_Size(pValue) != 3) {
+               radlog(L_ERR, "%s: tuple must be " \
+                      "(return, replyTuple, configTuple)",
+                      function_name);
+
+           }
+           else {
+               pTupleInt = PyTuple_GetItem(pValue, 0);
+
+               if ((pTupleInt == NULL) || !PyInt_Check(pTupleInt)) {
+                   radlog(L_ERR, "%s: first tuple element not an integer",
+                          function_name);
+               }
+               else {
+                   /* Now have the return value */
+                   return_value = PyInt_AsLong(pTupleInt);
+
+                   /* Reply item tuple */
+                   add_vp_tuple(&request->reply->vps,
+                                PyTuple_GetItem(pValue, 1), function_name);
+
+                   /* Config item tuple */
+                   add_vp_tuple(&request->config_items,
+                                PyTuple_GetItem(pValue, 2), function_name);
+               }
+           }
+       }
+       else if (PyInt_Check(pValue)) {
+           /* Just an integer */
+           return_value = PyInt_AsLong(pValue);
+       }
+       else if (pValue == Py_None) {
+           /* returned 'None', return value defaults to "OK, continue." */
+           return_value = RLM_MODULE_OK;
+       }
+       else {
+           /* Not tuple or None */
+           radlog(L_ERR, "%s function did not return a tuple or None\n",
+                  function_name);
+       }
+
+
+       /* Decrease reference counts for the argument and return tuple */
+       Py_DECREF(pArgs);
+       Py_DECREF(pValue);
+    }
+
+    /* Decrease reference count for the tuples passed, the
+     * container tuple, and the return value.
+     */
 
-static int python_function(REQUEST *request, PyObject *pFunc, const char *funcname) {
-        char            buf[1024];
-        VALUE_PAIR      *vp;
-        PyObject        *pRet = NULL;
-        PyObject        *pArgs = NULL;
-        int             tuplelen;
-        int             ret;
-
-       PyGILState_STATE gstate;
-
-        /* Return with "OK, continue" if the function is not defined. */
-        if (pFunc == NULL)
-                return RLM_MODULE_OK;
-
-        /* Default return value is "OK, continue" */
-        ret = RLM_MODULE_OK;
-
-        /* We will pass a tuple containing (name, value) tuples
-         * We can safely use the Python function to build up a tuple,
-         * since the tuple is not used elsewhere.
-         *
-         * Determine the size of our tuple by walking through the packet.
-         * If request is NULL, pass None.
-         */
-        tuplelen = 0;
-        if (request != NULL) {
-                for (vp = request->packet->vps; vp; vp = vp->next)
-                        tuplelen++;
-        }
-
-        gstate = PyGILState_Ensure();
-
-        if (tuplelen == 0) {
-                Py_INCREF(Py_None);
-                pArgs = Py_None;
-        } else {
-                int     i = 0;
-                if ((pArgs = PyTuple_New(tuplelen)) == NULL)
-                        goto failed;
-                for (vp = request->packet->vps; vp != NULL; vp = vp->next, i++) {
-                        PyObject *pPair;
-                        PyObject *pStr;
-                        /* The inside tuple has two only: */
-                        if ((pPair = PyTuple_New(2)) == NULL)
-                                goto failed;
-                        /* Put the tuple inside the container */
-                        PyTuple_SET_ITEM(pArgs, i, pPair);
-                        /* The name. logic from vp_prints, lib/print.c */
-                        if (vp->flags.has_tag)
-                                snprintf(buf, sizeof(buf), "%s:%d", vp->name, vp->flags.tag);
-                        else
-                                strcpy(buf, vp->name);
-                        if ((pStr = PyString_FromString(buf)) == NULL)
-                                goto failed;
-                        PyTuple_SET_ITEM(pPair, 0, pStr);
-                        vp_prints_value(buf, sizeof(buf), vp, 1);
-                        if ((pStr = PyString_FromString(buf)) == NULL)
-                                goto failed;
-                        PyTuple_SET_ITEM(pPair, 1, pStr);
-                }
-        }
-
-        /* Call Python function. */
-        pRet = PyObject_CallFunctionObjArgs(pFunc, pArgs, NULL);
-
-       if (pRet == NULL)
-                goto failed;
-
-        if (request == NULL)
-                goto okay;
-        /* The function returns either:
-         *  1. tuple containing the integer return value,
-         *  then the integer reply code (or None to not set),
-         *  then the string tuples to build the reply with.
-         *  (returnvalue, (p1, s1), (p2, s2))
-         *
-         *  2. the function return value alone
-         *
-         *  3. None - default return value is set
-         *
-         * xxx This code is messy!
-         */
-        if (PyTuple_CheckExact(pRet)) {
-                PyObject *pTupleInt;
-
-                if (PyTuple_GET_SIZE(pRet) != 3) {
-                        radlog(L_ERR, "rlm_python:%s: tuple must be (return, replyTuple, configTuple)", funcname);
-                        goto failed;
-                }
-                pTupleInt = PyTuple_GET_ITEM(pRet, 0);
-                if (!PyInt_CheckExact(pTupleInt)) {
-                        radlog(L_ERR, "rlm_python:%s: first tuple element not an integer", funcname);
-                        goto failed;
-                }
-                /* Now have the return value */
-                ret = PyInt_AsLong(pTupleInt);
-                /* Reply item tuple */
-                python_vptuple(&request->reply->vps, PyTuple_GET_ITEM(pRet, 1), funcname);
-                /* Config item tuple */
-                python_vptuple(&request->config_items, PyTuple_GET_ITEM(pRet, 2), funcname);
-        } else
-        if (PyInt_CheckExact(pRet)) {
-                /* Just an integer */
-                ret = PyInt_AsLong(pRet);
-        } else
-        if (pRet == Py_None) {
-                /* returned 'None', return value defaults to "OK, continue." */
-                ret = RLM_MODULE_OK;
-        } else {
-                /* Not tuple or None */
-                radlog(L_ERR, "rlm_python:%s: function did not return a tuple or None", funcname);
-                goto failed;
-        }
-        if (ret == RLM_MODULE_REJECT && request != NULL)
-                pairfree(&request->reply->vps);
-okay:
-        Py_DECREF(pArgs);
-        Py_DECREF(pRet);
-       PyGILState_Release(gstate);
-        return ret;
-failed:
-        python_error();
-        Py_XDECREF(pArgs);
-        Py_XDECREF(pRet);
-        PyGILState_Release(gstate);
-
-        return -1;
+    pValueHolderPtr = pValueHolder;
+    i = n_tuple;
+    while (i--) {
+       /* Can't write as pValueHolderPtr since Py_DECREF is a macro */
+       Py_DECREF(*pValueHolderPtr);
+       pValueHolderPtr++;
+    }
+    free(pValueHolder);
+    Py_DECREF(pValuePairContainer);
+
+    /* pDict and pFunc are borrowed and must not be Py_DECREF-ed */
+
+    /* Free pairs if we are rejecting.
+     * xxx Shouldn't the core do that?
+     */
+
+    if ((return_value == RLM_MODULE_REJECT) && (request != NULL)) {
+       pairfree(&(request->reply->vps));
+    }
+
+    /* Return the specified by the Python module */
+    return return_value;
 }
 
+
+static struct varlookup {
+       const char*     name;
+       int             value;
+} constants[] = {
+       { "L_DBG",              L_DBG                   },
+       { "L_AUTH",             L_AUTH                  },
+       { "L_INFO",             L_INFO                  },
+       { "L_ERR",              L_ERR                   },
+       { "L_PROXY",            L_PROXY                 },
+       { "L_CONS",             L_CONS                  },
+       { "RLM_MODULE_REJECT",  RLM_MODULE_REJECT       },
+       { "RLM_MODULE_FAIL",    RLM_MODULE_FAIL         },
+       { "RLM_MODULE_OK",      RLM_MODULE_OK           },
+       { "RLM_MODULE_HANDLED", RLM_MODULE_HANDLED      },
+       { "RLM_MODULE_INVALID", RLM_MODULE_INVALID      },
+       { "RLM_MODULE_USERLOCK",RLM_MODULE_USERLOCK     },
+       { "RLM_MODULE_NOTFOUND",RLM_MODULE_NOTFOUND     },
+       { "RLM_MODULE_NOOP",    RLM_MODULE_NOOP         },
+       { "RLM_MODULE_UPDATED", RLM_MODULE_UPDATED      },
+       { "RLM_MODULE_NUMCODES",RLM_MODULE_NUMCODES     },
+       { NULL, 0 },
+};
+
 /*
  * Import a user module and load a function from it
  */
+static int load_python_function(const char* module, const char* func,
+                               PyObject** pyModule, PyObject** pyFunc) {
+
+    if ((module==NULL) || (func==NULL)) {
+       *pyFunc=NULL;
+       *pyModule=NULL;
+    } else {
+       PyObject *pName;
+
+       pName = PyString_FromString(module);
+       Py_INCREF(pName);
+       *pyModule = PyImport_Import(pName);
+       Py_DECREF(pName);
+       if (*pyModule != NULL) {
+           PyObject *pDict;
+
+           pDict = PyModule_GetDict(*pyModule);
+           /* pDict: borrowed reference */
+
+           *pyFunc = PyDict_GetItemString(pDict, func);
+           /* pFunc: Borrowed reference */
+       } else {
+           python_error();
+
+           radlog(L_ERR, "Failed to import python module \"%s\"\n", module);
+           return -1;
+       }
+    }
 
-static int python_load_function(char *module, const char *func, PyObject **pModule, PyObject **pFunc) {
-        const char      funcname[] = "python_load_function";
-        PyGILState_STATE gstate;
-
-        *pFunc = NULL;
-        *pModule = NULL;
-        gstate = PyGILState_Ensure();
-
-        if (module != NULL && func != NULL) {
-                if ((*pModule = PyImport_ImportModule(module)) == NULL) {
-                        radlog(L_ERR, "rlm_python:%s: module '%s' is not found", funcname, module);
-                        goto failed;
-                }
-                if ((*pFunc = PyObject_GetAttrString(*pModule, func)) == NULL) {
-                        radlog(L_ERR, "rlm_python:%s: function '%s.%s' is not found", funcname, module, func);
-                        goto failed;
-                }
-                if (!PyCallable_Check(*pFunc)) {
-                        radlog(L_ERR, "rlm_python:%s: function '%s.%s' is not callable", funcname, module, func);
-                        goto failed;
-                }
-        }
-       PyGILState_Release(gstate);
-        return 0;
-failed:
-        python_error();
-        radlog(L_ERR, "rlm_python:%s: failed to import python function '%s.%s'", funcname, module, func);
-        Py_XDECREF(*pFunc);
-        *pFunc = NULL;
-        Py_XDECREF(*pModule);
-        PyGILState_Release(gstate);
-        *pModule = NULL;
-        return -1;
-}
-
-static void python_objclear(PyObject **ob) {
-        if (*ob != NULL) {
-               Pyx_BLOCK_THREADS
-                Py_DECREF(*ob);
-                Pyx_UNBLOCK_THREADS
-                *ob = NULL;
-        }
+    return 0;
 }
 
-static void python_instance_clear(struct rlm_python_t *data) {
-        python_objclear(&data->pFunc_instantiate);
-        python_objclear(&data->pFunc_authorize);
-        python_objclear(&data->pFunc_authenticate);
-        python_objclear(&data->pFunc_preacct);
-        python_objclear(&data->pFunc_accounting);
-        python_objclear(&data->pFunc_checksimul);
-        python_objclear(&data->pFunc_detach);
-
-        python_objclear(&data->pModule_instantiate);
-        python_objclear(&data->pModule_authorize);
-        python_objclear(&data->pModule_authenticate);
-        python_objclear(&data->pModule_preacct);
-        python_objclear(&data->pModule_accounting);
-        python_objclear(&data->pModule_checksimul);
-        python_objclear(&data->pModule_detach);
-}
 
 /*
  *     Do any per-module initialization that is separate to each
@@ -513,93 +549,111 @@ static void python_instance_clear(struct rlm_python_t *data) {
  *     in *instance otherwise put a null pointer there.
  *
  */
+static int python_instantiate(CONF_SECTION *conf, void **instance)
+{
+    rlm_python_t *data;
+    PyObject *module;
+    int idx;
 
-static int python_instantiate(CONF_SECTION *conf, void **instance) {
-        struct rlm_python_t    *data = NULL;
-
-        /*
-         *      Set up a storage area for instance data
-         */
-        if ((data = malloc(sizeof(*data))) == NULL)
-                return -1;
-        bzero(data, sizeof(*data));
-
-        /*
-         *      If the configuration parameters can't be parsed, then
-         *      fail.
-         */
-        if (cf_section_parse(conf, data, module_config) < 0) {
-                free(data);
-                return -1;
-        }
-
-        /*
-         * Import user modules.
-         */
-        if (python_load_function(data->mod_instantiate,
-                                data->func_instantiate,
-                                &data->pModule_instantiate,
-                                &data->pFunc_instantiate) < 0)
-                goto failed;
-
-        if (python_load_function(data->mod_authenticate,
-                                data->func_authenticate,
-                                &data->pModule_authenticate,
-                                &data->pFunc_authenticate) < 0)
-                goto failed;
-
-        if (python_load_function(data->mod_authorize,
-                                data->func_authorize,
-                                &data->pModule_authorize,
-                                &data->pFunc_authorize) < 0)
-                goto failed;
-
-        if (python_load_function(data->mod_preacct,
-                                data->func_preacct,
-                                &data->pModule_preacct,
-                                &data->pFunc_preacct) < 0)
-                goto failed;
-
-        if (python_load_function(data->mod_accounting,
-                                data->func_accounting,
-                                &data->pModule_accounting,
-                                &data->pFunc_accounting) < 0)
-                goto failed;
-
-        if (python_load_function(data->mod_checksimul,
-                                data->func_checksimul,
-                                &data->pModule_checksimul,
-                                &data->pFunc_checksimul) < 0)
-                goto failed;
-
-        if (python_load_function(data->mod_detach,
-                                data->func_detach,
-                                &data->pModule_detach,
-                                &data->pFunc_detach) < 0)
-                goto failed;
-
-        *instance = data;
-        /* Call the instantiate function.  No request.  Use the return value. */
-
-        return python_function(NULL, data->pFunc_instantiate, "instantiate");
-failed:
-        python_error();
-        python_instance_clear(data);
-        return -1;
-}
+    /*
+     * Initialize Python interpreter. Fatal error if this fails.
+     */
+    Py_Initialize();
 
-static int python_detach(void *instance) {
-        struct rlm_python_t    *data = (struct rlm_python_t *) instance;
-        int             ret;
+    /*
+     * Set up a storage area for instance data
+     */
+    data = rad_malloc(sizeof(*data));
+    if (!data) {
+      return -1;
+    }
+    memset(data, 0, sizeof(*data));
+
+    /*
+        *      If the configuration parameters can't be parsed, then
+        *      fail.
+        */
+    if (cf_section_parse(conf, data, module_config) < 0) {
+       free(data);
+       return -1;
+    }
 
-        ret = python_function(NULL, data->pFunc_detach, "detach");
 
-        python_instance_clear(data);
+    /*
+     * Setup our 'radiusd' module.
+     */
 
-        free(data);
-        return ret;
-}
+    /* Code */
+    if ((module = data->pModule_builtin =
+        Py_InitModule3("radiusd", radiusd_methods,
+                       "FreeRADIUS Module.")) == NULL) {
+
+       radlog(L_ERR, "Python Py_InitModule3 failed");
+       free(data);
+       return -1;
+    }
+
+    /*
+     * Load constants into module
+     */
+    for (idx=0; constants[idx].name; idx++)
+       if ((PyModule_AddIntConstant(module, constants[idx].name, constants[idx].value)) == -1) {
+
+           radlog(L_ERR, "Python AddIntConstant failed");
+       }
+
+
+    /*
+     * Import user modules.
+     */
 
+    if (load_python_function(data->mod_instantiate, data->func_instantiate,
+               &data->pModule_instantiate, &data->pFunc_instantiate)==-1) {
+       /* TODO: check if we need to cleanup data */
+       return -1;
+    }
+
+    if (load_python_function(data->mod_authenticate, data->func_authenticate,
+               &data->pModule_authenticate, &data->pFunc_authenticate)==-1) {
+       /* TODO: check if we need to cleanup data */
+       return -1;
+    }
+
+    if (load_python_function(data->mod_authorize, data->func_authorize,
+               &data->pModule_authorize, &data->pFunc_authorize)==-1) {
+       /* TODO: check if we need to cleanup data */
+       return -1;
+    }
+
+    if (load_python_function(data->mod_preacct, data->func_preacct,
+               &data->pModule_preacct, &data->pFunc_preacct)==-1) {
+       /* TODO: check if we need to cleanup data */
+       return -1;
+    }
+
+    if (load_python_function(data->mod_accounting, data->func_accounting,
+               &data->pModule_accounting, &data->pFunc_accounting)==-1) {
+       /* TODO: check if we need to cleanup data */
+       return -1;
+    }
+
+    if (load_python_function(data->mod_checksimul, data->func_checksimul,
+               &data->pModule_checksimul, &data->pFunc_checksimul)==-1) {
+       /* TODO: check if we need to cleanup data */
+       return -1;
+    }
+
+    if (load_python_function(data->mod_detach, data->func_detach,
+               &data->pModule_detach, &data->pFunc_detach)==-1) {
+       /* TODO: check if we need to cleanup data */
+       return -1;
+    }
+
+    *instance=data;
+
+    /* Call the instantiate function.  No request.  Use the return value. */
+    return python_function(NULL, data->pFunc_instantiate, "instantiate");
+}
 
 /* Wrapper functions */
 static int python_authorize(void *instance, REQUEST *request)
@@ -642,6 +696,57 @@ static int python_checksimul(void *instance, REQUEST *request)
 }
 
 
+static int python_detach(void *instance)
+{
+    int return_value;
+
+    /* Default return value is failure */
+    return_value = -1;
+
+    if (((rlm_python_t *)instance)->pFunc_detach &&
+       PyCallable_Check(((rlm_python_t *)instance)->pFunc_detach)) {
+
+       PyObject *pArgs, *pValue;
+
+       /* call the function with an empty tuple */
+
+       pArgs = PyTuple_New(0);
+       pValue = PyObject_CallObject(((rlm_python_t *)instance)->pFunc_detach,
+                                    pArgs);
+
+       if (pValue == NULL) {
+           python_error();
+           return -1;
+       }
+       else {
+           if (!PyInt_Check(pValue)) {
+               radlog(L_ERR, "detach: return value not an integer");
+           }
+           else {
+               return_value = PyInt_AsLong(pValue);
+           }
+       }
+
+       /* Decrease reference counts for the argument and return tuple */
+       Py_DECREF(pArgs);
+       Py_DECREF(pValue);
+    }
+
+    free(instance);
+
+#if 0
+    /* xxx test delete module object so it will be reloaded later.
+     * xxx useless since we can't SIGHUP reliably, anyway.
+     */
+    PyObject_Del(((struct rlm_python_t *)instance)->pModule_accounting);
+#endif
+
+    radlog(L_DBG, "python_detach done");
+
+    /* Return the specified by the Python module */
+    return return_value;
+}
+
 /*
  *     The module name should be the only globally exported symbol.
  *     That is, everything else should be 'static'.
@@ -652,10 +757,11 @@ static int python_checksimul(void *instance, REQUEST *request)
  *     is single-threaded.
  */
 module_t rlm_python = {
+       RLM_MODULE_INIT,
        "python",
        RLM_TYPE_THREAD_SAFE,           /* type */
-       python_init,                    /* initialization */
        python_instantiate,             /* instantiation */
+       python_detach,                  /* detach */
        {
                python_authenticate,    /* authentication */
                python_authorize,       /* authorization */
@@ -666,6 +772,4 @@ module_t rlm_python = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       python_detach,                  /* detach */
-       python_destroy,                         /* destroy */
 };
index ff080a0..c66094f 100644 (file)
@@ -1,12 +1,49 @@
-/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
-/*
+/* config.h.in.  Generated from configure.in by autoheader.  */
 
-acconfig.h - template used by autoheader to create config.h.in
-config.h.in - used by autoconf to create config.h
-config.h - created by autoconf; contains defines generated by autoconf
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
 
-*/
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
 
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
 
-/* Define if you have the <sys/mman.h> header file.  */
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
 #undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
index 6d17f9a..f4c519d 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.1 .
+# From configure.in Revision: 1.2 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -938,7 +938,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1858,8 +1858,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1917,8 +1916,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2034,8 +2032,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2089,8 +2086,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2135,8 +2131,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2180,8 +2175,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2504,8 +2498,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2675,8 +2668,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2743,8 +2735,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3658,11 +3649,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3701,6 +3687,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 0ef48ab..52d0084 100644 (file)
@@ -1,3 +1,4 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_radutmp.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_radutmp])
index fd08d64..84350db 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * FIXME add copyrights
  */
 
-#include       "autoconf.h"
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include       <freeradius-devel/autoconf.h>
 
 #include       <sys/types.h>
 #include       <stdio.h>
 
 #include "config.h"
 
-#include       "radiusd.h"
-#include       "radutmp.h"
-#include       "modules.h"
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/radutmp.h>
+#include       <freeradius-devel/modules.h>
+#include       <freeradius-devel/rad_assert.h>
 
 #define LOCK_LEN sizeof(struct radutmp)
 
@@ -64,7 +68,7 @@ typedef struct rlm_radutmp_t {
        int             callerid_ok;
 } rlm_radutmp_t;
 
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
        { "filename", PW_TYPE_STRING_PTR,
          offsetof(rlm_radutmp_t,filename), NULL,  RADUTMP },
        { "username", PW_TYPE_STRING_PTR,
@@ -113,8 +117,6 @@ static int radutmp_detach(void *instance)
                next = p->next;
                free(p);
        }
-       if (inst->filename) free(inst->filename);
-       if (inst->username) free(inst->username);
        free(inst);
        return 0;
 }
@@ -207,6 +209,11 @@ static int radutmp_accounting(void *instance, REQUEST *request)
        NAS_PORT        *cache;
        int             r;
 
+       if (request->packet->src_ipaddr.af != AF_INET) {
+               DEBUG("rlm_radutmp: IPv6 not supported!");
+               return RLM_MODULE_NOOP;
+       }
+
        /*
         *      Which type is this.
         */
@@ -238,7 +245,7 @@ static int radutmp_accounting(void *instance, REQUEST *request)
                        check1 = 1;
                if ((vp = pairfind(request->packet->vps, PW_ACCT_SESSION_ID))
                     != NULL && vp->length == 8 &&
-                    memcmp(vp->strvalue, "00000000", 8) == 0)
+                    memcmp(vp->vp_strvalue, "00000000", 8) == 0)
                        check2 = 1;
                if (check1 == 0 || check2 == 0) {
 #if 0 /* Cisco sometimes sends START records without username. */
@@ -295,10 +302,10 @@ static int radutmp_accounting(void *instance, REQUEST *request)
                                 *      Compensate.
                                 */
                                if (vp->length > 0 &&
-                                   vp->strvalue[vp->length - 1] == 0)
+                                   vp->vp_strvalue[vp->length - 1] == 0)
                                        off--;
                                if (off < 0) off = 0;
-                               memcpy(ut.session_id, vp->strvalue + off,
+                               memcpy(ut.session_id, vp->vp_strvalue + off,
                                        sizeof(ut.session_id));
                                break;
                        case PW_NAS_PORT_TYPE:
@@ -308,8 +315,8 @@ static int radutmp_accounting(void *instance, REQUEST *request)
                                break;
                        case PW_CALLING_STATION_ID:
                                if(inst->callerid_ok)
-                                       strNcpy(ut.caller_id,
-                                               (char *)vp->strvalue,
+                                       strlcpy(ut.caller_id,
+                                               (char *)vp->vp_strvalue,
                                                sizeof(ut.caller_id));
                                break;
                }
@@ -320,32 +327,31 @@ static int radutmp_accounting(void *instance, REQUEST *request)
         *      originator's IP address.
         */
        if (nas_address == 0) {
-               nas_address = request->packet->src_ipaddr;
+               nas_address = request->packet->src_ipaddr.ipaddr.ip4addr.s_addr;
                ut.nas_address = nas_address;
-               nas = client_name(nas_address); /* MUST be a valid client */
+               nas = client_name_old(&request->packet->src_ipaddr); /* MUST be a valid client */
 
-       } else {                /* might be a client, might not be. */
+       } else if (request->packet->src_ipaddr.ipaddr.ip4addr.s_addr == nas_address) {          /* might be a client, might not be. */
                RADCLIENT *cl;
-
+               
                /*
                 *      Hack like 'client_name()', but with sane
                 *      fall-back.
                 */
-               cl = client_find(nas_address);
-               if (cl) {
-                       if (cl->shortname[0]) {
-                               nas = cl->shortname;
-                       } else {
-                               nas = cl->longname;
-                       }
+               cl = client_find_old(&request->packet->src_ipaddr);
+               if (!cl) rad_assert(0 == 1); /* WTF? */
+               if (cl->shortname && cl->shortname[0]) {
+                       nas = cl->shortname;
                } else {
-                       /*
-                        *      The NAS isn't a client, it's behind
-                        *      a proxy server.  In that case, just
-                        *      get the IP address.
-                        */
-                       nas = ip_ntoa(ip_name, nas_address);
+                       nas = cl->longname;
                }
+       } else {
+               /*
+                *      The NAS isn't a client, it's behind
+                *      a proxy server.  In that case, just
+                *      get the IP address.
+                */
+               nas = ip_ntoa(ip_name, nas_address);
        }
 
        /*
@@ -406,7 +412,7 @@ static int radutmp_accounting(void *instance, REQUEST *request)
        /*
         *  Copy the previous translated user name.
         */
-       strncpy(ut.login, buffer, RUT_NAMESIZE);
+       strlcpy(ut.login, buffer, RUT_NAMESIZE);
 
        /*
         *      Perhaps we don't want to store this record into
@@ -655,7 +661,7 @@ static int radutmp_checksimul(void *instance, REQUEST *request)
        if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS)) != NULL)
                ipno = vp->lvalue;
        if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) != NULL)
-               call_num = vp->strvalue;
+               call_num = vp->vp_strvalue;
 
        /*
         *      lock the file while reading/writing.
@@ -677,7 +683,7 @@ static int radutmp_checksimul(void *instance, REQUEST *request)
                        char session_id[sizeof(u.session_id) + 1];
                        char utmp_login[sizeof(u.login) + 1];
 
-                       strNcpy(session_id, u.session_id, sizeof(session_id));
+                       strlcpy(session_id, u.session_id, sizeof(session_id));
 
                        /*
                         *      The login name MAY fill the whole field,
@@ -695,7 +701,7 @@ static int radutmp_checksimul(void *instance, REQUEST *request)
                         *      and the NAS says "no", because "BOB"
                         *      is using the port.
                         */
-                       strNcpy(utmp_login, u.login, sizeof(u.login));
+                       strlcpy(utmp_login, u.login, sizeof(u.login));
 
                        /*
                         *      rad_check_ts may take seconds
@@ -707,16 +713,18 @@ static int radutmp_checksimul(void *instance, REQUEST *request)
                                             utmp_login, session_id);
                        rad_lockfd(fd, LOCK_LEN);
 
-                       /*
-                        *      Failed to check the terminal server for
-                        *      duplicate logins: Return an error.
-                        */
-                       if (rcode < 0) {
-                               close(fd);
-                               return RLM_MODULE_FAIL;
+                       if (rcode == 0) {
+                               /*
+                                *      Stale record - zap it.
+                                */
+                               session_zap(request, u.nas_address,
+                                           u.nas_port, login, session_id,
+                                           u.framed_address, u.proto,0);
                        }
-
-                       if (rcode == 1) {
+                       else if (rcode == 1) {
+                               /*
+                                *      User is still logged in.
+                                */
                                ++request->simul_count;
 
                                /*
@@ -731,12 +739,13 @@ static int radutmp_checksimul(void *instance, REQUEST *request)
                        }
                        else {
                                /*
-                                *      False record - zap it.
+                                *      Failed to check the terminal
+                                *      server for duplicate logins:
+                                *      Return an error.
                                 */
-                               session_zap(request,
-                                           u.nas_address, u.nas_port, login,
-                                           session_id, u.framed_address,
-                                           u.proto);
+                               close(fd);
+                               radlog(L_ERR, "rlm_radutmp: Failed to check the terminal server for user '%s'.", utmp_login);
+                               return RLM_MODULE_FAIL;
                        }
                }
        }
@@ -747,21 +756,20 @@ static int radutmp_checksimul(void *instance, REQUEST *request)
 
 /* globally exported name */
 module_t rlm_radutmp = {
-  "radutmp",
-  0,                            /* type: reserved */
-  NULL,                        /* initialization */
-  radutmp_instantiate,          /* instantiation */
-  {
-         NULL,                 /* authentication */
-         NULL,                 /* authorization */
-         NULL,                 /* preaccounting */
-         radutmp_accounting,   /* accounting */
-         radutmp_checksimul,   /* checksimul */
-         NULL,                 /* pre-proxy */
-         NULL,                 /* post-proxy */
-         NULL                  /* post-auth */
-  },
-  radutmp_detach,               /* detach */
-  NULL,                        /* destroy */
+       RLM_MODULE_INIT,
+       "radutmp",
+       0,                            /* type: reserved */
+       radutmp_instantiate,          /* instantiation */
+       radutmp_detach,               /* detach */
+       {
+               NULL,                 /* authentication */
+               NULL,                 /* authorization */
+               NULL,                 /* preaccounting */
+               radutmp_accounting,   /* accounting */
+               radutmp_checksimul,     /* checksimul */
+               NULL,                   /* pre-proxy */
+               NULL,                   /* post-proxy */
+               NULL                    /* post-auth */
+       },
 };
 
diff --git a/src/modules/rlm_radutmp/rlm_radutmp2.c b/src/modules/rlm_radutmp/rlm_radutmp2.c
new file mode 100644 (file)
index 0000000..f38ab0b
--- /dev/null
@@ -0,0 +1,1528 @@
+/*
+ * rlm_radutmp.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 2000,2001,2002,2003,2004,2006  The FreeRADIUS server project
+ */
+
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include       <freeradius-devel/autoconf.h>
+
+#include       <sys/types.h>
+#include       <stdio.h>
+#include       <string.h>
+#include       <stdlib.h>
+#include       <unistd.h>
+#include       <fcntl.h>
+#include       <time.h>
+#include       <errno.h>
+#include        <limits.h>
+
+#include "config.h"
+
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/radutmp.h>
+#include       <freeradius-devel/modules.h>
+#include       <freeradius-devel/rad_assert.h>
+
+#define LOCK_LEN sizeof(struct radutmp)
+
+static const char porttypes[] = "ASITX";
+
+/*
+ *     Used for caching radutmp lookups in the accounting
+ *     component. The session (checksimul) component doesn't use it,
+ *     but probably should, though we're not sure how...
+ *
+ *     The intent here is to keep this structure as small as
+ *     possible, so that it doesn't take up too much memory.
+ */
+typedef struct nas_port {
+       uint32_t                nas_address;
+       unsigned int            nas_port;
+       off_t                   offset;
+
+       struct nas_port         *next; /* for the free list */
+} NAS_PORT;
+
+
+/*
+ *     Per-file information.
+ *
+ *     Hmm... having multiple filenames managed by one instance
+ *     of the module makes it difficult for the module to do
+ *     simultaneous-use checking, without more code edits.
+ */
+typedef struct radutmp_cache_t {
+       const char      *filename; /* for future reference */
+       time_t          last_used; /* for future reference */
+
+       rbtree_t        *nas_ports;
+       NAS_PORT        *free_offsets;
+       off_t           max_offset;
+       int             cached_file;
+       int             permission;
+#ifdef HAVE_PTHREAD_H
+       pthread_mutex_t mutex;
+#endif
+} radutmp_cache_t;
+
+
+/*
+ *     We cache the users, too, so that we only have to read radutmp
+ *     once.
+ */
+typedef struct radutmp_simul_t {
+       char            login[sizeof(((struct radutmp *) NULL)->login) + 1];
+       int             simul_count;
+} radutmp_simul_t;
+
+
+/*
+ *     Data we store per module.
+ */
+typedef struct rlm_radutmp_t {
+       char            *filename;
+       char            *username;
+       int             case_sensitive;
+       int             check_nas;
+       int             permission;
+       int             callerid_ok;
+
+       rbtree_t        *user_tree; /* for simultaneous-use */
+
+       /*
+        *      As the filenames can be dynamically translated,
+        *      we want to keep track of them in a separate data
+        *      structure, so that we can have per-file caches.
+        */
+       radutmp_cache_t cache;
+} rlm_radutmp_t;
+
+#ifndef HAVE_PTHREAD_H
+/*
+ *     This is easier than ifdef's throughout the code.
+ */
+#define pthread_mutex_init(_x, _y)
+#define pthread_mutex_destroy(_x)
+#define pthread_mutex_lock(_x)
+#define pthread_mutex_unlock(_x)
+#endif
+
+static const CONF_PARSER module_config[] = {
+       { "filename", PW_TYPE_STRING_PTR,
+         offsetof(rlm_radutmp_t,filename), NULL,  RADUTMP },
+       { "username", PW_TYPE_STRING_PTR,
+         offsetof(rlm_radutmp_t,username), NULL,  "%{User-Name}"},
+       { "case_sensitive", PW_TYPE_BOOLEAN,
+         offsetof(rlm_radutmp_t,case_sensitive), NULL,  "yes"},
+       { "check_with_nas", PW_TYPE_BOOLEAN,
+         offsetof(rlm_radutmp_t,check_nas), NULL,  "yes"},
+       { "perm",     PW_TYPE_INTEGER,
+         offsetof(rlm_radutmp_t,permission), NULL,  "0644" },
+       { "callerid", PW_TYPE_BOOLEAN,
+         offsetof(rlm_radutmp_t,callerid_ok), NULL, "no" },
+       { NULL, -1, 0, NULL, NULL }             /* end the list */
+};
+
+
+/*
+ *     NAS PORT cmp
+ */
+static int nas_port_cmp(const void *a, const void *b)
+{
+       const NAS_PORT *one = a;
+       const NAS_PORT *two = b;
+
+       if (one->nas_address < two->nas_address) return -1;
+       if (one->nas_address > two->nas_address) return +1;
+
+       if (one->nas_port < two->nas_port) return -1;
+       if (one->nas_port > two->nas_port) return +1;
+
+       return 0;
+}
+
+
+/*
+ *     Compare two user names.
+ */
+static int user_cmp(const void *a, const void *b)
+{
+       const radutmp_simul_t *one = a;
+       const radutmp_simul_t *two = b;
+
+       return strcmp(one->login, two->login);
+}
+
+
+/*
+ *     Compare two user names, case insensitive.
+ */
+static int user_case_cmp(const void *a, const void *b)
+{
+       const radutmp_simul_t *one = a;
+       const radutmp_simul_t *two = b;
+
+       return strcasecmp(one->login, two->login);
+}
+
+
+/*
+ *     Detach.
+ */
+static int radutmp_detach(void *instance)
+{
+       NAS_PORT        *this, *next;
+       rlm_radutmp_t *inst = instance;
+
+       rbtree_free(inst->cache.nas_ports);
+
+       for (this = inst->cache.free_offsets;
+            this != NULL;
+            this = next) {
+               next = this->next;
+               free(this);
+       }
+
+       if (inst->cache.filename) free(inst->cache.filename);
+
+       pthread_mutex_destroy(&(inst->cache.mutex));
+
+
+       rbtree_free(inst->user_tree);
+
+       free(inst);
+       return 0;
+}
+
+
+/*
+ *     Instantiate.
+ */
+static int radutmp_instantiate(CONF_SECTION *conf, void **instance)
+{
+       rlm_radutmp_t *inst;
+
+       inst = rad_malloc(sizeof(*inst));
+       if (!inst) {
+               return -1;
+       }
+       memset(inst, 0, sizeof(*inst));
+
+       if (cf_section_parse(conf, inst, module_config)) {
+               radutmp_detach(inst);
+               return -1;
+       }
+
+       inst->cache.nas_ports = rbtree_create(nas_port_cmp, free, 0);
+       if (!inst->cache.nas_ports) {
+               radlog(L_ERR, "rlm_radutmp: Failed to create nas tree");
+               radutmp_detach(inst);
+               return -1;
+       }
+
+       pthread_mutex_init(&(inst->cache.mutex), NULL);
+       inst->cache.permission = inst->permission;
+
+       if (inst->case_sensitive) {
+               inst->user_tree = rbtree_create(user_cmp, free, 0);
+       } else {
+               inst->user_tree = rbtree_create(user_case_cmp, free, 0);
+       }
+       if (!inst->user_tree) {
+               radlog(L_ERR, "rlm_radutmp: Failed to create user tree");
+               radutmp_detach(inst);
+               return -1;
+       }
+
+       *instance = inst;
+       return 0;
+}
+
+
+/*
+ *     Reset the cached entries.
+ */
+static int cache_reset(rlm_radutmp_t *inst, radutmp_cache_t *cache)
+{
+       NAS_PORT *this, *next;
+       
+       /*
+        *      Cache is already reset, do nothing.
+        */
+       if ((rbtree_num_elements(cache->nas_ports) == 0) &&
+           (cache->free_offsets == NULL)) {
+               DEBUG2("  rlm_radutmp: Not resetting the cache");
+               return 1;
+       }
+       DEBUG2("  rlm_radutmp: Resetting the cache");
+
+       pthread_mutex_lock(&cache->mutex);
+
+       rbtree_free(inst->user_tree);
+
+       rbtree_free(cache->nas_ports);
+       
+       for (this = cache->free_offsets;
+            this != NULL;
+            this = next) {
+               next = this->next;
+               free(this);
+       }
+       cache->free_offsets = NULL;
+
+       /*
+        *      Re-create the caches.
+        */
+       cache->nas_ports = rbtree_create(nas_port_cmp, free, 0);
+       if (!cache->nas_ports) {
+               pthread_mutex_unlock(&cache->mutex);
+               radlog(L_ERR, "rlm_radutmp: No memory");
+               return 0;
+       }
+       
+       cache->max_offset = 0;
+       
+       cache->cached_file = 1;
+
+       if (inst->case_sensitive) {
+               inst->user_tree = rbtree_create(user_cmp, free, 0);
+       } else {
+               inst->user_tree = rbtree_create(user_case_cmp, free, 0);
+       }
+       if (!inst->user_tree) {
+               pthread_mutex_unlock(&cache->mutex);
+               radlog(L_ERR, "rlm_radutmp: No memory");
+               return 0;
+       }
+
+       pthread_mutex_unlock(&cache->mutex);
+
+       return 1;
+}
+
+
+/*
+ *     Compare two offsets in a tree.
+ */
+static int offset_cmp(const void *a, const void *b)
+{
+       const NAS_PORT *one = a;
+       const NAS_PORT *two = b;
+
+       if (one->offset < two->offset) return -1;
+       if (one->offset > two->offset) return +1;
+
+       return 0;
+}
+
+
+/*
+ *     Data structure to use when walking the trees, for zap.
+ */
+typedef struct offset_walk_t {
+       rlm_radutmp_t   *inst;
+       radutmp_cache_t *cache;
+       rbtree_t        *offset_tree;
+       uint32_t        nas_address;
+       int             fd;
+       time_t          now;
+} offset_walk_t;
+
+
+/*
+ *     Walk over the cache, finding entries with the matching NAS IP address.
+ */
+static int nas_port_walk(void *context, void *data)
+{
+       offset_walk_t   *walk = context;
+       NAS_PORT        *nas_port = data;
+
+       /*
+        *      Doesn't match, keep going.
+        */
+       if (walk->nas_address != nas_port->nas_address) return 0;
+
+       /*
+        *      Insert it into the offset tree, for later deletion.
+        */
+       if (rbtree_insert(walk->offset_tree, nas_port) != 1) {
+               DEBUG2("  rlm_radumtp: Insertion failed in nas port walk.");
+               return 1;
+       }
+
+       return 0;
+}
+
+
+/*
+ *     Walk through the offset tree, operating on the cache
+ */
+static int offset_walk(void *context, void *data)
+{
+       offset_walk_t   *walk = context;
+       NAS_PORT        *nas_port = data;
+       struct radutmp  utmp;
+       radutmp_simul_t *user, myUser;
+
+       /*
+        *      Seek to the entry, and possibly re-write it.
+        */
+       if (lseek(walk->fd, nas_port->offset, SEEK_SET) < 0) {
+               rad_assert(0 == 1);
+       }
+
+       if (read(walk->fd, &utmp, sizeof(utmp)) != sizeof(utmp)) {
+               rad_assert(0 == 1);
+       }
+       
+       /*
+        *      If the entry in the file is NEWER than the reboot
+        *      packet, don't re-write it, and don't delete it.
+        */
+       if (utmp.time > walk->now) {
+               return 0;
+       }
+
+       utmp.type = P_IDLE;
+       utmp.time = walk->now;
+
+       if (lseek(walk->fd, -(off_t)sizeof(utmp), SEEK_CUR) < 0) {
+               radlog(L_ERR, "rlm_radutmp: offset_walk: failed in lseek: %s",
+                      strerror(errno));
+               return 1;
+       }
+
+       write(walk->fd, &utmp, sizeof(utmp));
+
+       strlcpy(myUser.login, utmp.login, sizeof(myUser.login));
+       user = rbtree_finddata(walk->inst->user_tree, &myUser);
+       rad_assert(user != NULL);
+       rad_assert(user->simul_count > 0);
+       user->simul_count--;
+       if (user->simul_count == 0) {
+               rbtree_deletebydata(walk->inst->user_tree, user);
+       }
+
+       if (rbtree_deletebydata(walk->cache->nas_ports, nas_port) == 0) {
+               radlog(L_ERR, "rlm_radutmp: Failed to delete entry from cache");
+               return 1;
+       }
+
+       /*
+        *      Insert the entry into the free list.
+        */
+       nas_port->next = walk->cache->free_offsets;
+       walk->cache->free_offsets = nas_port;
+
+       return 0;
+}
+
+
+/*
+ *     Zap all users on a NAS from the radutmp file.
+ */
+static int radutmp_zap(rlm_radutmp_t *inst,
+                      radutmp_cache_t *cache,
+                      uint32_t nas_address,
+                      time_t now)
+{
+       int             rcode;
+       rbtree_t        *offset_tree;
+       offset_walk_t   walk;
+
+       rad_assert(now != 0);
+
+       /*
+        *      If there's nothing in the file, do nothing,
+        *      but truncate the file, just to be safe.
+        */
+       if (rbtree_num_elements(cache->nas_ports) == 0) {
+               truncate(cache->filename, (off_t) 0);
+               DEBUG2("  rlm_radutmp: No entries in file.  Quenching zap.");
+               return 1;
+       }
+
+       /*
+        *      Create the offset tree, as we want to delete utmp
+        *      entries starting from the start of the file, and we
+        *      can't delete nodes from an rbtree while we're walking
+        *      it.
+        */
+       offset_tree = rbtree_create(offset_cmp, NULL, 0);
+       if (!offset_tree) {
+               radlog(L_ERR, "rlm_radutmp: Out of memory");
+               return 0;
+       }
+       
+       pthread_mutex_lock(&cache->mutex);
+
+       /*
+        *      Walk through the cache, finding entries for this NAS,
+        *      and add those entries to the offset tree.
+        */
+       memset(&walk, 0, sizeof(walk));
+       walk.inst = inst;
+       walk.offset_tree = offset_tree;
+       walk.nas_address = nas_address;
+       rcode = rbtree_walk(cache->nas_ports, PreOrder, nas_port_walk, &walk);
+       if (rcode != 0) {
+               pthread_mutex_unlock(&cache->mutex);
+               rbtree_free(offset_tree);
+               radlog(L_ERR, "rlm_radutmp: Failed walking the cache.");
+               return 0;
+       }
+
+       /*
+        *      If both trees have the same number of elements, then
+        *      don't do anything special, as UDP packets may be
+        *      received out of order, by several seconds.  The
+        *      "offset_walk" routine MAY NOT delete the entries, if
+        *      it sees that the entries in the file are newer than
+        *      the reboot packet.
+        */
+
+       /*
+        *      If there's nothing to do, don't do anything.
+        */
+       if (rbtree_num_elements(offset_tree) == 0) {
+               DEBUG2("  rlm_radutmp: NAS IP %08x has no users recorded in file %s.",
+                      htonl(nas_address), cache->filename);
+               pthread_mutex_unlock(&cache->mutex);
+               rbtree_free(offset_tree);
+               return 1;
+       }
+
+       /*
+        *      Open the file, to re-write only a few of the entries.
+        */
+       walk.fd = open(cache->filename, O_RDWR);
+       if (walk.fd < 0) {
+               pthread_mutex_unlock(&cache->mutex);
+               rbtree_free(offset_tree);
+               radlog(L_ERR, "rlm_radutmp: Error accessing file %s: %s",
+                      cache->filename, strerror(errno));
+               return 0;
+       }
+
+       /*
+        *      Lock the utmp file, prefer lockf() over flock().
+        *
+        *      FIXME: maybe we want to lock per-record?
+        */
+       rad_lockfd(walk.fd, LOCK_LEN);
+
+       /*
+        *      Walk through the offset tree, from start to finish,
+        *      deleting entries from the NAS tree, adding them to
+        *      the "free offset" cache, and lseek'ing to that offset
+        *      in the file, and clearing out the data.
+        */
+       walk.cache = cache;
+       walk.now = now;
+       rcode = rbtree_walk(offset_tree, InOrder, offset_walk, &walk);
+       rbtree_free(offset_tree);
+       if (rcode != 0) {
+               radlog(L_ERR, "rlm_radutmp: Failed walking the offsets.");
+               return 0;
+       }
+
+       close(walk.fd); /* and implicitly release the locks */
+
+       /*
+        *      Just to clean up the file.  If it's empty,
+        *      nuke everything.
+        */
+       if (rbtree_num_elements(cache->nas_ports) == 0) {
+               NAS_PORT        *this, *next; /* too many copies of code */
+               
+               for (this = inst->cache.free_offsets;
+                    this != NULL;
+                    this = next) {
+                       next = this->next;
+                       free(this);
+               }
+               
+               truncate(cache->filename, 0);
+               rad_assert(rbtree_num_elements(inst->user_tree) == 0);
+       }
+
+       pthread_mutex_unlock(&cache->mutex);
+       
+       return 1;
+}
+
+
+/*
+ *     Read a file, to cache all of its entries.
+ */
+static int cache_file(rlm_radutmp_t *inst, radutmp_cache_t *cache)
+{
+       int             fd;
+       int             read_size;
+       struct          stat buf;
+       struct          radutmp utmp;
+       NAS_PORT        **tail;
+
+       rad_assert(cache->max_offset == 0);
+       rad_assert(cache->free_offsets == NULL);
+
+       /*
+        *      Doesn't exist, we're fine.
+        */
+       if (stat(cache->filename, &buf) < 0) {
+               if (errno == ENOENT) {
+                       cache->cached_file = 1;
+                       return 0;
+               }
+               radlog(L_ERR, "rlm_radutmp: Cannot stat %s: %s",
+                      cache->filename, strerror(errno));
+               return 1;
+       }
+
+       /*
+        *      Nothing's there, we're OK.
+        */
+       if (buf.st_size == 0) {
+               cache->cached_file = 1;
+               return 0;
+       }
+
+       /*
+        *      Don't let others much around with our data.
+        */
+       pthread_mutex_lock(&cache->mutex);
+
+       /*
+        *      Read the file and cache it's entries.
+        */
+       fd = open(cache->filename, O_RDONLY, cache->permission);
+       if (fd < 0) {
+               pthread_mutex_unlock(&cache->mutex);
+               radlog(L_ERR, "rlm_radutmp: Error opening %s: %s",
+                      cache->filename, strerror(errno));
+               return 1;
+       }
+
+       /*
+        *      Insert free entries into the tail, so that entries
+        *      get used from the start.
+        */
+       tail = &(cache->free_offsets);
+
+       /*
+        *      Don't lock the file, as we're only reading it.
+        */
+       do {
+               read_size = read(fd, &utmp, sizeof(utmp));
+
+               /*
+                *      Read one record.
+                */
+               if (read_size == sizeof(utmp)) {
+                       radutmp_simul_t *user, myUser;
+                       NAS_PORT *nas_port = rad_malloc(sizeof(*nas_port));
+
+                       memset(nas_port, 0, sizeof(nas_port));
+                       nas_port->offset = cache->max_offset;
+                       cache->max_offset += sizeof(utmp);
+
+                       /*
+                        *      Idle.  Add it to the list of free
+                        *      offsets.
+                        */
+                       if (utmp.type == P_IDLE) {
+                               *tail = nas_port;
+                               tail = &(nas_port->next);
+                               continue;
+                       }
+
+                       /*
+                        *      It's a login record, 
+                        */
+                       nas_port->nas_address = utmp.nas_address;
+                       nas_port->nas_port = utmp.nas_port;
+
+                       if (!rbtree_insert(cache->nas_ports, nas_port)) {
+                               rad_assert(0 == 1);
+                       }
+
+                       /*
+                        *      Adds a trailing \0, so myUser.login has
+                        *      an extra char allocated..
+                        */
+                       strlcpy(myUser.login, utmp.login, sizeof(myUser.login));
+                       user = rbtree_finddata(inst->user_tree, &myUser);
+                       if (user) {
+                               user->simul_count++;
+                       } else {
+                               /*
+                                *      Allocate new entry, and add it
+                                *      to the tree.
+                                */
+                               user = rad_malloc(sizeof(user));
+                               strlcpy(user->login, utmp.login,
+                                       sizeof(user->login));
+                               user->simul_count = 1;
+
+                               if (!rbtree_insert(inst->user_tree, user)) {
+                                       rad_assert(0 == 1);
+                               }
+                       }
+                       continue;
+               }
+               
+               /*
+                *      We've read a partial record.  WTF?
+                */
+               if (read_size != 0) {
+                       pthread_mutex_unlock(&cache->mutex);
+                       close(fd);
+                       radlog(L_ERR, "rlm_radutmp: Badly formed file %s",
+                              cache->filename);
+                       return 1;
+               }
+
+               /*
+                *      Read nothing, stop.
+                */
+       } while (read_size != 0);
+
+       pthread_mutex_unlock(&cache->mutex);
+       close(fd);              /* and release the lock. */
+       cache->cached_file = 1;
+
+       return 0;
+}
+
+
+/*
+ *     Store logins in the RADIUS utmp file.
+ */
+static int radutmp_accounting(void *instance, REQUEST *request)
+{
+       rlm_radutmp_t   *inst = instance;
+       struct radutmp  utmp, u;
+       VALUE_PAIR      *vp;
+       int             status = -1;
+       uint32_t        nas_address = 0;
+       uint32_t        framed_address = 0;
+       int             protocol = -1;
+       int             fd;
+       int             port_seen = 0;
+       char            buffer[256];
+       char            filename[1024];
+       char            ip_name[32]; /* 255.255.255.255 */
+       const char      *nas;
+       NAS_PORT        *nas_port, myPort;
+       radutmp_cache_t *cache;
+       int             read_size;
+       rbnode_t        *node;
+
+       /*
+        *      Which type is this.
+        */
+       if ((vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) == NULL) {
+               radlog(L_ERR, "rlm_radutmp: No Accounting-Status-Type record.");
+               return RLM_MODULE_NOOP;
+       }
+       status = vp->lvalue;
+
+       /*
+        *      Look for weird reboot packets.
+        *
+        *      ComOS (up to and including 3.5.1b20) does not send
+        *      standard PW_STATUS_ACCOUNTING_* messages.
+        *
+        *      Check for:  o no Acct-Session-Time, or time of 0
+        *                  o Acct-Session-Id of "00000000".
+        *
+        *      We could also check for NAS-Port, that attribute
+        *      should NOT be present (but we don't right now).
+        */
+       if ((status != PW_STATUS_ACCOUNTING_ON) &&
+           (status != PW_STATUS_ACCOUNTING_OFF)) do {
+               int check1 = 0;
+               int check2 = 0;
+
+               if ((vp = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME))
+                    == NULL || vp->lvalue == 0)
+                       check1 = 1;
+               if ((vp = pairfind(request->packet->vps, PW_ACCT_SESSION_ID))
+                    != NULL && vp->length == 8 &&
+                    memcmp(vp->vp_strvalue, "00000000", 8) == 0)
+                       check2 = 1;
+               if (check1 == 0 || check2 == 0) {
+#if 0 /* Cisco sometimes sends START records without username. */
+                       radlog(L_ERR, "rlm_radutmp: no username in record");
+                       return RLM_MODULE_FAIL;
+#else
+                       break;
+#endif
+               }
+               radlog(L_INFO, "rlm_radutmp: converting reboot records.");
+               if (status == PW_STATUS_STOP)
+                       status = PW_STATUS_ACCOUNTING_OFF;
+               if (status == PW_STATUS_START)
+                       status = PW_STATUS_ACCOUNTING_ON;
+       } while(0);
+
+       memset(&utmp, 0, sizeof(utmp));
+       utmp.porttype = 'A';
+
+       /*
+        *      First, find the interesting attributes.
+        */
+       for (vp = request->packet->vps; vp; vp = vp->next) {
+               switch (vp->attribute) {
+                       case PW_LOGIN_IP_HOST:
+                       case PW_FRAMED_IP_ADDRESS:
+                               framed_address = vp->lvalue;
+                               utmp.framed_address = vp->lvalue;
+                               break;
+                       case PW_FRAMED_PROTOCOL:
+                               protocol = vp->lvalue;
+                               break;
+                       case PW_NAS_IP_ADDRESS:
+                               nas_address = vp->lvalue;
+                               utmp.nas_address = vp->lvalue;
+                               break;
+                       case PW_NAS_PORT:
+                               utmp.nas_port = vp->lvalue;
+                               port_seen = 1;
+                               break;
+                       case PW_ACCT_DELAY_TIME:
+                               utmp.delay = vp->lvalue;
+                               break;
+                       case PW_ACCT_SESSION_ID:
+                               /*
+                                *      If it's too big, only use the
+                                *      last bit.
+                                */
+                               if (vp->length > sizeof(utmp.session_id)) {
+                                       int length = vp->length - sizeof(utmp.session_id);
+
+                                       /*
+                                        *      Ascend is br0ken - it
+                                        *      adds a \0 to the end
+                                        *      of any string.
+                                        *      Compensate.
+                                        */
+                                       if (vp->vp_strvalue[vp->length - 1] == 0) {
+                                               length--;
+                                       }
+
+                                       memcpy(utmp.session_id,
+                                             vp->vp_strvalue + length,
+                                             sizeof(utmp.session_id));
+                               } else {
+                                       memset(utmp.session_id, 0,
+                                              sizeof(utmp.session_id));
+                                       memcpy(utmp.session_id,
+                                              vp->vp_strvalue,
+                                              vp->length);
+                               }
+                               break;
+                       case PW_NAS_PORT_TYPE:
+                               if (vp->lvalue <= 4)
+                                       utmp.porttype = porttypes[vp->lvalue];
+                               break;
+                       case PW_CALLING_STATION_ID:
+                               if(inst->callerid_ok)
+                                       strlcpy(utmp.caller_id,
+                                               (char *)vp->vp_strvalue,
+                                               sizeof(utmp.caller_id));
+                               break;
+               }
+       }
+
+       /*
+        *      If we didn't find out the NAS address, use the
+        *      originator's IP address.
+        */
+       if (nas_address == 0) {
+               nas_address = request->packet->src_ipaddr;
+               utmp.nas_address = nas_address;
+               nas = client_name(nas_address); /* MUST be a valid client */
+
+       } else {                /* might be a client, might not be. */
+               RADCLIENT *cl;
+
+               /*
+                *      Hack like 'client_name()', but with sane
+                *      fall-back.
+                */
+               cl = client_find(nas_address);
+               if (cl) {
+                       if (cl->shortname && cl->shortname[0]) {
+                               nas = cl->shortname;
+                       } else {
+                               nas = cl->longname;
+                       }
+               } else {
+                       /*
+                        *      The NAS isn't a client, it's behind
+                        *      a proxy server.  In that case, just
+                        *      get the IP address.
+                        */
+                       nas = ip_ntoa(ip_name, nas_address);
+               }
+       }
+
+       /*
+        *      Set the protocol field.
+        */
+       if (protocol == PW_PPP)
+               utmp.proto = 'P';
+       else if (protocol == PW_SLIP)
+               utmp.proto = 'S';
+       else
+               utmp.proto = 'T';
+
+       utmp.time = request->timestamp - utmp.delay;
+
+       /*
+        *      Get the utmp filename, via xlat.
+        */
+       radius_xlat(filename, sizeof(filename), inst->filename, request, NULL);
+
+       /*
+        *      Future: look up filename in filename tree, to get
+        *      radutmp_cache_t pointer
+        */
+       cache = &inst->cache;
+
+       /*
+        *      For now, double-check the filename, to be sure it isn't
+        *      changing.
+        */
+       if (!cache->filename) {
+               cache->filename = strdup(filename);
+               rad_assert(cache->filename != NULL);
+
+       } else if (strcmp(cache->filename, filename) != 0) {
+               radlog(L_ERR, "rlm_radutmp: We do not support dynamically named files.");
+               return RLM_MODULE_FAIL;
+       }
+
+       /*
+        *      If the lookup failed, create a new one, and add it
+        *      to the filename tree, and cache the file, as below.
+        */
+
+       /*
+        *      For aging, in the future.
+        */
+       cache->last_used = request->timestamp;
+
+       /*
+        *      If we haven't already read the file, then read the
+        *      entire file, in order to cache its entries.
+        */
+       if (!cache->cached_file) {
+               cache_file(inst, cache);
+       }
+
+       /*
+        *      See if this was a reboot.
+        *
+        *      Hmm... we may not want to zap all of the users when
+        *      the NAS comes up, because of issues with receiving
+        *      UDP packets out of order.
+        */
+       if (status == PW_STATUS_ACCOUNTING_ON && nas_address) {
+               radlog(L_INFO, "rlm_radutmp: NAS %s restarted (Accounting-On packet seen)",
+                      nas);
+               if (!radutmp_zap(inst, cache, nas_address, utmp.time)) {
+                       rad_assert(0 == 1);
+               }
+               return RLM_MODULE_OK;
+       }
+
+       if (status == PW_STATUS_ACCOUNTING_OFF && nas_address) {
+               radlog(L_INFO, "rlm_radutmp: NAS %s rebooted (Accounting-Off packet seen)",
+                      nas);
+               if (!radutmp_zap(inst, cache, nas_address, utmp.time)) {
+                       rad_assert(0 == 1);
+               }
+               return RLM_MODULE_OK;
+       }
+
+       /*
+        *      If we don't know this type of entry, then pretend we
+        *      succeeded.
+        */
+       if (status != PW_STATUS_START &&
+           status != PW_STATUS_STOP &&
+           status != PW_STATUS_ALIVE) {
+               radlog(L_ERR, "rlm_radutmp: NAS %s port %u unknown packet type %d, ignoring it.",
+                      nas, utmp.nas_port, status);
+               return RLM_MODULE_NOOP;
+       }
+
+       /*
+        *      Perhaps we don't want to store this record into
+        *      radutmp. We skip records:
+        *
+        *      - without a NAS-Port (telnet / tcp access)
+        *      - with the username "!root" (console admin login)
+        */
+       if (!port_seen) {
+               DEBUG2("  rlm_radutmp: No NAS-Port in the packet.  Cannot do anything.");
+               DEBUG2("  rlm_radumtp: WARNING: checkrad will probably not work!");
+               return RLM_MODULE_NOOP;
+       }
+
+       /*
+        *      Translate the User-Name attribute, or whatever else
+        *      they told us to use.
+        */
+       *buffer = '\0';
+       radius_xlat(buffer, sizeof(buffer), inst->username, request, NULL);
+
+       /*
+        *      Don't log certain things...
+        */
+       if (strcmp(buffer, "!root") == 0) {
+               DEBUG2("  rlm_radutmp: Not recording administrative user");
+
+               return RLM_MODULE_NOOP;
+       }
+       strlcpy(utmp.login, buffer, RUT_NAMESIZE);
+
+       /*
+        *      First, try to open the file.  If it doesn't exist,
+        *      nuke the existing caches, and try to create it.
+        *
+        *      FIXME: Create any intermediate directories, as
+        *      appropriate.  See rlm_detail.
+        */
+       fd = open(cache->filename, O_RDWR, inst->permission);
+       if (fd < 0) {
+               if (errno == ENOENT) {
+                       DEBUG2("  rlm_radutmp: File %s doesn't exist, creating it.", cache->filename);
+                       if (!cache_reset(inst, cache)) return RLM_MODULE_FAIL;
+                       
+                       /*
+                        *      Try to create the file.
+                        */
+                       fd = open(cache->filename, O_RDWR | O_CREAT,
+                                 inst->permission);
+               }
+       } else {                /* exists, but may be empty */
+               struct stat buf;
+
+               /*
+                *      If the file is empty, reset the cache.
+                */
+               if ((stat(cache->filename, &buf) == 0) &&
+                   (buf.st_size == 0) &&
+                   (!cache_reset(inst, cache))) {
+                       return RLM_MODULE_FAIL;
+               }
+               DEBUG2("  rlm_radutmp: File %s was truncated.  Resetting cache.",
+                      cache->filename);
+       }
+
+       /*
+        *      Error from creation, or error other than ENOENT: die.
+        */
+       if (fd < 0) {
+               radlog(L_ERR, "rlm_radutmp: Error accessing file %s: %s",
+                      cache->filename, strerror(errno));
+               return RLM_MODULE_FAIL;
+       }
+
+       /*
+        *      OK.  Now that we've prepared everything we want to do,
+        *      let's see if we've cached the entry.
+        */
+       myPort.nas_address = utmp.nas_address;
+       myPort.nas_port = utmp.nas_port;
+
+       pthread_mutex_lock(&cache->mutex);
+       node = rbtree_find(cache->nas_ports, &myPort);
+       pthread_mutex_unlock(&cache->mutex);
+
+       if (node) {
+               nas_port = rbtree_node2data(cache->nas_ports, node);
+#if 0
+
+               /*
+                *      stat the file, and get excited if it's been
+                *      truncated.
+                *
+                *      i.e wipe out the cache, and re-read the file.
+                */
+
+               /*
+                *      Now find the new entry.
+                */
+               pthread_mutex_lock(&cache->mutex);
+               node = rbtree_find(cache->nas_ports, &myPort);
+               pthread_mutex_unlock(&cache->mutex);
+#endif
+       }
+
+       if (!node) {
+               radutmp_simul_t *user;
+
+               /*
+                *      Not found in the cache, and we're trying to
+                *      delete an existing record: ignore it.
+                */
+               if (status == PW_STATUS_STOP) {
+                       DEBUG2("  rlm_radumtp: Logout entry for NAS %s port %u with no Login: ignoring it.",
+                              nas, utmp.nas_port);
+                       return RLM_MODULE_NOOP;
+               }
+
+               pthread_mutex_lock(&cache->mutex);
+
+               /*
+                *      It's a START or ALIVE.  Try to find a free
+                *      offset where we can store the new entry, or
+                *      create one, if one doesn't already exist.
+                */
+               if (!cache->free_offsets) {
+                       cache->free_offsets = rad_malloc(sizeof(NAS_PORT));
+                       memset(cache->free_offsets, 0,
+                              sizeof(*(cache->free_offsets)));
+                       cache->free_offsets->offset = cache->max_offset;
+                       cache->max_offset += sizeof(u);
+               }
+
+               /*
+                *      Grab the offset, and put it into the various
+                *      caches.
+                */
+               nas_port = cache->free_offsets;
+               cache->free_offsets = nas_port->next;
+
+               nas_port->nas_address = nas_address;
+               nas_port->nas_port = utmp.nas_port;
+
+               if (!rbtree_insert(cache->nas_ports, nas_port)) {
+                       rad_assert(0 == 1);
+               }
+
+               /*
+                *      Allocate new entry, and add it
+                *      to the tree.
+                */
+               user = rad_malloc(sizeof(user));
+               strlcpy(user->login, utmp.login,
+                       sizeof(user->login));
+               user->simul_count = 1;
+               
+               if (!rbtree_insert(inst->user_tree, user)) {
+                       rad_assert(0 == 1);
+               }
+
+               pthread_mutex_unlock(&cache->mutex);
+
+       }
+               
+       /*
+        *      Entry was found, or newly created in the cache.
+        *      Seek to the place in the file.
+        */
+       lseek(fd, nas_port->offset, SEEK_SET);
+
+       /*
+        *      Lock the utmp file, prefer lockf() over flock().
+        */
+       rad_lockfd(fd, LOCK_LEN);
+
+       /*
+        *      If it WAS found in the cache, double-check it against
+        *      what is in the file.
+        */
+       if (node) {
+               /*
+                *      If we didn't read anything, then this entry
+                *      doesn't exist.
+                *
+                *      Similarly, if the entry in the file doesn't
+                *      match what we recall, then nuke the cache
+                *      entry.
+                */
+               read_size = read(fd, &u, sizeof(u));
+               if ((read_size < 0) ||
+                   ((read_size > 0) && (read_size  != sizeof(u)))) {
+                       /*
+                        *      Bad read, or bad record.
+                        */
+                       radlog(L_ERR, "rlm_radutmp: Badly formed file %s",
+                              cache->filename);
+                       close(fd);
+                       return RLM_MODULE_FAIL;
+               }
+
+               rad_assert(read_size != 0);
+
+               /*
+                *      We've read a record, go poke at it.
+                */
+               if (read_size > 0) {
+                       /*
+                        *      If these aren't true, then
+                        *
+                        *      a) we have cached a "logout" entry,
+                        *         which we don't do.
+                        *
+                        *      b) we have cached the wrong NAS address
+                        *
+                        *      c) we have cached the wrong NAS port.
+                        */
+                       rad_assert(u.type == P_LOGIN);
+                       rad_assert(u.nas_address == utmp.nas_address);
+                       rad_assert(u.nas_port == utmp.nas_port);
+                       
+                       /*
+                        *      An update for the same session.
+                        */
+                       if (strncmp(utmp.session_id, u.session_id,
+                                   sizeof(u.session_id)) == 0) {
+
+                               /*
+                                *      It's a duplicate start, so we
+                                *      don't bother writing it.
+                                */
+                               if (status == PW_STATUS_START) {
+                                       DEBUG2("  rlm_radutmp: Login entry for NAS %s port %u duplicate, ignoring it.",
+                                              nas, u.nas_port);
+                                       close(fd);
+                                       return RLM_MODULE_OK;
+
+
+                               /*
+                                *      ALIVE for this session, keep the
+                                *      original login time.
+                                */
+                               } else if (status == PW_STATUS_ALIVE) {
+                                       utmp.time = u.time;
+
+                               /*
+                                *      Stop: delete it from our cache.
+                                */
+                               } else if (status == PW_STATUS_STOP) {
+                                       radutmp_simul_t *user, myUser;
+
+                                       pthread_mutex_lock(&cache->mutex);
+                                       rbtree_deletebydata(cache->nas_ports,
+                                                           nas_port);
+
+                                       strlcpy(myUser.login,
+                                               u.login, sizeof(myUser.login));
+                                       user = rbtree_finddata(inst->user_tree,
+                                                              &myUser);
+                                       rad_assert(user != NULL);
+                                       rad_assert(user->simul_count > 0);
+
+                                       user->simul_count--;
+                                       if (user->simul_count == 0) {
+                                               rbtree_deletebydata(inst->user_tree, user);
+                                       }
+
+                                       pthread_mutex_unlock(&cache->mutex);
+
+                               } else {
+                                       /*
+                                        *      We don't know how to
+                                        *      handle this.
+                                        */
+                                       rad_assert(0 == 1);
+                               }
+
+                       } else { /* session ID doesn't match */
+                               /*
+                                *      STOP for the right NAS & port,
+                                *      but the Acct-Session-Id is
+                                *      different.  This means that
+                                *      we missed the original "stop",
+                                *      and a new "start".
+                                */
+                               if (status == PW_STATUS_STOP) {
+                                       radlog(L_ERR, "rlm_radutmp: Logout entry for NAS %s port %u has old Acct-Session-ID, ignoring it.",
+                                              nas, u.nas_port);
+                                       close(fd);
+                                       return RLM_MODULE_OK;
+                               }
+                       } /* checked session ID's */
+               }  /* else we haven't read anything from the file. */
+       } /* else the entry wasn't cached, but could have been inserted */
+
+       /*
+        *      Hmm... we may have received a start or alive packet
+        *      AFTER a stop or nas-down, in that case, we want to
+        *      discard the new packet.  However, the original code
+        *      could over-write an idle record with a new login
+        *      record for another NAS && port, so we won't worry
+        *      about this case too much.
+        */
+
+       /*
+        *      Seek to where the entry is, and write it blindly.
+        */
+       lseek(fd, nas_port->offset, SEEK_SET); /* FIXME: err */
+
+       if (status != PW_STATUS_STOP) {
+               utmp.type = P_LOGIN;
+               rad_assert(nas_port != NULL); /* it WAS cached */
+       } else {
+               /* FIXME: maybe assert that the entry was deleted... */
+               memcpy(&utmp, &u, sizeof(utmp));
+               utmp.type = P_IDLE;
+       }
+
+       write(fd, &utmp, sizeof(utmp)); /* FIXME: err */
+
+       close(fd);      /* and implicitly release the locks */
+
+       return RLM_MODULE_OK;
+}
+
+/*
+ *     See if a user is already logged in. Sets request->simul_count
+ *     to the current session count for this user and sets
+ *     request->simul_mpp to 2 if it looks like a multilink attempt
+ *     based on the requested IP address, otherwise leaves
+ *     request->simul_mpp alone.
+ *
+ *     Check twice. If on the first pass the user exceeds his
+ *     max. number of logins, do a second pass and validate all
+ *     logins by querying the terminal server (using eg. SNMP).
+ */
+static int radutmp_checksimul(void *instance, REQUEST *request)
+{
+       struct radutmp  u;
+       int             fd;
+       VALUE_PAIR      *vp;
+       uint32_t        ipno = 0;
+       char            *call_num = NULL;
+       int             rcode;
+       rlm_radutmp_t   *inst = instance;
+       char            login[256];
+       char            filename[1024];
+       radutmp_cache_t *cache;
+       radutmp_simul_t *user, myUser;
+
+       /*
+        *      Get the filename, via xlat.
+        */
+       radius_xlat(filename, sizeof(filename), inst->filename, request, NULL);
+
+       /*
+        *      Future: look up filename in filename tree, to get
+        *      radutmp_cache_t pointer
+        */
+       cache = &inst->cache;
+
+       /*
+        *      For now, double-check the filename, to be sure it isn't
+        *      changing.
+        */
+       if (!cache->filename) {
+               cache->filename = strdup(filename);
+               rad_assert(cache->filename != NULL);
+
+       } else if (strcmp(cache->filename, filename) != 0) {
+               radlog(L_ERR, "rlm_radutmp: We do not support dynamically named files.");
+               return RLM_MODULE_FAIL;
+       }
+
+       *login = '\0';
+       radius_xlat(login, sizeof(login), inst->username, request, NULL);
+       if (!*login) {
+               return RLM_MODULE_NOOP;
+       }
+
+       /*
+        *      WTF?  This is probably wrong... we probably want to
+        *      be able to check users across multiple session accounting
+        *      methods.
+        */
+       request->simul_count = 0;
+
+       strlcpy(myUser.login, login, sizeof(myUser.login));
+       pthread_mutex_lock(&inst->cache.mutex);
+       user = rbtree_finddata(inst->user_tree, &myUser);
+       if (user) request->simul_count = user->simul_count;
+       user = NULL;            /* someone else may delete it */
+       pthread_mutex_unlock(&inst->cache.mutex);
+
+       /*
+        *      The number of users logged in is OK,
+        *      OR, we've been told to not check the NAS.
+        */
+       if ((request->simul_count < request->simul_max) ||
+           !inst->check_nas) {
+               return RLM_MODULE_OK;
+       }
+
+       /*
+        *      The user is logged in at least N times, and
+        *      we're told to check the NAS.  In that case,
+        *      we've got to read the file, and check each
+        *      NAS port by hand.
+        */
+       if ((fd = open(cache->filename, O_RDWR)) < 0) {
+               /*
+                *      If the file doesn't exist, then no users
+                *      are logged in.
+                */
+               if (errno == ENOENT) {
+                       request->simul_count = 0;
+                       return RLM_MODULE_OK;
+               }
+
+               /*
+                *      Error accessing the file.
+                */
+               radlog(L_ERR, "rlm_radumtp: Error accessing file %s: %s",
+                      cache->filename, strerror(errno));
+               return RLM_MODULE_FAIL;
+       }
+
+       /*
+        *      Setup some stuff, like for MPP detection.
+        */
+       if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS)) != NULL)
+               ipno = vp->lvalue;
+       if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) != NULL)
+               call_num = vp->vp_strvalue;
+
+       /*
+        *      lock the file while reading/writing.
+        */
+       rad_lockfd(fd, LOCK_LEN);
+
+       /*
+        *      FIXME: If we get a 'Start' for a user/nas/port which is
+        *      listed, but for which we did NOT get a 'Stop', then
+        *      it's not a duplicate session.  This happens with
+        *      static IP's like DSL.
+        */
+       request->simul_count = 0;
+       while (read(fd, &u, sizeof(u)) == sizeof(u)) {
+               if (((strncmp(login, u.login, RUT_NAMESIZE) == 0) ||
+                    (!inst->case_sensitive &&
+                     (strncasecmp(login, u.login, RUT_NAMESIZE) == 0))) &&
+                   (u.type == P_LOGIN)) {
+                       char session_id[sizeof(u.session_id) + 1];
+                       char utmp_login[sizeof(u.login) + 1];
+
+                       strlcpy(session_id, u.session_id, sizeof(session_id));
+
+                       /*
+                        *      The login name MAY fill the whole field,
+                        *      and thus won't be zero-filled.
+                        *
+                        *      Note that we take the user name from
+                        *      the utmp file, as that's the canonical
+                        *      form.  The 'login' variable may contain
+                        *      a string which is an upper/lowercase
+                        *      version of u.login.  When we call the
+                        *      routine to check the terminal server,
+                        *      the NAS may be case sensitive.
+                        *
+                        *      e.g. We ask if "bob" is using a port,
+                        *      and the NAS says "no", because "BOB"
+                        *      is using the port.
+                        */
+                       strlcpy(utmp_login, u.login, sizeof(u.login));
+
+                       /*
+                        *      rad_check_ts may take seconds
+                        *      to return, and we don't want
+                        *      to block everyone else while
+                        *      that's happening.  */
+                       rad_unlockfd(fd, LOCK_LEN);
+                       rcode = rad_check_ts(u.nas_address, u.nas_port,
+                                            utmp_login, session_id);
+                       rad_lockfd(fd, LOCK_LEN);
+
+                       if (rcode == 0) {
+                               /*
+                                *      Stale record - zap it.
+                                *
+                                *      Hmm... this ends up calling
+                                *      the accounting section
+                                *      recursively...
+                                */
+                               session_zap(request, u.nas_address,
+                                           u.nas_port, login, session_id,
+                                           u.framed_address, u.proto,0);
+                       }
+                       else if (rcode == 1) {
+                               /*
+                                *      User is still logged in.
+                                */
+                               ++request->simul_count;
+
+                               /*
+                                *      Does it look like a MPP attempt?
+                                */
+                               if (strchr("SCPA", u.proto) &&
+                                   ipno && u.framed_address == ipno)
+                                       request->simul_mpp = 2;
+                               else if (strchr("SCPA", u.proto) && call_num &&
+                                       !strncmp(u.caller_id,call_num,16))
+                                       request->simul_mpp = 2;
+                       }
+                       else {
+                               /*
+                                *      Failed to check the terminal
+                                *      server for duplicate logins:
+                                *      Return an error.
+                                */
+                               close(fd);
+                               radlog(L_ERR, "rlm_radutmp: Failed to check the terminal server for user '%s'.", utmp_login);
+                               return RLM_MODULE_FAIL;
+                       }
+               }
+       }
+       close(fd);              /* and implicitly release the locks */
+
+       return RLM_MODULE_OK;
+}
+
+/* globally exported name */
+module_t rlm_radutmp = {
+  "radutmp",
+  0,                           /* type: reserved */
+  NULL,                        /* initialization */
+  radutmp_instantiate,          /* instantiation */
+  {
+         NULL,                 /* authentication */
+         NULL,                 /* authorization */
+         NULL,                 /* preaccounting */
+         radutmp_accounting,   /* accounting */
+         radutmp_checksimul,   /* checksimul */
+         NULL,                 /* pre-proxy */
+         NULL,                 /* post-proxy */
+         NULL                  /* post-auth */
+  },
+  radutmp_detach,               /* detach */
+  NULL,                        /* destroy */
+};
+
index 60e05a5..baffe84 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * FIXME add copyrights
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <netinet/in.h>
 #endif
 
-#include "libradius.h"
-#include "radiusd.h"
-#include "modules.h"
-
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 #define  REALM_FORMAT_PREFIX   0
 #define  REALM_FORMAT_SUFFIX   1
@@ -84,6 +84,11 @@ static int check_for_realm(void *instance, REQUEST *request, REALM **returnrealm
        /* initiate returnrealm */
        *returnrealm = NULL;
 
+       if (request->packet->src_ipaddr.af != AF_INET) {
+               DEBUG2("rlm_realm: IPv6 is not supported!");
+               return 0;
+       }
+
        /*
         *      If the request has a proxy entry, then it's a proxy
         *      reply, and we're walking through the module list again.
@@ -114,7 +119,7 @@ static int check_for_realm(void *instance, REQUEST *request, REALM **returnrealm
         *      We will be modifing this later, so we want our own copy
         *      of it.
         */
-       strNcpy(namebuf, (char *)request->username->strvalue, sizeof(namebuf));
+       strlcpy(namebuf, (char *)request->username->vp_strvalue, sizeof(namebuf));
        username = namebuf;
 
        switch(inst->format)
@@ -155,15 +160,15 @@ static int check_for_realm(void *instance, REQUEST *request, REALM **returnrealm
         */
        if (realmname) {
                DEBUG2("    rlm_realm: Looking up realm \"%s\" for User-Name = \"%s\"",
-                      realmname, request->username->strvalue);
+                      realmname, request->username->vp_strvalue);
        } else {
                if( inst->ignore_null ) {
                        DEBUG2("    rlm_realm: No '%c' in User-Name = \"%s\", skipping NULL due to config.",
-                       inst->delim[0], request->username->strvalue);
+                       inst->delim[0], request->username->vp_strvalue);
                        return 0;
                }
                DEBUG2("    rlm_realm: No '%c' in User-Name = \"%s\", looking up realm NULL",
-                      inst->delim[0], request->username->strvalue);
+                      inst->delim[0], request->username->vp_strvalue);
        }
 
        /*
@@ -206,8 +211,8 @@ static int check_for_realm(void *instance, REQUEST *request, REALM **returnrealm
                        DEBUG2("    rlm_realm: Setting Stripped-User-Name = \"%s\"", username);
                }
 
-               strcpy(vp->strvalue, username);
-               vp->length = strlen((char *)vp->strvalue);
+               strcpy(vp->vp_strvalue, username);
+               vp->length = strlen((char *)vp->vp_strvalue);
                request->username = vp;
        }
 
@@ -234,7 +239,7 @@ static int check_for_realm(void *instance, REQUEST *request, REALM **returnrealm
                 *      Perhaps accounting proxying was turned off.
                 */
        case PW_ACCOUNTING_REQUEST:
-               if (realm->acct_ipaddr == htonl(INADDR_NONE)) {
+               if (realm->acct_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)) {
                        DEBUG2("    rlm_realm: Accounting realm is LOCAL.");
                        return 0;
                }
@@ -249,7 +254,7 @@ static int check_for_realm(void *instance, REQUEST *request, REALM **returnrealm
                 *      Perhaps authentication proxying was turned off.
                 */
        case PW_AUTHENTICATION_REQUEST:
-               if (realm->ipaddr == htonl(INADDR_NONE)) {
+               if (realm->ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_NONE)) {
                        DEBUG2("    rlm_realm: Authentication realm is LOCAL.");
                        return 0;
                }
@@ -269,12 +274,12 @@ static int check_for_realm(void *instance, REQUEST *request, REALM **returnrealm
        for (vp = request->packet->vps; vp; vp = vp->next) {
                if (vp->attribute == PW_FREERADIUS_PROXIED_TO) {
                        if (request->packet->code == PW_AUTHENTICATION_REQUEST &&
-                           vp->lvalue == realm->ipaddr) {
+                           vp->lvalue == realm->ipaddr.ipaddr.ip4addr.s_addr) {
                                DEBUG2("    rlm_realm: Request not proxied due to Freeradius-Proxied-To");
                                return 0;
                        }
                        if (request->packet->code == PW_ACCOUNTING_REQUEST &&
-                           vp->lvalue == realm->acct_ipaddr) {
+                           vp->lvalue == realm->acct_ipaddr.ipaddr.ip4addr.s_addr) {
                                DEBUG2("    rlm_realm: Request not proxied due to Freeradius-Proxied-To");
                                return 0;
                        }
@@ -341,7 +346,6 @@ static int realm_instantiate(CONF_SECTION *conf, void **instance)
             free(inst);
             return -1;
        }
-       free(inst->formatstring);
        if(strlen(inst->delim) != 1) {
             radlog(L_ERR, "Bad value \"%s\" for realm delimiter value", inst->delim);
             free(inst);
@@ -396,7 +400,7 @@ static int realm_authorize(void *instance, REQUEST *request)
  */
 static int realm_preacct(void *instance, REQUEST *request)
 {
-       const char *name = (char *)request->username->strvalue;
+       const char *name = (char *)request->username->vp_strvalue;
        REALM *realm;
 
        if (!name)
@@ -429,27 +433,25 @@ static int realm_preacct(void *instance, REQUEST *request)
 static int realm_detach(void *instance)
 {
        struct realm_config_t *inst = instance;
-       free(inst->delim);
        free(instance);
        return 0;
 }
 
 /* globally exported name */
 module_t rlm_realm = {
-  "realm",
-  0,                           /* type: reserved */
-  NULL,                                /* initialization */
-  realm_instantiate,           /* instantiation */
-  {
-         NULL,                 /* authentication */
-         realm_authorize,      /* authorization */
-         realm_preacct,        /* preaccounting */
-         NULL,                 /* accounting */
-         NULL,                 /* checksimul */
-         NULL,                 /* pre-proxy */
-         NULL,                 /* post-proxy */
-         NULL                  /* post-auth */
-  },
-  realm_detach,                        /* detach */
-  NULL,                                /* destroy */
+       RLM_MODULE_INIT,
+       "realm",
+       0,                              /* type: reserved */
+       realm_instantiate,              /* instantiation */
+       realm_detach,                   /* detach */
+       {
+               NULL,                   /* authentication */
+               realm_authorize,        /* authorization */
+               realm_preacct,  /* preaccounting */
+               NULL,                   /* accounting */
+               NULL,                   /* checksimul */
+               NULL,                   /* pre-proxy */
+               NULL,                   /* post-proxy */
+               NULL                    /* post-auth */
+       },
 };
index 300e607..72573c6 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * Copyright 2004  Michael Richardson <mcr@sandelman.ottawa.on.ca>
+ * Copyright 2006  The FreeRADIUS server project
  *
  * (Adapted from rlm_files/rlm_files.c )
  */
  */
 
 
-static const char rcsid[] = "$Id$";
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include       "autoconf.h"
-#include       "libradius.h"
+#include       <freeradius-devel/autoconf.h>
 
 #include       <sys/stat.h>
 
@@ -67,8 +68,8 @@ static const char rcsid[] = "$Id$";
 #include       <fcntl.h>
 #include       <limits.h>
 
-#include       "radiusd.h"
-#include       "modules.h"
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/modules.h>
 #include        "../rlm_eap/libeap/eap_sim.h"
 
 struct sim_file_instance {
@@ -76,7 +77,7 @@ struct sim_file_instance {
        char *file;
 };
 
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
        { "simtriplets",        PW_TYPE_STRING_PTR,
          offsetof(struct sim_file_instance, file),
          NULL, "${raddbdir}/simtriplets.dat" },
@@ -134,7 +135,7 @@ static int sim_file_authorize(void *instance, REQUEST *request)
         *      Grab the canonical user name.
         */
        namepair = request->username;
-       name = namepair ? (char *) namepair->strvalue : "NONE";
+       name = namepair ? (char *) namepair->vp_strvalue : "NONE";
 
        triplets = fopen(inst->file, "r");
 
@@ -275,10 +276,11 @@ static int sim_file_detach(void *instance)
 
 /* globally exported name */
 module_t rlm_sim_files = {
+       RLM_MODULE_INIT,
        "sim_files",
        0,                              /* type: reserved */
-       NULL,                           /* initialization */
        sim_file_instantiate,           /* instantiation */
+       sim_file_detach,                /* detach */
        {
                NULL,                   /* authentication */
                sim_file_authorize,     /* authorization */
@@ -289,7 +291,5 @@ module_t rlm_sim_files = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       sim_file_detach,                /* detach */
-       NULL                            /* destroy */
 };
 
index 2dae575..5700c29 100644 (file)
@@ -3,6 +3,7 @@
    Version 1.9.
    SMB Byte handling
    Copyright (C) Andrew Tridgell 1992-1995
+   Copyright 2006 The FreeRADIUS server project
 
    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
@@ -24,6 +25,9 @@
    int manipulation
 */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(byteorder_h, "$Id$")
+
 #undef CAREFUL_ALIGNMENT
 
 /* we know that the 386 can handle misalignment and has the "right"
index 707c0da..72ff765 100644 (file)
@@ -1,45 +1,79 @@
-/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
-/*
+/* config.h.in.  Generated from configure.in by autoheader.  */
 
-acconfig.h - template used by autoheader to create config.h.in
-config.h.in - used by autoconf to create config.h
-config.h - created by autoconf; contains defines generated by autoconf
-
-*/
-
-
-/* Define if you have the <arpa/inet.h> header file.  */
+/* Define to 1 if you have the <arpa/inet.h> header file. */
 #undef HAVE_ARPA_INET_H
 
-/* Define if you have the <ctype.h> header file.  */
+/* Define to 1 if you have the <ctype.h> header file. */
 #undef HAVE_CTYPE_H
 
-/* Define if you have the <dirent.h> header file.  */
+/* Define to 1 if you have the <dirent.h> header file. */
 #undef HAVE_DIRENT_H
 
-/* Define if you have the <netdb.h> header file.  */
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
 #undef HAVE_NETDB_H
 
-/* Define if you have the <netinet/in.h> header file.  */
+/* Define to 1 if you have the <netinet/in.h> header file. */
 #undef HAVE_NETINET_IN_H
 
-/* Define if you have the <netinet/tcp.h> header file.  */
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
 #undef HAVE_NETINET_TCP_H
 
-/* Define if you have the <signal.h> header file.  */
+/* Define to 1 if you have the <signal.h> header file. */
 #undef HAVE_SIGNAL_H
 
-/* Define if you have the <sys/signal.h> header file.  */
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/signal.h> header file. */
 #undef HAVE_SYS_SIGNAL_H
 
-/* Define if you have the <sys/socket.h> header file.  */
+/* Define to 1 if you have the <sys/socket.h> header file. */
 #undef HAVE_SYS_SOCKET_H
 
-/* Define if you have the <sys/uio.h> header file.  */
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
 #undef HAVE_SYS_UIO_H
 
-/* Define if you have the <sys/vfs.h> header file.  */
+/* Define to 1 if you have the <sys/vfs.h> header file. */
 #undef HAVE_SYS_VFS_H
 
-/* Define if you have the <unistd.h> header file.  */
+/* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
index f8f380c..4842ecf 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.3 .
+# From configure.in Revision: 1.4 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -944,7 +944,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1866,8 +1866,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1925,8 +1924,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2042,8 +2040,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2097,8 +2094,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2143,8 +2139,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2188,8 +2183,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2553,8 +2547,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2724,8 +2717,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2815,8 +2807,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3743,11 +3734,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3786,6 +3772,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 248f6d8..149e87c 100644 (file)
@@ -1,3 +1,4 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_smb.c)
 AC_CONFIG_HEADER(config.h)
 AC_REVISION($Revision$)
index 0d7d5dd..c3213a3 100644 (file)
@@ -4,6 +4,7 @@
    RFCNB Common Structures etc Defines
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
@@ -23,6 +24,9 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(rfcnb_common_h, "$Id$")
+
 /* A data structure we need */
 
 typedef struct RFCNB_Pkt {
index a942434..6db9c43 100644 (file)
@@ -4,6 +4,7 @@
    RFCNB Error Response Defines
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
@@ -23,6 +24,9 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(rfcnb_error_h, "$Id$")
+
 /* Error responses */
 
 #define RFCNBE_Bad -1          /* Bad response */
index 0869b2a..2c57d73 100644 (file)
@@ -4,6 +4,7 @@
    RFCNB IO Routines ...
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 /* #include <features.h> */
 #include "std-includes.h"
 #include "rfcnb-priv.h"
@@ -53,7 +58,6 @@ void rfcnb_alarm(int sig)
 int RFCNB_Set_Timeout(int seconds)
 
 {
-  int temp;
   /* If we are on a Bezerkeley system, use sigvec, else sigaction */
 #ifndef SA_RESTART
   struct sigvec invec, outvec;
index 9af8e90..5f8963a 100644 (file)
@@ -4,6 +4,7 @@
    RFCNB IO Routines Defines
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
@@ -23,6 +24,9 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(rfcnb_io_h, "$Id$")
+
 int RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len);
 
 int RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len);
index f2043d4..02c071d 100644 (file)
@@ -4,6 +4,7 @@
    RFCNB Defines
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
@@ -23,6 +24,9 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(rfcnb_priv_h, "$Id$")
+
 /* Defines we need */
 
 typedef unsigned short uint16;
index e241864..b502e9e 100644 (file)
@@ -4,6 +4,7 @@
    RFCNB Utility Routines ...
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <string.h>
 
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/libradius.h>
 #include "std-includes.h"
 #include "rfcnb-priv.h"
 #include "rfcnb-util.h"
@@ -242,11 +248,11 @@ void RFCNB_Print_Pkt(FILE *fd, char *dirn, struct RFCNB_Pkt *pkt, int len)
     fprintf(fd, "SESSION MESSAGE: Length = %i\n", RFCNB_Pkt_Len(pkt -> data));
     RFCNB_Print_Hex(fd, pkt, RFCNB_Pkt_Hdr_Len,
 #ifdef RFCNB_PRINT_DATA
-                   RFCNB_Pkt_Len(pkt -> data) - RFCNB_Pkt_Hdr_Len);
+                   RFCNB_Pkt_Len(pkt -> data) - RFCNB_Pkt_Hdr_Len
 #else
-                    40);
+                    40
 #endif
-
+           );
   if (Prot_Print_Routine != 0) { /* Print the rest of the packet */
 
     Prot_Print_Routine(fd, strcmp(dirn, "sent"), pkt, RFCNB_Pkt_Hdr_Len,
@@ -313,28 +319,20 @@ void RFCNB_Print_Pkt(FILE *fd, char *dirn, struct RFCNB_Pkt *pkt, int len)
 
 int RFCNB_Name_To_IP(char *host, struct in_addr *Dest_IP)
 
-{ int addr;         /* Assumes IP4, 32 bit network addresses */
-  struct hostent *hp;
-
-        /* Use inet_addr to try to convert the address */
-
-  if ((addr = ip_getaddr(host)) == INADDR_NONE) { /* Not in DNS */
-
-        /* Try NetBIOS name lookup, how the hell do we do that? */
-
-      RFCNB_errno = RFCNBE_BadName;   /* Is this right? */
-      RFCNB_saved_errno = errno;
-      return(RFCNBE_Bad);
+{
+       lrad_ipaddr_t ipaddr;
 
-  }
-  else { /* We got an IP address */
+       if (ip_hton(host, AF_INET, &ipaddr) < 0) {
+               /* Try NetBIOS name lookup, how the hell do we do that? */
 
-    memcpy((void *)Dest_IP, (void *)&addr, sizeof(struct in_addr));
+               RFCNB_errno = RFCNBE_BadName;   /* Is this right? */
+               RFCNB_saved_errno = errno;
+               return(RFCNBE_Bad);
 
-  }
-
-  return 0;
+       }
 
+       memcpy(Dest_IP, &ipaddr.ipaddr.ip4addr, sizeof(struct in_addr));
+       return 0;
 }
 
 /* Disconnect the TCP connection to the server */
@@ -404,7 +402,7 @@ int RFCNB_Session_Req(struct RFCNB_Con *con,
 
   /* Response packet should be no more than 9 bytes, make 16 jic */
 
-  char ln1[16], ln2[16], n1[32], n2[32], resp[16];
+  char resp[16];
   int len;
   struct RFCNB_Pkt *pkt, res_pkt;
 
@@ -513,12 +511,3 @@ int RFCNB_Session_Req(struct RFCNB_Con *con,
       break;
     }
 }
-
-
-
-
-
-
-
-
-
index b3f2315..d6e6cc7 100644 (file)
@@ -4,6 +4,7 @@
    RFCNB Utility Defines
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
@@ -23,6 +24,9 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(rfcnb_util_h, "$Id$")
+
 void RFCNB_CvtPad_Name(char *name1, char *name2);
 
 void RFCNB_AName_To_NBName(char *AName, char *NBName);
index 72a8cac..db00d99 100644 (file)
@@ -4,6 +4,7 @@
    RFCNB Defines
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
@@ -23,6 +24,9 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(rfcnb_h, "$Id$")
+
 /* Error responses */
 
 #include "rfcnb-error.h"
index fefc87d..c88eddc 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2002  The FreeRADIUS server project
+ * Copyright 2002,2006  The FreeRADIUS server project
  * Copyright 2002  Alan DeKok <aland@ox.org>
  */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/conffile.h>
 
 #include "valid.h"
 
-static const char rcsid[] = "$Id$";
-
 /*
  *     Define a structure for our module configuration.
  *
@@ -57,7 +57,7 @@ typedef struct rlm_smb_t {
  *     to the strdup'd string into 'config.string'.  This gets around
  *     buffer over-flows.
  */
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
   { "server",  PW_TYPE_STRING_PTR, offsetof(rlm_smb_t,server), NULL,  NULL},
   { "backup",  PW_TYPE_STRING_PTR, offsetof(rlm_smb_t,backup), NULL,  NULL},
   { "domain",  PW_TYPE_STRING_PTR, offsetof(rlm_smb_t,domain), NULL,  NULL},
@@ -132,7 +132,7 @@ static int smb_authenticate(void *instance, REQUEST *request)
         *  Ensure that we're being passed a plain-text password,
         *  and not anything else.
         */
-       if (request->password->attribute != PW_PASSWORD) {
+       if (request->password->attribute != PW_USER_PASSWORD) {
                radlog(L_AUTH, "rlm_smb: Attribute \"User-Password\" is required for authentication.  Cannot use \"%s\".", request->password->name);
                return RLM_MODULE_INVALID;
        }
@@ -140,8 +140,8 @@ static int smb_authenticate(void *instance, REQUEST *request)
        /*
         *  Call the SMB magic to do the work.
         */
-       rcode = Valid_User(request->username->strvalue,
-                          request->password->strvalue,
+       rcode = Valid_User(request->username->vp_strvalue,
+                          request->password->vp_strvalue,
                           data->server, data->backup, data->domain);
 
        switch (rcode) {
@@ -168,9 +168,6 @@ static int smb_detach(void *instance)
 {
        rlm_smb_t *data = (rlm_smb_t *) instance;
 
-       if (data->server) free(data->server);
-       if (data->backup) free(data->backup);
-       if (data->domain) free(data->domain);
 
        free(instance);
        return 0;
@@ -186,10 +183,11 @@ static int smb_detach(void *instance)
  *     is single-threaded.
  */
 module_t rlm_smb = {
+       RLM_MODULE_INIT,
        "SMB",
        RLM_TYPE_THREAD_UNSAFE,         /* type */
-       NULL,                           /* initialization */
        smb_instantiate,                /* instantiation */
+       smb_detach,                     /* detach */
        {
                smb_authenticate,       /* authentication */
                NULL,                   /* authorization */
@@ -200,6 +198,4 @@ module_t rlm_smb = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       smb_detach,                     /* detach */
-       NULL,                           /* destroy */
 };
index e7c891a..ed6aa2b 100644 (file)
@@ -4,6 +4,7 @@
    Session Routines ...
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
@@ -23,6 +24,9 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <string.h>
 
 int RFCNB_errno = 0;
@@ -228,7 +232,8 @@ int RFCNB_Send(struct RFCNB_Con *Con_Handle, struct RFCNB_Pkt *udata, int Length
 
 int RFCNB_Recv(void *con_Handle, struct RFCNB_Pkt *Data, int Length)
 
-{ struct RFCNB_Pkt *pkt; struct RFCNB_Hdr *hdr;
+{
+  struct RFCNB_Pkt *pkt;
   int ret_len;
 
   if (con_Handle == NULL){
index 93fa330..045cc3d 100644 (file)
@@ -6,6 +6,7 @@
    SMB authentication protocol
 
    Copyright (C) Andrew Tridgell 1997
+   Copyright 2006 The FreeRADIUS server project
 
    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
@@ -45,6 +46,9 @@
    up with a different answer to the one above)
 */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 
 
 static int perm1[56] = {57, 49, 41, 33, 25, 17,  9,
index 7bb1969..601e905 100644 (file)
@@ -4,6 +4,7 @@
    SMB parameters and setup
    Copyright (C) Andrew Tridgell 1992-1997
    Modified by Jeremy Allison 1995.
+   Copyright 2006 The FreeRADIUS server project
 
    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
@@ -20,6 +21,9 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include "smblib-priv.h"
 #define uchar unsigned char
 extern int DEBUGLEVEL;
@@ -33,7 +37,6 @@ extern int DEBUGLEVEL;
 
 #include "byteorder.h"
 
-char *StrnCpy(char *dest,char *src,int n);
 void strupper(char *s);
 
 /*
@@ -46,7 +49,7 @@ void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24)
 
   memset(p21,'\0',21);
   memset(p14,'\0',14);
-  StrnCpy((char *)p14,(char *)passwd,14);
+  strlcpy((char *)p14,(char *)passwd,14);
 
   strupper((char *)p14);
   E_P16(p14, p21);
@@ -124,7 +127,7 @@ void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24)
 void nt_lm_owf_gen(char *pwd, char *nt_p16, char *p16)
 {
        char passwd[130];
-       StrnCpy(passwd, pwd, sizeof(passwd)-1);
+       strlcpy(passwd, pwd, sizeof(passwd));
 
        /* Calculate the MD4 hash (NT compatible) of the password */
        memset(nt_p16, '\0', 16);
@@ -143,22 +146,6 @@ void nt_lm_owf_gen(char *pwd, char *nt_p16, char *p16)
        bzero(passwd, sizeof(passwd));
 }
 
-/****************************************************************************
-line strncpy but always null terminates. Make sure there is room!
-****************************************************************************/
-char *StrnCpy(char *dest,char *src,int n)
-{
-  char *d = dest;
-  if (!dest) return(NULL);
-  if (!src) {
-    *dest = 0;
-    return(dest);
-  }
-  while (n-- && (*d++ = *src++)) ;
-  *d = 0;
-  return(dest);
-}
-
 void strupper(char *s)
 {
   while (*s)
index ff2a160..13751f6 100644 (file)
@@ -4,6 +4,7 @@
    SMBlib Common Defines
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
@@ -23,6 +24,9 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(smblib_common_h, "$Id$")
+
 /* To get the error class we want the first 8 bits */
 /* Because we just grab 4bytes from the SMB header, we have to re-order */
 /* here, but it makes the NtStatus part easier in future                */
index 2f530d8..34ee24e 100644 (file)
@@ -4,6 +4,7 @@
    SMBlib private Defines
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
@@ -23,6 +24,9 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(smblib_priv_h, "$Id$")
+
 #include "std-includes.h"
 #include "smblib-common.h"
 
index 6f62971..61f3871 100644 (file)
@@ -4,6 +4,7 @@
    SMBlib Utility Routines
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include "smblib-priv.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
+#include <string.h>
+#include "smblib-priv.h"
 #include "rfcnb.h"
 
 /* Print out an SMB pkt in all its gory detail ... */
@@ -196,8 +200,7 @@ int SMB_Figure_Protocol(char *dialects[], int prot_index)
 
 int SMB_Negotiate(SMB_Handle_Type Con_Handle, char *Prots[])
 
-{ struct SMB_Neg_Prot_Def *prot_pkt;
-  struct SMB_Neg_Prot_Resp_Def *resp_pkt;
+{
   struct RFCNB_Pkt *pkt;
   int prots_len, i, pkt_len, prot, alloc_len;
   char *p;
@@ -356,7 +359,7 @@ int SMB_Negotiate(SMB_Handle_Type Con_Handle, char *Prots[])
     Con_Handle -> Encrypt_Key_Len = SVAL(SMB_Hdr(pkt), SMB_negrLM_ekl_offset);
 
     p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset);
-    fprintf(stderr, "%d", (char *)(SMB_Hdr(pkt) + SMB_negrLM_buf_offset));
+    fprintf(stderr, "%s", (char *)(SMB_Hdr(pkt) + SMB_negrLM_buf_offset));
     memcpy(Con_Handle->Encrypt_Key, p, 8);
 
     p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset + Con_Handle -> Encrypt_Key_Len);
@@ -410,8 +413,7 @@ int SMB_Negotiate(SMB_Handle_Type Con_Handle, char *Prots[])
 
 void SMB_Get_My_Name(char *name, int len)
 
-{ int loc;
-
+{
   if (gethostname(name, len) < 0) { /* Error getting name */
 
     strncpy(name, "unknown", len);
@@ -438,8 +440,9 @@ SMB_Tree_Handle SMB_TreeConnect(SMB_Handle_Type Con_Handle,
                                char *password,
                                char *device)
 
-{ struct RFCNB_Pkt *pkt;
-  int param_len, i, pkt_len;
+{
+  struct RFCNB_Pkt *pkt;
+  int param_len, pkt_len;
   char *p;
   SMB_Tree_Handle tree;
 
@@ -587,8 +590,8 @@ SMB_Tree_Handle SMB_TreeConnect(SMB_Handle_Type Con_Handle,
 
   if (Con_Handle -> first_tree == NULL) {
 
-    Con_Handle -> first_tree == tree;
-    Con_Handle -> last_tree == tree;
+    Con_Handle -> first_tree = tree;
+    Con_Handle -> last_tree = tree;
 
   }
   else {
index 42640ce..b41ccf0 100644 (file)
@@ -4,6 +4,7 @@
    SMBlib Routines
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-int SMBlib_errno;
-int SMBlib_SMB_Error;
-#define SMBLIB_ERRNO
-#define uchar unsigned char
-#include "smblib-priv.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
+#include <ctype.h>
+#include <string.h>
+#include "smblib-priv.h"
 #include "rfcnb.h"
 
+#define SMBLIB_ERRNO
+#define uchar unsigned char
+
+int SMBlib_errno;
+int SMBlib_SMB_Error;
 SMB_State_Types SMBlib_State;
 
 /* Initialize the SMBlib package     */
@@ -104,8 +110,9 @@ int SMBlib_Set_Sock_NoDelay(SMB_Handle_Type Con_Handle, BOOL yn)
 SMB_Handle_Type SMB_Connect_Server(SMB_Handle_Type Con_Handle,
                                   char *server, char *NTdomain)
 
-{ SMB_Handle_Type con;
-  char temp[80], called[80], calling[80], *address;
+{
+  SMB_Handle_Type con;
+  char called[80], calling[80], *address;
   int i;
 
   /* Get a connection structure if one does not exist */
@@ -314,8 +321,9 @@ SMB_Handle_Type SMB_Connect(SMB_Handle_Type Con_Handle,
 int SMB_Logon_Server(SMB_Handle_Type Con_Handle, char *UserName,
                     char *PassWord)
 
-{ struct RFCNB_Pkt *pkt;
-  int param_len, i, pkt_len, pass_len,a;
+{
+  struct RFCNB_Pkt *pkt;
+  int param_len, pkt_len, pass_len;
   char *p, pword[256];
 
   /* First we need a packet etc ... but we need to know what protocol has  */
index 0d6428a..67b5b9e 100644 (file)
@@ -4,6 +4,7 @@
    SMBlib Defines
 
    Copyright (C) Richard Sharpe 1996
+   Copyright 2006 The FreeRADIUS server project
 
 */
 
@@ -23,6 +24,9 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(smblib_h, "$Id$")
+
 #include "std-defines.h"
 #include "smblib-common.h"
 
index c999879..1558097 100644 (file)
@@ -4,6 +4,7 @@
    RFCNB Standard Includes
 
    Copyright (C) 1996, Richard Sharpe
+   Copyright 2006 The FreeRADIUS server project
 
    One day we will conditionalize these on OS types ...
 
@@ -22,6 +23,9 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <freeradius-devel/ident.h>
+RCSIDH(std_includes_h, "$Id$")
+
 #include "config.h"
 
 #define BOOL int
index f3b00c0..98ada35 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
 #include <sys/types.h>
 #include <unistd.h>
 #include <syslog.h>
index 00d068b..25c132e 100644 (file)
@@ -1,5 +1,11 @@
+/* Copyright 2006 The FreeRADIUS server project */
+
 #ifndef _VALID_H_
 #define _VALID_H_
+
+#include <freeradius-devel/ident.h>
+RCSIDH(valid_h, "$Id$")
+
 /* SMB User verification function */
 
 #define NTV_NO_ERROR 0
index c93be92..3235dab 100644 (file)
@@ -8,6 +8,9 @@
 *                                     Mike Machado <mike@innercite.com>    *
 ***************************************************************************/
 
+#include <freeradius-devel/ident.h>
+RCSIDH(conf_h, "$Id$")
+
 typedef struct sql_config {
        char   *sql_driver;
        char   *sql_server;
@@ -15,9 +18,9 @@ typedef struct sql_config {
        char   *sql_login;
        char   *sql_password;
        char   *sql_db;
-       char   *sql_nas_table;
        char   *query_user;
        char   *default_profile;
+       char   *nas_query;
        char   *authorize_check_query;
        char   *authorize_reply_query;
        char   *authorize_group_check_query;
@@ -34,12 +37,12 @@ typedef struct sql_config {
        char   *groupmemb_query;
        int     sqltrace;
        int     do_clients;
+       int     read_groups;
        char   *tracefile;
        char   *xlat_name;
        int     deletestalesessions;
        int     num_sql_socks;
        int     connect_failure_retry_delay;
-       int     query_on_not_found;
        char   *postauth_query;
        char   *allowed_chars;
 
index eef807e..5b5c322 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.2 .
+# From configure.in Revision: 1.3 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -902,7 +902,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1825,8 +1825,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1884,8 +1883,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2001,8 +1999,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2056,8 +2053,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2102,8 +2098,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2147,8 +2142,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3106,11 +3100,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3149,6 +3138,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
@@ -3380,7 +3375,7 @@ echo "$as_me: error: $ac_sub_configure failed for $ac_dir" >&2;}
    { (exit 1); exit 1; }; }
     fi
 
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
index b7bac8f..e76e93d 100644 (file)
@@ -1,3 +1,4 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_sql.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_sql])
index fb3f562..4660942 100755 (executable)
@@ -908,7 +908,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1826,8 +1826,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1885,8 +1884,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2002,8 +2000,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2057,8 +2054,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2103,8 +2099,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2148,8 +2143,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2481,8 +2475,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2533,8 +2526,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2604,8 +2596,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3472,11 +3463,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3515,6 +3501,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index b0e7ff8..e903062 100644 (file)
@@ -15,9 +15,9 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Mike Machado <mike@innercite.com>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  * Copyright 2001  Joerg Wendland <wendland@scan-plus.de>
  * by Joerg Wendland <wendland@scan-plus.de>
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
 #include <stdio.h>
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "radiusd.h"
+#include <freeradius-devel/radiusd.h>
 #include <sql.h>
 #include <sqlcli.h>
 #include "rlm_sql.h"
diff --git a/src/modules/rlm_sql/drivers/rlm_sql_firebird/Makefile.in b/src/modules/rlm_sql/drivers/rlm_sql_firebird/Makefile.in
deleted file mode 100644 (file)
index f2a87ed..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-include ../../../../../Make.inc
-
-TARGET         = @targetname@
-SRCS           = sql_firebird.c sql_fbapi.c
-RLM_SQL_CFLAGS = @sql_firebird_cflags@ $(INCLTDL)
-RLM_SQL_LIBS   = @sql_firebird_ldflags@
-
-include ../rules.mak
diff --git a/src/modules/rlm_sql/drivers/rlm_sql_firebird/configure b/src/modules/rlm_sql/drivers/rlm_sql_firebird/configure
deleted file mode 100755 (executable)
index 0477319..0000000
+++ /dev/null
@@ -1,3575 +0,0 @@
-#! /bin/sh
-# From configure.in Revision: 1.1 .
-# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59.
-#
-# Copyright (C) 2003 Free Software Foundation, Inc.
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-## --------------------- ##
-## M4sh Initialization.  ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
-  set -o posix
-fi
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
-  as_unset=unset
-else
-  as_unset=false
-fi
-
-
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
-  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
-  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
-  LC_TELEPHONE LC_TIME
-do
-  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
-    eval $as_var=C; export $as_var
-  else
-    $as_unset $as_var
-  fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
-  as_basename=basename
-else
-  as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
-        X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)$' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
-         /^X\/\(\/\/\)$/{ s//\1/; q; }
-         /^X\/\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-
-
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
-fi
-
-
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
-  # Find who we are.  Look in the path if we contain no path at all
-  # relative or not.
-  case $0 in
-    *[\\/]* ) as_myself=$0 ;;
-    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
-       ;;
-  esac
-  # We did not find ourselves, most probably we were run as `sh COMMAND'
-  # in which case we are not to be found in the path.
-  if test "x$as_myself" = x; then
-    as_myself=$0
-  fi
-  if test ! -f "$as_myself"; then
-    { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
-   { (exit 1); exit 1; }; }
-  fi
-  case $CONFIG_SHELL in
-  '')
-    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for as_base in sh bash ksh sh5; do
-        case $as_dir in
-        /*)
-          if ("$as_dir/$as_base" -c '
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
-            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
-            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
-            CONFIG_SHELL=$as_dir/$as_base
-            export CONFIG_SHELL
-            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
-          fi;;
-        esac
-       done
-done
-;;
-  esac
-
-  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
-  # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line before each line; the second 'sed' does the real
-  # work.  The second script uses 'N' to pair each line-number line
-  # with the numbered line, and appends trailing '-' during
-  # substitution so that $LINENO is not a special case at line end.
-  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
-  sed '=' <$as_myself |
-    sed '
-      N
-      s,$,-,
-      : loop
-      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
-      t loop
-      s,-$,,
-      s,^['$as_cr_digits']*\n,,
-    ' >$as_me.lineno &&
-  chmod +x $as_me.lineno ||
-    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
-   { (exit 1); exit 1; }; }
-
-  # Don't try to exec as it changes $[0], causing all sort of problems
-  # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensible to this).
-  . ./$as_me.lineno
-  # Exit status is that of the last command.
-  exit
-}
-
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
-  *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T='     ' ;;
-  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
-  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
-  # We could just check for DJGPP; but this test a) works b) is more generic
-  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
-  if test -f conf$$.exe; then
-    # Don't use ln at all; we don't have any links
-    as_ln_s='cp -p'
-  else
-    as_ln_s='ln -s'
-  fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s=ln
-else
-  as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.file
-
-if mkdir -p . 2>/dev/null; then
-  as_mkdir_p=:
-else
-  test -d ./-p && rmdir ./-p
-  as_mkdir_p=false
-fi
-
-as_executable_p="test -f"
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS="  $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
-
-# Name of the host.
-# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
-# so uname gets run too.
-ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
-
-exec 6>&1
-
-#
-# Initializations.
-#
-ac_default_prefix=/usr/local
-ac_config_libobj_dir=.
-cross_compiling=no
-subdirs=
-MFLAGS=
-MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-
-# Maximum number of lines to put in a shell here document.
-# This variable seems obsolete.  It should probably be removed, and
-# only ac_max_sed_lines should be used.
-: ${ac_max_here_lines=38}
-
-# Identity of this package.
-PACKAGE_NAME=
-PACKAGE_TARNAME=
-PACKAGE_VERSION=
-PACKAGE_STRING=
-PACKAGE_BUGREPORT=
-
-ac_unique_file="sql_firebird.c"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP sql_firebird_ldflags sql_firebird_cflags targetname LIBOBJS LTLIBOBJS'
-ac_subst_files=''
-
-# Initialize some variables set by options.
-ac_init_help=
-ac_init_version=false
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-cache_file=/dev/null
-exec_prefix=NONE
-no_create=
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-verbose=
-x_includes=NONE
-x_libraries=NONE
-
-# Installation directory options.
-# These are left unexpanded so users can "make install exec_prefix=/foo"
-# and all the variables that are supposed to be based on exec_prefix
-# by default will actually change.
-# Use braces instead of parens because sh, perl, etc. also accept them.
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-libdir='${exec_prefix}/lib'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-infodir='${prefix}/info'
-mandir='${prefix}/man'
-
-ac_prev=
-for ac_option
-do
-  # If the previous option needs an argument, assign it.
-  if test -n "$ac_prev"; then
-    eval "$ac_prev=\$ac_option"
-    ac_prev=
-    continue
-  fi
-
-  ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
-
-  # Accept the important Cygnus configure options, so we can diagnose typos.
-
-  case $ac_option in
-
-  -bindir | --bindir | --bindi | --bind | --bin | --bi)
-    ac_prev=bindir ;;
-  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
-    bindir=$ac_optarg ;;
-
-  -build | --build | --buil | --bui | --bu)
-    ac_prev=build_alias ;;
-  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
-    build_alias=$ac_optarg ;;
-
-  -cache-file | --cache-file | --cache-fil | --cache-fi \
-  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
-    ac_prev=cache_file ;;
-  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
-  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
-    cache_file=$ac_optarg ;;
-
-  --config-cache | -C)
-    cache_file=config.cache ;;
-
-  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
-    ac_prev=datadir ;;
-  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
-  | --da=*)
-    datadir=$ac_optarg ;;
-
-  -disable-* | --disable-*)
-    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
-   { (exit 1); exit 1; }; }
-    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
-    eval "enable_$ac_feature=no" ;;
-
-  -enable-* | --enable-*)
-    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid feature name: $ac_feature" >&2
-   { (exit 1); exit 1; }; }
-    ac_feature=`echo $ac_feature | sed 's/-/_/g'`
-    case $ac_option in
-      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
-      *) ac_optarg=yes ;;
-    esac
-    eval "enable_$ac_feature='$ac_optarg'" ;;
-
-  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
-  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
-  | --exec | --exe | --ex)
-    ac_prev=exec_prefix ;;
-  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
-  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
-  | --exec=* | --exe=* | --ex=*)
-    exec_prefix=$ac_optarg ;;
-
-  -gas | --gas | --ga | --g)
-    # Obsolete; use --with-gas.
-    with_gas=yes ;;
-
-  -help | --help | --hel | --he | -h)
-    ac_init_help=long ;;
-  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
-    ac_init_help=recursive ;;
-  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
-    ac_init_help=short ;;
-
-  -host | --host | --hos | --ho)
-    ac_prev=host_alias ;;
-  -host=* | --host=* | --hos=* | --ho=*)
-    host_alias=$ac_optarg ;;
-
-  -includedir | --includedir | --includedi | --included | --include \
-  | --includ | --inclu | --incl | --inc)
-    ac_prev=includedir ;;
-  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
-  | --includ=* | --inclu=* | --incl=* | --inc=*)
-    includedir=$ac_optarg ;;
-
-  -infodir | --infodir | --infodi | --infod | --info | --inf)
-    ac_prev=infodir ;;
-  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
-    infodir=$ac_optarg ;;
-
-  -libdir | --libdir | --libdi | --libd)
-    ac_prev=libdir ;;
-  -libdir=* | --libdir=* | --libdi=* | --libd=*)
-    libdir=$ac_optarg ;;
-
-  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
-  | --libexe | --libex | --libe)
-    ac_prev=libexecdir ;;
-  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
-  | --libexe=* | --libex=* | --libe=*)
-    libexecdir=$ac_optarg ;;
-
-  -localstatedir | --localstatedir | --localstatedi | --localstated \
-  | --localstate | --localstat | --localsta | --localst \
-  | --locals | --local | --loca | --loc | --lo)
-    ac_prev=localstatedir ;;
-  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
-  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
-  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
-    localstatedir=$ac_optarg ;;
-
-  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
-    ac_prev=mandir ;;
-  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
-    mandir=$ac_optarg ;;
-
-  -nfp | --nfp | --nf)
-    # Obsolete; use --without-fp.
-    with_fp=no ;;
-
-  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
-  | --no-cr | --no-c | -n)
-    no_create=yes ;;
-
-  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
-  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
-    no_recursion=yes ;;
-
-  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
-  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
-  | --oldin | --oldi | --old | --ol | --o)
-    ac_prev=oldincludedir ;;
-  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
-  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
-  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
-    oldincludedir=$ac_optarg ;;
-
-  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
-    ac_prev=prefix ;;
-  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
-    prefix=$ac_optarg ;;
-
-  -program-prefix | --program-prefix | --program-prefi | --program-pref \
-  | --program-pre | --program-pr | --program-p)
-    ac_prev=program_prefix ;;
-  -program-prefix=* | --program-prefix=* | --program-prefi=* \
-  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
-    program_prefix=$ac_optarg ;;
-
-  -program-suffix | --program-suffix | --program-suffi | --program-suff \
-  | --program-suf | --program-su | --program-s)
-    ac_prev=program_suffix ;;
-  -program-suffix=* | --program-suffix=* | --program-suffi=* \
-  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
-    program_suffix=$ac_optarg ;;
-
-  -program-transform-name | --program-transform-name \
-  | --program-transform-nam | --program-transform-na \
-  | --program-transform-n | --program-transform- \
-  | --program-transform | --program-transfor \
-  | --program-transfo | --program-transf \
-  | --program-trans | --program-tran \
-  | --progr-tra | --program-tr | --program-t)
-    ac_prev=program_transform_name ;;
-  -program-transform-name=* | --program-transform-name=* \
-  | --program-transform-nam=* | --program-transform-na=* \
-  | --program-transform-n=* | --program-transform-=* \
-  | --program-transform=* | --program-transfor=* \
-  | --program-transfo=* | --program-transf=* \
-  | --program-trans=* | --program-tran=* \
-  | --progr-tra=* | --program-tr=* | --program-t=*)
-    program_transform_name=$ac_optarg ;;
-
-  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-  | -silent | --silent | --silen | --sile | --sil)
-    silent=yes ;;
-
-  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
-    ac_prev=sbindir ;;
-  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
-  | --sbi=* | --sb=*)
-    sbindir=$ac_optarg ;;
-
-  -sharedstatedir | --sharedstatedir | --sharedstatedi \
-  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
-  | --sharedst | --shareds | --shared | --share | --shar \
-  | --sha | --sh)
-    ac_prev=sharedstatedir ;;
-  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
-  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
-  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
-  | --sha=* | --sh=*)
-    sharedstatedir=$ac_optarg ;;
-
-  -site | --site | --sit)
-    ac_prev=site ;;
-  -site=* | --site=* | --sit=*)
-    site=$ac_optarg ;;
-
-  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
-    ac_prev=srcdir ;;
-  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
-    srcdir=$ac_optarg ;;
-
-  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
-  | --syscon | --sysco | --sysc | --sys | --sy)
-    ac_prev=sysconfdir ;;
-  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
-  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
-    sysconfdir=$ac_optarg ;;
-
-  -target | --target | --targe | --targ | --tar | --ta | --t)
-    ac_prev=target_alias ;;
-  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
-    target_alias=$ac_optarg ;;
-
-  -v | -verbose | --verbose | --verbos | --verbo | --verb)
-    verbose=yes ;;
-
-  -version | --version | --versio | --versi | --vers | -V)
-    ac_init_version=: ;;
-
-  -with-* | --with-*)
-    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid package name: $ac_package" >&2
-   { (exit 1); exit 1; }; }
-    ac_package=`echo $ac_package| sed 's/-/_/g'`
-    case $ac_option in
-      *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
-      *) ac_optarg=yes ;;
-    esac
-    eval "with_$ac_package='$ac_optarg'" ;;
-
-  -without-* | --without-*)
-    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid package name: $ac_package" >&2
-   { (exit 1); exit 1; }; }
-    ac_package=`echo $ac_package | sed 's/-/_/g'`
-    eval "with_$ac_package=no" ;;
-
-  --x)
-    # Obsolete; use --with-x.
-    with_x=yes ;;
-
-  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
-  | --x-incl | --x-inc | --x-in | --x-i)
-    ac_prev=x_includes ;;
-  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
-  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
-    x_includes=$ac_optarg ;;
-
-  -x-libraries | --x-libraries | --x-librarie | --x-librari \
-  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
-    ac_prev=x_libraries ;;
-  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
-  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
-    x_libraries=$ac_optarg ;;
-
-  -*) { echo "$as_me: error: unrecognized option: $ac_option
-Try \`$0 --help' for more information." >&2
-   { (exit 1); exit 1; }; }
-    ;;
-
-  *=*)
-    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
-    # Reject names that are not valid shell variable names.
-    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
-      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
-   { (exit 1); exit 1; }; }
-    ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
-    eval "$ac_envvar='$ac_optarg'"
-    export $ac_envvar ;;
-
-  *)
-    # FIXME: should be removed in autoconf 3.0.
-    echo "$as_me: WARNING: you should use --build, --host, --target" >&2
-    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
-      echo "$as_me: WARNING: invalid host type: $ac_option" >&2
-    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
-    ;;
-
-  esac
-done
-
-if test -n "$ac_prev"; then
-  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
-  { echo "$as_me: error: missing argument to $ac_option" >&2
-   { (exit 1); exit 1; }; }
-fi
-
-# Be sure to have absolute paths.
-for ac_var in exec_prefix prefix
-do
-  eval ac_val=$`echo $ac_var`
-  case $ac_val in
-    [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
-    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
-   { (exit 1); exit 1; }; };;
-  esac
-done
-
-# Be sure to have absolute paths.
-for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
-             localstatedir libdir includedir oldincludedir infodir mandir
-do
-  eval ac_val=$`echo $ac_var`
-  case $ac_val in
-    [\\/$]* | ?:[\\/]* ) ;;
-    *)  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
-   { (exit 1); exit 1; }; };;
-  esac
-done
-
-# There might be people who depend on the old broken behavior: `$host'
-# used to hold the argument of --host etc.
-# FIXME: To remove some day.
-build=$build_alias
-host=$host_alias
-target=$target_alias
-
-# FIXME: To remove some day.
-if test "x$host_alias" != x; then
-  if test "x$build_alias" = x; then
-    cross_compiling=maybe
-    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
-    If a cross compiler is detected then cross compile mode will be used." >&2
-  elif test "x$build_alias" != "x$host_alias"; then
-    cross_compiling=yes
-  fi
-fi
-
-ac_tool_prefix=
-test -n "$host_alias" && ac_tool_prefix=$host_alias-
-
-test "$silent" = yes && exec 6>/dev/null
-
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
-  ac_srcdir_defaulted=yes
-  # Try the directory containing this script, then its parent.
-  ac_confdir=`(dirname "$0") 2>/dev/null ||
-$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$0" : 'X\(//\)[^/]' \| \
-        X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X"$0" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-         /^X\(\/\/\)$/{ s//\1/; q; }
-         /^X\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-  srcdir=$ac_confdir
-  if test ! -r $srcdir/$ac_unique_file; then
-    srcdir=..
-  fi
-else
-  ac_srcdir_defaulted=no
-fi
-if test ! -r $srcdir/$ac_unique_file; then
-  if test "$ac_srcdir_defaulted" = yes; then
-    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
-   { (exit 1); exit 1; }; }
-  else
-    { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
-   { (exit 1); exit 1; }; }
-  fi
-fi
-(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
-  { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
-   { (exit 1); exit 1; }; }
-srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
-ac_env_build_alias_set=${build_alias+set}
-ac_env_build_alias_value=$build_alias
-ac_cv_env_build_alias_set=${build_alias+set}
-ac_cv_env_build_alias_value=$build_alias
-ac_env_host_alias_set=${host_alias+set}
-ac_env_host_alias_value=$host_alias
-ac_cv_env_host_alias_set=${host_alias+set}
-ac_cv_env_host_alias_value=$host_alias
-ac_env_target_alias_set=${target_alias+set}
-ac_env_target_alias_value=$target_alias
-ac_cv_env_target_alias_set=${target_alias+set}
-ac_cv_env_target_alias_value=$target_alias
-ac_env_CC_set=${CC+set}
-ac_env_CC_value=$CC
-ac_cv_env_CC_set=${CC+set}
-ac_cv_env_CC_value=$CC
-ac_env_CFLAGS_set=${CFLAGS+set}
-ac_env_CFLAGS_value=$CFLAGS
-ac_cv_env_CFLAGS_set=${CFLAGS+set}
-ac_cv_env_CFLAGS_value=$CFLAGS
-ac_env_LDFLAGS_set=${LDFLAGS+set}
-ac_env_LDFLAGS_value=$LDFLAGS
-ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
-ac_cv_env_LDFLAGS_value=$LDFLAGS
-ac_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_env_CPPFLAGS_value=$CPPFLAGS
-ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
-ac_cv_env_CPPFLAGS_value=$CPPFLAGS
-ac_env_CPP_set=${CPP+set}
-ac_env_CPP_value=$CPP
-ac_cv_env_CPP_set=${CPP+set}
-ac_cv_env_CPP_value=$CPP
-
-#
-# Report the --help message.
-#
-if test "$ac_init_help" = "long"; then
-  # Omit some internal or obsolete options to make the list less imposing.
-  # This message is too long to be a string in the A/UX 3.1 sh.
-  cat <<_ACEOF
-\`configure' configures this package to adapt to many kinds of systems.
-
-Usage: $0 [OPTION]... [VAR=VALUE]...
-
-To assign environment variables (e.g., CC, CFLAGS...), specify them as
-VAR=VALUE.  See below for descriptions of some of the useful variables.
-
-Defaults for the options are specified in brackets.
-
-Configuration:
-  -h, --help              display this help and exit
-      --help=short        display options specific to this package
-      --help=recursive    display the short help of all the included packages
-  -V, --version           display version information and exit
-  -q, --quiet, --silent   do not print \`checking...' messages
-      --cache-file=FILE   cache test results in FILE [disabled]
-  -C, --config-cache      alias for \`--cache-file=config.cache'
-  -n, --no-create         do not create output files
-      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
-
-_ACEOF
-
-  cat <<_ACEOF
-Installation directories:
-  --prefix=PREFIX         install architecture-independent files in PREFIX
-                         [$ac_default_prefix]
-  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
-                         [PREFIX]
-
-By default, \`make install' will install all the files in
-\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
-an installation prefix other than \`$ac_default_prefix' using \`--prefix',
-for instance \`--prefix=\$HOME'.
-
-For better control, use the options below.
-
-Fine tuning of the installation directories:
-  --bindir=DIR           user executables [EPREFIX/bin]
-  --sbindir=DIR          system admin executables [EPREFIX/sbin]
-  --libexecdir=DIR       program executables [EPREFIX/libexec]
-  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
-  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
-  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]
-  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]
-  --libdir=DIR           object code libraries [EPREFIX/lib]
-  --includedir=DIR       C header files [PREFIX/include]
-  --oldincludedir=DIR    C header files for non-gcc [/usr/include]
-  --infodir=DIR          info documentation [PREFIX/info]
-  --mandir=DIR           man documentation [PREFIX/man]
-_ACEOF
-
-  cat <<\_ACEOF
-_ACEOF
-fi
-
-if test -n "$ac_init_help"; then
-
-  cat <<\_ACEOF
-
-Optional Packages:
-  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
-  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
-  --with-firebird-include-dir=DIR       Directory where the firebird includes may be found
-  --with-firebird-lib-dir=DIR       Directory where the firebird libraries may be found
-  --with-firebird-dir=DIR       Base directory where firebird is installed
-
-Some influential environment variables:
-  CC          C compiler command
-  CFLAGS      C compiler flags
-  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
-              nonstandard directory <lib dir>
-  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
-              headers in a nonstandard directory <include dir>
-  CPP         C preprocessor
-
-Use these variables to override the choices made by `configure' or to help
-it to find libraries and programs with nonstandard names/locations.
-
-_ACEOF
-fi
-
-if test "$ac_init_help" = "recursive"; then
-  # If there are subdirs, report their specific --help.
-  ac_popdir=`pwd`
-  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
-    test -d $ac_dir || continue
-    ac_builddir=.
-
-if test "$ac_dir" != .; then
-  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A "../" for each directory in $ac_dir_suffix.
-  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
-  ac_dir_suffix= ac_top_builddir=
-fi
-
-case $srcdir in
-  .)  # No --srcdir option.  We are building in place.
-    ac_srcdir=.
-    if test -z "$ac_top_builddir"; then
-       ac_top_srcdir=.
-    else
-       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
-    fi ;;
-  [\\/]* | ?:[\\/]* )  # Absolute path.
-    ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir ;;
-  *) # Relative path.
-    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
-  case "$ac_dir" in
-  .) ac_abs_builddir=`pwd`;;
-  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
-  *) ac_abs_builddir=`pwd`/"$ac_dir";;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
-  case ${ac_top_builddir}. in
-  .) ac_abs_top_builddir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
-  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
-  case $ac_srcdir in
-  .) ac_abs_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
-  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
-  case $ac_top_srcdir in
-  .) ac_abs_top_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
-  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
-  esac;;
-esac
-
-    cd $ac_dir
-    # Check for guested configure; otherwise get Cygnus style configure.
-    if test -f $ac_srcdir/configure.gnu; then
-      echo
-      $SHELL $ac_srcdir/configure.gnu  --help=recursive
-    elif test -f $ac_srcdir/configure; then
-      echo
-      $SHELL $ac_srcdir/configure  --help=recursive
-    elif test -f $ac_srcdir/configure.ac ||
-          test -f $ac_srcdir/configure.in; then
-      echo
-      $ac_configure --help
-    else
-      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
-    fi
-    cd $ac_popdir
-  done
-fi
-
-test -n "$ac_init_help" && exit 0
-if $ac_init_version; then
-  cat <<\_ACEOF
-
-Copyright (C) 2003 Free Software Foundation, Inc.
-This configure script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it.
-_ACEOF
-  exit 0
-fi
-exec 5>config.log
-cat >&5 <<_ACEOF
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-
-It was created by $as_me, which was
-generated by GNU Autoconf 2.59.  Invocation command line was
-
-  $ $0 $@
-
-_ACEOF
-{
-cat <<_ASUNAME
-## --------- ##
-## Platform. ##
-## --------- ##
-
-hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
-uname -m = `(uname -m) 2>/dev/null || echo unknown`
-uname -r = `(uname -r) 2>/dev/null || echo unknown`
-uname -s = `(uname -s) 2>/dev/null || echo unknown`
-uname -v = `(uname -v) 2>/dev/null || echo unknown`
-
-/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
-/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
-
-/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
-/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
-/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
-hostinfo               = `(hostinfo) 2>/dev/null               || echo unknown`
-/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
-/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
-/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
-
-_ASUNAME
-
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  echo "PATH: $as_dir"
-done
-
-} >&5
-
-cat >&5 <<_ACEOF
-
-
-## ----------- ##
-## Core tests. ##
-## ----------- ##
-
-_ACEOF
-
-
-# Keep a trace of the command line.
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Strip out --silent because we don't want to record it for future runs.
-# Also quote any args containing shell meta-characters.
-# Make two passes to allow for proper duplicate-argument suppression.
-ac_configure_args=
-ac_configure_args0=
-ac_configure_args1=
-ac_sep=
-ac_must_keep_next=false
-for ac_pass in 1 2
-do
-  for ac_arg
-  do
-    case $ac_arg in
-    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
-    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-    | -silent | --silent | --silen | --sile | --sil)
-      continue ;;
-    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
-      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
-    esac
-    case $ac_pass in
-    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
-    2)
-      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
-      if test $ac_must_keep_next = true; then
-       ac_must_keep_next=false # Got value, back to normal.
-      else
-       case $ac_arg in
-         *=* | --config-cache | -C | -disable-* | --disable-* \
-         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
-         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
-         | -with-* | --with-* | -without-* | --without-* | --x)
-           case "$ac_configure_args0 " in
-             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
-           esac
-           ;;
-         -* ) ac_must_keep_next=true ;;
-       esac
-      fi
-      ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
-      # Get rid of the leading space.
-      ac_sep=" "
-      ;;
-    esac
-  done
-done
-$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
-$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
-
-# When interrupted or exit'd, cleanup temporary files, and complete
-# config.log.  We remove comments because anyway the quotes in there
-# would cause problems or look ugly.
-# WARNING: Be sure not to use single quotes in there, as some shells,
-# such as our DU 5.0 friend, will then `close' the trap.
-trap 'exit_status=$?
-  # Save into config.log some information that might help in debugging.
-  {
-    echo
-
-    cat <<\_ASBOX
-## ---------------- ##
-## Cache variables. ##
-## ---------------- ##
-_ASBOX
-    echo
-    # The following way of writing the cache mishandles newlines in values,
-{
-  (set) 2>&1 |
-    case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
-    *ac_space=\ *)
-      sed -n \
-       "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
-         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
-      ;;
-    *)
-      sed -n \
-       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
-      ;;
-    esac;
-}
-    echo
-
-    cat <<\_ASBOX
-## ----------------- ##
-## Output variables. ##
-## ----------------- ##
-_ASBOX
-    echo
-    for ac_var in $ac_subst_vars
-    do
-      eval ac_val=$`echo $ac_var`
-      echo "$ac_var='"'"'$ac_val'"'"'"
-    done | sort
-    echo
-
-    if test -n "$ac_subst_files"; then
-      cat <<\_ASBOX
-## ------------- ##
-## Output files. ##
-## ------------- ##
-_ASBOX
-      echo
-      for ac_var in $ac_subst_files
-      do
-       eval ac_val=$`echo $ac_var`
-       echo "$ac_var='"'"'$ac_val'"'"'"
-      done | sort
-      echo
-    fi
-
-    if test -s confdefs.h; then
-      cat <<\_ASBOX
-## ----------- ##
-## confdefs.h. ##
-## ----------- ##
-_ASBOX
-      echo
-      sed "/^$/d" confdefs.h | sort
-      echo
-    fi
-    test "$ac_signal" != 0 &&
-      echo "$as_me: caught signal $ac_signal"
-    echo "$as_me: exit $exit_status"
-  } >&5
-  rm -f core *.core &&
-  rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
-    exit $exit_status
-     ' 0
-for ac_signal in 1 2 13 15; do
-  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
-done
-ac_signal=0
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo >confdefs.h
-
-# Predefined preprocessor variables.
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
-
-
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
-
-
-# Let the site file select an alternate cache file if it wants to.
-# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
-  if test "x$prefix" != xNONE; then
-    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
-  else
-    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
-  fi
-fi
-for ac_site_file in $CONFIG_SITE; do
-  if test -r "$ac_site_file"; then
-    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
-echo "$as_me: loading site script $ac_site_file" >&6;}
-    sed 's/^/| /' "$ac_site_file" >&5
-    . "$ac_site_file"
-  fi
-done
-
-if test -r "$cache_file"; then
-  # Some versions of bash will fail to source /dev/null (special
-  # files actually), so we avoid doing that.
-  if test -f "$cache_file"; then
-    { echo "$as_me:$LINENO: loading cache $cache_file" >&5
-echo "$as_me: loading cache $cache_file" >&6;}
-    case $cache_file in
-      [\\/]* | ?:[\\/]* ) . $cache_file;;
-      *)                      . ./$cache_file;;
-    esac
-  fi
-else
-  { echo "$as_me:$LINENO: creating cache $cache_file" >&5
-echo "$as_me: creating cache $cache_file" >&6;}
-  >$cache_file
-fi
-
-# Check that the precious variables saved in the cache have kept the same
-# value.
-ac_cache_corrupted=false
-for ac_var in `(set) 2>&1 |
-              sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
-  eval ac_old_set=\$ac_cv_env_${ac_var}_set
-  eval ac_new_set=\$ac_env_${ac_var}_set
-  eval ac_old_val="\$ac_cv_env_${ac_var}_value"
-  eval ac_new_val="\$ac_env_${ac_var}_value"
-  case $ac_old_set,$ac_new_set in
-    set,)
-      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
-      ac_cache_corrupted=: ;;
-    ,set)
-      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
-echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
-      ac_cache_corrupted=: ;;
-    ,);;
-    *)
-      if test "x$ac_old_val" != "x$ac_new_val"; then
-       { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
-echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
-       { echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5
-echo "$as_me:   former value:  $ac_old_val" >&2;}
-       { echo "$as_me:$LINENO:   current value: $ac_new_val" >&5
-echo "$as_me:   current value: $ac_new_val" >&2;}
-       ac_cache_corrupted=:
-      fi;;
-  esac
-  # Pass precious variables to config.status.
-  if test "$ac_new_set" = set; then
-    case $ac_new_val in
-    *" "*|*"   "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
-      ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
-    *) ac_arg=$ac_var=$ac_new_val ;;
-    esac
-    case " $ac_configure_args " in
-      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
-      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
-    esac
-  fi
-done
-if $ac_cache_corrupted; then
-  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
-echo "$as_me: error: changes in the environment can compromise the build" >&2;}
-  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
-echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}gcc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_CC"; then
-  ac_ct_CC=$CC
-  # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="gcc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  CC=$ac_ct_CC
-else
-  CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
-  if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$ac_cv_prog_CC"; then
-  ac_ct_CC=$CC
-  # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  CC=$ac_ct_CC
-else
-  CC="$ac_cv_prog_CC"
-fi
-
-fi
-if test -z "$CC"; then
-  # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-  ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
-       ac_prog_rejected=yes
-       continue
-     fi
-    ac_cv_prog_CC="cc"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-if test $ac_prog_rejected = yes; then
-  # We found a bogon in the path, so make sure we never use it.
-  set dummy $ac_cv_prog_CC
-  shift
-  if test $# != 0; then
-    # We chose a different compiler from the bogus one.
-    # However, it has the same basename, so the bogon will be chosen
-    # first if we set CC to just the basename; use the full file name.
-    shift
-    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
-  fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-fi
-if test -z "$CC"; then
-  if test -n "$ac_tool_prefix"; then
-  for ac_prog in cl
-  do
-    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  echo "$as_me:$LINENO: result: $CC" >&5
-echo "${ECHO_T}$CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-    test -n "$CC" && break
-  done
-fi
-if test -z "$CC"; then
-  ac_ct_CC=$CC
-  for ac_prog in cl
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo "$as_me:$LINENO: checking for $ac_word" >&5
-echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
-if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for ac_exec_ext in '' $ac_executable_extensions; do
-  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="$ac_prog"
-    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-done
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
-echo "${ECHO_T}$ac_ct_CC" >&6
-else
-  echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-fi
-
-  test -n "$ac_ct_CC" && break
-done
-
-  CC=$ac_ct_CC
-fi
-
-fi
-
-
-test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&5
-echo "$as_me: error: no acceptable C compiler found in \$PATH
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-
-# Provide some information about the compiler.
-echo "$as_me:$LINENO:" \
-     "checking for C compiler version" >&5
-ac_compiler=`set X $ac_compile; echo $2`
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
-  (eval $ac_compiler --version </dev/null >&5) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
-  (eval $ac_compiler -v </dev/null >&5) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
-  (eval $ac_compiler -V </dev/null >&5) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files a.out a.exe b.out"
-# Try to create an executable without -o first, disregard a.out.
-# It will help us diagnose broken compilers, and finding out an intuition
-# of exeext.
-echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
-echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
-ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
-if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
-  (eval $ac_link_default) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  # Find the output, starting from the most likely.  This scheme is
-# not robust to junk in `.', hence go to wildcards (a.*) only as a last
-# resort.
-
-# Be careful to initialize this variable, since it used to be cached.
-# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
-ac_cv_exeext=
-# b.out is created by i960 compilers.
-for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
-do
-  test -f "$ac_file" || continue
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
-       ;;
-    conftest.$ac_ext )
-       # This is the source file.
-       ;;
-    [ab].out )
-       # We found the default executable, but exeext='' is most
-       # certainly right.
-       break;;
-    *.* )
-       ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-       # FIXME: I believe we export ac_cv_exeext for Libtool,
-       # but it would be cool to find out if it's true.  Does anybody
-       # maintain Libtool? --akim.
-       export ac_cv_exeext
-       break;;
-    * )
-       break;;
-  esac
-done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
-See \`config.log' for more details." >&5
-echo "$as_me: error: C compiler cannot create executables
-See \`config.log' for more details." >&2;}
-   { (exit 77); exit 77; }; }
-fi
-
-ac_exeext=$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_file" >&5
-echo "${ECHO_T}$ac_file" >&6
-
-# Check the compiler produces executables we can run.  If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether the C compiler works" >&5
-echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
-# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
-# If not cross compiling, check that we can run a simple program.
-if test "$cross_compiling" != yes; then
-  if { ac_try='./$ac_file'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-    cross_compiling=no
-  else
-    if test "$cross_compiling" = maybe; then
-       cross_compiling=yes
-    else
-       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot run C compiled programs.
-If you meant to cross compile, use \`--host'.
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-    fi
-  fi
-fi
-echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
-
-rm -f a.out a.exe conftest$ac_cv_exeext b.out
-ac_clean_files=$ac_clean_files_save
-# Check the compiler produces executables we can run.  If not, either
-# the compiler is broken, or we cross compile.
-echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
-echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
-echo "$as_me:$LINENO: result: $cross_compiling" >&5
-echo "${ECHO_T}$cross_compiling" >&6
-
-echo "$as_me:$LINENO: checking for suffix of executables" >&5
-echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  # If both `conftest.exe' and `conftest' are `present' (well, observable)
-# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
-# work properly (i.e., refer to `conftest.exe'), while it won't with
-# `rm'.
-for ac_file in conftest.exe conftest conftest.*; do
-  test -f "$ac_file" || continue
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
-    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
-         export ac_cv_exeext
-         break;;
-    * ) break;;
-  esac
-done
-else
-  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest$ac_cv_exeext
-echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
-echo "${ECHO_T}$ac_cv_exeext" >&6
-
-rm -f conftest.$ac_ext
-EXEEXT=$ac_cv_exeext
-ac_exeext=$EXEEXT
-echo "$as_me:$LINENO: checking for suffix of object files" >&5
-echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
-if test "${ac_cv_objext+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.o conftest.obj
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; then
-  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
-  case $ac_file in
-    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
-    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
-       break;;
-  esac
-done
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&5
-echo "$as_me: error: cannot compute suffix of object files: cannot compile
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-rm -f conftest.$ac_cv_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
-echo "${ECHO_T}$ac_cv_objext" >&6
-OBJEXT=$ac_cv_objext
-ac_objext=$OBJEXT
-echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
-echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
-if test "${ac_cv_c_compiler_gnu+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-#ifndef __GNUC__
-       choke me
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_compiler_gnu=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_compiler_gnu=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
-fi
-echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
-echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
-GCC=`test $ac_compiler_gnu = yes && echo yes`
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-CFLAGS="-g"
-echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
-echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_g+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_prog_cc_g=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_prog_cc_g=no
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
-if test "$ac_test_CFLAGS" = set; then
-  CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
-  if test "$GCC" = yes; then
-    CFLAGS="-g -O2"
-  else
-    CFLAGS="-g"
-  fi
-else
-  if test "$GCC" = yes; then
-    CFLAGS="-O2"
-  else
-    CFLAGS=
-  fi
-fi
-echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
-echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_stdc+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_cv_prog_cc_stdc=no
-ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
-     char **p;
-     int i;
-{
-  return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
-  char *s;
-  va_list v;
-  va_start (v,p);
-  s = g (p, va_arg (v,int));
-  va_end (v);
-  return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
-   function prototypes and stuff, but not '\xHH' hex character constants.
-   These don't provoke an error unfortunately, instead are silently treated
-   as 'x'.  The following induces an error, until -std1 is added to get
-   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
-   array size at least.  It's necessary to write '\x00'==0 to get something
-   that's true only with -std1.  */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
-
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
-  ;
-  return 0;
-}
-_ACEOF
-# Don't try gcc -ansi; that turns off useful extensions and
-# breaks some systems' header files.
-# AIX                  -qlanglvl=ansi
-# Ultrix and OSF/1     -std1
-# HP-UX 10.20 and later        -Ae
-# HP-UX older versions -Aa -D_HPUX_SOURCE
-# SVR4                 -Xc -D__EXTENSIONS__
-for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
-  CC="$ac_save_CC $ac_arg"
-  rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_prog_cc_stdc=$ac_arg
-break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext
-done
-rm -f conftest.$ac_ext conftest.$ac_objext
-CC=$ac_save_CC
-
-fi
-
-case "x$ac_cv_prog_cc_stdc" in
-  x|xno)
-    echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6 ;;
-  *)
-    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
-    CC="$CC $ac_cv_prog_cc_stdc" ;;
-esac
-
-# Some people use a C++ compiler to compile C.  Since we use `exit',
-# in C++ we need to declare it.  In case someone uses the same compiler
-# for both compiling C and C++ we need to have the C++ compiler decide
-# the declaration of exit, since it's the most demanding environment.
-cat >conftest.$ac_ext <<_ACEOF
-#ifndef __cplusplus
-  choke me
-#endif
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  for ac_declaration in \
-   '' \
-   'extern "C" void std::exit (int) throw (); using std::exit;' \
-   'extern "C" void std::exit (int); using std::exit;' \
-   'extern "C" void exit (int) throw ();' \
-   'extern "C" void exit (int);' \
-   'void exit (int);'
-do
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_declaration
-#include <stdlib.h>
-int
-main ()
-{
-exit (42);
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-continue
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-$ac_declaration
-int
-main ()
-{
-exit (42);
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  break
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-done
-rm -f conftest*
-if test -n "$ac_declaration"; then
-  echo '#ifdef __cplusplus' >>confdefs.h
-  echo $ac_declaration      >>confdefs.h
-  echo '#endif'             >>confdefs.h
-fi
-
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
-echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
-  CPP=
-fi
-if test -z "$CPP"; then
-  if test "${ac_cv_prog_CPP+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-      # Double quotes because CPP needs to be expanded
-    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
-    do
-      ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-                    Syntax error
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether non-existent headers
-  # can be detected and how.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  # Broken: success on invalid input.
-continue
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
-  break
-fi
-
-    done
-    ac_cv_prog_CPP=$CPP
-
-fi
-  CPP=$ac_cv_prog_CPP
-else
-  ac_cv_prog_CPP=$CPP
-fi
-echo "$as_me:$LINENO: result: $CPP" >&5
-echo "${ECHO_T}$CPP" >&6
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
-  # Use a header file that comes with gcc, so configuring glibc
-  # with a fresh cross-compiler works.
-  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-  # <limits.h> exists even on freestanding compilers.
-  # On the NeXT, cc -E runs the code through the compiler's parser,
-  # not just through cpp. "Syntax error" is here to catch this case.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-                    Syntax error
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  :
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.$ac_ext
-
-  # OK, works on sane cases.  Now check whether non-existent headers
-  # can be detected and how.
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ac_nonexistent.h>
-_ACEOF
-if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
-  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } >/dev/null; then
-  if test -s conftest.err; then
-    ac_cpp_err=$ac_c_preproc_warn_flag
-    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
-  else
-    ac_cpp_err=
-  fi
-else
-  ac_cpp_err=yes
-fi
-if test -z "$ac_cpp_err"; then
-  # Broken: success on invalid input.
-continue
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-  # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then
-  :
-else
-  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&5
-echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details." >&2;}
-   { (exit 1); exit 1; }; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-# Check whether --with-firebird-include-dir or --without-firebird-include-dir was given.
-if test "${with_firebird_include_dir+set}" = set; then
-  withval="$with_firebird_include_dir"
-   firebird_include_dir="$withval"
-
-fi;
-
-
-# Check whether --with-firebird-lib-dir or --without-firebird-lib-dir was given.
-if test "${with_firebird_lib_dir+set}" = set; then
-  withval="$with_firebird_lib_dir"
-   firebird_lib_dir="$withval"
-
-fi;
-
-
-# Check whether --with-firebird-dir or --without-firebird-dir was given.
-if test "${with_firebird_dir+set}" = set; then
-  withval="$with_firebird_dir"
-   firebird_lib_dir="$withval/lib"
-  firebird_include_dir="$withval/include"
-
-
-fi;
-
-if test x$with_rlm_sql_firebird != xno; then
-
-       targetname=rlm_sql_firebird   # we might change this later.
-
-       echo "$as_me:$LINENO: checking for ibase.h" >&5
-echo $ECHO_N "checking for ibase.h... $ECHO_C" >&6
-
-
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ibase.h>
-int
-main ()
-{
-int a = 1;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  FIREBIRD_INCLUDE=" "
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-FIREBIRD_INCLUDE=
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-
-       if test "x$FIREBIRD_INCLUDE" = "x"; then
-               old_CFLAGS="$CFLAGS"
-
-               for try in /usr/local/include $firebird_include_dir; do
-                       CFLAGS="$old_CFLAGS -I$try"
-                       cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-#include <ibase.h>
-int
-main ()
-{
-int a = 1;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
-  (eval $ac_compile) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest.$ac_objext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  FIREBIRD_INCLUDE="-I$try"
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-FIREBIRD_INCLUDE=
-
-fi
-rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
-                       if test "x$FIREBIRD_INCLUDE" != "x"; then
-                               break;
-                       fi
-               done
-               CFLAGS="$old_CFLAGS"
-       fi
-
-       if test "x$FIREBIRD_INCLUDE" = "x"; then
-               echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-               { echo "$as_me:$LINENO: WARNING: firebird headers not found.  Use --with-firebird-include-dir=<path>." >&5
-echo "$as_me: WARNING: firebird headers not found.  Use --with-firebird-include-dir=<path>." >&2;}
-               targetname=   # disabled module
-       else
-               sql_firebird_cflags="${sql_firebird_cflags} ${FIREBIRD_INCLUDE}"
-               echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
-
-               echo "$as_me:$LINENO: checking for isc_attach_database -l$GDS" >&5
-echo $ECHO_N "checking for isc_attach_database -l$GDS... $ECHO_C" >&6
-
-               old_LIBS="$LIBS"
-
-               for try in /usr/lib $firebird_lib_dir; do
-                       LIBS="$old_LIBS -L$try -lfbclient"
-                       cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-extern char isc_attach_database();
-int
-main ()
-{
-isc_attach_database()
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  FIREBIRD_LIBS="-L$try -lfbclient"
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-FIREBIRD_LIBS=
-
-fi
-rm -f conftest.err conftest.$ac_objext \
-      conftest$ac_exeext conftest.$ac_ext
-                       if test "x$FIREBIRD_LIBS" != "x"; then
-                               break;
-                       fi
-               done
-               LIBS="$old_LIBS"
-
-                                               if test "x$FIREBIRD_LIBS" = "x"; then
-                       echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6
-                       FIREBIRD_INCLUDE=
-                       { echo "$as_me:$LINENO: WARNING: firebird libraries not found.  Use --with-firebird-lib-dir=<path>." >&5
-echo "$as_me: WARNING: firebird libraries not found.  Use --with-firebird-lib-dir=<path>." >&2;}
-                       targetname=   # disabled module
-               else
-                       echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6
-                       sql_firebird_ldflags="$sql_firebird_ldflags $FIREBIRD_LIBS"
-               fi
-       fi
-
-       sql_firebird_ldflags="$sql_firebird_ldflags $LIBS"
-
-       if test "x$targetname" = "x"; then
-               { echo "$as_me:$LINENO: WARNING: sql submodule 'firebird' disabled" >&5
-echo "$as_me: WARNING: sql submodule 'firebird' disabled" >&2;}
-       fi
-
-else
-       targetname=
-       echo \*\*\* module rlm_sql_firebird is disabled.
-fi
-
-
-
-
-          ac_config_files="$ac_config_files Makefile"
-cat >confcache <<\_ACEOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs, see configure's option --config-cache.
-# It is not useful on other systems.  If it contains results you don't
-# want to keep, you may remove or edit it.
-#
-# config.status only pays attention to the cache file if you give it
-# the --recheck option to rerun configure.
-#
-# `ac_cv_env_foo' variables (set or unset) will be overridden when
-# loading this file, other *unset* `ac_cv_foo' will be assigned the
-# following values.
-
-_ACEOF
-
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-{
-  (set) 2>&1 |
-    case `(ac_space=' '; set | grep ac_space) 2>&1` in
-    *ac_space=\ *)
-      # `set' does not quote correctly, so add quotes (double-quote
-      # substitution turns \\\\ into \\, and sed turns \\ into \).
-      sed -n \
-       "s/'/'\\\\''/g;
-         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
-      ;;
-    *)
-      # `set' quotes correctly as required by POSIX, so do not add quotes.
-      sed -n \
-       "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
-      ;;
-    esac;
-} |
-  sed '
-     t clear
-     : clear
-     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
-     t end
-     /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
-     : end' >>confcache
-if diff $cache_file confcache >/dev/null 2>&1; then :; else
-  if test -w $cache_file; then
-    test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
-    cat confcache >$cache_file
-  else
-    echo "not updating unwritable cache $cache_file"
-  fi
-fi
-rm -f confcache
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-# VPATH may cause trouble with some makes, so we remove $(srcdir),
-# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
-# trailing colons and then remove the whole line if VPATH becomes empty
-# (actually we leave an empty line to preserve line numbers).
-if test "x$srcdir" = x.; then
-  ac_vpsub='/^[         ]*VPATH[        ]*=/{
-s/:*\$(srcdir):*/:/;
-s/:*\${srcdir}:*/:/;
-s/:*@srcdir@:*/:/;
-s/^\([^=]*=[    ]*\):*/\1/;
-s/:*$//;
-s/^[^=]*=[      ]*$//;
-}'
-fi
-
-# Transform confdefs.h into DEFS.
-# Protect against shell expansion while executing Makefile rules.
-# Protect against Makefile macro expansion.
-#
-# If the first sed substitution is executed (which looks for macros that
-# take arguments), then we branch to the quote section.  Otherwise,
-# look for a macro that doesn't take arguments.
-cat >confdef2opt.sed <<\_ACEOF
-t clear
-: clear
-s,^[    ]*#[    ]*define[       ][      ]*\([^  (][^    (]*([^)]*)\)[   ]*\(.*\),-D\1=\2,g
-t quote
-s,^[    ]*#[    ]*define[       ][      ]*\([^  ][^     ]*\)[   ]*\(.*\),-D\1=\2,g
-t quote
-d
-: quote
-s,[     `~#$^&*(){}\\|;'"<>?],\\&,g
-s,\[,\\&,g
-s,\],\\&,g
-s,\$,$$,g
-p
-_ACEOF
-# We use echo to avoid assuming a particular line-breaking character.
-# The extra dot is to prevent the shell from consuming trailing
-# line-breaks from the sub-command output.  A line-break within
-# single-quotes doesn't work because, if this script is created in a
-# platform that uses two characters for line-breaks (e.g., DOS), tr
-# would break.
-ac_LF_and_DOT=`echo; echo .`
-DEFS=`sed -n -f confdef2opt.sed confdefs.h | tr "$ac_LF_and_DOT" ' .'`
-rm -f confdef2opt.sed
-
-
-ac_libobjs=
-ac_ltlibobjs=
-for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
-  # 1. Remove the extension, and $U if already installed.
-  ac_i=`echo "$ac_i" |
-        sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
-  # 2. Add them.
-  ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
-  ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
-done
-LIBOBJS=$ac_libobjs
-
-LTLIBOBJS=$ac_ltlibobjs
-
-
-
-: ${CONFIG_STATUS=./config.status}
-ac_clean_files_save=$ac_clean_files
-ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
-echo "$as_me: creating $CONFIG_STATUS" >&6;}
-cat >$CONFIG_STATUS <<_ACEOF
-#! $SHELL
-# Generated by $as_me.
-# Run this file to recreate the current configuration.
-# Compiler output produced by configure, useful for debugging
-# configure, is in config.log if it exists.
-
-debug=false
-ac_cs_recheck=false
-ac_cs_silent=false
-SHELL=\${CONFIG_SHELL-$SHELL}
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-## --------------------- ##
-## M4sh Initialization.  ##
-## --------------------- ##
-
-# Be Bourne compatible
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
-  emulate sh
-  NULLCMD=:
-  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
-  # is contrary to our usage.  Disable this feature.
-  alias -g '${1+"$@"}'='"$@"'
-elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
-  set -o posix
-fi
-DUALCASE=1; export DUALCASE # for MKS sh
-
-# Support unset when possible.
-if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
-  as_unset=unset
-else
-  as_unset=false
-fi
-
-
-# Work around bugs in pre-3.0 UWIN ksh.
-$as_unset ENV MAIL MAILPATH
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-for as_var in \
-  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
-  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
-  LC_TELEPHONE LC_TIME
-do
-  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
-    eval $as_var=C; export $as_var
-  else
-    $as_unset $as_var
-  fi
-done
-
-# Required to use basename.
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
-  as_basename=basename
-else
-  as_basename=false
-fi
-
-
-# Name of the executable.
-as_me=`$as_basename "$0" ||
-$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
-        X"$0" : 'X\(//\)$' \| \
-        X"$0" : 'X\(/\)$' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X/"$0" |
-    sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
-         /^X\/\(\/\/\)$/{ s//\1/; q; }
-         /^X\/\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-
-
-# PATH needs CR, and LINENO needs CR and PATH.
-# Avoid depending upon Character Ranges.
-as_cr_letters='abcdefghijklmnopqrstuvwxyz'
-as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
-as_cr_Letters=$as_cr_letters$as_cr_LETTERS
-as_cr_digits='0123456789'
-as_cr_alnum=$as_cr_Letters$as_cr_digits
-
-# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
-  echo "#! /bin/sh" >conf$$.sh
-  echo  "exit 0"   >>conf$$.sh
-  chmod +x conf$$.sh
-  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
-    PATH_SEPARATOR=';'
-  else
-    PATH_SEPARATOR=:
-  fi
-  rm -f conf$$.sh
-fi
-
-
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2"  || {
-  # Find who we are.  Look in the path if we contain no path at all
-  # relative or not.
-  case $0 in
-    *[\\/]* ) as_myself=$0 ;;
-    *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
-done
-
-       ;;
-  esac
-  # We did not find ourselves, most probably we were run as `sh COMMAND'
-  # in which case we are not to be found in the path.
-  if test "x$as_myself" = x; then
-    as_myself=$0
-  fi
-  if test ! -f "$as_myself"; then
-    { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
-echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
-   { (exit 1); exit 1; }; }
-  fi
-  case $CONFIG_SHELL in
-  '')
-    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-  for as_base in sh bash ksh sh5; do
-        case $as_dir in
-        /*)
-          if ("$as_dir/$as_base" -c '
-  as_lineno_1=$LINENO
-  as_lineno_2=$LINENO
-  as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
-  test "x$as_lineno_1" != "x$as_lineno_2" &&
-  test "x$as_lineno_3"  = "x$as_lineno_2" ') 2>/dev/null; then
-            $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
-            $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
-            CONFIG_SHELL=$as_dir/$as_base
-            export CONFIG_SHELL
-            exec "$CONFIG_SHELL" "$0" ${1+"$@"}
-          fi;;
-        esac
-       done
-done
-;;
-  esac
-
-  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
-  # uniformly replaced by the line number.  The first 'sed' inserts a
-  # line-number line before each line; the second 'sed' does the real
-  # work.  The second script uses 'N' to pair each line-number line
-  # with the numbered line, and appends trailing '-' during
-  # substitution so that $LINENO is not a special case at line end.
-  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
-  # second 'sed' script.  Blame Lee E. McMahon for sed's syntax.  :-)
-  sed '=' <$as_myself |
-    sed '
-      N
-      s,$,-,
-      : loop
-      s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
-      t loop
-      s,-$,,
-      s,^['$as_cr_digits']*\n,,
-    ' >$as_me.lineno &&
-  chmod +x $as_me.lineno ||
-    { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
-echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
-   { (exit 1); exit 1; }; }
-
-  # Don't try to exec as it changes $[0], causing all sort of problems
-  # (the dirname of $[0] is not the place where we might find the
-  # original and so on.  Autoconf is especially sensible to this).
-  . ./$as_me.lineno
-  # Exit status is that of the last command.
-  exit
-}
-
-
-case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
-  *c*,-n*) ECHO_N= ECHO_C='
-' ECHO_T='     ' ;;
-  *c*,*  ) ECHO_N=-n ECHO_C= ECHO_T= ;;
-  *)       ECHO_N= ECHO_C='\c' ECHO_T= ;;
-esac
-
-if expr a : '\(a\)' >/dev/null 2>&1; then
-  as_expr=expr
-else
-  as_expr=false
-fi
-
-rm -f conf$$ conf$$.exe conf$$.file
-echo >conf$$.file
-if ln -s conf$$.file conf$$ 2>/dev/null; then
-  # We could just check for DJGPP; but this test a) works b) is more generic
-  # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
-  if test -f conf$$.exe; then
-    # Don't use ln at all; we don't have any links
-    as_ln_s='cp -p'
-  else
-    as_ln_s='ln -s'
-  fi
-elif ln conf$$.file conf$$ 2>/dev/null; then
-  as_ln_s=ln
-else
-  as_ln_s='cp -p'
-fi
-rm -f conf$$ conf$$.exe conf$$.file
-
-if mkdir -p . 2>/dev/null; then
-  as_mkdir_p=:
-else
-  test -d ./-p && rmdir ./-p
-  as_mkdir_p=false
-fi
-
-as_executable_p="test -f"
-
-# Sed expression to map a string onto a valid CPP name.
-as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
-
-# Sed expression to map a string onto a valid variable name.
-as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
-
-
-# IFS
-# We need space, tab and new line, in precisely that order.
-as_nl='
-'
-IFS="  $as_nl"
-
-# CDPATH.
-$as_unset CDPATH
-
-exec 6>&1
-
-# Open the log real soon, to keep \$[0] and so on meaningful, and to
-# report actual input values of CONFIG_FILES etc. instead of their
-# values after options handling.  Logging --version etc. is OK.
-exec 5>>config.log
-{
-  echo
-  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
-## Running $as_me. ##
-_ASBOX
-} >&5
-cat >&5 <<_CSEOF
-
-This file was extended by $as_me, which was
-generated by GNU Autoconf 2.59.  Invocation command line was
-
-  CONFIG_FILES    = $CONFIG_FILES
-  CONFIG_HEADERS  = $CONFIG_HEADERS
-  CONFIG_LINKS    = $CONFIG_LINKS
-  CONFIG_COMMANDS = $CONFIG_COMMANDS
-  $ $0 $@
-
-_CSEOF
-echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
-echo >&5
-_ACEOF
-
-# Files that config.status was made for.
-if test -n "$ac_config_files"; then
-  echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_headers"; then
-  echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_links"; then
-  echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
-fi
-
-if test -n "$ac_config_commands"; then
-  echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
-fi
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-ac_cs_usage="\
-\`$as_me' instantiates files from templates according to the
-current configuration.
-
-Usage: $0 [OPTIONS] [FILE]...
-
-  -h, --help       print this help, then exit
-  -V, --version    print version number, then exit
-  -q, --quiet      do not print progress messages
-  -d, --debug      don't remove temporary files
-      --recheck    update $as_me by reconfiguring in the same conditions
-  --file=FILE[:TEMPLATE]
-                  instantiate the configuration file FILE
-
-Configuration files:
-$config_files
-
-Report bugs to <bug-autoconf@gnu.org>."
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-ac_cs_version="\\
-config.status
-configured by $0, generated by GNU Autoconf 2.59,
-  with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
-
-Copyright (C) 2003 Free Software Foundation, Inc.
-This config.status script is free software; the Free Software Foundation
-gives unlimited permission to copy, distribute and modify it."
-srcdir=$srcdir
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-# If no file are specified by the user, then we need to provide default
-# value.  By we need to know if files were specified by the user.
-ac_need_defaults=:
-while test $# != 0
-do
-  case $1 in
-  --*=*)
-    ac_option=`expr "x$1" : 'x\([^=]*\)='`
-    ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
-    ac_shift=:
-    ;;
-  -*)
-    ac_option=$1
-    ac_optarg=$2
-    ac_shift=shift
-    ;;
-  *) # This is not an option, so the user has probably given explicit
-     # arguments.
-     ac_option=$1
-     ac_need_defaults=false;;
-  esac
-
-  case $ac_option in
-  # Handling of the options.
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
-    ac_cs_recheck=: ;;
-  --version | --vers* | -V )
-    echo "$ac_cs_version"; exit 0 ;;
-  --he | --h)
-    # Conflict between --help and --header
-    { { echo "$as_me:$LINENO: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: ambiguous option: $1
-Try \`$0 --help' for more information." >&2;}
-   { (exit 1); exit 1; }; };;
-  --help | --hel | -h )
-    echo "$ac_cs_usage"; exit 0 ;;
-  --debug | --d* | -d )
-    debug=: ;;
-  --file | --fil | --fi | --f )
-    $ac_shift
-    CONFIG_FILES="$CONFIG_FILES $ac_optarg"
-    ac_need_defaults=false;;
-  --header | --heade | --head | --hea )
-    $ac_shift
-    CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
-    ac_need_defaults=false;;
-  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
-  | -silent | --silent | --silen | --sile | --sil | --si | --s)
-    ac_cs_silent=: ;;
-
-  # This is an error.
-  -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&5
-echo "$as_me: error: unrecognized option: $1
-Try \`$0 --help' for more information." >&2;}
-   { (exit 1); exit 1; }; } ;;
-
-  *) ac_config_targets="$ac_config_targets $1" ;;
-
-  esac
-  shift
-done
-
-ac_configure_extra_args=
-
-if $ac_cs_silent; then
-  exec 6>/dev/null
-  ac_configure_extra_args="$ac_configure_extra_args --silent"
-fi
-
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-if \$ac_cs_recheck; then
-  echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
-  exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
-fi
-
-_ACEOF
-
-
-
-
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_config_target in $ac_config_targets
-do
-  case "$ac_config_target" in
-  # Handling of arguments.
-  "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
-  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
-echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
-   { (exit 1); exit 1; }; };;
-  esac
-done
-
-# If the user did not use the arguments to specify the items to instantiate,
-# then the envvar interface is used.  Set only those that are not.
-# We use the long form for the default assignment because of an extremely
-# bizarre bug on SunOS 4.1.3.
-if $ac_need_defaults; then
-  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
-fi
-
-# Have a temporary directory for convenience.  Make it in the build tree
-# simply because there is no reason to put it here, and in addition,
-# creating and moving files from /tmp can sometimes cause problems.
-# Create a temporary directory, and hook for its removal unless debugging.
-$debug ||
-{
-  trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
-  trap '{ (exit 1); exit 1; }' 1 2 13 15
-}
-
-# Create a (secure) tmp directory for tmp files.
-
-{
-  tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
-  test -n "$tmp" && test -d "$tmp"
-}  ||
-{
-  tmp=./confstat$$-$RANDOM
-  (umask 077 && mkdir $tmp)
-} ||
-{
-   echo "$me: cannot create a temporary directory in ." >&2
-   { (exit 1); exit 1; }
-}
-
-_ACEOF
-
-cat >>$CONFIG_STATUS <<_ACEOF
-
-#
-# CONFIG_FILES section.
-#
-
-# No need to generate the scripts if there are no CONFIG_FILES.
-# This happens for instance when ./config.status config.h
-if test -n "\$CONFIG_FILES"; then
-  # Protect against being on the right side of a sed subst in config.status.
-  sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
-   s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
-s,@SHELL@,$SHELL,;t t
-s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
-s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
-s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
-s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
-s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
-s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
-s,@exec_prefix@,$exec_prefix,;t t
-s,@prefix@,$prefix,;t t
-s,@program_transform_name@,$program_transform_name,;t t
-s,@bindir@,$bindir,;t t
-s,@sbindir@,$sbindir,;t t
-s,@libexecdir@,$libexecdir,;t t
-s,@datadir@,$datadir,;t t
-s,@sysconfdir@,$sysconfdir,;t t
-s,@sharedstatedir@,$sharedstatedir,;t t
-s,@localstatedir@,$localstatedir,;t t
-s,@libdir@,$libdir,;t t
-s,@includedir@,$includedir,;t t
-s,@oldincludedir@,$oldincludedir,;t t
-s,@infodir@,$infodir,;t t
-s,@mandir@,$mandir,;t t
-s,@build_alias@,$build_alias,;t t
-s,@host_alias@,$host_alias,;t t
-s,@target_alias@,$target_alias,;t t
-s,@DEFS@,$DEFS,;t t
-s,@ECHO_C@,$ECHO_C,;t t
-s,@ECHO_N@,$ECHO_N,;t t
-s,@ECHO_T@,$ECHO_T,;t t
-s,@LIBS@,$LIBS,;t t
-s,@CC@,$CC,;t t
-s,@CFLAGS@,$CFLAGS,;t t
-s,@LDFLAGS@,$LDFLAGS,;t t
-s,@CPPFLAGS@,$CPPFLAGS,;t t
-s,@ac_ct_CC@,$ac_ct_CC,;t t
-s,@EXEEXT@,$EXEEXT,;t t
-s,@OBJEXT@,$OBJEXT,;t t
-s,@CPP@,$CPP,;t t
-s,@sql_firebird_ldflags@,$sql_firebird_ldflags,;t t
-s,@sql_firebird_cflags@,$sql_firebird_cflags,;t t
-s,@targetname@,$targetname,;t t
-s,@LIBOBJS@,$LIBOBJS,;t t
-s,@LTLIBOBJS@,$LTLIBOBJS,;t t
-CEOF
-
-_ACEOF
-
-  cat >>$CONFIG_STATUS <<\_ACEOF
-  # Split the substitutions into bite-sized pieces for seds with
-  # small command number limits, like on Digital OSF/1 and HP-UX.
-  ac_max_sed_lines=48
-  ac_sed_frag=1 # Number of current file.
-  ac_beg=1 # First line for current file.
-  ac_end=$ac_max_sed_lines # Line after last line for current file.
-  ac_more_lines=:
-  ac_sed_cmds=
-  while $ac_more_lines; do
-    if test $ac_beg -gt 1; then
-      sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
-    else
-      sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
-    fi
-    if test ! -s $tmp/subs.frag; then
-      ac_more_lines=false
-    else
-      # The purpose of the label and of the branching condition is to
-      # speed up the sed processing (if there are no `@' at all, there
-      # is no need to browse any of the substitutions).
-      # These are the two extra sed commands mentioned above.
-      (echo ':t
-  /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
-      if test -z "$ac_sed_cmds"; then
-       ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
-      else
-       ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
-      fi
-      ac_sed_frag=`expr $ac_sed_frag + 1`
-      ac_beg=$ac_end
-      ac_end=`expr $ac_end + $ac_max_sed_lines`
-    fi
-  done
-  if test -z "$ac_sed_cmds"; then
-    ac_sed_cmds=cat
-  fi
-fi # test -n "$CONFIG_FILES"
-
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
-  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
-  case $ac_file in
-  - | *:- | *:-:* ) # input from stdin
-       cat >$tmp/stdin
-       ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
-       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
-  *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
-       ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
-  * )   ac_file_in=$ac_file.in ;;
-  esac
-
-  # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
-  ac_dir=`(dirname "$ac_file") 2>/dev/null ||
-$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$ac_file" : 'X\(//\)[^/]' \| \
-        X"$ac_file" : 'X\(//\)$' \| \
-        X"$ac_file" : 'X\(/\)' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X"$ac_file" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-         /^X\(\/\/\)$/{ s//\1/; q; }
-         /^X\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-  { if $as_mkdir_p; then
-    mkdir -p "$ac_dir"
-  else
-    as_dir="$ac_dir"
-    as_dirs=
-    while test ! -d "$as_dir"; do
-      as_dirs="$as_dir $as_dirs"
-      as_dir=`(dirname "$as_dir") 2>/dev/null ||
-$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
-        X"$as_dir" : 'X\(//\)[^/]' \| \
-        X"$as_dir" : 'X\(//\)$' \| \
-        X"$as_dir" : 'X\(/\)' \| \
-        .     : '\(.\)' 2>/dev/null ||
-echo X"$as_dir" |
-    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
-         /^X\(\/\/\)[^/].*/{ s//\1/; q; }
-         /^X\(\/\/\)$/{ s//\1/; q; }
-         /^X\(\/\).*/{ s//\1/; q; }
-         s/.*/./; q'`
-    done
-    test ! -n "$as_dirs" || mkdir $as_dirs
-  fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
-echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
-   { (exit 1); exit 1; }; }; }
-
-  ac_builddir=.
-
-if test "$ac_dir" != .; then
-  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
-  # A "../" for each directory in $ac_dir_suffix.
-  ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
-else
-  ac_dir_suffix= ac_top_builddir=
-fi
-
-case $srcdir in
-  .)  # No --srcdir option.  We are building in place.
-    ac_srcdir=.
-    if test -z "$ac_top_builddir"; then
-       ac_top_srcdir=.
-    else
-       ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
-    fi ;;
-  [\\/]* | ?:[\\/]* )  # Absolute path.
-    ac_srcdir=$srcdir$ac_dir_suffix;
-    ac_top_srcdir=$srcdir ;;
-  *) # Relative path.
-    ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
-    ac_top_srcdir=$ac_top_builddir$srcdir ;;
-esac
-
-# Do not use `cd foo && pwd` to compute absolute paths, because
-# the directories may not exist.
-case `pwd` in
-.) ac_abs_builddir="$ac_dir";;
-*)
-  case "$ac_dir" in
-  .) ac_abs_builddir=`pwd`;;
-  [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";;
-  *) ac_abs_builddir=`pwd`/"$ac_dir";;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_builddir=${ac_top_builddir}.;;
-*)
-  case ${ac_top_builddir}. in
-  .) ac_abs_top_builddir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;;
-  *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_srcdir=$ac_srcdir;;
-*)
-  case $ac_srcdir in
-  .) ac_abs_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;;
-  *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;;
-  esac;;
-esac
-case $ac_abs_builddir in
-.) ac_abs_top_srcdir=$ac_top_srcdir;;
-*)
-  case $ac_top_srcdir in
-  .) ac_abs_top_srcdir=$ac_abs_builddir;;
-  [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;;
-  *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;;
-  esac;;
-esac
-
-
-
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
-  # Let's still pretend it is `configure' which instantiates (i.e., don't
-  # use $as_me), people would be surprised to read:
-  #    /* config.h.  Generated by config.status.  */
-  if test x"$ac_file" = x-; then
-    configure_input=
-  else
-    configure_input="$ac_file.  "
-  fi
-  configure_input=$configure_input"Generated from `echo $ac_file_in |
-                                    sed 's,.*/,,'` by configure."
-
-  # First look for the input files in the build tree, otherwise in the
-  # src tree.
-  ac_file_inputs=`IFS=:
-    for f in $ac_file_in; do
-      case $f in
-      -) echo $tmp/stdin ;;
-      [\\/$]*)
-        # Absolute (can't be DOS-style, as IFS=:)
-        test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
-   { (exit 1); exit 1; }; }
-        echo "$f";;
-      *) # Relative
-        if test -f "$f"; then
-          # Build tree
-          echo "$f"
-        elif test -f "$srcdir/$f"; then
-          # Source tree
-          echo "$srcdir/$f"
-        else
-          # /dev/null tree
-          { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
-echo "$as_me: error: cannot find input file: $f" >&2;}
-   { (exit 1); exit 1; }; }
-        fi;;
-      esac
-    done` || { (exit 1); exit 1; }
-_ACEOF
-cat >>$CONFIG_STATUS <<_ACEOF
-  sed "$ac_vpsub
-$extrasub
-_ACEOF
-cat >>$CONFIG_STATUS <<\_ACEOF
-:t
-/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
-s,@configure_input@,$configure_input,;t t
-s,@srcdir@,$ac_srcdir,;t t
-s,@abs_srcdir@,$ac_abs_srcdir,;t t
-s,@top_srcdir@,$ac_top_srcdir,;t t
-s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
-s,@builddir@,$ac_builddir,;t t
-s,@abs_builddir@,$ac_abs_builddir,;t t
-s,@top_builddir@,$ac_top_builddir,;t t
-s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
-" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
-  rm -f $tmp/stdin
-  if test x"$ac_file" != x-; then
-    mv $tmp/out $ac_file
-  else
-    cat $tmp/out
-    rm -f $tmp/out
-  fi
-
-done
-_ACEOF
-
-cat >>$CONFIG_STATUS <<\_ACEOF
-
-{ (exit 0); exit 0; }
-_ACEOF
-chmod +x $CONFIG_STATUS
-ac_clean_files=$ac_clean_files_save
-
-
-# configure is writing to config.log, and then calls config.status.
-# config.status does its own redirection, appending to config.log.
-# Unfortunately, on DOS this fails, as config.log is still kept open
-# by configure, so config.status won't be able to write to it; its
-# output is simply discarded.  So we exec the FD to /dev/null,
-# effectively closing config.log, so it can be properly (re)opened and
-# appended to by config.status.  When coming back to configure, we
-# need to make the FD available again.
-if test "$no_create" != yes; then
-  ac_cs_success=:
-  ac_config_status_args=
-  test "$silent" = yes &&
-    ac_config_status_args="$ac_config_status_args --quiet"
-  exec 5>/dev/null
-  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
-  exec 5>>config.log
-  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
-  # would make configure fail if this is the last instruction.
-  $ac_cs_success || { (exit 1); exit 1; }
-fi
-
diff --git a/src/modules/rlm_sql/drivers/rlm_sql_firebird/configure.in b/src/modules/rlm_sql/drivers/rlm_sql_firebird/configure.in
deleted file mode 100644 (file)
index c1679f9..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-AC_INIT(sql_firebird.c)
-AC_REVISION($Revision$)
-AC_DEFUN(modname,[rlm_sql_firebird])
-
-AC_PROG_CC
-AC_PROG_CPP
-
-AC_ARG_WITH(firebird-include-dir,
-[  --with-firebird-include-dir=DIR       Directory where the firebird includes may be found ],
-[ firebird_include_dir="$withval" ]
-)
-
-AC_ARG_WITH(firebird-lib-dir,
-[  --with-firebird-lib-dir=DIR       Directory where the firebird libraries may be found ],
-[ firebird_lib_dir="$withval" ]
-)
-
-AC_ARG_WITH(firebird-dir,
-[  --with-firebird-dir=DIR       Base directory where firebird is installed ],
-[ firebird_lib_dir="$withval/lib"
-  firebird_include_dir="$withval/include"
-]
-)
-
-if test x$with_[]modname != xno; then
-
-       targetname=modname   # we might change this later.
-
-       AC_MSG_CHECKING([for ibase.h])
-
-       AC_TRY_COMPILE([#include <ibase.h>], [int a = 1;],
-               FIREBIRD_INCLUDE=" ",
-               FIREBIRD_INCLUDE=
-       )
-
-       if test "x$FIREBIRD_INCLUDE" = "x"; then
-               old_CFLAGS="$CFLAGS"
-
-               for try in /usr/local/include $firebird_include_dir; do
-                       CFLAGS="$old_CFLAGS -I$try"
-                       AC_TRY_COMPILE([#include <ibase.h>], [int a = 1;],
-                               FIREBIRD_INCLUDE="-I$try",
-                               FIREBIRD_INCLUDE=
-                       )
-                       if test "x$FIREBIRD_INCLUDE" != "x"; then
-                               break;
-                       fi
-               done
-               CFLAGS="$old_CFLAGS"
-       fi
-
-       if test "x$FIREBIRD_INCLUDE" = "x"; then
-               AC_MSG_RESULT(no)
-               AC_MSG_WARN([firebird headers not found.  Use --with-firebird-include-dir=<path>.])
-               targetname=   # disabled module
-       else
-               sql_firebird_cflags="${sql_firebird_cflags} ${FIREBIRD_INCLUDE}"
-               AC_MSG_RESULT(yes)
-  
-               AC_MSG_CHECKING([for isc_attach_database -l$GDS])
-
-               old_LIBS="$LIBS"
-
-               for try in /usr/lib $firebird_lib_dir; do
-                       LIBS="$old_LIBS -L$try -lfbclient"
-                       AC_TRY_LINK([extern char isc_attach_database();], [isc_attach_database()],
-                               FIREBIRD_LIBS="-L$try -lfbclient",
-                               FIREBIRD_LIBS=
-                       )
-                       if test "x$FIREBIRD_LIBS" != "x"; then
-                               break;
-                       fi
-               done
-               LIBS="$old_LIBS"
-
-               dnl #  If one or the other isn't found, disable them both..
-               dnl #  If both are found, enable them both.
-               if test "x$FIREBIRD_LIBS" = "x"; then
-                       AC_MSG_RESULT(no)
-                       FIREBIRD_INCLUDE=
-                       AC_MSG_WARN([firebird libraries not found.  Use --with-firebird-lib-dir=<path>.])
-                       targetname=   # disabled module
-               else
-                       AC_MSG_RESULT(yes) 
-                       sql_firebird_ldflags="$sql_firebird_ldflags $FIREBIRD_LIBS"
-               fi
-       fi
-
-       sql_firebird_ldflags="$sql_firebird_ldflags $LIBS"
-
-       if test "x$targetname" = "x"; then
-               AC_MSG_WARN([sql submodule 'firebird' disabled])
-       fi
-
-else
-       targetname=
-       echo \*\*\* module modname is disabled.
-fi
-
-AC_SUBST(sql_firebird_ldflags)
-AC_SUBST(sql_firebird_cflags)
-AC_SUBST(targetname)
-AC_OUTPUT(Makefile)
diff --git a/src/modules/rlm_sql/drivers/rlm_sql_firebird/sql_fbapi.c b/src/modules/rlm_sql/drivers/rlm_sql_firebird/sql_fbapi.c
deleted file mode 100644 (file)
index e780bc1..0000000
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * sql_fbapi.c Part of Firebird rlm_sql driver
- *
- *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Copyright 2006  The FreeRADIUS server project
- * Copyright 2006  Vitaly Bodzhgua <vitaly@eastera.net>
- */
-
-
-#include "sql_fbapi.h"
-
-#include <stdarg.h>
-
-int fb_lasterror(rlm_sql_firebird_sock *sock) {
- char msg[512+2];
- int l;
- ISC_LONG *pstatus;
- char *p=0;
-
- sock->sql_code=0;
-
- if (IS_ISC_ERROR(sock->status)) {
-//if error occured, free the previous error's text and create a new one
-   pstatus=sock->status;
-   if (sock->lasterror) free(sock->lasterror);
-   sock->lasterror=0;
-   sock->sql_code=isc_sqlcode(sock->status);
-   isc_interprete(msg,&pstatus);
-   p=strdup(msg);
-   msg[0]='.';msg[1]=' ';
-   while (isc_interprete(msg+2,&pstatus)) {
-     l=strlen(p);
-     p=(char *) realloc(p,l+strlen(msg)+2);
-     strcat(p,msg);
-   }
-   sock->lasterror=p;
- } else {
-//return empty (but not null) string if there are  no error
-  if (sock->lasterror) *sock->lasterror=0;
-  else sock->lasterror=strdup("");
- }
- return sock->sql_code;
-}
-
-
-void fb_set_tpb(rlm_sql_firebird_sock * sock, int count,...) {
- int i;
- va_list arg;
- va_start(arg,count);
- sock->tpb=(char *) malloc(count);
- for (i=0; i<count; i++) {
-    sock->tpb[i]=(char ) va_arg(arg,int);
- }
- sock->tpb_len=count;
-}
-
-
-void fb_dpb_add_str(char **dpb, char name, char *value) {
- int l;
- if (!value) return;
- l=strlen(value);
-
- *(*dpb)++ = name;
- *(*dpb)++ = (char ) l;
- memmove(*dpb,value,l);
- *dpb+=l;
-
-}
-
-void fb_free_sqlda(XSQLDA *sqlda) {
- int i;
- for (i=0; i<sqlda->sqld; i++) {
-  free(sqlda->sqlvar[i].sqldata);
-  free(sqlda->sqlvar[i].sqlind);
- }
- sqlda->sqld=0;
-}
-
-void fb_set_sqlda(XSQLDA *sqlda) {
- int i;
- for (i=0; i<sqlda->sqld; i++) {
-  if ((sqlda->sqlvar[i].sqltype & ~1)==SQL_VARYING)
-    sqlda->sqlvar[i].sqldata = (char*)malloc(sqlda->sqlvar[i].sqllen + sizeof(short));
-  else
-   sqlda->sqlvar[i].sqldata = (char*)malloc(sqlda->sqlvar[i].sqllen);
-
-  if (sqlda->sqlvar[i].sqltype & 1) sqlda->sqlvar[i].sqlind = (short*)calloc(sizeof(short),1);
-  else sqlda->sqlvar[i].sqlind = 0;
- }
-}
-
-
-//Macro for NULLs check
-#define IS_NULL(x) (x->sqltype & 1) && (*x->sqlind < 0)
-
-//Structure to manage a SQL_VARYING Firebird's data types
-typedef struct vary_fb {
-  short vary_length;
-  char vary_string[1];
-} VARY;
-
-//function fb_store_row based on fiebird's apifull example
-void fb_store_row(rlm_sql_firebird_sock *sock) {
- int dtype;
- struct tm times;
- ISC_QUAD bid;
- int i;
- XSQLVAR *var;
- VARY * vary;
-
-//assumed: id,username,attribute,value,op
- if (sock->row_fcount<sock->sqlda_out->sqld)  {
-   i=sock->row_fcount;
-   sock->row_fcount=sock->sqlda_out->sqld;
-   sock->row=(char **) realloc(sock->row,sock->row_fcount*sizeof(char *));
-   sock->row_sizes=(int *) realloc(sock->row_sizes,sock->row_fcount*sizeof(int));
-   while(i<sock->row_fcount) {
-     sock->row[i]=0;
-     sock->row_sizes[i++]=0;
-   }
- }
-
-for (i=0, var=sock->sqlda_out->sqlvar; i<sock->sqlda_out->sqld; var++,i++) {
-//Initial buffer size to store field's data is 256 bytes
-  if (sock->row_sizes[i]<256) {
-   sock->row[i]=(char *) realloc(sock->row[i],256);
-   sock->row_sizes[i]=256;
-  }
-
- if (IS_NULL(var)) {
-  strcpy(sock->row[i],"NULL");
-  continue;
- }
- dtype=var->sqltype & ~1;
- switch (dtype) {
-   case SQL_TEXT:
-           if (sock->row_sizes[i]<=var->sqllen) {
-           sock->row_sizes[i]=var->sqllen+1;
-           sock->row[i]=(char *) realloc(sock->row[i],sock->row_sizes[i]);
-          }
-          memmove(sock->row[i],var->sqldata,var->sqllen);
-          sock->row[i][var->sqllen]=0;
-          break;
-   case        SQL_VARYING:
-          vary = (VARY*) var->sqldata;
-           if (sock->row_sizes[i]<=vary->vary_length) {
-           sock->row_sizes[i]=vary->vary_length+1;
-           sock->row[i]=(char *) realloc(sock->row[i],sock->row_sizes[i]);
-          }
-          memmove(sock->row[i],vary->vary_string,vary->vary_length);
-           sock->row[i][vary->vary_length] =0;
-           break;
-
-    case SQL_FLOAT:
-            snprintf(sock->row[i],sock->row_sizes[i], "%15g", *(float ISC_FAR *) (var->sqldata));
-            break;
-    case SQL_SHORT:
-    case SQL_LONG:
-    case SQL_INT64:
-               {
-               ISC_INT64       value;
-               short           field_width;
-               short           dscale;
-               char *p;
-               p=sock->row[i];
-               switch (dtype)
-                   {
-                   case SQL_SHORT:
-                       value = (ISC_INT64) *(short *) var->sqldata;
-                       field_width = 6;
-                       break;
-                   case SQL_LONG:
-                       value = (ISC_INT64) *(int *) var->sqldata;
-                       field_width = 11;
-                       break;
-                   case SQL_INT64:
-                       value = (ISC_INT64) *(ISC_INT64 *) var->sqldata;
-                       field_width = 21;
-                       break;
-                   }
-               dscale = var->sqlscale;
-               if (dscale < 0)
-                   {
-                   ISC_INT64   tens;
-                   short       j;
-
-                   tens = 1;
-                   for (j = 0; j > dscale; j--) tens *= 10;
-
-                   if (value >= 0)
-                       sprintf (p, "%*lld.%0*lld",
-                               field_width - 1 + dscale,
-                               (ISC_INT64) value / tens,
-                               -dscale,
-                               (ISC_INT64) value % tens);
-                   else if ((value / tens) != 0)
-                       sprintf (p, "%*lld.%0*lld",
-                               field_width - 1 + dscale,
-                               (ISC_INT64) (value / tens),
-                               -dscale,
-                               (ISC_INT64) -(value % tens));
-                   else
-                       sprintf (p, "%*s.%0*lld",
-                               field_width - 1 + dscale,
-                               "-0",
-                               -dscale,
-                               (ISC_INT64) -(value % tens));
-                   }
-               else if (dscale)
-                   sprintf (p, "%*lld%0*d",
-                           field_width,
-                           (ISC_INT64) value,
-                           dscale, 0);
-               else
-                   sprintf (p, "%*lld",
-                           field_width,
-                           (ISC_INT64) value);
-               }
-                break;
-
-
-    case SQL_DOUBLE: case SQL_D_FLOAT:
-           snprintf(sock->row[i],sock->row_sizes[i], "%24f", *(double ISC_FAR *) (var->sqldata));
-            break;
-
-    case SQL_TIMESTAMP:
-               isc_decode_timestamp((ISC_TIMESTAMP ISC_FAR *)var->sqldata, &times);
-               snprintf(sock->row[i],sock->row_sizes[i],"%04d-%02d-%02d %02d:%02d:%02d.%04d",
-                               times.tm_year + 1900,
-                               times.tm_mon+1,
-                               times.tm_mday,
-                               times.tm_hour,
-                               times.tm_min,
-                               times.tm_sec,
-                               ((ISC_TIMESTAMP *)var->sqldata)->timestamp_time % 10000);
-               break;
-
-    case SQL_TYPE_DATE:
-               isc_decode_sql_date((ISC_DATE ISC_FAR *)var->sqldata, &times);
-               snprintf(sock->row[i],sock->row_sizes[i], "%04d-%02d-%02d",
-                               times.tm_year + 1900,
-                               times.tm_mon+1,
-                               times.tm_mday);
-               break;
-
-    case SQL_TYPE_TIME:
-               isc_decode_sql_time((ISC_TIME ISC_FAR *)var->sqldata, &times);
-               snprintf(sock->row[i],sock->row_sizes[i], "%02d:%02d:%02d.%04d",
-                               times.tm_hour,
-                               times.tm_min,
-                               times.tm_sec,
-                               (*((ISC_TIME *)var->sqldata)) % 10000);
-               break;
-
-    case SQL_BLOB:
-    case SQL_ARRAY:
-                /* Print the blob id on blobs or arrays */
-                bid = *(ISC_QUAD ISC_FAR *) var->sqldata;
-                snprintf(sock->row[i],sock->row_sizes[i],"%08x:%08x", bid.gds_quad_high, bid.gds_quad_low);
-                break;
-
- } //END SWITCH
-} //END FOR
-}
-
-
-//=================
-int fb_init_socket(rlm_sql_firebird_sock *sock) {
-    memset(sock, 0, sizeof(*sock));
-    sock->sqlda_out = (XSQLDA ISC_FAR *) calloc(XSQLDA_LENGTH (5),1);
-    sock->sqlda_out->sqln = 5;
-    sock->sqlda_out->version =  SQLDA_VERSION1;
-    sock->sql_dialect=3;
-#ifdef _PTHREAD_H
-    pthread_mutex_init (&sock->mut, NULL);
-    radlog(L_DBG,"Init mutex %p\n",&sock->mut);
-#endif
-
-
-//set tpb to read_committed/wait/no_rec_version
-    fb_set_tpb(sock,5,
-        isc_tpb_version3,
-       isc_tpb_wait,
-       isc_tpb_write,
-       isc_tpb_read_committed,
-       isc_tpb_no_rec_version);
-    if (!sock->tpb) return -1;
-    return 0;
-}
-
-int fb_connect(rlm_sql_firebird_sock * sock,SQL_CONFIG *config) {
- char *p;
- char * database;
-
- sock->dpb_len=4;
- if (config->sql_login) sock->dpb_len+=strlen(config->sql_login)+2;
- if (config->sql_password) sock->dpb_len+=strlen(config->sql_password)+2;
-
- sock->dpb=(char *) malloc(sock->dpb_len);
- p=sock->dpb;
-
- *sock->dpb++ = isc_dpb_version1;
- *sock->dpb++ = isc_dpb_num_buffers;
- *sock->dpb++ = 1;
- *sock->dpb++ = 90;
-
- fb_dpb_add_str(&sock->dpb,isc_dpb_user_name,config->sql_login);
- fb_dpb_add_str(&sock->dpb,isc_dpb_password,config->sql_password);
-
- sock->dpb=p;
-// Check if database and server in the form of server:database.
-// If config->sql_server contains ':', then config->sql_db
-// parameter ignored
- if (strchr(config->sql_server,':'))  database=strdup(config->sql_server);
- else {
-// Make database and server to be in the form of server:database
-  int ls=strlen(config->sql_server);
-  int ld=strlen(config->sql_db);
-  database=(char *) calloc(ls+ld+2,1);
-  strcpy(database,config->sql_server);
-  database[ls]=':';
-  memmove(database+ls+1,config->sql_db,ld);
- }
- isc_attach_database(sock->status, 0, database, &sock->dbh, sock->dpb_len, sock->dpb);
- free(database);
- return fb_lasterror(sock);
-}
-
-
-int fb_fetch(rlm_sql_firebird_sock *sock) {
- long fetch_stat;
- if (sock->statement_type!=isc_info_sql_stmt_select) return 100;
- fetch_stat=isc_dsql_fetch(sock->status, &sock->stmt, SQL_DIALECT_V6, sock->sqlda_out);
- if (fetch_stat) {
-   if (fetch_stat!=100L) fb_lasterror(sock);
-   else  sock->sql_code=0;
- }
- return fetch_stat;
-}
-
-int fb_prepare(rlm_sql_firebird_sock *sock,char *sqlstr) {
- static char     stmt_info[] = { isc_info_sql_stmt_type };
- char            info_buffer[128];
- short l;
-
- if (!sock->trh) {
-  isc_start_transaction(sock->status,&sock->trh,1,&sock->dbh,sock->tpb_len,sock->tpb);
-  if (!sock->trh) return -4;
- }
-
- fb_free_statement(sock);
- if (!sock->stmt) {
-   isc_dsql_allocate_statement(sock->status, &sock->dbh, &sock->stmt);
-   if (!sock->stmt) return -1;
- }
-
- fb_free_sqlda(sock->sqlda_out);
- isc_dsql_prepare(sock->status, &sock->trh, &sock->stmt, 0, sqlstr, sock->sql_dialect, sock->sqlda_out);
- if (IS_ISC_ERROR(sock->status)) return -2;
-
- if (sock->sqlda_out->sqln<sock->sqlda_out->sqld) {
-   sock->sqlda_out->sqln=sock->sqlda_out->sqld;
-   sock->sqlda_out = (XSQLDA ISC_FAR *) realloc(sock->sqlda_out, XSQLDA_LENGTH (sock->sqlda_out->sqld));
-   isc_dsql_describe(sock->status,&sock->stmt,SQL_DIALECT_V6,sock->sqlda_out);
-   if (IS_ISC_ERROR(sock->status)) return -3;
- }
-
-//get statement type
- isc_dsql_sql_info(sock->status, &sock->stmt, sizeof (stmt_info), stmt_info,sizeof (info_buffer), info_buffer);
- if (IS_ISC_ERROR(sock->status)) return -4;
-
- l = (short) isc_vax_integer((char ISC_FAR *) info_buffer + 1, 2);
- sock->statement_type = isc_vax_integer((char ISC_FAR *) info_buffer + 3, l);
-
- if (sock->sqlda_out->sqld) fb_set_sqlda(sock->sqlda_out); //set out sqlda
-
- return 0;
-}
-
-
-int fb_sql_query(rlm_sql_firebird_sock *sock,char *sqlstr) {
- if (fb_prepare(sock,sqlstr)) return fb_lasterror(sock);
- switch (sock->statement_type) {
-    case isc_info_sql_stmt_exec_procedure:
-         isc_dsql_execute2(sock->status, &sock->trh, &sock->stmt, SQL_DIALECT_V6,0,sock->sqlda_out);
-        break;
-    default:
-         isc_dsql_execute(sock->status, &sock->trh, &sock->stmt, SQL_DIALECT_V6,0);
-        break;
- }
- return fb_lasterror(sock);
-}
-
-int fb_affected_rows(rlm_sql_firebird_sock *sock) {
- static char    count_info[] = {isc_info_sql_records};
- char            info_buffer[128];
- char *p ;
- int affected_rows=-1;
-
- if (!sock->stmt) return -1;
-
- isc_dsql_sql_info(sock->status, &sock->stmt,
-    sizeof (count_info), count_info,sizeof (info_buffer), info_buffer);
- if (IS_ISC_ERROR(sock->status)) return fb_lasterror(sock);
-
- p=info_buffer+3;
- while (*p != isc_info_end) {
-       p++;
-       short len = (short)isc_vax_integer(p,2);
-       p+=2;
-       affected_rows = isc_vax_integer(p,len);
-       if (affected_rows>0) break;
-       p += len;
- }
- return affected_rows;
-}
-
-int fb_close_cursor(rlm_sql_firebird_sock *sock) {
- isc_dsql_free_statement(sock->status, &sock->stmt, DSQL_close);
- return fb_lasterror(sock);
-}
-
-void fb_free_statement(rlm_sql_firebird_sock *sock) {
- if (sock->stmt) {
-  isc_dsql_free_statement(sock->status, &sock->stmt, DSQL_drop);
-  sock->stmt=0;
- }
-}
-
-int fb_rollback(rlm_sql_firebird_sock *sock) {
-    sock->sql_code=0;
-    if (sock->trh)  {
-       isc_rollback_transaction (sock->status,&sock->trh);
-//       sock->in_use=0;
-#ifdef _PTHREAD_H
-        pthread_mutex_unlock(&sock->mut);
-#endif
-
-       if (IS_ISC_ERROR(sock->status)) {
-         return fb_lasterror(sock);
-       }
-    }
-    return sock->sql_code;
-}
-
-int fb_commit(rlm_sql_firebird_sock *sock) {
-    sock->sql_code=0;
-    if (sock->trh)  {
-       isc_commit_transaction (sock->status,&sock->trh);
-       if (IS_ISC_ERROR(sock->status)) {
-         fb_lasterror(sock);
-        radlog(L_ERR,"Fail to commit. Error: %s. Try to rollback.\n",sock->lasterror);
-        return fb_rollback(sock);
-       }
-    }
-//    sock->in_use=0;
-#ifdef _PTHREAD_H
-    pthread_mutex_unlock(&sock->mut);
-#endif
-    return sock->sql_code;
-}
-
-int fb_disconnect(rlm_sql_firebird_sock *sock) {
- if (sock->dbh) {
-   fb_free_statement(sock);
-   isc_detach_database(sock->status,&sock->dbh);
-   return fb_lasterror(sock);
- }
- return 0;
-}
-
-void fb_destroy_socket(rlm_sql_firebird_sock *sock) {
- int i;
- fb_commit(sock);
- if (fb_disconnect(sock)) {
-  radlog(L_ERR,"Fatal. Fail to disconnect DB. Error :%s\n",sock->lasterror);
- }
-#ifdef _PTHREAD_H
- pthread_mutex_destroy (&sock->mut);
-#endif
- for (i=0; i<sock->row_fcount;i++) free(sock->row[i]);
- free(sock->row);free(sock->row_sizes);
- fb_free_sqlda(sock->sqlda_out);
- free(sock->sqlda_out);
- free(sock->tpb);
- free(sock->dpb);
- if (sock->lasterror) free(sock->lasterror);
- memset(sock,0,sizeof(rlm_sql_firebird_sock));
-}
diff --git a/src/modules/rlm_sql/drivers/rlm_sql_firebird/sql_fbapi.h b/src/modules/rlm_sql/drivers/rlm_sql_firebird/sql_fbapi.h
deleted file mode 100644 (file)
index 4e00451..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * sql_fbapi.h Part of Firebird rlm_sql driver
- *
- *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Copyright 2006  The FreeRADIUS server project
- * Copyright 2006  Vitaly Bodzhgua <vitaly@eastera.net>
- */
-
-
-#ifndef _SQL_FBAPI_H_
-#define _SQL_FBAPI_H_
-
-#include <stdlib.h>
-#include <string.h>
-#include <ibase.h>
-
-#include "radiusd.h"
-#include "rlm_sql.h"
-
-#define IS_ISC_ERROR(status)  (status[0] == 1 && status[1])
-
-#define DEADLOCK_SQL_CODE      -913
-#define DOWN_SQL_CODE          -902
-
-typedef struct rlm_sql_firebird_sock {
-       isc_db_handle dbh;
-       isc_stmt_handle stmt;
-       isc_tr_handle trh;
-       ISC_STATUS status[20];
-       ISC_LONG sql_code;
-       XSQLDA *sqlda_out;
-       int sql_dialect;
-       int statement_type;
-       char *tpb;
-       int tpb_len;
-       char *dpb;
-       int dpb_len;
-       char *lasterror;
-
-       SQL_ROW row;
-       int *row_sizes;
-       int row_fcount;
-
-#ifdef _PTHREAD_H
-       pthread_mutex_t mut;
-#endif
-
-
-} rlm_sql_firebird_sock;
-
-
-int fb_free_result(rlm_sql_firebird_sock *sock);
-int fb_lasterror(rlm_sql_firebird_sock *);
-int fb_init_socket(rlm_sql_firebird_sock *sock);
-int fb_connect(rlm_sql_firebird_sock * sock,SQL_CONFIG *config);
-int fb_disconnect(rlm_sql_firebird_sock * sock);
-int fb_sql_query(rlm_sql_firebird_sock * sock,char *sqlstr);
-int fb_affected_rows(rlm_sql_firebird_sock * sock);
-int fb_fetch(rlm_sql_firebird_sock * sock);
-void fb_free_statement(rlm_sql_firebird_sock *sock);
-int fb_close_cursor(rlm_sql_firebird_sock *sock);
-int fb_rollback(rlm_sql_firebird_sock * sock);
-int fb_commit(rlm_sql_firebird_sock * sock);
-void fb_destroy_socket(rlm_sql_firebird_sock *);
-void fb_store_row(rlm_sql_firebird_sock *sock);
-
-#endif
diff --git a/src/modules/rlm_sql/drivers/rlm_sql_firebird/sql_firebird.c b/src/modules/rlm_sql/drivers/rlm_sql_firebird/sql_firebird.c
deleted file mode 100644 (file)
index 2995081..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * sql_firebird.c Part of Firebird rlm_sql driver
- *
- *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Copyright 2006  The FreeRADIUS server project
- * Copyright 2006  Vitaly Bodzhgua <vitaly@eastera.net>
- */
-
-
-#include "sql_fbapi.h"
-
-
-/* Forward declarations */
-static char *sql_error(SQLSOCK *sqlsocket, SQL_CONFIG *config);
-static int sql_free_result(SQLSOCK *sqlsocket, SQL_CONFIG *config);
-static int sql_affected_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config);
-static int sql_num_fields(SQLSOCK *sqlsocket, SQL_CONFIG *config);
-static int sql_finish_query(SQLSOCK *sqlsocket, SQL_CONFIG *config);
-
-/*************************************************************************
- *
- *     Function: sql_init_socket
- *
- *     Purpose: Establish connection to the db
- *
- *************************************************************************/
-static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
-    rlm_sql_firebird_sock *firebird_sock;
-    long res;
-
-
-    if (!sqlsocket->conn) {
-       sqlsocket->conn = (rlm_sql_firebird_sock *)rad_malloc(sizeof(rlm_sql_firebird_sock));
-       if (!sqlsocket->conn) return -1;
-    }
-
-    firebird_sock = sqlsocket->conn;
-
-    res=fb_init_socket(firebird_sock);
-    if (res)  return -1;
-
-    if (fb_connect(firebird_sock,config)) {
-     radlog(L_ERR, "rlm_sql_firebird: Connection failed %s\n", firebird_sock->lasterror);
-     return SQL_DOWN;
-    }
-
-    return 0;
-}
-
-
-/*************************************************************************
- *
- *      Function: sql_destroy_socket
- *
- *      Purpose: Free socket and private connection data
- *
- *************************************************************************/
-static int sql_destroy_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config)
-{
-    free(sqlsocket->conn);
-    sqlsocket->conn = NULL;
-    return 0;
-}
-
-
-/*************************************************************************
- *
- *     Function: sql_query
- *
- *     Purpose: Issue a non-SELECT query (ie: update/delete/insert) to
- *               the database.
- *
- *************************************************************************/
-
-static int sql_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querystr) {
-    rlm_sql_firebird_sock *firebird_sock = sqlsocket->conn;
-    int deadlock=0;
- if (config->sqltrace)
-        radlog(L_DBG, "sock_id %i: query:  %s", sqlsocket->id,querystr);
-
-#ifdef _PTHREAD_H
- pthread_mutex_lock(&firebird_sock->mut);
-#endif
-
-TryAgain:
- if (fb_sql_query(firebird_sock,querystr)) {
-//Try again query when deadlock, beacuse in any case it will be retried.
-// but may be lost for short sessions
-   if ((firebird_sock->sql_code==DEADLOCK_SQL_CODE) && !deadlock) {
-      radlog(L_DBG,"sock_id %i: deadlock. Retry query %s\n",sqlsocket->id,querystr);
-//For non READ_COMMITED transactions put rollback here
-// fb_rollback(sock);
-      deadlock=1;
-      goto TryAgain;
-   }
-   radlog(L_ERR, "sock_id %i: rlm_sql_firebird,sql_query error:sql_code=%i, error='%s', query=%s\n",
-     sqlsocket->id,
-     firebird_sock->sql_code,
-     firebird_sock->lasterror,
-     querystr);
-
-   if ((firebird_sock->sql_code==DOWN_SQL_CODE)) return SQL_DOWN;
-//free problem query
-   if (fb_rollback(firebird_sock)) {
-    //assume the network is down if rollback had failed
-    radlog(L_ERR,"Fail to rollback transaction after previous error. Error: %s\n",
-       firebird_sock->lasterror);
-    return SQL_DOWN;
-   }
-//   firebird_sock->in_use=0;
-   return -1;
- }
-
- if (firebird_sock->statement_type!=isc_info_sql_stmt_select) {
-    if (fb_commit(firebird_sock)) return -1;
- }
-
- return 0;
-}
-
-
-/*************************************************************************
- *
- *     Function: sql_select_query
- *
- *     Purpose: Issue a select query to the database
- *
- *************************************************************************/
-static int sql_select_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querystr) {
-//    rlm_sql_firebird_sock *firebird_sock = sqlsocket->conn;
-    return (sql_query(sqlsocket, config, querystr));
-
-}
-
-
-/*************************************************************************
- *
- *     Function: sql_store_result
- *
- *     Purpose: database specific store_result function. Returns a result
- *               set for the query.
- *
- *************************************************************************/
-static int sql_store_result(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
-  /*   Not used   */
-    return 0;
-}
-
-
-/*************************************************************************
- *
- *     Function: sql_num_fields
- *
- *     Purpose: database specific num_fields function. Returns number
- *               of columns from query
- *
- *************************************************************************/
-static int sql_num_fields(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
-    return  ((rlm_sql_firebird_sock *) sqlsocket->conn)->sqlda_out->sqld;
-}
-
-
-/*************************************************************************
- *
- *     Function: sql_num_rows
- *
- *     Purpose: database specific num_rows. Returns number of rows in
- *               query
- *
- *************************************************************************/
-static int sql_num_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
-    int res=sql_affected_rows(sqlsocket, config);
-    radlog(L_DBG,"sock_id %i: sql_num_rows: %i\n",sqlsocket->id,res);
-    return res;
-}
-
-
-/*************************************************************************
- *
- *     Function: sql_fetch_row
- *
- *     Purpose: database specific fetch_row. Returns a SQL_ROW struct
- *               with all the data for the query in 'sqlsocket->row'. Returns
- *              0 on success, -1 on failure, SQL_DOWN if 'database is down'.
- *
- *************************************************************************/
-static int sql_fetch_row(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
-    rlm_sql_firebird_sock *firebird_sock = sqlsocket->conn;
-    int res;
-
-    sqlsocket->row = NULL;
-    if (firebird_sock->statement_type!=isc_info_sql_stmt_exec_procedure) {
-     res=fb_fetch(firebird_sock);
-     if (res==100) return 0;
-     if (res) {
-       radlog(L_ERR, "rlm_sql_firebird. Fetch problem:'%s'\n", firebird_sock->lasterror);
-       return -1;
-     }
-    } else firebird_sock->statement_type=0;
-    fb_store_row(firebird_sock);
-
-    sqlsocket->row = firebird_sock->row;
-    return 0;
-}
-
-
-/*************************************************************************
- *
- *     Function: sql_finish_select_query
- *
- *     Purpose: End the select query, such as freeing memory or result
- *
- *************************************************************************/
-static int sql_finish_select_query(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
-    rlm_sql_firebird_sock *sock=(rlm_sql_firebird_sock *) sqlsocket->conn;
-    fb_commit(sock);
-    fb_close_cursor(sock);
-    return 0;
-}
-
-/*************************************************************************
- *
- *     Function: sql_finish_query
- *
- *     Purpose: End the query, such as freeing memory
- *
- *************************************************************************/
-static int sql_finish_query(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
-//    sql_free_result(sqlsocket,config);
-    return 0;
-}
-
-/*************************************************************************
- *
- *     Function: sql_free_result
- *
- *     Purpose: database specific free_result. Frees memory allocated
- *               for a result set
- *
- *************************************************************************/
-static int sql_free_result(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
-    return 0;
-}
-
-/*************************************************************************
- *
- *     Function: sql_close
- *
- *     Purpose: database specific close. Closes an open database
- *               connection and cleans up any open handles.
- *
- *************************************************************************/
-static int sql_close(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
-//    radlog(L_INFO,"Closing sql\n");
-    fb_destroy_socket((rlm_sql_firebird_sock *) sqlsocket->conn);
-    return 0;
-}
-
-/*************************************************************************
- *
- *     Function: sql_error
- *
- *     Purpose: database specific error. Returns error associated with
- *               connection
- *
- *************************************************************************/
-static char *sql_error(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
-    rlm_sql_firebird_sock *firebird_sock = sqlsocket->conn;
-    return firebird_sock->lasterror;
-}
-/*************************************************************************
- *
- *     Function: sql_affected_rows
- *
- *     Purpose: Return the number of rows affected by the query (update,
- *               or insert)
- *
- *************************************************************************/
-static int sql_affected_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
- int affected_rows=fb_affected_rows(sqlsocket->conn);
- if (affected_rows<0)
-   radlog(L_ERR, "sql_affected_rows, rlm_sql_firebird. error:%s\n", sql_error(sqlsocket,config));
- radlog(L_DBG,"sock_id %i: affected_rows: %i\n",sqlsocket->id,affected_rows);
- return affected_rows;
-}
-
-/* Exported to rlm_sql */
-rlm_sql_module_t rlm_sql_firebird = {
-       "rlm_sql_firebird",
-       sql_init_socket,
-       sql_destroy_socket,
-       sql_query,
-       sql_select_query,
-       sql_store_result,
-       sql_num_fields,
-       sql_num_rows,
-       sql_fetch_row,
-       sql_free_result,
-       sql_error,
-       sql_close,
-       sql_finish_query,
-       sql_finish_select_query,
-       sql_affected_rows
-};
diff --git a/src/modules/rlm_sql/drivers/rlm_sql_freetds/Makefile b/src/modules/rlm_sql/drivers/rlm_sql_freetds/Makefile
deleted file mode 100644 (file)
index e2baf78..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-#  The FreeTDS libraries are still in development, and the API to use
-#  them has not been finalized.  As a result, if you want to use this
-#  module, you MUST edit the source, and update the rest of this
-#  file by hand.
-#
-#  Please do NOT ask questions about the FreeTDS libraries or API's
-#  on the FreeRADIUS list.  No one there can answer your questions.
-#  Instead, ask questions on the FreeTDS mailing list.
-#
-
-include ../../../../../Make.inc
-
-TARGET                 = 
-SRCS                   = sql_freetds.c
-RLM_SQL_CFLAGS         = 
-RLM_SQL_CXXFLAGS       = 
-RLM_SQL_LDFLAGS                =
-RLM_SQL_LIBS           =
-
-include ../rules.mak
index cd57a7b..db8fae9 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.2 .
+# From configure.in Revision: 1.3 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -908,7 +908,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1826,8 +1826,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1885,8 +1884,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2002,8 +2000,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2057,8 +2054,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2103,8 +2099,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2148,8 +2143,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2481,8 +2475,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2534,8 +2527,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2611,8 +2603,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3479,11 +3470,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3522,6 +3508,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 28c5371..4468084 100644 (file)
@@ -36,7 +36,7 @@ if test x$with_[]modname != xno; then
        if test "x$IODBC_INCLUDE" = "x"; then
                old_CFLAGS="$CFLAGS"
 
-dnl            AC_LOCATE_DIR(iodbc_include_dir,[isql.h])
+dnl            FR_LOCATE_DIR(iodbc_include_dir,[isql.h])
 
                for try in /usr/local/include /usr/local/iodbc/include $iodbc_include_dir; do
                        CFLAGS="$old_CFLAGS -I$try"
@@ -65,8 +65,8 @@ dnl           AC_LOCATE_DIR(iodbc_include_dir,[isql.h])
 
                old_LIBS="$LIBS"
 
-dnl            AC_LOCATE_DIR(iodbc_lib_dir,[libodbc${libltdl_cv_shlibext}])
-dnl            AC_LOCATE_DIR(iodbc_lib_dir,[libodbc.a])
+dnl            FR_LOCATE_DIR(iodbc_lib_dir,[libodbc${libltdl_cv_shlibext}])
+dnl            FR_LOCATE_DIR(iodbc_lib_dir,[libodbc.a])
 
                for try in /usr/lib /usr/lib/iodbc /usr/local/lib/iodbc /usr/local/iodbc/lib/iodbc $iodbc_lib_dir; do
                        LIBS="$old_LIBS -L$try -liodbc"
index 0784232..308ed12 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * sql_iodbc.c iODBC support for FreeRadius
  *
+ * 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
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Jeff Carneal <jeff@apex.net>
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
 #include <stdio.h>
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include       "radiusd.h"
-#include  "rlm_sql.h"
-
 #include <isql.h>
 #include <isqlext.h>
 #include <sqltypes.h>
+
+#include <freeradius-devel/radiusd.h>
 #include "rlm_sql.h"
 
 typedef struct rlm_sql_iodbc_sock {
@@ -57,6 +63,7 @@ static int sql_num_fields(SQLSOCK *sqlsocket, SQL_CONFIG *config);
 static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
 
        rlm_sql_iodbc_sock *iodbc_sock;
+       SQLRETURN rcode;
 
        if (!sqlsocket->conn) {
                sqlsocket->conn = (rlm_sql_iodbc_sock *)rad_malloc(sizeof(rlm_sql_iodbc_sock));
@@ -67,21 +74,25 @@ static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
        iodbc_sock = sqlsocket->conn;
        memset(iodbc_sock, 0, sizeof(*iodbc_sock));
 
-       if(SQLAllocEnv(&iodbc_sock->env_handle) != SQL_SUCCESS) {
+       rcode = SQLAllocEnv(&iodbc_sock->env_handle);
+       if (!SQL_SUCCEEDED(rcode)) {
                radlog(L_CONS|L_ERR, "sql_create_socket: SQLAllocEnv failed:  %s",
                                sql_error(sqlsocket, config));
                return -1;
        }
 
-       if(SQLAllocConnect(iodbc_sock->env_handle, &iodbc_sock->dbc_handle) != SQL_SUCCESS) {
+       rcode = SQLAllocConnect(iodbc_sock->env_handle,
+                               &iodbc_sock->dbc_handle);
+       if (!SQL_SUCCEEDED(rcode)) {
                radlog(L_CONS|L_ERR, "sql_create_socket: SQLAllocConnect failed:  %s",
                                sql_error(sqlsocket, config));
                return -1;
        }
 
-       if (SQLConnect(iodbc_sock->dbc_handle, config->sql_db, SQL_NTS,
-                               config->sql_login, SQL_NTS, config->sql_password,
-                               SQL_NTS) != SQL_SUCCESS) {
+       rcode = SQLConnect(iodbc_sock->dbc_handle, config->sql_db,
+                          SQL_NTS, config->sql_login, SQL_NTS,
+                          config->sql_password, SQL_NTS);
+       if (!SQL_SUCCEEDED(rcode)) {
                radlog(L_CONS|L_ERR, "sql_create_socket: SQLConnectfailed:  %s",
                                sql_error(sqlsocket, config));
                return -1;
@@ -97,7 +108,7 @@ static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
  *     Purpose: Free socket and private connection data
  *
  *************************************************************************/
-static int sql_destroy_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config)
+static int sql_destroy_socket(SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config)
 {
        free(sqlsocket->conn);
        sqlsocket->conn = NULL;
@@ -115,8 +126,11 @@ static int sql_destroy_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config)
 static int sql_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querystr) {
 
        rlm_sql_iodbc_sock *iodbc_sock = sqlsocket->conn;
+       SQLRETURN rcode;
 
-       if(SQLAllocStmt(iodbc_sock->dbc_handle, &iodbc_sock->stmt_handle) != SQL_SUCCESS) {
+       rcode = SQLAllocStmt(iodbc_sock->dbc_handle,
+                            &iodbc_sock->stmt_handle);
+       if (!SQL_SUCCEEDED(rcode)) {
                radlog(L_CONS|L_ERR, "sql_create_socket: SQLAllocStmt failed:  %s",
                                sql_error(sqlsocket, config));
                return -1;
@@ -129,7 +143,8 @@ static int sql_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querystr) {
                return -1;
        }
 
-       if (SQLExecDirect(iodbc_sock->stmt_handle, querystr, SQL_NTS) != SQL_SUCCESS) {
+       rcode = SQLExecDirect(iodbc_sock->stmt_handle, querystr, SQL_NTS);
+       if (!SQL_SUCCEEDED(rcode)) {
                radlog(L_CONS|L_ERR, "sql_query: failed:  %s",
                                sql_error(sqlsocket, config));
                return -1;
@@ -198,7 +213,7 @@ static int sql_select_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querys
  *               set for the query.
  *
  *************************************************************************/
-static int sql_store_result(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
+static int sql_store_result(UNUSED SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config) {
 
        return 0;
 }
@@ -212,7 +227,7 @@ static int sql_store_result(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
  *               of columns from query
  *
  *************************************************************************/
-static int sql_num_fields(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
+static int sql_num_fields(SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config) {
 
        SQLSMALLINT count=0;
        rlm_sql_iodbc_sock *iodbc_sock = sqlsocket->conn;
@@ -230,7 +245,7 @@ static int sql_num_fields(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
  *               query
  *
  *************************************************************************/
-static int sql_num_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
+static int sql_num_rows(UNUSED SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config) {
        /*
         * I presume this function is used to determine the number of
         * rows in a result set *before* fetching them.  I don't think
@@ -250,7 +265,7 @@ static int sql_num_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
  *              0 on success, -1 on failure, SQL_DOWN if 'database is down'
  *
  *************************************************************************/
-static int sql_fetch_row(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
+static int sql_fetch_row(SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config) {
 
        SQLRETURN rc;
        rlm_sql_iodbc_sock *iodbc_sock = sqlsocket->conn;
@@ -301,7 +316,7 @@ static int sql_free_result(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
  *               connection
  *
  *************************************************************************/
-static char *sql_error(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
+static char *sql_error(SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config) {
 
        SQLINTEGER errornum = 0;
        SQLSMALLINT length = 0;
@@ -323,7 +338,7 @@ static char *sql_error(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
  *               connection and cleans up any open handles.
  *
  *************************************************************************/
-static int sql_close(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
+static int sql_close(SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config) {
 
        rlm_sql_iodbc_sock *iodbc_sock = sqlsocket->conn;
 
@@ -374,7 +389,7 @@ static int sql_finish_select_query(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
  *               or insert)
  *
  *************************************************************************/
-static int sql_affected_rows(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
+static int sql_affected_rows(SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config) {
 
        SQLINTEGER count;
        rlm_sql_iodbc_sock *iodbc_sock = sqlsocket->conn;
index e205cb9..0d4d035 100644 (file)
@@ -1,12 +1,4 @@
-/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
-/*
-
-acconfig.h - template used by autoheader to create config.h.in
-config.h.in - used by autoconf to create config.h
-config.h - created by autoconf; contains defines generated by autoconf
-
-*/
-
+/* config.h.in.  Generated from configure.in by autoheader.  */
 
 /* Define if you have <mysql.h> */
 #undef HAVE_MYSQL_H
@@ -14,3 +6,17 @@ config.h - created by autoconf; contains defines generated by autoconf
 /* Define if you have <mysql/mysql.h> */
 #undef HAVE_MYSQL_MYSQL_H
 
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
index e173482..f9f540f 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.9.4.1 .
+# From configure.in Revision: 1.12 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -904,7 +904,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1875,8 +1875,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1934,8 +1933,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2051,8 +2049,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2106,8 +2103,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2152,8 +2148,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2197,8 +2192,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2314,8 +2308,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2382,8 +2375,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2458,8 +2450,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2530,8 +2521,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2584,8 +2574,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2690,8 +2679,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2774,8 +2762,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2846,8 +2833,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2900,8 +2886,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3006,8 +2991,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3085,8 +3069,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3161,8 +3144,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3215,8 +3197,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3294,8 +3275,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -4146,11 +4126,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -4189,6 +4164,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 9146800..0e328b1 100644 (file)
@@ -91,7 +91,7 @@ if test x$with_[]modname != xno; then
            dnl mysql_config didn't work :(
            smart_try_dir="$mysql_lib_dir /usr/lib /usr/lib/mysql \
                /usr/local/lib/mysql /usr/local/mysql/lib/mysql"
-           AC_SMART_CHECK_LIB(mysqlclient_r, mysql_init)
+           FR_SMART_CHECK_LIB(mysqlclient_r, mysql_init)
            if test "x$ac_cv_lib_mysqlclient_r_mysql_init" != "xyes"
                then
                dnl nothing worked :(
@@ -119,7 +119,7 @@ if test x$with_[]modname != xno; then
            dnl mysql_config didn't work :(
            smart_try_dir="$mysql_lib_dir /usr/lib /usr/lib/mysql \
                /usr/local/lib/mysql /usr/local/mysql/lib/mysql"
-           AC_SMART_CHECK_LIB(mysqlclient, mysql_init)
+           FR_SMART_CHECK_LIB(mysqlclient, mysql_init)
            if test "x$ac_cv_lib_mysqlclient_mysql_init" != "xyes"
                then
                dnl nothing worked :(
@@ -153,7 +153,7 @@ if test x$with_[]modname != xno; then
        dnl mysql_config didn't work :(
        smart_try_dir="$mysql_include_dir /usr/local/include \
                /usr/local/mysql/include"
-       AC_SMART_CHECK_INCLUDE(mysql/mysql.h)
+       FR_SMART_CHECK_INCLUDE(mysql/mysql.h)
        if test "$ac_cv_header_mysql_mysql_h" = "yes"; then
            AC_DEFINE(HAVE_MYSQL_MYSQL_H, [],
                      [Define if you have <mysql/mysql.h>])
index 483c8d2..fa32728 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Mike Machado <mike@innercite.com>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
 #include <stdio.h>
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include       "radiusd.h"
+#include <freeradius-devel/radiusd.h>
 
 #include "config.h"
 
@@ -101,7 +106,7 @@ static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config)
  *     Purpose: Free socket and any private connection data
  *
  *************************************************************************/
-static int sql_destroy_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config)
+static int sql_destroy_socket(SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config)
 {
        free(sqlsocket->conn);
        sqlsocket->conn = NULL;
@@ -171,7 +176,7 @@ static int sql_query(SQLSOCK * sqlsocket, SQL_CONFIG *config, char *querystr)
  *               set for the query.
  *
  *************************************************************************/
-static int sql_store_result(SQLSOCK * sqlsocket, SQL_CONFIG *config)
+static int sql_store_result(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
 {
        rlm_sql_mysql_sock *mysql_sock = sqlsocket->conn;
 
@@ -197,7 +202,7 @@ static int sql_store_result(SQLSOCK * sqlsocket, SQL_CONFIG *config)
  *               of columns from query
  *
  *************************************************************************/
-static int sql_num_fields(SQLSOCK * sqlsocket, SQL_CONFIG *config)
+static int sql_num_fields(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
 {
        int     num = 0;
        rlm_sql_mysql_sock *mysql_sock = sqlsocket->conn;
@@ -253,7 +258,7 @@ static int sql_select_query(SQLSOCK *sqlsocket, SQL_CONFIG *config,
  *               query
  *
  *************************************************************************/
-static int sql_num_rows(SQLSOCK * sqlsocket, SQL_CONFIG *config)
+static int sql_num_rows(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
 {
        rlm_sql_mysql_sock *mysql_sock = sqlsocket->conn;
 
@@ -273,7 +278,7 @@ static int sql_num_rows(SQLSOCK * sqlsocket, SQL_CONFIG *config)
  *              0 on success, -1 on failure, SQL_DOWN if database is down.
  *
  *************************************************************************/
-static int sql_fetch_row(SQLSOCK * sqlsocket, SQL_CONFIG *config)
+static int sql_fetch_row(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
 {
        rlm_sql_mysql_sock *mysql_sock = sqlsocket->conn;
 
@@ -301,7 +306,7 @@ static int sql_fetch_row(SQLSOCK * sqlsocket, SQL_CONFIG *config)
  *               for a result set
  *
  *************************************************************************/
-static int sql_free_result(SQLSOCK * sqlsocket, SQL_CONFIG *config)
+static int sql_free_result(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
 {
        rlm_sql_mysql_sock *mysql_sock = sqlsocket->conn;
 
@@ -323,7 +328,7 @@ static int sql_free_result(SQLSOCK * sqlsocket, SQL_CONFIG *config)
  *               connection
  *
  *************************************************************************/
-static char *sql_error(SQLSOCK * sqlsocket, SQL_CONFIG *config)
+static char *sql_error(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
 {
        rlm_sql_mysql_sock *mysql_sock = sqlsocket->conn;
 
@@ -342,7 +347,7 @@ static char *sql_error(SQLSOCK * sqlsocket, SQL_CONFIG *config)
  *               connection
  *
  *************************************************************************/
-static int sql_close(SQLSOCK * sqlsocket, SQL_CONFIG *config)
+static int sql_close(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
 {
        rlm_sql_mysql_sock *mysql_sock = sqlsocket->conn;
 
@@ -362,7 +367,7 @@ static int sql_close(SQLSOCK * sqlsocket, SQL_CONFIG *config)
  *     Purpose: End the query, such as freeing memory
  *
  *************************************************************************/
-static int sql_finish_query(SQLSOCK * sqlsocket, SQL_CONFIG *config)
+static int sql_finish_query(UNUSED SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
 {
        return 0;
 }
@@ -391,7 +396,7 @@ static int sql_finish_select_query(SQLSOCK * sqlsocket, SQL_CONFIG *config)
  *     Purpose: End the select query, such as freeing memory or result
  *
  *************************************************************************/
-static int sql_affected_rows(SQLSOCK * sqlsocket, SQL_CONFIG *config)
+static int sql_affected_rows(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
 {
        rlm_sql_mysql_sock *mysql_sock = sqlsocket->conn;
 
index df1c4a4..b863af2 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.7 .
+# From configure.in Revision: 1.9 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -901,7 +901,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1822,8 +1822,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1881,8 +1880,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1998,8 +1996,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2053,8 +2050,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2099,8 +2095,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2144,8 +2139,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2453,8 +2447,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2476,6 +2469,96 @@ ORACLE_INCLUDE=
 fi
 rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
 
+        # Look for Oracle10g "Instant Client" installed from RPM
+        if test "x$ORACLE_INCLUDE" = "x"; then
+                old_CFLAGS="$CFLAGS"
+
+        { echo "$as_me:$LINENO: WARNING: PETER XXXXXXXXXXXXXXXX1." >&5
+echo "$as_me: WARNING: PETER XXXXXXXXXXXXXXXX1." >&2;}
+
+
+if test "x$LOCATE" != "x"; then
+        DIRS=
+  file=oci.h
+
+  for x in `${LOCATE} $file 2>/dev/null`; do
+                                        base=`echo $x | sed "s%/${file}%%"`
+    if test "x$x" = "x$base"; then
+      continue;
+    fi
+
+    dir=`${DIRNAME} $x 2>/dev/null`
+                exclude=`echo ${dir} | ${GREP} /home`
+    if test "x$exclude" != "x"; then
+      continue
+    fi
+
+                    already=`echo \$oracle_include_dir ${DIRS} | ${GREP} ${dir}`
+    if test "x$already" = "x"; then
+      DIRS="$DIRS $dir"
+    fi
+  done
+fi
+
+eval "oracle_include_dir=\"\$oracle_include_dir $DIRS\""
+
+
+                for try in /usr/include/oracle/10.1.0.3/client $oracle_include_dir; do
+                        CFLAGS="$old_CFLAGS -I$try"
+                        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <oci.h>
+int
+main ()
+{
+ int a = 1;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ORACLE_INCLUDE="-I$try"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ORACLE_INCLUDE=
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+                        if test "x$ORACLE_INCLUDE" != "x"; then
+                                ORACLE_LIBS="-L$/usr/lib/oracle/10.1.0.3/client/lib -lclntsh -lm"
+                                break;
+                        fi
+                done
+                CFLAGS="$old_CFLAGS"
+        fi
+        # Finish Looking for Oracle10g includes installed from RPM
+
        # Look for Oracle8i.
        if test "x$ORACLE_INCLUDE" = "x"; then
                old_CFLAGS="$CFLAGS"
@@ -2534,8 +2617,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2587,8 +2669,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2677,8 +2758,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2812,8 +2892,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3684,11 +3763,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3727,6 +3801,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 866654c..345858c 100644 (file)
@@ -30,11 +30,34 @@ if test x$with_[]modname != xno; then
                ORACLE_INCLUDE=
        )
 
+        # Look for Oracle10g "Instant Client" installed from RPM
+        if test "x$ORACLE_INCLUDE" = "x"; then
+                old_CFLAGS="$CFLAGS"
+
+        AC_MSG_WARN([PETER XXXXXXXXXXXXXXXX1.])
+                FR_LOCATE_DIR(oracle_include_dir,oci.h)
+
+                for try in /usr/include/oracle/10.1.0.3/client $oracle_include_dir; do
+                        CFLAGS="$old_CFLAGS -I$try"
+                        AC_TRY_COMPILE([#include <oci.h>],
+                                [ int a = 1; ],
+                                ORACLE_INCLUDE="-I$try",
+                                ORACLE_INCLUDE=
+                        )
+                        if test "x$ORACLE_INCLUDE" != "x"; then
+                                ORACLE_LIBS="-L$/usr/lib/oracle/10.1.0.3/client/lib -lclntsh -lm"
+                                break;
+                        fi
+                done
+                CFLAGS="$old_CFLAGS"
+        fi
+        # Finish Looking for Oracle10g includes installed from RPM
+
        # Look for Oracle8i.
        if test "x$ORACLE_INCLUDE" = "x"; then
                old_CFLAGS="$CFLAGS"
 
-               AC_LOCATE_DIR(oracle_home_dir,oci.h)
+               FR_LOCATE_DIR(oracle_home_dir,oci.h)
 
                for try in $oracle_home_dir $oracle_include_dir; do
                        CFLAGS="$old_CFLAGS -I${try}/rdbms/demo -I${try}/rdbms/public -I${try}/plsql/public -I${try}/network/public -I${try}/oci/include"
@@ -69,7 +92,7 @@ if test x$with_[]modname != xno; then
        if test "x$ORACLE_INCLUDE" = "x"; then
                old_CFLAGS="$CFLAGS"
 
-               AC_LOCATE_DIR(oracle_include_dir,oci.h)
+               FR_LOCATE_DIR(oracle_include_dir,oci.h)
 
                for try in /usr/local/include/oracle /usr/local/oracle/include $oracle_include_dir; do
                        CFLAGS="$old_CFLAGS -I$try"
@@ -109,8 +132,8 @@ if test x$with_[]modname != xno; then
                        dnl #
                        old_LIBS="$LIBS"
 
-                       AC_LOCATE_DIR(oracle_lib_dir,[oracleclient.so])
-                       AC_LOCATE_DIR(oracle_lib_dir,[oracleclient.a])
+                       FR_LOCATE_DIR(oracle_lib_dir,[oracleclient.so])
+                       FR_LOCATE_DIR(oracle_lib_dir,[oracleclient.a])
 
                        for try in /usr/lib/oracle /usr/local/lib/oracle /usr/local/oracle/lib $oracle_lib_dir; do
                                LIBS="$old_LIBS -L$try -loracleclient"
index 915ee15..da14953 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  David Kerry <davidk@snti.com>
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
 #include <stdio.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include       "radiusd.h"
+#include       <freeradius-devel/radiusd.h>
 
 #include <oci.h>
 #include "rlm_sql.h"
@@ -73,6 +78,25 @@ static char *sql_error(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
        }
 }
 
+/*************************************************************************
+ *
+ *     Function: sql_check_error
+ *
+ *     Purpose: check the error to see if the server is down
+ *
+ *************************************************************************/
+static int sql_check_error(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
+
+       if (strstr(sql_error(sqlsocket, config), "ORA-03113") ||
+                       strstr(sql_error(sqlsocket, config), "ORA-03114")) {
+               radlog(L_ERR,"rlm_sql_oracle: OCI_SERVER_NOT_CONNECTED");
+               return SQL_DOWN;
+       }
+       else {
+               radlog(L_ERR,"rlm_sql_oracle: OCI_SERVER_NORMAL");
+               return -1;
+       }
+}
 
 /*************************************************************************
  *
@@ -244,22 +268,20 @@ static int sql_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querystr) {
                                (ub4) 0,
                                (OCISnapshot *) NULL,
                                (OCISnapshot *) NULL,
-                               (ub4) OCI_DEFAULT);
+                               (ub4) OCI_COMMIT_ON_SUCCESS);
 
-       if ((x != OCI_NO_DATA) && (x != OCI_SUCCESS)) {
-               radlog(L_ERR,"rlm_sql_oracle: execute query failed in sql_query: %s",
-                               sql_error(sqlsocket, config));
-               return SQL_DOWN;
+       if (x == OCI_SUCCESS) {
+               return 0;
        }
 
-       x = OCITransCommit(oracle_sock->conn, oracle_sock->errHandle, (ub4) 0);
-       if (x != OCI_SUCCESS) {
-               radlog(L_ERR,"rlm_sql_oracle: commit failed in sql_query: %s",
+       if (x == OCI_ERROR) {
+               radlog(L_ERR,"rlm_sql_oracle: execute query failed in sql_query: %s",
                                sql_error(sqlsocket, config));
-               return SQL_DOWN;
+               return sql_check_error(sqlsocket, config);
+       }
+       else {
+               return -1;
        }
-
-       return 0;
 }
 
 
@@ -311,9 +333,11 @@ static int sql_select_query(SQLSOCK *sqlsocket, SQL_CONFIG *config, char *querys
                /* Nothing to fetch */
                return 0;
        }
-       else if (x != OCI_SUCCESS) {
-               radlog(L_ERR,"rlm_sql_oracle: query failed in sql_select_query: %s",sql_error(sqlsocket, config));
-               return SQL_DOWN;
+
+       if (x != OCI_SUCCESS) {
+               radlog(L_ERR,"rlm_sql_oracle: query failed in sql_select_query: %s",
+                               sql_error(sqlsocket, config));
+               return sql_check_error(sqlsocket, config);
        }
 
        /*
@@ -492,18 +516,20 @@ static int sql_fetch_row(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
                        1,
                        OCI_FETCH_NEXT,
                        OCI_DEFAULT);
-       if (x == OCI_NO_DATA) {
-               return -1;
+
+       if (x == OCI_SUCCESS) {
+               sqlsocket->row = oracle_sock->results;
+               return 0;
        }
-       else if (x != OCI_SUCCESS) {
-               /* XXX Check if x suggests we should return SQL_DOWN */
+
+       if (x == OCI_ERROR) {
                radlog(L_ERR,"rlm_sql_oracle: fetch failed in sql_fetch_row: %s",
                                sql_error(sqlsocket, config));
-               return SQL_DOWN;
+               return sql_check_error(sqlsocket, config);
+       }
+       else {
+               return -1;
        }
-
-       sqlsocket->row = oracle_sock->results;
-       return 0;
 }
 
 
index 6061c73..3e15c0d 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.6 .
+# From configure.in Revision: 1.7 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -902,7 +902,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1825,8 +1825,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1884,8 +1883,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2001,8 +1999,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2056,8 +2053,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2102,8 +2098,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2147,8 +2142,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2268,8 +2262,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2292,8 +2285,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" = "x"; then
@@ -2322,8 +2315,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2401,8 +2393,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2425,8 +2416,8 @@ rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
     if test "x$smart_include" != "x"; then
       break;
     fi
+    CFLAGS="$old_CFLAGS"
   done
-  CFLAGS="$old_CFLAGS"
 fi
 
 if test "x$smart_include" != "x"; then
@@ -2483,8 +2474,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2507,8 +2497,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" = "x"; then
@@ -2537,8 +2527,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2643,8 +2632,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2667,8 +2655,8 @@ rm -f conftest.err conftest.$ac_objext \
     if test "x$smart_lib" != "x"; then
       break;
     fi
+    LIBS="$old_LIBS"
   done
-  LIBS="$old_LIBS"
 fi
 
 if test "x$smart_lib" != "x"; then
@@ -3528,11 +3516,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3571,6 +3554,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 68af69e..b24be0c 100644 (file)
@@ -42,13 +42,13 @@ if test x$with_[]modname != xno; then
        )
 
        smart_try_dir="$rlm_sql_postgresql_include_dir /usr/include/postgresql /usr/local/pgsql/include /usr/include/pgsql"
-       AC_SMART_CHECK_INCLUDE(libpq-fe.h)
+       FR_SMART_CHECK_INCLUDE(libpq-fe.h)
        if test "x$ac_cv_header_libpqmfe_h" != "xyes"; then
          fail="$fail libpq-fe.h"
        fi
 
        smart_try_dir="$rlm_sql_postgresql_lib_dir /usr/lib /usr/local/pgsql/lib"
-       AC_SMART_CHECK_LIB(pq, PQconnectdb)
+       FR_SMART_CHECK_LIB(pq, PQconnectdb)
         if test "x$ac_cv_lib_pq_PQconnectdb" != "xyes"; then
          fail="$fail libpq"
         fi
index e5ce5df..8618adc 100644 (file)
@@ -15,9 +15,9 @@
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Mike Machado <mike@innercite.com>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
  * Bernhard Herzog <bh@intevation.de>
  */
 
-/* Modification of rlm_sql_mysql to handle postgres */
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "radiusd.h"
+#include <freeradius-devel/radiusd.h>
 
-#include        <libpq-fe.h>
-#include       "rlm_sql.h"
+#include <libpq-fe.h>
+#include "rlm_sql.h"
+#include "sql_postgresql.h"
 
 typedef struct rlm_sql_postgres_sock {
    PGconn          *conn;
    PGresult        *result;
    int             cur_row;
    int             num_fields;
-    int                   affected_rows;
+   int            affected_rows;
    char            **row;
 } rlm_sql_postgres_sock;
 
 /* Prototypes */
-static int sql_store_result(SQLSOCK * sqlsocket, SQL_CONFIG *config);
-static int sql_num_fields(SQLSOCK * sqlsocket, SQL_CONFIG *config);
-static int sql_close(SQLSOCK * sqlsocket, SQL_CONFIG *config);
+static int sql_close(SQLSOCK *sqlsocket, SQL_CONFIG *config);
 
 /* Internal function. Return true if the postgresql status value
  * indicates successful completion of the query. Return false otherwise
- */
 static int
 status_is_ok(ExecStatusType status)
 {
        return status == PGRES_COMMAND_OK || status == PGRES_TUPLES_OK;
 }
+*/
 
 
 /* Internal function. Return the number of affected rows of the result
@@ -90,52 +92,51 @@ free_result_row(rlm_sql_postgres_sock * pg_sock)
        if (pg_sock->row != NULL) {
                for (i = pg_sock->num_fields-1; i >= 0; i--) {
                        if (pg_sock->row[i] != NULL) {
-                               xfree(pg_sock->row[i]);
+                               free(pg_sock->row[i]);
                        }
                }
-               xfree((char*)pg_sock->row);
+               free((char*)pg_sock->row);
                pg_sock->row = NULL;
                pg_sock->num_fields = 0;
        }
 }
 
+
 /*************************************************************************
- *
- *      Function: sql_check_error
- *
- *      Purpose: check the error to see if the server is down
- *
- *     Note: It is possible that something other than a connection error
- *     could cause PGRES_FATAL_ERROR. If that happens a reconnect will
- *     occur anyway. Not optimal, but I couldn't find a way to check it.
- *                             Peter Nixon <codemonkey@peternixon.net>
- *
-
-************************************************************************/
-static int sql_check_error(int error) {
-        switch(error) {
-        case PGRES_FATAL_ERROR:
-        case -1:
-                radlog(L_DBG, "rlm_sql_postgresql: Postgresql check_error: %s, returning SQL_DOWN", PQresStatus(error));
-                return SQL_DOWN;
-                break;
-
-        case PGRES_COMMAND_OK:
-        case PGRES_TUPLES_OK:
-        case 0:
-                return 0;
-                break;
-
-        case PGRES_NONFATAL_ERROR:
-        case PGRES_BAD_RESPONSE:
-        default:
-                radlog(L_DBG, "rlm_sql_postgresql: Postgresql check_error: %s received", PQresStatus(error));
-                return -1;
-                break;
-        }
+*      Function: check_fatal_error
+*      
+*      Purpose:  Check error type and behave accordingly
+*
+*************************************************************************/
+
+static int check_fatal_error (char *errorcode)
+{
+       int x = 0;
+
+       /*      
+       Check the error code to see if we should reconnect or not
+       Error Code table taken from
+       http://www.postgresql.org/docs/8.1/interactive/errcodes-appendix.html
+       */
+
+       while(errorcodes[x].errorcode != NULL){
+               if (strcmp(errorcodes[x].errorcode, errorcode) == 0){
+                       radlog(L_DBG, "rlm_sql_postgresql: Postgresql Fatal Error: [%s: %s] Occurred!!", errorcode, errorcodes[x].meaning);
+                       if (errorcodes[x].shouldreconnect == 1)
+                               return SQL_DOWN;
+                       else
+                               return -1;
+               }       
+               x++;
+       }
+
+       radlog(L_DBG, "rlm_sql_postgresql: Postgresql Fatal Error: [%s] Occurred!!", errorcode);        
+       /*      We don't seem to have a matching error class/code */
+       return -1;
 }
 
 
+
 /*************************************************************************
  *
  *     Function: sql_create_socket
@@ -179,9 +180,9 @@ static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
        pg_sock->result=NULL;
        pg_sock->conn=PQconnectdb(connstring);
 
-       if (PQstatus(pg_sock->conn) == CONNECTION_BAD) {
+       if (PQstatus(pg_sock->conn) != CONNECTION_OK) {
                radlog(L_ERR, "rlm_sql_postgresql: Couldn't connect socket to PostgreSQL server %s@%s:%s", config->sql_login, config->sql_server, config->sql_db);
-               radlog(L_ERR, "rlm_sql_postgresql: Postgresql error '%s'", PQerrorMessage(pg_sock->conn));
+               /*radlog(L_ERR, "rlm_sql_postgresql: Postgresql error '%s'", PQerrorMessage(pg_sock->conn));*/
                sql_close(sqlsocket, config);
                return SQL_DOWN;
        }
@@ -199,6 +200,9 @@ static int sql_init_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
 static int sql_query(SQLSOCK * sqlsocket, SQL_CONFIG *config, char *querystr) {
 
        rlm_sql_postgres_sock *pg_sock = sqlsocket->conn;
+       int numfields = 0;
+       char *errorcode; 
+       char *errormsg;
 
        if (config->sqltrace)
                radlog(L_DBG,"rlm_sql_postgresql: query:\n%s", querystr);
@@ -209,35 +213,97 @@ static int sql_query(SQLSOCK * sqlsocket, SQL_CONFIG *config, char *querystr) {
        }
 
        pg_sock->result = PQexec(pg_sock->conn, querystr);
-               /* Returns a result pointer or possibly a NULL pointer.
-                * A non-NULL pointer will generally be returned except in
+               /*
+                * Returns a PGresult pointer or possibly a null pointer.
+                * A non-null pointer will generally be returned except in
                 * out-of-memory conditions or serious errors such as inability
-                * to send the command to the backend. If a NULL is returned,
-                *  it should be treated like a PGRES_FATAL_ERROR result.
-                * Use PQerrorMessage to get more information about the error.
+                * to send the command to the server. If a null pointer is
+                * returned, it should be treated like a PGRES_FATAL_ERROR
+                * result.
                 */
        if (!pg_sock->result)
        {
                radlog(L_ERR, "rlm_sql_postgresql: PostgreSQL Query failed Error: %s",
                                PQerrorMessage(pg_sock->conn));
+               /* As this error COULD be a connection error OR an out-of-memory
+                * condition return value WILL be wrong SOME of the time regardless!
+                * Pick your poison....
+                */
                return  SQL_DOWN;
        } else {
                ExecStatusType status = PQresultStatus(pg_sock->result);
-
                radlog(L_DBG, "rlm_sql_postgresql: Status: %s", PQresStatus(status));
 
-               radlog(L_DBG, "rlm_sql_postgresql: affected rows = %s",
-                               PQcmdTuples(pg_sock->result));
+               switch (status){
+
+                       case PGRES_COMMAND_OK: 
+                               /*Successful completion of a command returning no data.*/
+
+                               /*affected_rows function only returns 
+                               the number of affected rows of a command 
+                               returning no data...    
+                               */
+                               pg_sock->affected_rows  = affected_rows(pg_sock->result); 
+                               radlog(L_DBG, "rlm_sql_postgresql: query affected rows = %i", pg_sock->affected_rows);
+                               return 0;
+
+                       break;
 
-               if (!status_is_ok(status))
-                       return sql_check_error(status);
+                       case PGRES_TUPLES_OK:
+                               /*Successful completion of a command returning data (such as a SELECT or SHOW).*/
 
-               if (strncasecmp("select", querystr, 6) != 0) {
-                       /* store the number of affected rows because the sql module
-                        * calls finish_query before it retrieves the number of affected
-                        * rows from the driver */
-                       pg_sock->affected_rows = affected_rows(pg_sock->result);
-                       return 0;
+                               pg_sock->cur_row = 0;
+                               pg_sock->affected_rows = PQntuples(pg_sock->result);
+                               numfields = PQnfields(pg_sock->result); /*Check row storing functions..*/
+                               radlog(L_DBG, "rlm_sql_postgresql: query affected rows = %i , fields = %i", pg_sock->affected_rows, numfields);
+                               return 0;
+
+                       break;
+
+                       case PGRES_BAD_RESPONSE:
+                               /*The server's response was not understood.*/
+                               radlog(L_DBG, "rlm_sql_postgresql: Bad Response From Server!!");
+                               return -1;
+
+                       break;
+
+                       case PGRES_NONFATAL_ERROR:
+                               /*A nonfatal error (a notice or warning) occurred. Possibly never returns*/
+
+                               return -1;
+
+                       break;
+
+                       case PGRES_FATAL_ERROR:
+                               /*A fatal error occurred.*/
+
+                               errorcode = PQresultErrorField(pg_sock->result, PG_DIAG_SQLSTATE);
+                               errormsg  = PQresultErrorField(pg_sock->result, PG_DIAG_MESSAGE_PRIMARY);
+                               radlog(L_DBG, "rlm_sql_postgresql: Error %s", errormsg);
+                               return check_fatal_error(errorcode);
+
+                       break;
+
+                       default:
+                               /* FIXME: An unhandled error occurred.*/
+
+                               /* PGRES_EMPTY_QUERY PGRES_COPY_OUT PGRES_COPY_IN */
+
+                               return -1;
+
+                       break;
+
+
+               }       
+       
+               /*
+                       Note to self ... sql_store_result returns 0 anyway
+                       after setting the sqlsocket->affected_rows.. 
+                       sql_num_fields returns 0 at worst case which means the check below
+                       has a really small chance to return false..
+                       lets remove it then .. yuck!!
+               */
+               /*
                } else {
                        if ((sql_store_result(sqlsocket, config) == 0)
                                        && (sql_num_fields(sqlsocket, config) >= 0))
@@ -245,6 +311,7 @@ static int sql_query(SQLSOCK * sqlsocket, SQL_CONFIG *config, char *querystr) {
                        else
                                return -1;
                }
+               */
        }
 }
 
@@ -263,29 +330,12 @@ static int sql_select_query(SQLSOCK * sqlsocket, SQL_CONFIG *config, char *query
 
 /*************************************************************************
  *
- *     Function: sql_store_result
- *
- *     Purpose: database specific store_result function. Returns a result
- *               set for the query.
- *
- *************************************************************************/
-static int sql_store_result(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
-       rlm_sql_postgres_sock *pg_sock = sqlsocket->conn;
-
-       pg_sock->cur_row = 0;
-       pg_sock->affected_rows = PQntuples(pg_sock->result);
-       return 0;
-}
-
-
-/*************************************************************************
- *
  *      Function: sql_destroy_socket
  *
  *      Purpose: Free socket and private connection data
  *
  *************************************************************************/
-static int sql_destroy_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config)
+static int sql_destroy_socket(SQLSOCK *sqlsocket, UNUSED SQL_CONFIG *config)
 {
         free(sqlsocket->conn);
        sqlsocket->conn = NULL;
@@ -294,35 +344,14 @@ static int sql_destroy_socket(SQLSOCK *sqlsocket, SQL_CONFIG *config)
 
 /*************************************************************************
  *
- *     Function: sql_num_fields
- *
- *     Purpose: database specific num_fields function. Returns number
- *               of columns from query
- *
- *************************************************************************/
-static int sql_num_fields(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
-
-       int num = 0;
-       rlm_sql_postgres_sock *pg_sock = sqlsocket->conn;
-
-       if (!(num = PQnfields(pg_sock->result))) {
-               radlog(L_ERR, "rlm_sql_postgresql: PostgreSQL Error: Cannot get result");
-               radlog(L_ERR, "rlm_sql_postgresql: PostgreSQL error: %s", PQerrorMessage(pg_sock->conn));
-       }
-       return num;
-}
-
-
-/*************************************************************************
- *
  *     Function: sql_fetch_row
  *
  *     Purpose: database specific fetch_row. Returns a SQL_ROW struct
- *               with all the data for the query in 'sqlsocket->row'. Returns
- *              0 on success, -1 on failure, SQL_DOWN if 'database is down'.
+ *     with all the data for the query in 'sqlsocket->row'. Returns
+ *     0 on success, -1 on failure, SQL_DOWN if 'database is down'.
  *
  *************************************************************************/
-static int sql_fetch_row(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
+static int sql_fetch_row(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config) {
 
        int records, i, len;
        rlm_sql_postgres_sock *pg_sock = sqlsocket->conn;
@@ -345,14 +374,13 @@ static int sql_fetch_row(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
                        len = PQgetlength(pg_sock->result, pg_sock->cur_row, i);
                        pg_sock->row[i] = (char *)rad_malloc(len+1);
                        memset(pg_sock->row[i], '\0', len+1);
-                       strncpy(pg_sock->row[i], PQgetvalue(pg_sock->result, pg_sock->cur_row,i),len);
+                       strlcpy(pg_sock->row[i], PQgetvalue(pg_sock->result, pg_sock->cur_row,i),len + 1);
                }
                pg_sock->cur_row++;
                sqlsocket->row = pg_sock->row;
-               return 0;
-       } else {
-               return 0;
        }
+
+       return 0;
 }
 
 
@@ -365,7 +393,7 @@ static int sql_fetch_row(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
  *               for a result set
  *
  *************************************************************************/
-static int sql_free_result(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
+static int sql_free_result(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config) {
 
        rlm_sql_postgres_sock *pg_sock = sqlsocket->conn;
 
@@ -373,12 +401,8 @@ static int sql_free_result(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
                PQclear(pg_sock->result);
                pg_sock->result = NULL;
        }
-#if 0
-       /*
-        *  Commented out because it appears to free memory too early.
-        */
+
        free_result_row(pg_sock);
-#endif
 
        return 0;
 }
@@ -393,7 +417,7 @@ static int sql_free_result(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
  *               connection
  *
  *************************************************************************/
-static char *sql_error(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
+static char *sql_error(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config) {
 
        rlm_sql_postgres_sock *pg_sock = sqlsocket->conn;
 
@@ -409,7 +433,7 @@ static char *sql_error(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
  *               connection
  *
  *************************************************************************/
-static int sql_close(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
+static int sql_close(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config) {
 
        rlm_sql_postgres_sock *pg_sock = sqlsocket->conn;
 
@@ -457,7 +481,7 @@ static int sql_finish_select_query(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
  *     Purpose: Return the number of rows affected by the last query.
  *
  *************************************************************************/
-static int sql_affected_rows(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
+static int sql_affected_rows(SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config) {
        rlm_sql_postgres_sock *pg_sock = sqlsocket->conn;
 
        return pg_sock->affected_rows;
@@ -465,7 +489,7 @@ static int sql_affected_rows(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
 
 
 static int NEVER_RETURNS
-not_implemented(SQLSOCK * sqlsocket, SQL_CONFIG *config)
+not_implemented(UNUSED SQLSOCK * sqlsocket, UNUSED SQL_CONFIG *config)
 {
        radlog(L_ERR, "sql_postgresql: calling unimplemented function");
        exit(1);
diff --git a/src/modules/rlm_sql/drivers/rlm_sql_postgresql/sql_postgresql.h b/src/modules/rlm_sql/drivers/rlm_sql_postgresql/sql_postgresql.h
new file mode 100644 (file)
index 0000000..d729d8d
--- /dev/null
@@ -0,0 +1,241 @@
+/* Copyright 2006 The FreeRADIUS server project */
+
+#ifndef _SQL_POSTGRESQL_H_
+#define _SQL_POSTGRESQL_H_
+
+#include <freeradius-devel/ident.h>
+RCSIDH(sql_postgresql_h, "$Id$")
+
+/************************************************** 
+* Error Codes and required information Lookup table
+* Does this shite ever needed? Lets c.. 
+***************************************************/
+typedef struct pgsql_error{
+       char *errorcode;
+       char *meaning;
+       int  shouldreconnect;
+}pgerror;
+
+pgerror errorcodes[]=
+{
+       "1000", "WARNING", 0,
+       "0100C", "DYNAMIC RESULT SETS RETURNED", 0,
+       "1008", "IMPLICIT ZERO BIT PADDING", 0,
+       "1003", "NULL VALUE ELIMINATED IN SET FUNCTION", 0,
+       "1007", "PRIVILEGE NOT GRANTED", 0,
+       "1006", "PRIVILEGE NOT REVOKED", 0,
+       "1004", "STRING DATA RIGHT TRUNCATION", 0,
+       "01P01", "DEPRECATED FEATURE", 0,
+
+       "2000", "NO DATA", 0,
+       "2001", "NO ADDITIONAL DYNAMIC RESULT SETS RETURNED", 0,
+       
+       "3000", "SQL STATEMENT NOT YET COMPLETE", 0,
+
+       "8000", "CONNECTION EXCEPTION", 0,
+       "8003", "CONNECTION DOES NOT EXIST", 0,
+       "8006", "CONNECTION FAILURE", 0,
+       "8001", "SQLCLIENT UNABLE TO ESTABLISH SQLCONNECTION", 0,
+       "8004", "SQLSERVER REJECTED ESTABLISHMENT OF SQLCONNECTION", 0,
+       "8007", "TRANSACTION RESOLUTION UNKNOWN", 0,
+       "08P01", "PROTOCOL VIOLATION", 0,
+
+       "9000", "TRIGGERED ACTION EXCEPTION", 0,
+
+       "0A000", "FEATURE NOT SUPPORTED", 0,
+
+       "0B000", "INVALID TRANSACTION INITIATION", 0,
+
+       "0F000", "LOCATOR EXCEPTION", 0,
+       "0F001", "INVALID LOCATOR SPECIFICATION", 0,
+
+       "0L000", "INVALID GRANTOR", 0,
+       "0LP01", "INVALID GRANT OPERATION", 0,
+
+       "21000", "CARDINALITY VIOLATION", 0,
+
+       "22000", "DATA EXCEPTION", 0,
+       "2202E", "ARRAY SUBSCRIPT ERROR", 0,
+       "22021", "CHARACTER NOT IN REPERTOIRE", 0,
+       "22008", "DATETIME FIELD OVERFLOW", 0,
+       "22012", "DIVISION BY ZERO", 0,
+       "22005", "ERROR IN ASSIGNMENT", 0,
+       "2200B", "ESCAPE CHARACTER CONFLICT", 0,
+       "22022", "INDICATOR OVERFLOW", 0,
+       "22015", "INTERVAL FIELD OVERFLOW", 0,
+       "2201E", "INVALID ARGUMENT FOR LOGARITHM", 0,
+       "2201F", "INVALID ARGUMENT FOR POWER FUNCTION", 0,
+       "2201G", "INVALID ARGUMENT FOR WIDTH BUCKET FUNCTION", 0,
+       "22018", "INVALID CHARACTER VALUE FOR CAST", 0,
+       "22007", "INVALID DATETIME FORMAT", 0,
+       "22019", "INVALID ESCAPE CHARACTER", 0,
+       "2200D", "INVALID ESCAPE OCTET", 0,
+       "22025", "INVALID ESCAPE SEQUENCE", 0,
+       "22P06", "NONSTANDARD USE OF ESCAPE CHARACTER", 0,
+       "22010", "INVALID INDICATOR PARAMETER VALUE", 0,
+       "22020", "INVALID LIMIT VALUE", 0,
+       "22023", "INVALID PARAMETER VALUE", 0,
+       "2201B", "INVALID REGULAR EXPRESSION", 0,
+       "22009", "INVALID TIME ZONE DISPLACEMENT VALUE", 0,
+       "2200C", "INVALID USE OF ESCAPE CHARACTER", 0,
+       "2200G", "MOST SPECIFIC TYPE MISMATCH", 0,
+       "22004", "NULL VALUE NOT ALLOWED", 0,
+       "22002", "NULL VALUE NO INDICATOR PARAMETER", 0,
+       "22003", "NUMERIC VALUE OUT OF RANGE", 0,
+       "22026", "STRING DATA LENGTH MISMATCH", 0,
+       "22001", "STRING DATA RIGHT TRUNCATION", 0,
+       "22011", "SUBSTRING ERROR", 0,
+       "22027", "TRIM ERROR", 0,
+       "22024", "UNTERMINATED C STRING", 0,
+       "2200F", "ZERO LENGTH CHARACTER STRING", 0,
+       "22P01", "FLOATING POINT EXCEPTION", 0,
+       "22P02", "INVALID TEXT REPRESENTATION", 0,
+       "22P03", "INVALID BINARY REPRESENTATION", 0,
+       "22P04", "BAD COPY FILE FORMAT", 0,
+       "22P05", "UNTRANSLATABLE CHARACTER", 0,
+
+       "23000", "INTEGRITY CONSTRAINT VIOLATION", 0,
+       "23001", "RESTRICT VIOLATION", 0,
+       "23502", "NOT NULL VIOLATION", 0,
+       "23503", "FOREIGN KEY VIOLATION", 0,
+       "23505", "UNIQUE VIOLATION", 0,
+       "23514", "CHECK VIOLATION", 0,
+
+       "24000", "INVALID CURSOR STATE", 0,
+
+       "25000", "INVALID TRANSACTION STATE", 0,
+       "25001", "ACTIVE SQL TRANSACTION", 0,
+       "25002", "BRANCH TRANSACTION ALREADY ACTIVE", 0,
+       "25008", "HELD CURSOR REQUIRES SAME ISOLATION LEVEL", 0,
+       "25003", "INAPPROPRIATE ACCESS MODE FOR BRANCH TRANSACTION", 0,
+       "25004", "INAPPROPRIATE ISOLATION LEVEL FOR BRANCH TRANSACTION", 0,
+       "25005", "NO ACTIVE SQL TRANSACTION FOR BRANCH TRANSACTION", 0,
+       "25006", "READ ONLY SQL TRANSACTION", 0,
+       "25007", "SCHEMA AND DATA STATEMENT MIXING NOT SUPPORTED", 0,
+       "25P01", "NO ACTIVE SQL TRANSACTION", 0,
+       "25P02", "IN FAILED SQL TRANSACTION", 0,
+
+       "26000", "INVALID SQL STATEMENT NAME", 0,
+
+       "27000", "TRIGGERED DATA CHANGE VIOLATION", 0,
+
+       "28000", "INVALID AUTHORIZATION SPECIFICATION", 0,
+
+       "2B000", "DEPENDENT PRIVILEGE DESCRIPTORS STILL EXIST", 0,
+       "2BP01", "DEPENDENT OBJECTS STILL EXIST", 0,
+       
+       "2D000", "INVALID TRANSACTION TERMINATION", 0,
+       
+       "2F000", "SQL ROUTINE EXCEPTION", 0,
+       "2F005", "FUNCTION EXECUTED NO RETURN STATEMENT", 0,
+       "2F002", "MODIFYING SQL DATA NOT PERMITTED", 0,
+       "2F003", "PROHIBITED SQL STATEMENT ATTEMPTED", 0,
+       "2F004", "READING SQL DATA NOT PERMITTED", 0,
+
+       "34000", "INVALID CURSOR NAME", 0,
+       
+       "38000", "EXTERNAL ROUTINE EXCEPTION", 0,
+       "38001", "CONTAINING SQL NOT PERMITTED", 0,
+       "38002", "MODIFYING SQL DATA NOT PERMITTED", 0,
+       "38003", "PROHIBITED SQL STATEMENT ATTEMPTED", 0,
+       "38004", "READING SQL DATA NOT PERMITTED", 0,
+
+       "39000", "EXTERNAL ROUTINE INVOCATION EXCEPTION", 0,
+       "39001", "INVALID SQLSTATE RETURNED", 0,
+       "39004", "NULL VALUE NOT ALLOWED", 0,
+       "39P01", "TRIGGER PROTOCOL VIOLATED", 0,
+       "39P02", "SRF PROTOCOL VIOLATED", 0,
+
+       "3B000", "SAVEPOINT EXCEPTION", 0,
+       "3B001", "INVALID SAVEPOINT SPECIFICATION", 0,
+
+       "3D000", "INVALID CATALOG NAME", 0,
+       "3F000", "INVALID SCHEMA NAME", 0,
+
+       "40000", "TRANSACTION ROLLBACK", 0,
+       "40002", "TRANSACTION INTEGRITY CONSTRAINT VIOLATION", 0,
+       "40001", "SERIALIZATION FAILURE", 0,
+       "40003", "STATEMENT COMPLETION UNKNOWN", 0,
+       "40P01", "DEADLOCK DETECTED", 0,
+
+       "44000", "WITH CHECK OPTION VIOLATION", 0,
+
+       "53000", "INSUFFICIENT RESOURCES", 0,
+       "53100", "DISK FULL", 0,
+       "53200", "OUT OF MEMORY", 0,
+       "53300", "TOO MANY CONNECTIONS", 0,
+       
+       "54000", "PROGRAM LIMIT EXCEEDED", 0,
+       "54001", "STATEMENT TOO COMPLEX", 0,
+       "54011", "TOO MANY COLUMNS", 0,
+       "54023", "TOO MANY ARGUMENTS", 0,
+
+       "55000", "OBJECT NOT IN PREREQUISITE STATE", 0,
+       "55006", "OBJECT IN USE", 0,
+       "55P02", "CANT CHANGE RUNTIME PARAM", 0,        
+       "55P03", "LOCK NOT AVAILABLE", 0,
+       
+       "57000", "OPERATOR INTERVENTION", 1,
+       "57014", "QUERY CANCELED", 1,
+       "57P01", "ADMIN SHUTDOWN", 1,
+       "57P02", "CRASH SHUTDOWN", 1,
+       "57P03", "CANNOT CONNECT NOW", 1,
+
+       "58030", "IO ERROR", 1,
+       "58P01", "UNDEFINED FILE", 1,
+       "58P02", "DUPLICATE FILE", 1,
+
+       "F0000", "CONFIG FILE ERROR", 1,
+       "F0001", "LOCK FILE EXISTS", 1,
+
+       "P0000", "PLPGSQL ERROR", 0,
+       "P0001", "RAISE EXCEPTION", 0,
+
+       "42000", "SYNTAX ERROR OR ACCESS RULE VIOLATION", 0,
+       "42601", "SYNTAX ERROR", 0,
+       "42501", "INSUFFICIENT PRIVILEGE", 0,
+       "42846", "CANNOT COERCE", 0,
+       "42803", "GROUPING ERROR", 0,
+       "42830", "INVALID FOREIGN KEY", 0,
+       "42602", "INVALID NAME", 0,
+       "42622", "NAME TOO LONG", 0,
+       "42939", "RESERVED NAME", 0,
+       "42804", "DATATYPE MISMATCH", 0,
+       "42P18", "INDETERMINATE DATATYPE", 0,
+       "42809", "WRONG OBJECT TYPE", 0,
+       "42703", "UNDEFINED COLUMN", 0,
+       "42883", "UNDEFINED FUNCTION", 0,
+       "42P01", "UNDEFINED TABLE", 0,
+       "42P02", "UNDEFINED PARAMETER", 0,
+       "42704", "UNDEFINED OBJECT", 0,
+       "42701", "DUPLICATE COLUMN", 0, 
+       "42P03", "DUPLICATE CURSOR", 0,
+       "42P04", "DUPLICATE DATABASE", 0,
+       "42723", "DUPLICATE FUNCTION", 0,
+       "42P05", "DUPLICATE PREPARED STATEMENT", 0,
+       "42P06", "DUPLICATE SCHEMA", 0,
+       "42P07", "DUPLICATE TABLE", 0,
+       "42712", "DUPLICATE ALIAS", 0,
+       "42710", "DUPLICATE OBJECT", 0,
+       "42702", "AMBIGUOUS COLUMN", 0,
+       "42725", "AMBIGUOUS FUNCTION", 0,
+       "42P08", "AMBIGUOUS PARAMETER", 0,
+       "42P09", "AMBIGUOUS ALIAS", 0,
+       "42P10", "INVALID COLUMN REFERENCE", 0,
+       "42611", "INVALID COLUMN DEFINITION", 0,
+       "42P11", "INVALID CURSOR DEFINITION", 0,
+       "42P12", "INVALID DATABASE DEFINITION", 0,
+       "42P13", "INVALID FUNCTION DEFINITION", 0,
+       "42P14", "INVALID PREPARED STATEMENT DEFINITION", 0,
+       "42P15", "INVALID SCHEMA DEFINITION", 0,
+       "42P16", "INVALID TABLE DEFINITION", 0,
+       "42P17", "INVALID OBJECT DEFINITION", 0,
+
+       "XX000", "INTERNAL ERROR", 0,
+       "XX001", "DATA CORRUPTED", 0,
+       "XX002", "INDEX CORRUPTED", 0,
+
+       NULL, NULL, 0
+};
+
+#endif /*_SQL_POSTGRESQL_H_*/
index efdd860..17faeb6 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Mattias Sjostrom <mattias@nogui.se>
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
 #include <stdio.h>
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include       "radiusd.h"
+#include       <freeradius-devel/radiusd.h>
 
 #include <ctpublic.h>
 #include "rlm_sql.h"
index d21d6a3..3a75e81 100755 (executable)
@@ -908,7 +908,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1826,8 +1826,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1885,8 +1884,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2002,8 +2000,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2057,8 +2054,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2103,8 +2099,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2148,8 +2143,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2481,8 +2475,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2533,8 +2526,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2604,8 +2596,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3472,11 +3463,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -3515,6 +3501,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 3dd0636..146785e 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Dmitri Ageev <d_ageev@ortcc.ru>
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+
 #include <stdlib.h>
 #include <string.h>
-#include "radiusd.h"
+#include <freeradius-devel/radiusd.h>
 
 #include <sqltypes.h>
 #include "rlm_sql.h"
@@ -290,7 +295,9 @@ static int sql_finish_select_query(SQLSOCK * sqlsocket, SQL_CONFIG *config) {
  *
  *************************************************************************/
 static int sql_finish_query(SQLSOCK *sqlsocket, SQL_CONFIG *config) {
-  /* Not used */
+    rlm_sql_unixodbc_sock *unixodbc_sock = sqlsocket->conn;
+
+    SQLFreeStmt(unixodbc_sock->stmt_handle, SQL_CLOSE);
     return 0;
 }
 
index beb24a2..627b68a 100644 (file)
@@ -38,7 +38,7 @@ all: build-module
 #
 #######################################################################
 LT_OBJS                = $(SRCS:.c=.lo)
-CFLAGS         += -I../.. -I$(top_builddir)/src/include
+CFLAGS         += -I../.. -I$(top_builddir)/src/
 
 #######################################################################
 #
index 98afac2..babcc8e 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Mike Machado <mike@innercite.com>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  */
 
-static const char rcsid[] =
-       "$Id$";
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
 
-#include "autoconf.h"
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <sys/stat.h>
@@ -42,15 +42,14 @@ static const char rcsid[] =
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 #include "rlm_sql.h"
-#include "rad_assert.h"
+#include <freeradius-devel/rad_assert.h>
 
 static char *allowed_chars = NULL;
 
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
        {"driver",PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,sql_driver), NULL, "mysql"},
        {"server",PW_TYPE_STRING_PTR,
@@ -63,8 +62,6 @@ static CONF_PARSER module_config[] = {
         offsetof(SQL_CONFIG,sql_password), NULL, ""},
        {"radius_db", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,sql_db), NULL, "radius"},
-       {"nas_table", PW_TYPE_STRING_PTR,
-        offsetof(SQL_CONFIG,sql_nas_table), NULL, "nas"},
        {"sqltrace", PW_TYPE_BOOLEAN,
         offsetof(SQL_CONFIG,sqltrace), NULL, "no"},
        {"sqltracefile", PW_TYPE_STRING_PTR,
@@ -72,15 +69,15 @@ static CONF_PARSER module_config[] = {
        {"readclients", PW_TYPE_BOOLEAN,
         offsetof(SQL_CONFIG,do_clients), NULL, "no"},
        {"deletestalesessions", PW_TYPE_BOOLEAN,
-        offsetof(SQL_CONFIG,deletestalesessions), NULL, "no"},
+        offsetof(SQL_CONFIG,deletestalesessions), NULL, "yes"},
        {"num_sql_socks", PW_TYPE_INTEGER,
         offsetof(SQL_CONFIG,num_sql_socks), NULL, "5"},
        {"sql_user_name", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,query_user), NULL, ""},
        {"default_user_profile", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,default_profile), NULL, ""},
-       {"query_on_not_found", PW_TYPE_BOOLEAN,
-        offsetof(SQL_CONFIG,query_on_not_found), NULL, "no"},
+       {"nas_query", PW_TYPE_STRING_PTR,
+        offsetof(SQL_CONFIG,nas_query), NULL, "SELECT id,nasname,shortname,type,secret FROM nas"},
        {"authorize_check_query", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,authorize_check_query), NULL, ""},
        {"authorize_reply_query", PW_TYPE_STRING_PTR,
@@ -114,27 +111,25 @@ static CONF_PARSER module_config[] = {
        {"postauth_query", PW_TYPE_STRING_PTR,
         offsetof(SQL_CONFIG,postauth_query), NULL, ""},
        {"safe-characters", PW_TYPE_STRING_PTR,
-        offsetof(SQL_CONFIG,allowed_chars), NULL, 
+        offsetof(SQL_CONFIG,allowed_chars), NULL,
        "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"},
 
        {NULL, -1, 0, NULL, NULL}
 };
 
-/***********************************************************************
- * start of main routines
- ***********************************************************************/
-static int rlm_sql_init(void) {
+/*
+ *     Fall-Through checking function from rlm_files.c
+ */
+static int fallthrough(VALUE_PAIR *vp)
+{
+       VALUE_PAIR *tmp;
+       tmp = pairfind(vp, PW_FALL_THROUGH);
 
-       /*
-        * FIXME:
-        * We should put the sqlsocket array here once
-        * the module code is reworked to not unload
-        * modules on HUP.  This way we can have
-        * persistant connections.  -jcarneal
-        */
-       return 0;
+       return tmp ? tmp->lvalue : 0;
 }
 
+
+
 /*
  *     Yucky prototype.
  */
@@ -148,7 +143,7 @@ static int sql_escape_func(char *out, int outlen, const char *in);
  */
 static int sql_xlat(void *instance, REQUEST *request,
                    char *fmt, char *out, size_t freespace,
-                   RADIUS_ESCAPE_STRING func)
+                   UNUSED RADIUS_ESCAPE_STRING func)
 {
        SQLSOCK *sqlsocket;
        SQL_ROW row;
@@ -220,7 +215,7 @@ static int sql_xlat(void *instance, REQUEST *request,
                return 0;
        }
 
-       strncpy(out,row[0],ret);
+       strlcpy(out,row[0],ret);
 
        DEBUG("rlm_sql (%s): - sql_xlat finished",
              inst->config->xlat_name);
@@ -236,18 +231,17 @@ static int generate_sql_clients(SQL_INST *inst)
        SQL_ROW row;
        char querystr[MAX_QUERY_LEN];
        RADCLIENT *c;
-       char *netmask;
+       char *prefix_ptr = NULL;
        unsigned int i = 0;
-       
-       DEBUG("rlm_sql (%s): - generate_sql_clients",inst->config->xlat_name);
 
-       if (inst->config->sql_nas_table == NULL){
-               radlog(L_ERR, "rlm_sql (%s): sql_nas_table is NULL.",inst->config->xlat_name);
-               return -1;
-       }
-       snprintf(querystr,MAX_QUERY_LEN - 1,"SELECT * FROM %s",inst->config->sql_nas_table);
+       DEBUG("rlm_sql (%s): Processing generate_sql_clients",
+             inst->config->xlat_name);
+
+       /* NAS query isn't xlat'ed */
+       strlcpy(querystr, inst->config->nas_query, sizeof(querystr));
+       DEBUG("rlm_sql (%s) in generate_sql_clients: query is %s",
+             inst->config->xlat_name, querystr);
 
-       DEBUG("rlm_sql (%s): Query: %s",inst->config->xlat_name,querystr);
        sqlsocket = sql_get_socket(inst);
        if (sqlsocket == NULL)
                return -1;
@@ -264,14 +258,15 @@ static int generate_sql_clients(SQL_INST *inst)
                row = sqlsocket->row;
                if (row == NULL)
                        break;
-/*
- * Format:
- * Row1        Row2    Row3            Row4    Row5    Row6    Row7            Row8
- *
- * id  nasname shortname       type    ports   secret  community       description
- *
- */
-
+       /*
+        *  The return data for each row MUST be in the following order:
+        *
+        *  0. Row ID (currently unused)
+        *  1. Name (or IP address)
+        *  2. Shortname
+        *  3. Type
+        *  4. Secret
+        */
                if (!row[0]){
                        radlog(L_ERR, "rlm_sql (%s): No row id found on pass %d",inst->config->xlat_name,i);
                        continue;
@@ -280,101 +275,79 @@ static int generate_sql_clients(SQL_INST *inst)
                        radlog(L_ERR, "rlm_sql (%s): No nasname found for row %s",inst->config->xlat_name,row[0]);
                        continue;
                }
-               if (strlen(row[1]) >= sizeof(c->longname)){
-                       radlog(L_ERR, "rlm_sql (%s): nasname of length %d is greater than the allowed maximum of %d",
-                               inst->config->xlat_name,strlen(row[1]),sizeof(c->longname) - 1);
-                       continue;
-               }       
-               
                if (!row[2]){
                        radlog(L_ERR, "rlm_sql (%s): No short name found for row %s",inst->config->xlat_name,row[0]);
                        continue;
                }
-               if (strlen(row[2]) >= sizeof(c->shortname)){
-                       radlog(L_ERR, "rlm_sql (%s): shortname of length %d is greater than the allowed maximum of %d",
-                               inst->config->xlat_name,strlen(row[2]),sizeof(c->shortname) - 1);
-                       continue;
-               }
-               if (row[3] && strlen(row[3]) >= sizeof(c->nastype)){
-                       radlog(L_ERR, "rlm_sql (%s): nastype of length %d is greater than the allowed maximum of %d",
-                               inst->config->xlat_name,strlen(row[3]),sizeof(c->nastype) - 1);
-                       continue;
-               }
-               if (!row[5]){
+               if (!row[4]){
                        radlog(L_ERR, "rlm_sql (%s): No secret found for row %s",inst->config->xlat_name,row[0]);
                        continue;
                }
-               if (strlen(row[5]) >= sizeof(c->secret)){
-                       radlog(L_ERR, "rlm_sql (%s): secret of length %d is greater than the allowed maximum of %d",
-                               inst->config->xlat_name,strlen(row[5]),sizeof(c->secret) - 1);
-                       continue;
-               }
 
                DEBUG("rlm_sql (%s): Read entry nasname=%s,shortname=%s,secret=%s",inst->config->xlat_name,
-                       row[1],row[2],row[5]);
+                       row[1],row[2],row[4]);
 
                c = rad_malloc(sizeof(RADCLIENT));
                memset(c, 0, sizeof(RADCLIENT));
 
-               c->netmask = ~0;
-               netmask = strchr(row[1], '/');
-               
                /*
-                *      Look for netmasks.
+                *      Look for prefixes
                 */
-               c->netmask = ~0;
-               if (netmask) {
-                       int mask_length;
-
-                       mask_length = atoi(netmask + 1);
-                       if ((mask_length < 0) || (mask_length > 32)) {
-                               radlog(L_ERR, "rlm_sql (%s): Invalid value '%s' for IP network mask for nasname %s.",
-                                               inst->config->xlat_name, netmask + 1,row[1]);
+               c->prefix = -1;
+               prefix_ptr = strchr(row[1], '/');
+               if (prefix_ptr) {
+                       c->prefix = atoi(prefix_ptr + 1);
+                       if ((c->prefix < 0) || (c->prefix > 128)) {
+                               radlog(L_ERR, "rlm_sql (%s): Invalid Prefix value '%s' for IP.",
+                                      inst->config->xlat_name, prefix_ptr + 1);
                                free(c);
                                continue;
                        }
-
-                       if (mask_length == 0) {
-                               c->netmask = 0;
-                       } else {
-                               c->netmask = ~0 << (32 - mask_length);
-                       }
-
-                       *netmask = '\0';
-                       c->netmask = htonl(c->netmask);
+                       /* Replace '/' with '\0' */
+                       *prefix_ptr = '\0';
                }
 
-               c->ipaddr = ip_getaddr(row[1]);
-               if (c->ipaddr == INADDR_NONE) {
-                       radlog(L_CONS|L_ERR, "rlm_sql (%s): Failed to look up hostname %s",
-                                       inst->config->xlat_name, row[1]);
+               /*
+                *      Always get the numeric representation of IP
+                */
+               if (ip_hton(row[1], AF_UNSPEC, &c->ipaddr) < 0) {
+                       radlog(L_CONS|L_ERR, "rlm_sql (%s): Failed to look up hostname %s: %s",
+                              inst->config->xlat_name,
+                              row[1], librad_errstr);
                        free(c);
                        continue;
+               } else {
+                       char buffer[256];
+                       ip_ntoh(&c->ipaddr, buffer, sizeof(buffer));
+                       c->longname = strdup(buffer);
                }
 
-               /*
-                *      Update the client name again...
-                */
-               if (netmask) {
-                       *netmask = '/';
-                       c->ipaddr &= c->netmask;
-                       strcpy(c->longname, row[1]);
-               } else {
-                       ip_hostname(c->longname, sizeof(c->longname),
-                                       c->ipaddr);
+               if (c->prefix < 0) switch (c->ipaddr.af) {
+               case AF_INET:
+                       c->prefix = 32;
+                       break;
+               case AF_INET6:
+                       c->prefix = 128;
+                       break;
+               default:
+                       break;
                }
 
-               strcpy((char *)c->secret, row[5]);
-               strcpy(c->shortname, row[2]);
+               /*
+                *      Other values (secret, shortname, nastype)
+                */
+               c->secret = (u_char *)strdup(row[4]);
+               c->shortname = strdup(row[2]);
                if(row[3] != NULL)
-                       strcpy(c->nastype, row[3]);
-
-               DEBUG("rlm_sql (%s): Adding client %s (%s) to clients list",inst->config->xlat_name,
-                       c->longname,c->shortname);
-
-               c->next = mainconfig.clients;
-               mainconfig.clients = c;
+                       c->nastype = strdup(row[3]);
 
+               DEBUG("rlm_sql (%s): Adding client %s (%s) to clients list",
+                     inst->config->xlat_name,
+                     c->longname,c->shortname);
+               if (!client_add(mainconfig.clients, c)) {
+                       client_free(c);
+                       return -1;
+               }
        }
        (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
        sql_release_socket(inst, sqlsocket);
@@ -452,29 +425,94 @@ static int sql_set_user(SQL_INST *inst, REQUEST *request, char *sqlusername, con
        pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
 
        if (username != NULL) {
-               strNcpy(tmpuser, username, MAX_STRING_LEN);
+               strlcpy(tmpuser, username, MAX_STRING_LEN);
        } else if (strlen(inst->config->query_user)) {
                radius_xlat(tmpuser, sizeof(tmpuser), inst->config->query_user, request, NULL);
        } else {
                return 0;
        }
 
-       if (*tmpuser) {
-               strNcpy(sqlusername, tmpuser, MAX_STRING_LEN);
-               DEBUG2("rlm_sql (%s): sql_set_user escaped user --> '%s'",
+       strlcpy(sqlusername, tmpuser, MAX_STRING_LEN);
+       DEBUG2("rlm_sql (%s): sql_set_user escaped user --> '%s'",
                       inst->config->xlat_name, sqlusername);
-               vp = pairmake("SQL-User-Name", sqlusername, 0);
-               if (vp == NULL) {
-                       radlog(L_ERR, "%s", librad_errstr);
+       vp = pairmake("SQL-User-Name", sqlusername, 0);
+       if (vp == NULL) {
+               radlog(L_ERR, "%s", librad_errstr);
+               return -1;
+       }
+
+       pairadd(&request->packet->vps, vp);
+       return 0;
+
+}
+
+
+static void sql_grouplist_free (SQL_GROUPLIST **group_list)
+{
+       SQL_GROUPLIST *last;
+
+       while(*group_list) {
+               last = *group_list;
+               *group_list = (*group_list)->next;
+               free(last);
+       }
+}
+
+
+static int sql_get_grouplist (SQL_INST *inst, SQLSOCK *sqlsocket, REQUEST *request, SQL_GROUPLIST **group_list)
+{
+       char    querystr[MAX_QUERY_LEN];
+       int     num_groups = 0;
+       SQL_ROW row;
+       SQL_GROUPLIST   *group_list_tmp;
+
+       /* NOTE: sql_set_user should have been run before calling this function */
+
+       group_list_tmp = *group_list = NULL;
+
+       if (inst->config->groupmemb_query[0] == 0)
+               return 1;
+
+       if (!radius_xlat(querystr, sizeof(querystr), inst->config->groupmemb_query, request, sql_escape_func)) {
+               radlog(L_ERR, "rlm_sql (%s): xlat failed.",
+                       inst->config->xlat_name);
+               return -1;
+       }
+
+       if (rlm_sql_select_query(sqlsocket, inst, querystr) < 0) {
+               radlog(L_ERR, "rlm_sql (%s): database query error, %s: %s",
+                       inst->config->xlat_name,querystr,
+                       (char *)(inst->module->sql_error)(sqlsocket,inst->config));
+               return -1;
+       }
+       while (rlm_sql_fetch_row(sqlsocket, inst) == 0) {
+               row = sqlsocket->row;
+               if (row == NULL)
+                       break;
+               if (row[0] == NULL){
+                       DEBUG("rlm_sql (%s): row[0] returned NULL",
+                               inst->config->xlat_name);
+                       (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
+                       sql_grouplist_free(group_list);
                        return -1;
                }
-
-               pairadd(&request->packet->vps, vp);
-               return 0;
+               if (*group_list == NULL) {
+                       *group_list = rad_malloc(sizeof(SQL_GROUPLIST));
+                       group_list_tmp = *group_list;
+               } else {
+                       group_list_tmp->next = rad_malloc(sizeof(SQL_GROUPLIST));
+                       group_list_tmp = group_list_tmp->next;
+               }
+               group_list_tmp->next = NULL;
+               strlcpy(group_list_tmp->groupname, row[0], MAX_STRING_LEN);
        }
-       return -1;
+
+       (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
+
+       return num_groups;
 }
 
+
 /*
  * sql groupcmp function. That way we can do group comparisons (in the users file for example)
  * with the group memberships reciding in sql
@@ -486,16 +524,16 @@ static int sql_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE
                        VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
 {
        SQLSOCK *sqlsocket;
-       SQL_ROW row;
        SQL_INST *inst = instance;
-       char querystr[MAX_QUERY_LEN];
        char sqlusername[MAX_STRING_LEN];
+       SQL_GROUPLIST *group_list, *group_list_tmp;
 
        check_pairs = check_pairs;
        reply_pairs = reply_pairs;
+       request = request;
 
        DEBUG("rlm_sql (%s): - sql_groupcmp", inst->config->xlat_name);
-       if (!check || !check->strvalue || !check->length){
+       if (!check || !check->vp_strvalue || !check->length){
                DEBUG("rlm_sql (%s): sql_groupcmp: Illegal group name",
                      inst->config->xlat_name);
                return 1;
@@ -505,63 +543,189 @@ static int sql_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE
                      inst->config->xlat_name);
                return 1;
        }
-       if (inst->config->groupmemb_query[0] == 0)
-               return 1;
        /*
         * Set, escape, and check the user attr here
         */
        if (sql_set_user(inst, req, sqlusername, NULL) < 0)
                return 1;
-       if (!radius_xlat(querystr, sizeof(querystr), inst->config->groupmemb_query, req, sql_escape_func)){
-               radlog(L_ERR, "rlm_sql (%s): xlat failed.",
-                      inst->config->xlat_name);
+
+       /*
+        *      Get a socket for this lookup
+        */
+       sqlsocket = sql_get_socket(inst);
+       if (sqlsocket == NULL) {
                /* Remove the username we (maybe) added above */
                pairdelete(&req->packet->vps, PW_SQL_USER_NAME);
                return 1;
        }
-       /* Remove the username we (maybe) added above */
-       pairdelete(&req->packet->vps, PW_SQL_USER_NAME);
 
-       sqlsocket = sql_get_socket(inst);
-       if (sqlsocket == NULL)
-               return 1;
-       if ((inst->module->sql_select_query)(sqlsocket,inst->config,querystr) <0){
-               radlog(L_ERR, "rlm_sql (%s): database query error, %s: %s",
-                      inst->config->xlat_name,querystr,
-                      (char *)(inst->module->sql_error)(sqlsocket,inst->config));
-               sql_release_socket(inst,sqlsocket);
+       /*
+        *      Get the list of groups this user is a member of
+        */
+       if (sql_get_grouplist(inst, sqlsocket, req, &group_list)) {
+               radlog(L_ERR, "rlm_sql (%s): Error getting group membership",
+                      inst->config->xlat_name);
+               /* Remove the username we (maybe) added above */
+               pairdelete(&req->packet->vps, PW_SQL_USER_NAME);
+               sql_release_socket(inst, sqlsocket);
                return 1;
        }
-       while (rlm_sql_fetch_row(sqlsocket, inst) == 0) {
-               row = sqlsocket->row;
-               if (row == NULL)
-                       break;
-               if (row[0] == NULL){
-                       DEBUG("rlm_sql (%s): row[0] returned NULL",
-                             inst->config->xlat_name);
-                       (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
-                       sql_release_socket(inst, sqlsocket);
-                       return 1;
-               }
-               if (strcmp(row[0],check->strvalue) == 0){
-                       DEBUG("rlm_sql (%s): - sql_groupcmp finished: User belongs in group %s",
+
+       for (group_list_tmp = group_list; group_list_tmp != NULL; group_list_tmp = group_list_tmp->next) {
+               if (strcmp(group_list_tmp->groupname, check->vp_strvalue) == 0){
+                       DEBUG("rlm_sql (%s): - sql_groupcmp finished: User is a member of group %s",
                              inst->config->xlat_name,
-                             (char *)check->strvalue);
-                       (inst->module->sql_finish_select_query)(sqlsocket, inst->config);                       sql_release_socket(inst, sqlsocket);
+                             (char *)check->vp_strvalue);
+                       /* Free the grouplist */
+                       sql_grouplist_free(&group_list);
+                       /* Remove the username we (maybe) added above */
+                       pairdelete(&req->packet->vps, PW_SQL_USER_NAME);
+                       sql_release_socket(inst, sqlsocket);
                        return 0;
                }
        }
 
-       (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
+       /* Free the grouplist */
+       sql_grouplist_free(&group_list);
+       /* Remove the username we (maybe) added above */
+       pairdelete(&req->packet->vps, PW_SQL_USER_NAME);
        sql_release_socket(inst,sqlsocket);
 
-       DEBUG("rlm_sql (%s): - sql_groupcmp finished: User does not belong in group %s",
-             inst->config->xlat_name, (char *)check->strvalue);
+       DEBUG("rlm_sql (%s): - sql_groupcmp finished: User is NOT a member of group %s",
+             inst->config->xlat_name, (char *)check->vp_strvalue);
 
        return 1;
 }
 
 
+
+static int rlm_sql_process_groups(SQL_INST *inst, REQUEST *request, SQLSOCK *sqlsocket, int *dofallthrough)
+{
+       VALUE_PAIR *check_tmp = NULL;
+       VALUE_PAIR *reply_tmp = NULL;
+       SQL_GROUPLIST *group_list, *group_list_tmp;
+       VALUE_PAIR *sql_group = NULL;
+       char    querystr[MAX_QUERY_LEN];
+       int found = 0;
+       int rows;
+
+       /*
+        *      Get the list of groups this user is a member of
+        */
+       if (sql_get_grouplist(inst, sqlsocket, request, &group_list)) {
+               radlog(L_ERR, "rlm_sql (%s): Error retrieving group list",
+                      inst->config->xlat_name);
+               return -1;
+       }
+
+       for (group_list_tmp = group_list; group_list_tmp != NULL && *dofallthrough != 0; group_list_tmp = group_list_tmp->next) {
+               /*
+                *      Add the Sql-Group attribute to the request list so we know
+                *      which group we're retrieving attributes for
+                */
+               sql_group = pairmake("Sql-Group", group_list_tmp->groupname, T_OP_EQ);
+               if (!sql_group) {
+                       radlog(L_ERR, "rlm_sql (%s): Error creating Sql-Group attribute",
+                              inst->config->xlat_name);
+                       return -1;
+               }
+               pairadd(&request->packet->vps, sql_group);
+               if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_check_query, request, sql_escape_func)) {
+                       radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user",
+                              inst->config->xlat_name);
+                       /* Remove the grouup we added above */
+                       pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                       return -1;
+               }
+               rows = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr);
+               if (rows < 0) {
+                       radlog(L_ERR, "rlm_sql (%s): Error retrieving check pairs for group %s",
+                              inst->config->xlat_name, group_list_tmp->groupname);
+                       /* Remove the grouup we added above */
+                       pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                       pairfree(&check_tmp);
+                       return -1;
+               } else if (rows > 0) {
+                       /*
+                        *      Only do this if *some* check pairs were returned
+                        */
+                       if (paircompare(request, request->packet->vps, check_tmp, &request->reply->vps) == 0) {
+                               found = 1;
+                               DEBUG2("rlm_sql (%s): User found in group %s",
+                                       inst->config->xlat_name, group_list_tmp->groupname);
+                               /*
+                                *      Now get the reply pairs since the paircompare matched
+                                */
+                               if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func)) {
+                                       radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user",
+                                              inst->config->xlat_name);
+                                       /* Remove the grouup we added above */
+                                       pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                                       pairfree(&check_tmp);
+                                       return -1;
+                               }
+                               if (sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr) < 0) {
+                                       radlog(L_ERR, "rlm_sql (%s): Error retrieving reply pairs for group %s",
+                                              inst->config->xlat_name, group_list_tmp->groupname);
+                                       /* Remove the grouup we added above */
+                                       pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                                       pairfree(&check_tmp);
+                                       pairfree(&reply_tmp);
+                                       return -1;
+                               }
+                               *dofallthrough = fallthrough(reply_tmp);
+                               pairxlatmove(request, &request->reply->vps, &reply_tmp);
+                               pairxlatmove(request, &request->config_items, &check_tmp);
+                       }
+               } else {
+                       /*
+                        *      rows == 0.  This is like having the username on a line
+                        *      in the user's file with no check vp's.  As such, we treat
+                        *      it as found and add the reply attributes, so that we
+                        *      match expected behavior
+                        */
+                       found = 1;
+                       DEBUG2("rlm_sql (%s): User found in group %s",
+                               inst->config->xlat_name, group_list_tmp->groupname);
+                       /*
+                        *      Now get the reply pairs since the paircompare matched
+                        */
+                       if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func)) {
+                               radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user",
+                                      inst->config->xlat_name);
+                               /* Remove the grouup we added above */
+                               pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                               pairfree(&check_tmp);
+                               return -1;
+                       }
+                       if (sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr) < 0) {
+                               radlog(L_ERR, "rlm_sql (%s): Error retrieving reply pairs for group %s",
+                                      inst->config->xlat_name, group_list_tmp->groupname);
+                               /* Remove the grouup we added above */
+                               pairdelete(&request->packet->vps, PW_SQL_GROUP);
+                               pairfree(&check_tmp);
+                               pairfree(&reply_tmp);
+                               return -1;
+                       }
+                       *dofallthrough = fallthrough(reply_tmp);
+                       pairxlatmove(request, &request->reply->vps, &reply_tmp);
+                       pairxlatmove(request, &request->config_items, &check_tmp);
+               }
+
+               /*
+                * Delete the Sql-Group we added above
+                * And clear out the pairlists
+                */
+               pairdelete(&request->packet->vps, PW_SQL_GROUP);
+               pairfree(&check_tmp);
+               pairfree(&reply_tmp);
+       }
+
+       sql_grouplist_free(&group_list);
+       return found;
+}
+
+
 static int rlm_sql_detach(void *instance)
 {
        SQL_INST *inst = instance;
@@ -571,7 +735,7 @@ static int rlm_sql_detach(void *instance)
        }
 
        if (inst->config->xlat_name) {
-               xlat_unregister(inst->config->xlat_name,sql_xlat);
+               xlat_unregister(inst->config->xlat_name,(RAD_XLAT_FUNC)sql_xlat);
                free(inst->config->xlat_name);
        }
 
@@ -622,7 +786,7 @@ static int rlm_sql_detach(void *instance)
 static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
 {
        SQL_INST *inst;
-       char *xlat_name;
+       const char *xlat_name;
 
        inst = rad_malloc(sizeof(SQL_INST));
        memset(inst, 0, sizeof(SQL_INST));
@@ -644,7 +808,7 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
                xlat_name = cf_section_name1(conf);
        if (xlat_name){
                inst->config->xlat_name = strdup(xlat_name);
-               xlat_register(xlat_name, sql_xlat, inst);
+               xlat_register(xlat_name, (RAD_XLAT_FUNC)sql_xlat, inst);
        }
 
        if (inst->config->num_sql_socks > MAX_SQL_SOCKS) {
@@ -712,11 +876,6 @@ static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
        return RLM_MODULE_OK;
 }
 
-static int rlm_sql_destroy(void)
-{
-       return 0;
-}
-
 
 static int rlm_sql_authorize(void *instance, REQUEST * request)
 {
@@ -724,27 +883,29 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
        VALUE_PAIR *reply_tmp = NULL;
        VALUE_PAIR *user_profile = NULL;
        int     found = 0;
+       int     dofallthrough = 1;
+       int     rows;
        SQLSOCK *sqlsocket;
        SQL_INST *inst = instance;
        char    querystr[MAX_QUERY_LEN];
        char    sqlusername[MAX_STRING_LEN];
-
        /*
-        *      They MUST have a user name to do SQL authorization.
+        * the profile username is used as the sqlusername during
+        * profile checking so that we don't overwrite the orignal
+        * sqlusername string
         */
-       if ((request->username == NULL) ||
-           (request->username->length == 0)) {
-               radlog(L_ERR, "rlm_sql (%s): zero length username not permitted\n", inst->config->xlat_name);
-               return RLM_MODULE_INVALID;
-       }
+       char   profileusername[MAX_STRING_LEN];
 
        /*
-        *      Set, escape, and check the user attr here.
+        * Set, escape, and check the user attr here
         */
        if (sql_set_user(inst, request, sqlusername, NULL) < 0)
                return RLM_MODULE_FAIL;
-       radius_xlat(querystr, sizeof(querystr), inst->config->authorize_check_query, request, sql_escape_func);
 
+
+       /*
+        * reserve a socket
+        */
        sqlsocket = sql_get_socket(inst);
        if (sqlsocket == NULL) {
                /* Remove the username we (maybe) added above */
@@ -752,22 +913,24 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                return RLM_MODULE_FAIL;
        }
 
+
        /*
-        *      After this point, ALL 'return's MUST release the SQL socket!
+        *  After this point, ALL 'return's MUST release the SQL socket!
         */
 
-       found = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr, PW_VP_USERDATA);
        /*
-        *      Find the entry for the user.
+        * Alright, start by getting the specific entry for the user
         */
-       if (found > 0) {
-               radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_check_query, request, sql_escape_func);
-               sql_getvpdata(inst, sqlsocket, &check_tmp, querystr, PW_VP_GROUPDATA);
-               radius_xlat(querystr, sizeof(querystr), inst->config->authorize_reply_query, request, sql_escape_func);
-               sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr, PW_VP_USERDATA);
-               radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func);
-               sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr, PW_VP_GROUPDATA);
-       } else if (found < 0) {
+       if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_check_query, request, sql_escape_func)) {
+               radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user",
+                      inst->config->xlat_name);
+               sql_release_socket(inst, sqlsocket);
+               /* Remove the username we (maybe) added above */
+               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+               return RLM_MODULE_FAIL;
+       }
+       rows = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr);
+       if (rows < 0) {
                radlog(L_ERR, "rlm_sql (%s): SQL query error; rejecting user",
                       inst->config->xlat_name);
                sql_release_socket(inst, sqlsocket);
@@ -775,26 +938,73 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
                pairfree(&check_tmp);
                return RLM_MODULE_FAIL;
+       } else if (rows > 0) {
+               /*
+                *      Only do this if *some* check pairs were returned
+                */
+               if (paircompare(request, request->packet->vps, check_tmp, &request->reply->vps) == 0) {
+                       found = 1;
+                       DEBUG2("rlm_sql (%s): User found in radcheck table", inst->config->xlat_name);
+                       /*
+                        *      Now get the reply pairs since the paircompare matched
+                        */
+                       if (!radius_xlat(querystr, sizeof(querystr), inst->config->authorize_reply_query, request, sql_escape_func)) {
+                               radlog(L_ERR, "rlm_sql (%s): Error generating query; rejecting user",
+                                      inst->config->xlat_name);
+                               sql_release_socket(inst, sqlsocket);
+                               /* Remove the username we (maybe) added above */
+                               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+                               pairfree(&check_tmp);
+                               return RLM_MODULE_FAIL;
+                       }
+                       if (sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr) < 0) {
+                               radlog(L_ERR, "rlm_sql (%s): SQL query error; rejecting user",
+                                      inst->config->xlat_name);
+                               sql_release_socket(inst, sqlsocket);
+                               /* Remove the username we (maybe) added above */
+                               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+                               pairfree(&check_tmp);
+                               pairfree(&reply_tmp);
+                               return RLM_MODULE_FAIL;
+                       }
+                       if (!inst->config->read_groups)
+                               dofallthrough = fallthrough(reply_tmp);
+                       pairxlatmove(request, &request->reply->vps, &reply_tmp);
+                       pairxlatmove(request, &request->config_items, &check_tmp);
+               }
+       }
 
-       } else {
-               radlog(L_DBG, "rlm_sql (%s): User %s not found in radcheck",
-                      inst->config->xlat_name, sqlusername);
+       /*
+        *      Clear out the pairlists
+        */
+       pairfree(&check_tmp);
+       pairfree(&reply_tmp);
 
-                /*
-                * We didn't find the user in radcheck, so we try looking
-                * for radgroupcheck entry
-                */
-                radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_check_query, request, sql_escape_func);
-                found = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr, PW_VP_GROUPDATA);
-                radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query, request, sql_escape_func);
-                sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr, PW_VP_GROUPDATA);
-        }
-       if (!found)
-               radlog(L_DBG, "rlm_sql (%s): User %s not found in radgroupcheck",
-                      inst->config->xlat_name, sqlusername);
-       if (found || (!found && inst->config->query_on_not_found)){
-               int def_found = 0;
+       /*
+        *      dofallthrough is set to 1 by default so that if the user information
+        *      is not found, we will still process groups.  If the user information,
+        *      however, *is* found, Fall-Through must be set in order to process
+        *      the groups as well
+        */
+       if (dofallthrough) {
+               rows = rlm_sql_process_groups(inst, request, sqlsocket, &dofallthrough);
+               if (rows < 0) {
+                       radlog(L_ERR, "rlm_sql (%s): Error processing groups; rejecting user",
+                              inst->config->xlat_name);
+                       sql_release_socket(inst, sqlsocket);
+                       /* Remove the username we (maybe) added above */
+                       pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+                       return RLM_MODULE_FAIL;
+               } else if (rows > 0) {
+                       found = 1;
+               }
+       }
 
+       /*
+        *      repeat the above process with the default profile or User-Profile
+        */
+       if (dofallthrough) {
+               int profile_found = 0;
                /*
                * Check for a default_profile or for a User-Profile.
                */
@@ -803,74 +1013,49 @@ static int rlm_sql_authorize(void *instance, REQUEST * request)
                        char *profile = inst->config->default_profile;
 
                        if (user_profile != NULL)
-                               profile = user_profile->strvalue;
+                               profile = user_profile->vp_strvalue;
                        if (profile && strlen(profile)){
                                radlog(L_DBG, "rlm_sql (%s): Checking profile %s",
                                       inst->config->xlat_name, profile);
-                               if (sql_set_user(inst, request, sqlusername, profile) < 0) {
+                               if (sql_set_user(inst, request, profileusername, profile) < 0) {
+                                       radlog(L_ERR, "rlm_sql (%s): Error setting profile; rejecting user",
+                                              inst->config->xlat_name);
                                        sql_release_socket(inst, sqlsocket);
-                                       pairfree(&reply_tmp);
-                                       pairfree(&check_tmp);
+                                       /* Remove the username we (maybe) added above */
+                                       pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
                                        return RLM_MODULE_FAIL;
+                               } else {
+                                       profile_found = 1;
                                }
-                               radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_check_query,
-                                                                       request, sql_escape_func);
-                               def_found = sql_getvpdata(inst, sqlsocket, &check_tmp, querystr, PW_VP_GROUPDATA);
-                               if (def_found)
-                                       found = 1;
-                               radius_xlat(querystr, sizeof(querystr), inst->config->authorize_group_reply_query,
-                                                                       request, sql_escape_func);
-                               sql_getvpdata(inst, sqlsocket, &reply_tmp, querystr, PW_VP_GROUPDATA);
+                       }
+               }
+
+               if (profile_found) {
+                       rows = rlm_sql_process_groups(inst, request, sqlsocket, &dofallthrough);
+                       if (rows < 0) {
+                               radlog(L_ERR, "rlm_sql (%s): Error processing profile groups; rejecting user",
+                                      inst->config->xlat_name);
+                               sql_release_socket(inst, sqlsocket);
+                               /* Remove the username we (maybe) added above */
+                               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
+                               return RLM_MODULE_FAIL;
+                       } else if (rows > 0) {
+                               found = 1;
                        }
                }
        }
 
-       /*
-        *      We don't need the SQL socket anymore.
-        */
+       /* Remove the username we (maybe) added above */
+       pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
        sql_release_socket(inst, sqlsocket);
 
        if (!found) {
-               radlog(L_DBG, "rlm_sql (%s): User not found",
-                      inst->config->xlat_name);
-               /* Remove the username we (maybe) added above */
-               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
-               pairfree(&reply_tmp);
-               pairfree(&check_tmp);
-               return RLM_MODULE_NOTFOUND;
-       }
-
-       /*
-        * Uncomment these lines for debugging
-        * Recompile, and run 'radiusd -X'
-        */
-
-       /*
-       DEBUG2("rlm_sql:  check items");
-       vp_listdebug(check_tmp);
-       DEBUG2("rlm_sql:  reply items");
-       vp_listdebug(reply_tmp);
-       */
-
-       if (paircmp(request, request->packet->vps, check_tmp, &reply_tmp) != 0) {
-               radlog(L_INFO, "rlm_sql (%s): No matching entry in the database for request from user [%s]",
+               radlog(L_DBG, "rlm_sql (%s): User %s not found",
                       inst->config->xlat_name, sqlusername);
-               /* Remove the username we (maybe) added above */
-               pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
-               pairfree(&reply_tmp);
-               pairfree(&check_tmp);
                return RLM_MODULE_NOTFOUND;
+       } else {
+               return RLM_MODULE_OK;
        }
-
-       pairxlatmove(request, &request->reply->vps, &reply_tmp);
-       pairxlatmove(request, &request->config_items, &check_tmp);
-       pairfree(&reply_tmp);
-       pairfree(&check_tmp);
-
-       /* Remove the username we (maybe) added above */
-       pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
-
-       return RLM_MODULE_OK;
 }
 
 /*
@@ -1183,10 +1368,11 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) {
                return RLM_MODULE_OK;
        }
 
-       /* Looks like too many sessions, so lets start verifying them */
-
-       if (inst->config->simul_verify_query[0] == 0) {
-               /* No verify query defined, so skip verify step and rely on count query only */
+       /*
+        *      Looks like too many sessions, so let's start verifying
+        *      them, unless told to rely on count query only.
+        */
+       if (inst->config->simul_verify_query[0] == '\0') {
                sql_release_socket(inst, sqlsocket);
                return RLM_MODULE_OK;
        }
@@ -1206,7 +1392,7 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) {
         if ((vp = pairfind(request->packet->vps, PW_FRAMED_IP_ADDRESS)) != NULL)
                 ipno = vp->lvalue;
         if ((vp = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) != NULL)
-                call_num = vp->strvalue;
+                call_num = vp->vp_strvalue;
 
 
        while (rlm_sql_fetch_row(sqlsocket, inst) == 0) {
@@ -1232,19 +1418,34 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) {
 
                check = rad_check_ts(nas_addr, nas_port, row[2], row[1]);
 
-                /*
-                 *      Failed to check the terminal server for
-                 *      duplicate logins: Return an error.
-                 */
-               if (check < 0) {
-                       (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
-                       sql_release_socket(inst, sqlsocket);
-                       DEBUG("rlm_sql (%s) rad_check_ts() failed.",
-                             inst->config->xlat_name);
-                       return RLM_MODULE_FAIL;
+               if (check == 0) {
+                       /*
+                        *      Stale record - zap it.
+                        */
+                       if (inst->config->deletestalesessions == TRUE) {
+                               uint32_t framed_addr = 0;
+                               char proto = 0;
+                               int sess_time = 0;
+
+                               if (row[5])
+                                       framed_addr = inet_addr(row[5]);
+                               if (row[7]){
+                                       if (strcmp(row[7], "PPP") == 0)
+                                               proto = 'P';
+                                       else if (strcmp(row[7], "SLIP") == 0)
+                                               proto = 'S';
+                               }
+                               if (row[8])
+                                       sess_time = atoi(row[8]);
+                               session_zap(request, nas_addr, nas_port,
+                                           row[2], row[1], framed_addr,
+                                           proto, sess_time);
+                       }
                }
-
-               if(check == 1) {
+               else if (check == 1) {
+                       /*
+                        *      User is still logged in.
+                        */
                        ++request->simul_count;
 
                         /*
@@ -1257,31 +1458,26 @@ static int rlm_sql_checksimul(void *instance, REQUEST * request) {
                                 request->simul_mpp = 2;
                }
                else {
-                        /*
-                         *      Stale record - zap it.
-                         */
-                       uint32_t framed_addr = 0;
-                       char proto = 'P';
-
-                       if (row[5])
-                               framed_addr = inet_addr(row[5]);
-                       if (row[7])
-                               if (strcmp(row[7],"SLIP") == 0)
-                                       proto = 'S';
-
-                       session_zap(request,
-                                   nas_addr,nas_port,row[2],row[1],
-                                   framed_addr, proto);
+                       /*
+                        *      Failed to check the terminal server for
+                        *      duplicate logins: return an error.
+                        */
+                       (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
+                       sql_release_socket(inst, sqlsocket);
+                       radlog(L_ERR, "rlm_sql (%s): sql_checksimul: Failed to check the terminal server for user '%s'.", inst->config->xlat_name, row[2]);
+                       return RLM_MODULE_FAIL;
                }
        }
 
        (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
        sql_release_socket(inst, sqlsocket);
 
-       /* The Auth module apparently looks at request->simul_count, not the return value
-          of this module when deciding to deny a call for too many sessions */
+       /*
+        *      The Auth module apparently looks at request->simul_count,
+        *      not the return value of this module when deciding to deny
+        *      a call for too many sessions.
+        */
        return RLM_MODULE_OK;
-
 }
 
 /*
@@ -1331,10 +1527,11 @@ static int rlm_sql_postauth(void *instance, REQUEST *request) {
 
 /* globally exported name */
 module_t rlm_sql = {
+       RLM_MODULE_INIT,
        "SQL",
        RLM_TYPE_THREAD_SAFE,   /* type: reserved */
-       rlm_sql_init,           /* initialization */
        rlm_sql_instantiate,    /* instantiation */
+       rlm_sql_detach,         /* detach */
        {
                NULL,                   /* authentication */
                rlm_sql_authorize,      /* authorization */
@@ -1345,6 +1542,4 @@ module_t rlm_sql = {
                NULL,                   /* post-proxy */
                rlm_sql_postauth        /* post-auth */
        },
-       rlm_sql_detach,         /* detach */
-       rlm_sql_destroy,        /* destroy */
 };
index 03e47ff..b69539a 100644 (file)
@@ -8,6 +8,9 @@
 #ifndef _RLM_SQL_H
 #define _RLM_SQL_H
 
+#include <freeradius-devel/ident.h>
+RCSIDH(rlm_sql_h, "$Id$")
+
 #ifdef HAVE_PTHREAD_H
 #include        <pthread.h>
 #endif
 #include       <ltdl.h>
 
 #include "conf.h"
-#include "conffile.h"
 
 #define SQLSOCK_LOCKED         0
 #define SQLSOCK_UNLOCKED       1
 
-#define PW_VP_USERDATA         1
-#define PW_VP_GROUPDATA                2
-#define PW_VP_REALMDATA                3
-
 #define PW_ITEM_CHECK                  0
 #define PW_ITEM_REPLY                  1
 
@@ -69,15 +67,20 @@ typedef struct sql_inst {
        rlm_sql_module_t *module;
 } SQL_INST;
 
+typedef struct sql_grouplist {
+       char                    groupname[MAX_STRING_LEN];
+       struct sql_grouplist    *next;
+} SQL_GROUPLIST;
+
 
 int     sql_init_socketpool(SQL_INST * inst);
 void    sql_poolfree(SQL_INST * inst);
 int     sql_close_socket(SQL_INST *inst, SQLSOCK * sqlsocket);
 SQLSOCK *sql_get_socket(SQL_INST * inst);
 int     sql_release_socket(SQL_INST * inst, SQLSOCK * sqlsocket);
-int     sql_userparse(VALUE_PAIR ** first_pair, SQL_ROW row, int mode);
+int     sql_userparse(VALUE_PAIR ** first_pair, SQL_ROW row);
 int     sql_read_realms(SQLSOCK * sqlsocket);
-int     sql_getvpdata(SQL_INST * inst, SQLSOCK * sqlsocket, VALUE_PAIR **pair, char *query, int mode);
+int     sql_getvpdata(SQL_INST * inst, SQLSOCK * sqlsocket, VALUE_PAIR **pair, char *query);
 int     sql_read_naslist(SQLSOCK * sqlsocket);
 int     sql_read_clients(SQLSOCK * sqlsocket);
 int     sql_dict_init(SQLSOCK * sqlsocket);
index 6888477..c0f713a 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2001  The FreeRADIUS server project
+ * Copyright 2001,2006  The FreeRADIUS server project
  * Copyright 2000  Mike Machado <mike@innercite.com>
  * Copyright 2000  Alan DeKok <aland@ox.org>
  * Copyright 2001  Chad Miller <cmiller@surfsouth.com>
  */
 
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include       <freeradius-devel/autoconf.h>
 
 #include       <sys/types.h>
 #include       <sys/socket.h>
 #include       <errno.h>
 #include       <sys/wait.h>
 
-#include       "radiusd.h"
-#include       "conffile.h"
+#include       <freeradius-devel/radiusd.h>
 #include       "rlm_sql.h"
 
 #ifdef HAVE_PTHREAD_H
-#include       <pthread.h>
 #endif
 
 
@@ -325,9 +327,9 @@ int sql_release_socket(SQL_INST * inst, SQLSOCK * sqlsocket)
  *     Purpose: Read entries from the database and fill VALUE_PAIR structures
  *
  *************************************************************************/
-int sql_userparse(VALUE_PAIR ** first_pair, SQL_ROW row, int querymode)
+int sql_userparse(VALUE_PAIR ** first_pair, SQL_ROW row)
 {
-       VALUE_PAIR *pair, *check;
+       VALUE_PAIR *pair;
        char *ptr, *value;
        char buf[MAX_STRING_LEN];
        char do_xlat = 0;
@@ -406,25 +408,11 @@ int sql_userparse(VALUE_PAIR ** first_pair, SQL_ROW row, int querymode)
        }
        if (do_xlat) {
                pair->flags.do_xlat = 1;
-               strNcpy(pair->strvalue, buf, sizeof(pair->strvalue));
+               strlcpy(pair->vp_strvalue, buf, sizeof(pair->vp_strvalue));
                pair->length = 0;
        }
 
        /*
-        *      If attribute is already there, skip it because we
-        *      checked usercheck first and we want user settings to
-        *      override group settings
-        */
-       if (operator != T_OP_ADD && (check = pairfind(*first_pair, pair->attribute)) != NULL &&
-#ifdef ASCEND_BINARY
-           pair->type != PW_TYPE_ABINARY &&
-#endif
-           querymode == PW_VP_GROUPDATA) {
-               pairbasicfree(pair);
-               return 0;
-       }
-
-       /*
         *      Add the pair into the packet
         */
        pairadd(first_pair, pair);
@@ -572,7 +560,7 @@ int rlm_sql_select_query(SQLSOCK *sqlsocket, SQL_INST *inst, char *query)
  *     Purpose: Get any group check or reply pairs
  *
  *************************************************************************/
-int sql_getvpdata(SQL_INST * inst, SQLSOCK * sqlsocket, VALUE_PAIR **pair, char *query, int mode)
+int sql_getvpdata(SQL_INST * inst, SQLSOCK * sqlsocket, VALUE_PAIR **pair, char *query)
 {
        SQL_ROW row;
        int     rows = 0;
@@ -592,7 +580,7 @@ int sql_getvpdata(SQL_INST * inst, SQLSOCK * sqlsocket, VALUE_PAIR **pair, char
                row = sqlsocket->row;
                if (!row)
                        break;
-               if (sql_userparse(pair, row, mode) != 0) {
+               if (sql_userparse(pair, row) != 0) {
                        radlog(L_ERR | L_CONS, "rlm_sql (%s): Error getting data from database", inst->config->xlat_name);
                        (inst->module->sql_finish_select_query)(sqlsocket, inst->config);
                        return -1;
index 8705845..d9c5047 100644 (file)
@@ -7,6 +7,7 @@
  *  Author:     Nicolas Baradakis <nicolas.baradakis@cegetel.net>
  *
  *  Copyright (C) 2005 Cegetel
+ *  Copyright 2006 The FreeRADIUS server project
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
  *
  *  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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "autoconf.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 
-#include "libradius.h"
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
-
-static const char rcsid[] = "$Id$";
+#include <freeradius-devel/libradius.h>
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 static int sql_log_instantiate(CONF_SECTION *conf, void **instance);
 static int sql_log_detach(void *instance);
@@ -230,7 +231,7 @@ static int sql_set_user(rlm_sql_log_t *inst, REQUEST *request, char *sqlusername
        pairdelete(&request->packet->vps, PW_SQL_USER_NAME);
 
        if (username != NULL) {
-               strNcpy(tmpuser, username, MAX_STRING_LEN);
+               strlcpy(tmpuser, username, MAX_STRING_LEN);
        } else if (inst->sql_user_name[0] != '\0') {
                radius_xlat(tmpuser, sizeof(tmpuser), inst->sql_user_name,
                            request, NULL);
@@ -239,7 +240,7 @@ static int sql_set_user(rlm_sql_log_t *inst, REQUEST *request, char *sqlusername
        }
 
        if (tmpuser[0] != '\0') {
-               strNcpy(sqlusername, tmpuser, sizeof(tmpuser));
+               strlcpy(sqlusername, tmpuser, sizeof(tmpuser));
                DEBUG2("rlm_sql_log (%s): sql_set_user escaped user --> '%s'",
                       inst->name, sqlusername);
                vp = pairmake("SQL-User-Name", sqlusername, 0);
@@ -428,10 +429,11 @@ static int sql_log_postauth(void *instance, REQUEST *request)
  *     is single-threaded.
  */
 module_t rlm_sql_log = {
+       RLM_MODULE_INIT,
        "sql_log",
        RLM_TYPE_THREAD_SAFE,           /* type */
-       NULL,                           /* initialization */
        sql_log_instantiate,            /* instantiation */
+       sql_log_detach,                 /* detach */
        {
                NULL,                   /* authentication */
                NULL,                   /* authorization */
@@ -442,6 +444,4 @@ module_t rlm_sql_log = {
                NULL,                   /* post-proxy */
                sql_log_postauth        /* post-auth */
        },
-       sql_log_detach,                 /* detach */
-       NULL,                           /* destroy */
 };
index 3e7fdb5..bd853f0 100644 (file)
@@ -4,6 +4,10 @@
 
 TARGET      = @targetname@
 SRCS        = rlm_sqlcounter.c
+HEADERS     =
+RLM_CFLAGS  = @sqlcounter_cflags@
+RLM_LIBS    = @sqlcounter_ldflags@
+RLM_INSTALL =
 
 include ../rules.mak
 
diff --git a/src/modules/rlm_sqlcounter/acconfig.h b/src/modules/rlm_sqlcounter/acconfig.h
deleted file mode 100644 (file)
index 1ec861a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/* do we need anything in here? */
index e8a6040..14531ed 100644 (file)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.2.6.1 .
+# From configure.in Revision: 1.4 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -273,7 +273,7 @@ PACKAGE_STRING=
 PACKAGE_BUGREPORT=
 
 ac_unique_file="rlm_sqlcounter.c"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS targetname LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP sqlcounter_ldflags sqlcounter_cflags targetname LIBOBJS LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -714,6 +714,26 @@ ac_env_target_alias_set=${target_alias+set}
 ac_env_target_alias_value=$target_alias
 ac_cv_env_target_alias_set=${target_alias+set}
 ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
 
 #
 # Report the --help message.
@@ -781,6 +801,18 @@ if test -n "$ac_init_help"; then
 
   cat <<\_ACEOF
 
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  CPPFLAGS    C/C++ preprocessor flags, e.g. -I<include dir> if you have
+              headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
 _ACEOF
 fi
 
@@ -869,7 +901,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1221,6 +1253,1164 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 if test x$with_rlm_sqlcounter != xno; then
 
+       ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  CC=$ac_ct_CC
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  echo "$as_me:$LINENO: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+  test -n "$ac_ct_CC" && break
+done
+
+  CC=$ac_ct_CC
+fi
+
+fi
+
+
+test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+     "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+  (eval $ac_compiler --version </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+  (eval $ac_compiler -v </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+  (eval $ac_compiler -V </dev/null >&5) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+  (eval $ac_link_default) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Find the output, starting from the most likely.  This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+       ;;
+    conftest.$ac_ext )
+       # This is the source file.
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+       ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       # FIXME: I believe we export ac_cv_exeext for Libtool,
+       # but it would be cool to find out if it's true.  Does anybody
+       # maintain Libtool? --akim.
+       export ac_cv_exeext
+       break;;
+    * )
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         export ac_cv_exeext
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_compiler_gnu=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_g=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cc_g=no
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std1 is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std1.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX                  -qlanglvl=ansi
+# Ultrix and OSF/1     -std1
+# HP-UX 10.20 and later        -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4                 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+  x|xno)
+    echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+  *)
+    echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+    CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+# Some people use a C++ compiler to compile C.  Since we use `exit',
+# in C++ we need to declare it.  In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+  choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  for ac_declaration in \
+   '' \
+   'extern "C" void std::exit (int) throw (); using std::exit;' \
+   'extern "C" void std::exit (int); using std::exit;' \
+   'extern "C" void exit (int) throw ();' \
+   'extern "C" void exit (int);' \
+   'void exit (int);'
+do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+#include <stdlib.h>
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+continue
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_declaration
+int
+main ()
+{
+exit (42);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  break
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+  echo '#ifdef __cplusplus' >>confdefs.h
+  echo $ac_declaration      >>confdefs.h
+  echo '#endif'             >>confdefs.h
+fi
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+       ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:$LINENO: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  :
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether non-existent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+  (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null; then
+  if test -s conftest.err; then
+    ac_cpp_err=$ac_c_preproc_warn_flag
+    ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
+  else
+    ac_cpp_err=
+  fi
+else
+  ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+  # Broken: success on invalid input.
+continue
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
 
        targetname=rlm_sqlcounter
 else
@@ -1228,6 +2418,24 @@ else
        echo \*\*\* module rlm_sqlcounter is disabled.
 fi
 
+if test x"$fail" != x""; then
+       if test x"${enable_strict_dependencies}" = x"yes"; then
+               { { echo "$as_me:$LINENO: error: set --without-rlm_sqlcounter to disable it explicitly." >&5
+echo "$as_me: error: set --without-rlm_sqlcounter to disable it explicitly." >&2;}
+   { (exit 1); exit 1; }; }
+       else
+               { echo "$as_me:$LINENO: WARNING: silently not building rlm_sqlcounter." >&5
+echo "$as_me: WARNING: silently not building rlm_sqlcounter." >&2;}
+               { echo "$as_me:$LINENO: WARNING: FAILURE: rlm_sqlcounter requires: $fail." >&5
+echo "$as_me: WARNING: FAILURE: rlm_sqlcounter requires: $fail." >&2;};
+               targetname=""
+       fi
+fi
+
+sqlcounter_ldflags=$SMART_LIBS
+sqlcounter_cflags=$SMART_CFLAGS
+
+
 
           ac_config_files="$ac_config_files Makefile"
 cat >confcache <<\_ACEOF
@@ -1864,6 +3072,16 @@ s,@ECHO_C@,$ECHO_C,;t t
 s,@ECHO_N@,$ECHO_N,;t t
 s,@ECHO_T@,$ECHO_T,;t t
 s,@LIBS@,$LIBS,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@CPP@,$CPP,;t t
+s,@sqlcounter_ldflags@,$sqlcounter_ldflags,;t t
+s,@sqlcounter_cflags@,$sqlcounter_cflags,;t t
 s,@targetname@,$targetname,;t t
 s,@LIBOBJS@,$LIBOBJS,;t t
 s,@LTLIBOBJS@,$LTLIBOBJS,;t t
@@ -2029,11 +3247,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -2072,6 +3285,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 7230e45..aab39b3 100644 (file)
@@ -1,11 +1,12 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_sqlcounter.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_sqlcounter])
 
 if test x$with_[]modname != xno; then
 
-       dnl  This module doesn't need any autoconf test which is not already
-       dnl  in top-level configure.
+       AC_PROG_CC
+       AC_PROG_CPP
 
        targetname=modname
 else
@@ -13,5 +14,19 @@ else
        echo \*\*\* module modname is disabled.
 fi
 
+if test x"$fail" != x""; then
+       if test x"${enable_strict_dependencies}" = x"yes"; then
+               AC_MSG_ERROR([set --without-]modname[ to disable it explicitly.])
+       else
+               AC_MSG_WARN([silently not building ]modname[.])
+               AC_MSG_WARN([FAILURE: ]modname[ requires: $fail.]); 
+               targetname=""
+       fi
+fi
+
+sqlcounter_ldflags=$SMART_LIBS
+sqlcounter_cflags=$SMART_CFLAGS
+AC_SUBST(sqlcounter_ldflags)
+AC_SUBST(sqlcounter_cflags)
 AC_SUBST(targetname)
 AC_OUTPUT(Makefile)
index 5d4c6a0..de68b1a 100644 (file)
  *   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  The FreeRADIUS server project
+ * Copyright 2001,2006  The FreeRADIUS server project
  * Copyright 2001  Alan DeKok <aland@ox.org>
  */
 
 /* This module is based directly on the rlm_counter module */
 
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 
 #define MAX_QUERY_LEN 1024
 
-#include <time.h>
-
+static int sqlcounter_detach(void *instance);
 
-/*     Note: When your counter spans more than 1 period (ie 3 months or 2 weeks), this module
- *     probably does NOT do what you want!  It calculates the range of dates to count across
- *     by first calculating the End of the Current period and then subtracting the number of
- *     periods you specify from that to determine the beginning of the range.
+/*
+ *     Note: When your counter spans more than 1 period (ie 3 months
+ *     or 2 weeks), this module probably does NOT do what you want! It
+ *     calculates the range of dates to count across by first calculating
+ *     the End of the Current period and then subtracting the number of
+ *     periods you specify from that to determine the beginning of the
+ *     range.
  *
- *     For example, if you specify a 3 month counter and today is June 15th, the end of the current
- *     period is June 30. Subtracting 3 months from that gives April 1st.  So, the counter will
- *     sum radacct entries from April 1st to June 30. Then, next month, it will sum entries
- *     from May 1st to July 31st.
+ *     For example, if you specify a 3 month counter and today is June 15th,
+ *     the end of the current period is June 30. Subtracting 3 months from
+ *     that gives April 1st. So, the counter will sum radacct entries from
+ *     April 1st to June 30. Then, next month, it will sum entries from
+ *     May 1st to July 31st.
  *
- *     To fix this behavior, we need to add some way of storing the Next Reset Time
+ *     To fix this behavior, we need to add some way of storing the Next
+ *     Reset Time.
  */
 
-
-static const char rcsid[] = "$Id$";
-
 /*
  *     Define a structure for our module configuration.
  *
@@ -89,7 +91,7 @@ typedef struct rlm_sqlcounter_t {
  *     to the strdup'd string into 'config.string'.  This gets around
  *     buffer over-flows.
  */
-static CONF_PARSER module_config[] = {
+static const CONF_PARSER module_config[] = {
   { "counter-name", PW_TYPE_STRING_PTR, offsetof(rlm_sqlcounter_t,counter_name), NULL,  NULL },
   { "check-name", PW_TYPE_STRING_PTR, offsetof(rlm_sqlcounter_t,check_name), NULL, NULL },
   { "reply-name", PW_TYPE_STRING_PTR, offsetof(rlm_sqlcounter_t,reply_name), NULL, NULL },
@@ -154,28 +156,28 @@ static int sql_escape_func(char *out, int outlen, const char *in)
 
 static int find_next_reset(rlm_sqlcounter_t *data, time_t timeval)
 {
-       int ret=0;
-       unsigned int num=1;
-       char last = 0;
+       int ret = 0;
+       size_t len;
+       unsigned int num = 1;
+       char last = '\0';
        struct tm *tm, s_tm;
        char sCurrentTime[40], sNextTime[40];
 
        tm = localtime_r(&timeval, &s_tm);
-       strftime(sCurrentTime, sizeof(sCurrentTime),"%Y-%m-%d %H:%M:%S",tm);
+       len = strftime(sCurrentTime, sizeof(sCurrentTime), "%Y-%m-%d %H:%M:%S", tm);
+       if (len == 0) *sCurrentTime = '\0';
        tm->tm_sec = tm->tm_min = 0;
 
        if (data->reset == NULL)
                return -1;
        if (isdigit((int) data->reset[0])){
-               unsigned int len=0;
-
                len = strlen(data->reset);
                if (len == 0)
                        return -1;
                last = data->reset[len - 1];
                if (!isalpha((int) last))
                        last = 'd';
-/*             num = atoi(data->reset); */
+               num = atoi(data->reset);
                DEBUG("rlm_sqlcounter: num=%d, last=%c",num,last);
        }
        if (strcmp(data->reset, "hourly") == 0 || last == 'h') {
@@ -210,9 +212,11 @@ static int find_next_reset(rlm_sqlcounter_t *data, time_t timeval)
                        data->reset);
                return -1;
        }
-       strftime(sNextTime, sizeof(sNextTime),"%Y-%m-%d %H:%M:%S",tm);
-       DEBUG2("rlm_sqlcounter: Current Time: %d [%s], Next reset %d [%s]",
-               (int)timeval,sCurrentTime,(int)data->reset_time, sNextTime);
+
+       len = strftime(sNextTime, sizeof(sNextTime),"%Y-%m-%d %H:%M:%S",tm);
+       if (len == 0) *sNextTime = '\0';
+       DEBUG2("rlm_sqlcounter: Current Time: %li [%s], Next reset %li [%s]",
+               timeval, sCurrentTime, data->reset_time, sNextTime);
 
        return ret;
 }
@@ -224,21 +228,21 @@ static int find_next_reset(rlm_sqlcounter_t *data, time_t timeval)
 
 static int find_prev_reset(rlm_sqlcounter_t *data, time_t timeval)
 {
-       int ret=0;
-       unsigned int num=1;
-       char last = 0;
+       int ret = 0;
+       size_t len;
+       unsigned int num = 1;
+       char last = '\0';
        struct tm *tm, s_tm;
        char sCurrentTime[40], sPrevTime[40];
 
        tm = localtime_r(&timeval, &s_tm);
-       strftime(sCurrentTime, sizeof(sCurrentTime),"%Y-%m-%d %H:%M:%S",tm);
+       len = strftime(sCurrentTime, sizeof(sCurrentTime), "%Y-%m-%d %H:%M:%S", tm);
+       if (len == 0) *sCurrentTime = '\0';
        tm->tm_sec = tm->tm_min = 0;
 
        if (data->reset == NULL)
                return -1;
        if (isdigit((int) data->reset[0])){
-               unsigned int len=0;
-
                len = strlen(data->reset);
                if (len == 0)
                        return -1;
@@ -280,9 +284,10 @@ static int find_prev_reset(rlm_sqlcounter_t *data, time_t timeval)
                        data->reset);
                return -1;
        }
-       strftime(sPrevTime, sizeof(sPrevTime),"%Y-%m-%d %H:%M:%S",tm);
-       DEBUG2("rlm_sqlcounter: Current Time: %d [%s], Prev reset %d [%s]",
-               (int)timeval,sCurrentTime,(int)data->last_reset, sPrevTime);
+       len = strftime(sPrevTime, sizeof(sPrevTime), "%Y-%m-%d %H:%M:%S", tm);
+       if (len == 0) *sPrevTime = '\0';
+       DEBUG2("rlm_sqlcounter: Current Time: %li [%s], Prev reset %li [%s]",
+              timeval, sCurrentTime, data->last_reset, sPrevTime);
 
        return ret;
 }
@@ -349,20 +354,20 @@ static int sqlcounter_expand(char *out, int outlen, const char *fmt, void *insta
                                *q++ = *p;
                        case 'b': /* last_reset */
                                snprintf(tmpdt, sizeof(tmpdt), "%lu", data->last_reset);
-                               strNcpy(q, tmpdt, freespace);
+                               strlcpy(q, tmpdt, freespace);
                                q += strlen(q);
                                break;
                        case 'e': /* reset_time */
                                snprintf(tmpdt, sizeof(tmpdt), "%lu", data->reset_time);
-                               strNcpy(q, tmpdt, freespace);
+                               strlcpy(q, tmpdt, freespace);
                                q += strlen(q);
                                break;
                        case 'k': /* Key Name */
-                               strNcpy(q, data->key_name, freespace);
+                               strlcpy(q, data->key_name, freespace);
                                q += strlen(q);
                                break;
                        case 'S': /* SQL module instance */
-                               strNcpy(q, data->sqlmod_inst, freespace);
+                               strlcpy(q, data->sqlmod_inst, freespace);
                                q += strlen(q);
                                break;
                        default:
@@ -382,8 +387,9 @@ static int sqlcounter_expand(char *out, int outlen, const char *fmt, void *insta
 /*
  *     See if the counter matches.
  */
-static int sqlcounter_cmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check,
-               VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+static int sqlcounter_cmp(void *instance, REQUEST *req,
+                         UNUSED VALUE_PAIR *request, VALUE_PAIR *check,
+                         VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
 {
        rlm_sqlcounter_t *data = (rlm_sqlcounter_t *) instance;
        int counter;
@@ -435,6 +441,7 @@ static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance)
         */
        data = rad_malloc(sizeof(*data));
        if (!data) {
+               radlog(L_ERR, "rlm_sqlcounter: Not enough memory.");
                return -1;
        }
        memset(data, 0, sizeof(*data));
@@ -444,7 +451,8 @@ static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance)
         *      fail.
         */
        if (cf_section_parse(conf, data, module_config) < 0) {
-               free(data);
+               radlog(L_ERR, "rlm_sqlcounter: Unable to parse parameters.");
+               sqlcounter_detach(data);
                return -1;
        }
 
@@ -453,6 +461,7 @@ static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance)
         */
        if (data->query == NULL) {
                radlog(L_ERR, "rlm_sqlcounter: 'query' must be set.");
+               sqlcounter_detach(data);
                return -1;
        }
 
@@ -467,17 +476,20 @@ static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance)
         */
        if (data->key_name == NULL) {
                radlog(L_ERR, "rlm_sqlcounter: 'key' must be set.");
+               sqlcounter_detach(data);
                return -1;
        }
        sql_escape_func(buffer, sizeof(buffer), data->key_name);
        if (strcmp(buffer, data->key_name) != 0) {
                radlog(L_ERR, "rlm_sqlcounter: The value for option 'key' is too long or contains unsafe characters.");
+               sqlcounter_detach(data);
                return -1;
        }
        dattr = dict_attrbyname(data->key_name);
        if (dattr == NULL) {
                radlog(L_ERR, "rlm_sqlcounter: No such attribute %s",
                                data->key_name);
+               sqlcounter_detach(data);
                return -1;
        }
        data->key_attr = dattr->attr;
@@ -497,6 +509,7 @@ static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance)
                if (dattr == NULL) {
                        radlog(L_ERR, "rlm_sqlcounter: No such attribute %s",
                               data->reply_name);
+                       sqlcounter_detach(data);
                        return -1;
                }
                data->reply_attr = dattr->attr;
@@ -509,11 +522,13 @@ static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance)
         */
        if (data->sqlmod_inst == NULL) {
                radlog(L_ERR, "rlm_sqlcounter: 'sqlmod-inst' must be set.");
+               sqlcounter_detach(data);
                return -1;
        }
        sql_escape_func(buffer, sizeof(buffer), data->sqlmod_inst);
        if (strcmp(buffer, data->sqlmod_inst) != 0) {
                radlog(L_ERR, "rlm_sqlcounter: The value for option 'sqlmod-inst' is too long or contains unsafe characters.");
+               sqlcounter_detach(data);
                return -1;
        }
 
@@ -522,6 +537,7 @@ static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance)
         */
        if (data->counter_name == NULL) {
                radlog(L_ERR, "rlm_sqlcounter: 'counter-name' must be set.");
+               sqlcounter_detach(data);
                return -1;
        }
 
@@ -531,6 +547,7 @@ static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance)
        if (dattr == NULL) {
                radlog(L_ERR, "rlm_sqlcounter: Failed to create counter attribute %s",
                                data->counter_name);
+               sqlcounter_detach(data);
                return -1;
        }
        data->dict_attr = dattr->attr;
@@ -542,6 +559,7 @@ static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance)
         */
        if (data->check_name == NULL) {
                radlog(L_ERR, "rlm_sqlcounter: 'check-name' must be set.");
+               sqlcounter_detach(data);
                return -1;
        }
        dict_addattr(data->check_name, 0, PW_TYPE_INTEGER, -1, flags);
@@ -549,6 +567,7 @@ static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance)
        if (dattr == NULL) {
                radlog(L_ERR, "rlm_sqlcounter: Failed to create check attribute %s",
                                data->check_name);
+               sqlcounter_detach(data);
                return -1;
        }
        DEBUG2("rlm_sqlcounter: Check attribute %s is number %d",
@@ -559,22 +578,28 @@ static int sqlcounter_instantiate(CONF_SECTION *conf, void **instance)
         */
        if (data->reset == NULL) {
                radlog(L_ERR, "rlm_sqlcounter: 'reset' must be set.");
+               sqlcounter_detach(data);
                return -1;
        }
        now = time(NULL);
        data->reset_time = 0;
 
-       if (find_next_reset(data,now) == -1)
+       if (find_next_reset(data,now) == -1) {
+               radlog(L_ERR, "rlm_sqlcounter: Failed to find the next reset time.");
+               sqlcounter_detach(data);
                return -1;
+       }
 
        /*
         *  Discover the beginning of the current time period.
         */
        data->last_reset = 0;
 
-       if (find_prev_reset(data,now) == -1)
+       if (find_prev_reset(data,now) == -1) {
+               radlog(L_ERR, "rlm_sqlcounter: Failed to find the previous reset time.");
+               sqlcounter_detach(data);
                return -1;
-
+       }
 
        /*
         *      Register the counter comparison operation.
@@ -706,9 +731,9 @@ static int sqlcounter_authorize(void *instance, REQUEST *request)
                ret=RLM_MODULE_OK;
 
                DEBUG2("rlm_sqlcounter: Authorized user %s, check_item=%d, counter=%d",
-                               key_vp->strvalue,check_vp->lvalue,counter);
+                               key_vp->vp_strvalue,check_vp->lvalue,counter);
                DEBUG2("rlm_sqlcounter: Sent Reply-Item for user %s, Type=%s, value=%d",
-                               key_vp->strvalue,data->reply_name,reply_item->lvalue);
+                               key_vp->vp_strvalue,data->reply_name,reply_item->lvalue);
        }
        else{
                char module_fmsg[MAX_STRING_LEN];
@@ -730,7 +755,7 @@ static int sqlcounter_authorize(void *instance, REQUEST *request)
                ret=RLM_MODULE_REJECT;
 
                DEBUG2("rlm_sqlcounter: Rejected user %s, check_item=%d, counter=%d",
-                               key_vp->strvalue,check_vp->lvalue,counter);
+                               key_vp->vp_strvalue,check_vp->lvalue,counter);
        }
 
        return ret;
@@ -738,19 +763,35 @@ static int sqlcounter_authorize(void *instance, REQUEST *request)
 
 static int sqlcounter_detach(void *instance)
 {
-       rlm_sqlcounter_t *data = (rlm_sqlcounter_t *) instance;
+       int i;
+       char **p;
+       rlm_sqlcounter_t *inst = (rlm_sqlcounter_t *)instance;
 
-       paircompare_unregister(data->dict_attr, sqlcounter_cmp);
-       free(data->reset);
-       free(data->query);
-       free(data->check_name);
-       if (data->reply_name) free(data->reply_name);
-       free(data->sqlmod_inst);
-       free(data->counter_name);
-       free(data->allowed_chars);
        allowed_chars = NULL;
+       paircompare_unregister(inst->dict_attr, sqlcounter_cmp);
 
-       free(instance);
+       /*
+        *      Free up dynamically allocated string pointers.
+        */
+       for (i = 0; module_config[i].name != NULL; i++) {
+               if (module_config[i].type != PW_TYPE_STRING_PTR) {
+                       continue;
+               }
+
+               /*
+                *      Treat 'config' as an opaque array of bytes,
+                *      and take the offset into it.  There's a
+                *      (char*) pointer at that offset, and we want
+                *      to point to it.
+                */
+               p = (char **) (((char *)inst) + module_config[i].offset);
+               if (!*p) { /* nothing allocated */
+                       continue;
+               }
+               free(*p);
+               *p = NULL;
+       }
+       free(inst);
        return 0;
 }
 
@@ -764,10 +805,11 @@ static int sqlcounter_detach(void *instance)
  *     is single-threaded.
  */
 module_t rlm_sqlcounter = {
+       RLM_MODULE_INIT,
        "SQL Counter",
        RLM_TYPE_THREAD_SAFE,           /* type */
-       NULL,                           /* initialization */
        sqlcounter_instantiate,         /* instantiation */
+       sqlcounter_detach,              /* detach */
        {
                NULL,                   /* authentication */
                sqlcounter_authorize,   /* authorization */
@@ -778,7 +820,5 @@ module_t rlm_sqlcounter = {
                NULL,                   /* post-proxy */
                NULL                    /* post-auth */
        },
-       sqlcounter_detach,              /* detach */
-       NULL,                           /* destroy */
 };
 
index 55f1571..b3038f7 100644 (file)
@@ -34,8 +34,8 @@
  */
 
 #include "config.h"
-#include "autoconf.h"
-#include "libradius.h"
+#include "freeradius-devel/autoconf.h"
+#include "freeradius-devel/libradius.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
 #include <netinet/in.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
-#include "modpriv.h"
+#include "freeradius-devel/radiusd.h"
+#include "freeradius-devel/modules.h"
+#include "freeradius-devel/conffile.h"
+#include "freeradius-devel/modpriv.h"
 
 #include "rlm_sql.h"
 
@@ -330,7 +330,7 @@ static int sqlhpwippool_instantiate(CONF_SECTION *conf, void **instance)
 
        data->sincesync = 0;
 
-       modinst = find_module_instance(data->sqlinst_name);
+       modinst = find_module_instance(cf_section_find("modules"), (data->sqlinst_name) );
        if (!modinst) {
                nvp_log(__LINE__, data, L_ERR,
                        "sqlhpwippool_instantiate(): cannot find module instance "
index 1eb4e33..3c56d8a 100644 (file)
@@ -1,65 +1,61 @@
 ---
---- SQL schema for rlm_sqlhpwippool
+--- Draft of Netvim SQL schema just for rlm_sqlhpwippool
 ---
 
--- CREATE DATABASE netvim DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
--- USE netvim;
+CREATE DATABASE `netvim` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
+USE netvim;
 
-CREATE TABLE gid_ip (
-  gid int NOT NULL CHECK (gid > 0) default '0' PRIMARY KEY,
-  ip_start bigint NOT NULL CHECK (ip_start > 0) default '0',
-  ip_stop bigint NOT NULL CHECK (ip_stop > 0) default '0'
-);
---COMMENT ON TABLE gid_ip IS 'Netvim: host groups to IP ranges relations';
+CREATE TABLE `gid_ip` (
+  `gid` int(10) unsigned NOT NULL default '0' COMMENT 'Host group ID',
+  `ip_start` bigint(20) unsigned NOT NULL default '0' COMMENT 'Beginning of IP range',
+  `ip_stop` bigint(20) unsigned NOT NULL default '0' COMMENT 'End of IP range',
+  KEY `gid` (`gid`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Netvim: host groups to IP ranges relations';
 
-CREATE TABLE host_groups (
-  gid int NOT NULL CHECK (gid > 0) default '0' PRIMARY KEY,
-  parent int default NULL CHECK (parent > 0),
-  name varchar(128) NOT NULL default ''
-);
-CREATE UNIQUE INDEX group_name ON host_groups (name);
---COMMENT ON TABLE host_groups IS 'Netvim: host groups';
+CREATE TABLE `host_groups` (
+  `gid` int(10) unsigned NOT NULL default '0' COMMENT 'Host group ID',
+  `parent` int(10) unsigned default NULL COMMENT 'ID of parent group',
+  `name` varchar(128) NOT NULL default '' COMMENT 'Host group UNIX name',
+  PRIMARY KEY  (`gid`),
+  UNIQUE KEY `group_name` (`name`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Netvim: host groups';
 
-CREATE TABLE ids (
-  id SERIAL,
-  enabled BOOLEAN NOT NULL default '1',
-  modified TIMESTAMP NOT NULL default '0',
-  created TIMESTAMP NOT NULL default '0',
-  type varchar(64) default NULL,
-  PRIMARY KEY (id)
-);
---COMMENT ON TABLE ids IS 'Entity: the source of ID numbers';
+CREATE TABLE `ids` (
+  `id` int(10) unsigned NOT NULL auto_increment COMMENT 'The One True ID',
+  `enabled` tinyint(1) NOT NULL default '1' COMMENT 'If 0, ignore the object',
+  `modified` datetime NOT NULL default '0000-00-00 00:00:00' COMMENT 'Time when any of object properties were modified',
+  `created` datetime NOT NULL default '0000-00-00 00:00:00' COMMENT 'Object creation date',
+  `type` varchar(64) default NULL COMMENT 'Link to an ef action',
+  PRIMARY KEY  (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Entity: the source of ID numbers';
 
-CREATE TABLE ip_pools (
-  pid int NOT NULL CHECK (pid > 0) default '0' COMMENT 'Named pool ID',
-  gid int NOT NULL CHECK (gid > 0) default '0' COMMENT 'Host group ID',
-  pnid int NOT NULL CHECK (pnid > 0) default '0' COMMENT 'Pool name ID',
-  ip_start bigint NOT NULL CHECK (ip_start > 0) default '0' COMMENT 'Beginning of IP range',
-  ip_stop bigint NOT NULL CHECK (ip_stop > 0) default '0' COMMENT 'End of IP range',
-  prio int NOT NULL default '0' COMMENT 'Pool priority',
-  weight int unsigned NOT NULL default '1' COMMENT 'Pool weight',
-  total bigint unsigned NOT NULL default '0' COMMENT 'Total number of IPs in pool',
-  free bigint unsigned NOT NULL default '0' COMMENT 'Number of free IPs in pool',
-  PRIMARY KEY (pid),
-  KEY gid (gid,pnid)
-);
--- ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Netvim: named IP pools assigned to given host group';
+CREATE TABLE `ip_pools` (
+  `pid` int(10) unsigned NOT NULL default '0' COMMENT 'Named pool ID',
+  `gid` int(10) unsigned NOT NULL default '0' COMMENT 'Host group ID',
+  `pnid` int(10) unsigned NOT NULL default '0' COMMENT 'Pool name ID',
+  `ip_start` bigint(20) unsigned NOT NULL default '0' COMMENT 'Beginning of IP range',
+  `ip_stop` bigint(20) unsigned NOT NULL default '0' COMMENT 'End of IP range',
+  `prio` int(11) NOT NULL default '0' COMMENT 'Pool priority',
+  `weight` int(10) unsigned NOT NULL default '1' COMMENT 'Pool weight',
+  `total` bigint(20) unsigned NOT NULL default '0' COMMENT 'Total number of IPs in pool',
+  `free` bigint(20) unsigned NOT NULL default '0' COMMENT 'Number of free IPs in pool',
+  PRIMARY KEY  (`pid`),
+  KEY `gid` (`gid`,`pnid`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Netvim: named IP pools assigned to given host group';
 
-CREATE TABLE ips (
-  ip bigint unsigned NOT NULL default '0' COMMENT 'IP address',
-  pid int NOT NULL CHECK (pid > 0) default '0' COMMENT 'Named pool ID',
-  rsv_since TIMESTAMP NOT NULL default '0000-00-00 00:00:00' COMMENT 'Time when IP was reserved',
-  rsv_by varchar(64) default NULL COMMENT 'Who/what reserved IP',
-  rsv_until TIMESTAMP NOT NULL default '0000-00-00 00:00:00' COMMENT 'Reservation timeout',
-  PRIMARY KEY (ip),
-  KEY pid (pid)
-);
--- ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Netvim: states of single IP addresses';
+CREATE TABLE `ips` (
+  `ip` bigint(20) unsigned NOT NULL default '0' COMMENT 'IP address',
+  `pid` int(10) unsigned NOT NULL default '0' COMMENT 'Named pool ID',
+  `rsv_since` datetime NOT NULL default '0000-00-00 00:00:00' COMMENT 'Time when IP was reserved',
+  `rsv_by` varchar(64) default NULL COMMENT 'Who/what reserved IP',
+  `rsv_until` datetime NOT NULL default '0000-00-00 00:00:00' COMMENT 'Reservation timeout',
+  PRIMARY KEY  (`ip`),
+  KEY `pid` (`pid`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Netvim: states of single IP addresses';
 
-CREATE TABLE pool_names (
-  pnid int NOT NULL CHECK (pnid > 0) default '0' COMMENT 'Named pool ID',
-  name varchar(128) NOT NULL default '' COMMENT 'Pool UNIX name',
-  PRIMARY KEY (pnid),
-  UNIQUE KEY pool_name (name)
-);
--- ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Netvim: definitions of pool names';
+CREATE TABLE `pool_names` (
+  `pnid` int(10) unsigned NOT NULL default '0' COMMENT 'Named pool ID',
+  `name` varchar(128) NOT NULL default '' COMMENT 'Pool UNIX name',
+  PRIMARY KEY  (`pnid`),
+  UNIQUE KEY `pool_name` (`name`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Netvim: definitions of pool names';
index c0eda85..af28710 100644 (file)
@@ -2,6 +2,8 @@
 # $Id$
 #
 
+INCLUDE += -I/usr/local/include/
+
 TARGET      = @targetname@
 SRCS        = rlm_sqlippool.c
 HEADERS     = $(top_builddir)/src/modules/rlm_sql/rlm_sql.h
index 00f9483..42d0884 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.1.2.3 .
+# From configure.in Revision: 1.2 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -869,7 +869,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -2029,11 +2029,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -2072,6 +2067,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index 8cbaad9..67c6259 100644 (file)
@@ -4,6 +4,7 @@
 # Version:     $Id$
 #
 
+AC_PREREQ([2.59])
 AC_INIT(rlm_sqlippool.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_sqlippool])
index 378aff3..836241d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  rlm_sqlippool.c     rlm_sqlippool - FreeRADIUS SQL IP Pool Module
  *
- * Version:     $Id$
+ * 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
  * Copyright 2006  Suntel Communications
  */
 
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/autoconf.h>
+#include <freeradius-devel/libradius.h>
 
-#include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 #include <ctype.h>
-#include <netinet/in.h>
 
-#include "radiusd.h"
-#include "modules.h"
-#include "conffile.h"
-#include "modpriv.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/modpriv.h>
 
 #include <rlm_sql.h>
 
-static const char rcsid[] = "$Id$";
-
-
-
 /*
  *     Define a structure for our module configuration.
  */
@@ -67,6 +62,8 @@ typedef struct rlm_sqlippool_t {
        char *allocate_commit;  /* SQL query to commit */
        char *allocate_rollback; /* SQL query to rollback */
 
+       char *pool_check;       /* Query to check for the existence of the pool */
+
                                /* Start sequence */
        char *start_begin;      /* SQL query to begin */
        char *start_update;     /* SQL query to update an IP entry */
@@ -97,23 +94,17 @@ typedef struct rlm_sqlippool_t {
        char *off_commit;       /* SQL query to commit */
        char *off_rollback;     /* SQL query to rollback */
        
-#ifdef HAVE_PTHREAD_H
-       pthread_mutex_t dlock;
-       long owner;
-#endif 
+                               /* Logging Section */
+       char *log_exists;       /* There was an ip address already assigned */
+       char *log_success;      /* We successfully allocated ip address from pool */
+       char *log_clear;        /* We successfully deallocated ip address from pool */
+       char *log_failed;       /* Failed to allocate ip from the pool */
+       char *log_nopool;       /* There was no Framed-IP-Address but also no Pool-Name */
 
-} rlm_sqlippool_t;
-
-#ifndef HAVE_PTHREAD_H
-/*
- *  This is easier than ifdef's throughout the code.
- */
-#define pthread_mutex_init(_x, _y)
-#define pthread_mutex_destroy(_x)
-#define pthread_mutex_lock(_x)
-#define pthread_mutex_unlock(_x)
-#endif
+                               /* Reserved to handle 255.255.255.254 Requests */
+       char *defaultpool;      /* Default Pool-Name if there is non in the check items */
 
+} rlm_sqlippool_t;
 
 /*
  *     A mapping of configuration file names to internal variables.
@@ -131,38 +122,48 @@ static CONF_PARSER module_config[] = {
 
   { "pool-name"            , PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, pool_name), NULL, ""},
 
-  { "allocate-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_begin), NULL, "BEGIN" },
+  { "allocate-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_begin), NULL, "START TRANSACTION" },
   { "allocate-clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_clear), NULL, "" },
   { "allocate-find", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_find), NULL, "" },
   { "allocate-update", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_update), NULL, "" },
   { "allocate-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_commit), NULL, "COMMIT" },
   { "allocate-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,allocate_rollback), NULL, "ROLLBACK" },
 
-  { "start-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_begin), NULL, "BEGIN" },
+  { "pool-check", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,pool_check), NULL, "" },
+
+  { "start-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_begin), NULL, "START TRANSACTION" },
   { "start-update", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_update), NULL, "" },
   { "start-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_commit), NULL, "COMMIT" },
   { "start-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,start_rollback), NULL, "ROLLBACK" },
 
-  { "alive-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_begin), NULL, "BEGIN" },
+  { "alive-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_begin), NULL, "START TRANSACTION" },
   { "alive-update", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_update), NULL, "" },
   { "alive-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_commit), NULL, "COMMIT" },
   { "alive-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,alive_rollback), NULL, "ROLLBACK" },
 
-  { "stop-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_begin), NULL, "BEGIN" },
+  { "stop-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_begin), NULL, "START TRANSACTION" },
   { "stop-clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_clear), NULL, "" },
   { "stop-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_commit), NULL, "COMMIT" },
   { "stop-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,stop_rollback), NULL, "ROLLBACK" },
 
-  { "on-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_begin), NULL, "BEGIN" },
+  { "on-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_begin), NULL, "START TRANSACTION" },
   { "on-clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_clear), NULL, "" },
   { "on-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_commit), NULL, "COMMIT" },
   { "on-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,on_rollback), NULL, "ROLLBACK" },
 
-  { "off-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_begin), NULL, "BEGIN" },
+  { "off-begin", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_begin), NULL, "START TRANSACTION" },
   { "off-clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_clear), NULL, "" },
   { "off-commit", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_commit), NULL, "COMMIT" },
   { "off-rollback", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t,off_rollback), NULL, "ROLLBACK" },
 
+  { "sqlippool_log_exists", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_exists), NULL, "" },
+  { "sqlippool_log_success", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_success), NULL, "" },
+  { "sqlippool_log_clear", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_clear), NULL, "" },
+  { "sqlippool_log_failed", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_failed), NULL, "" },
+  { "sqlippool_log_nopool", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, log_nopool), NULL, "" },
+
+  { "defaultpool", PW_TYPE_STRING_PTR, offsetof(rlm_sqlippool_t, defaultpool), NULL, "main_pool" },
+
   { NULL, -1, 0, NULL, NULL }
 };
 
@@ -234,13 +235,13 @@ static int sqlippool_expand(char * out, int outlen, const char * fmt, void * ins
                                *q++ = *p;
                                break;
                        case 'P': /* pool name */
-                               strNcpy(q, data->pool_name, freespace); 
+                               strlcpy(q, data->pool_name, freespace); 
                                q += strlen(q);
                                break;
                        case 'I': /* IP address */
                                if (param && param_len > 0) {
                                        if (param_len > freespace) {
-                                               strNcpy(q, param, freespace);
+                                               strlcpy(q, param, freespace);
                                                q += strlen(q);
                                        }
                                        else {
@@ -251,7 +252,7 @@ static int sqlippool_expand(char * out, int outlen, const char * fmt, void * ins
                                break;
                        case 'J': /* lease duration */
                                sprintf(tmp, "%d", data->lease_duration);
-                               strNcpy(q, tmp, freespace); 
+                               strlcpy(q, tmp, freespace); 
                                q += strlen(q);
                                break;
                        default:
@@ -286,7 +287,7 @@ static int sqlippool_command(const char * fmt, SQLSOCK * sqlsocket, void * insta
         */
        if (request) {
                if (!radius_xlat(query, sizeof(query), expansion, request, NULL)) {
-                       radlog(L_ERR, "sqlippool_command: xlat failed.");
+                       radlog(L_ERR, "sqlippool_command: xlat failed on: '%s'", query);
                        return 0;
                }
        }
@@ -298,7 +299,7 @@ static int sqlippool_command(const char * fmt, SQLSOCK * sqlsocket, void * insta
        DEBUG2("sqlippool_command: '%s'", query);
 #endif
        if (rlm_sql_query(sqlsocket, data->sql_inst, query)){
-               radlog(L_ERR, "sqlippool_command: database query error");
+               radlog(L_ERR, "sqlippool_command: database query error in: '%s'", query);
                return 0;
        }
 
@@ -315,7 +316,7 @@ static int sqlippool_query1(char * out, int outlen, const char * fmt, SQLSOCK *
        char expansion[MAX_STRING_LEN * 4];
        char query[MAX_STRING_LEN * 4];
        SQL_ROW row;
-       int r;
+       int rlen, retval = 0;
 
        sqlippool_expand(expansion, sizeof(expansion), fmt, instance, param, param_len);
 
@@ -342,39 +343,21 @@ static int sqlippool_query1(char * out, int outlen, const char * fmt, SQLSOCK *
                return 0;
        }
 
-       r = rlm_sql_fetch_row(sqlsocket, data->sql_inst);
-       (data->sql_inst->module->sql_finish_select_query)(sqlsocket, data->sql_inst->config);
-
-       if (r) {
-               DEBUG("sqlippool_query1: SQL query did not succeed");
-               out[0] = '\0';
-               return 0;
-       }
-
-       row = sqlsocket->row;
-       if (row == NULL) {
-               DEBUG("sqlippool_query1: SQL query did not return any results");
-               out[0] = '\0';
-               return 0;
-       }
+       out[0] = '\0';
 
-       if (row[0] == NULL){
-               DEBUG("sqlippool_query1: row[0] returned NULL");
-               out[0] = '\0';
-               return 0;
-       }
+       if (!rlm_sql_fetch_row(sqlsocket, data->sql_inst)) {
+               if (sqlsocket->row) {
+                       if (sqlsocket->row[0]) {
+                               if ((rlen = strlen(sqlsocket->row[0])) < outlen) {
+                                       strcpy(out, sqlsocket->row[0]);
+                                       retval = rlen;
+                               } else DEBUG("sqlippool_query1: insufficient string space");
+                       } else DEBUG("sqlippool_query1: row[0] returned NULL");
+               } else DEBUG("sqlippool_query1: SQL query did not return any results");
+       } else DEBUG("sqlippool_query1: SQL query did not succeed");
 
-       r = strlen(row[0]);
-       if (r >= outlen){
-               DEBUG("sqlippool_query1: insufficient string space");
-               out[0] = '\0';
-               return 0;
-       }
-
-       strncpy(out, row[0], r);
-       out[r] = '\0';
-
-       return r;
+       (data->sql_inst->module->sql_finish_select_query)(sqlsocket, data->sql_inst->config);
+       return retval;
 }
 
 static int sqlippool_initialize_sql(void * instance)
@@ -487,7 +470,7 @@ static int sqlippool_instantiate(CONF_SECTION * conf, void ** instance)
        else
                data->pool_name = strdup("ippool");
 
-       if ( !(data->sql_inst = (SQL_INST *) (find_module_instance(data->sql_instance_name))->insthandle) )
+       if ( !(data->sql_inst = (SQL_INST *) (find_module_instance(cf_section_find("modules"), data->sql_instance_name))->insthandle) )
        {
                radlog(L_ERR, "sqlippool_instantiate: failed to find sql instance named %s", data->sql_instance_name);
                free(data);
@@ -495,11 +478,23 @@ static int sqlippool_instantiate(CONF_SECTION * conf, void ** instance)
        }
 
        sqlippool_initialize_sql(data);
-       pthread_mutex_init(&data->dlock, NULL);
        *instance = data;
        return 0;
 }
 
+
+/*
+ * if we have something to log, then we log it
+ * otherwise we return the retcode as soon as possible 
+ */
+static int do_logging(char *str, int retcode)
+{
+       if (strlen(str))
+               radlog(L_INFO,"%s", str);       
+       return retcode;
+}
+
+
 /*
  *     Allocate an IP number from the pool.
  */
@@ -511,25 +506,32 @@ static int sqlippool_postauth(void *instance, REQUEST * request)
        uint32_t ip_allocation;
        VALUE_PAIR * vp;
        SQLSOCK * sqlsocket;
-       long self = (long) pthread_self();
+       lrad_ipaddr_t ipaddr;
+
+       VALUE_PAIR *callingsid;
+       VALUE_PAIR *pair;
+
+       int do_callingsid = 0;
+       int do_calledsid = 0;
+
+       char    logstr[MAX_STRING_LEN];
 
        /*
         * If there is a Framed-IP-Address attribute in the reply do nothing
         */
        if (pairfind(request->reply->vps, PW_FRAMED_IP_ADDRESS) != NULL) {
+               /* We already have a Framed-IP-Address */
+               radius_xlat(logstr, sizeof(logstr), data->log_exists, request, NULL);
                DEBUG("rlm_sqlippool: Framed-IP-Address already exists");
-               return RLM_MODULE_NOOP;
-       }
 
-       if ((vp = pairfind(request->config_items, PW_POOL_NAME)) != NULL) {
-               DEBUG("Value Of the Pool-Name is [%s] and its [%i] Chars \n", vp->strvalue, vp->length);
-               pthread_mutex_lock(&data->dlock);
-               strNcpy(data->pool_name, vp->strvalue, (vp->length + 1));
-               pthread_mutex_unlock(&data->dlock);     
+               return do_logging(logstr, RLM_MODULE_NOOP);
        }
-       else {
-               DEBUG("rlm_sqlippool: missing pool_name");
-               return RLM_MODULE_NOOP;
+
+       if (pairfind(request->config_items, PW_POOL_NAME) == NULL) {
+               DEBUG("rlm_sqlippool: We Dont have Pool-Name in check items.. Lets do nothing..");
+               radius_xlat(logstr, sizeof(logstr), data->log_nopool, request, NULL);
+
+               return do_logging(logstr, RLM_MODULE_NOOP);
        }
        
        if (pairfind(request->packet->vps, PW_NAS_IP_ADDRESS) == NULL) {
@@ -545,7 +547,7 @@ static int sqlippool_postauth(void *instance, REQUEST * request)
        sqlsocket = sql_get_socket(data->sql_inst);
        if (sqlsocket == NULL) {
                DEBUG("rlm_sqlippool: cannot allocate sql connection");
-               return RLM_MODULE_NOOP;
+               return RLM_MODULE_FAIL;
        }
 
        /*
@@ -566,7 +568,6 @@ static int sqlippool_postauth(void *instance, REQUEST * request)
        allocation_len = sqlippool_query1(allocation, sizeof(allocation),
                                          data->allocate_find, sqlsocket, instance, request,
                                          (char *) NULL, 0);
-       radlog(L_INFO,"rlm_sqlippool: ip=[%s] len=%d", allocation, allocation_len);
 
        if (allocation_len == 0)
        {       
@@ -576,13 +577,57 @@ static int sqlippool_postauth(void *instance, REQUEST * request)
                sqlippool_command(data->allocate_commit, sqlsocket, instance, request,
                                  (char *) NULL, 0);
 
-               DEBUG("rlm_sqlippool: IP number could not be allocated.");
+               /*
+                * Should we perform pool-check ?
+                */ 
+               if (data->pool_check && *data->pool_check) {
+
+                       /*
+                        * Ok, so the allocate-find query found nothing ...
+                        * Let's check if the pool exists at all
+                        */
+                       allocation_len = sqlippool_query1(allocation, sizeof(allocation),
+                                                data->pool_check, sqlsocket, instance, request,
+                                               (char *) NULL, 0);
+
+                       sql_release_socket(data->sql_inst, sqlsocket);
+
+                       if (allocation_len) {
+
+                               /*
+                                * Pool exists after all... So, the failure to allocate
+                                * the IP address was most likely due to the depletion 
+                                * of the pool. In that case, we should return NOTFOUND
+                                */
+                               DEBUG("rlm_sqlippool: IP address could not be allocated.");
+                               radius_xlat(logstr, sizeof(logstr), data->log_failed, request, NULL);
+                               return do_logging(logstr, RLM_MODULE_NOTFOUND);
+
+                       }
+                       /*
+                        * Pool doesn't exist in the table. It may be handled by some 
+                        * other instance of sqlippool, so we should just ignore
+                        * this allocation failure and return NOOP
+                        */
+                       DEBUG("rlm_sqlippool: IP address could not be allocated as not pool exists with that name.");
+                       return RLM_MODULE_NOOP;
+               
+               }
+               
                sql_release_socket(data->sql_inst, sqlsocket);
-               return RLM_MODULE_NOTFOUND;
+
+               DEBUG("rlm_sqlippool: IP address could not be allocated.");
+               radius_xlat(logstr, sizeof(logstr), data->log_failed, request, NULL);
+
+               return do_logging(logstr, RLM_MODULE_NOOP);
        }
 
-       ip_allocation = ip_addr(allocation);
-       if (ip_allocation == INADDR_NONE)
+       
+       /*
+        *  FIXME: Make it work with the ipv6 addresses
+        */
+       if ((ip_hton(allocation, AF_INET, &ipaddr) < 0) ||
+           ((ip_allocation = ipaddr.ipaddr.ip4addr.s_addr) == INADDR_NONE))
        {
                /*
                 * COMMIT
@@ -592,7 +637,9 @@ static int sqlippool_postauth(void *instance, REQUEST * request)
 
                DEBUG("rlm_sqlippool: Invalid IP number [%s] returned from database query.", allocation);
                sql_release_socket(data->sql_inst, sqlsocket);
-               return RLM_MODULE_NOOP;
+               radius_xlat(logstr, sizeof(logstr), data->log_failed, request, NULL);   
+               
+               return do_logging(logstr, RLM_MODULE_NOOP);
        }
 
        /*
@@ -618,7 +665,9 @@ static int sqlippool_postauth(void *instance, REQUEST * request)
                          (char *) NULL, 0);
 
        sql_release_socket(data->sql_inst, sqlsocket);
-       return RLM_MODULE_OK;
+       radius_xlat(logstr, sizeof(logstr), data->log_success, request, NULL);
+
+       return do_logging(logstr, RLM_MODULE_OK);
 }
 
 static int sqlippool_accounting_start(void * instance, REQUEST * request)
@@ -711,6 +760,8 @@ static int sqlippool_accounting_alive(void * instance, REQUEST * request)
 
 static int sqlippool_accounting_stop(void * instance, REQUEST * request)
 {
+       char    logstr[MAX_STRING_LEN];
+
        rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
        SQLSOCK * sqlsocket;
 
@@ -749,8 +800,9 @@ static int sqlippool_accounting_stop(void * instance, REQUEST * request)
                          (char *) NULL, 0);
 
        sql_release_socket(data->sql_inst, sqlsocket);
+       radius_xlat(logstr, sizeof(logstr), data->log_clear, request, NULL);
 
-       return RLM_MODULE_OK;
+       return do_logging(logstr, RLM_MODULE_OK);
 }
 
 static int sqlippool_accounting_on(void * instance, REQUEST * request)
@@ -873,41 +925,6 @@ static int sqlippool_detach(void *instance)
 {
        rlm_sqlippool_t * data = (rlm_sqlippool_t *) instance;
 
-       free(data->sql_instance_name);
-       free(data->pool_name);
-
-       free(data->allocate_begin);
-       free(data->allocate_clear);
-       free(data->allocate_find);
-       free(data->allocate_update);
-       free(data->allocate_commit);
-       free(data->allocate_rollback);
-
-       free(data->start_begin);
-       free(data->start_update);
-       free(data->start_commit);
-       free(data->start_rollback);
-
-       free(data->alive_begin);
-       free(data->alive_update);
-       free(data->alive_commit);
-       free(data->alive_rollback);
-
-       free(data->stop_begin);
-       free(data->stop_clear);
-       free(data->stop_commit);
-       free(data->stop_rollback);
-
-       free(data->on_begin);
-       free(data->on_clear);
-       free(data->on_commit);
-       free(data->on_rollback);
-
-       free(data->off_begin);
-       free(data->off_clear);
-       free(data->off_commit);
-       free(data->off_rollback);
-
        return 0;
 }
 
@@ -921,10 +938,11 @@ static int sqlippool_detach(void *instance)
  *     is single-threaded.
  */
 module_t rlm_sqlippool = {
+       RLM_MODULE_INIT,
        "SQL IP Pool",  
        RLM_TYPE_THREAD_SAFE,           /* type */
-       NULL,                           /* initialization */
        sqlippool_instantiate,          /* instantiation */
+       sqlippool_detach,               /* detach */
        {
                NULL,                   /* authentication */
                NULL,                   /* authorization */
@@ -935,6 +953,4 @@ module_t rlm_sqlippool = {
                NULL,                   /* post-proxy */
                sqlippool_postauth      /* post-auth */
        },
-       sqlippool_detach,               /* detach */
-       NULL,                           /* destroy */
 };
index 69de3ce..4b891ec 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 TARGET     = @targetname@
-SRCS       = rlm_unix.c cache.c compat.c
+SRCS       = rlm_unix.c
 HEADERS    =
 RLM_LIBS   = @unix_ldflags@
 RLM_CFLAGS = @unix_cflags@
diff --git a/src/modules/rlm_unix/cache.c b/src/modules/rlm_unix/cache.c
deleted file mode 100644 (file)
index b05bc1b..0000000
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * cache.c     Offers ability to cache /etc/group, /etc/passwd,
- *             /etc/shadow,
- *
- *             All users in the passwd/shadow files are stored in a hash table.
- *             the hash lookup is VERY fast,  generally 1.0673 comparisons per
- *             lookup.  For the unitiated, that's blazing.  You can't have less
- *             than one comparison, for example.
- *
- *             The /etc/group file is stored in a singly linked list, as that
- *             appears to be fast enough.  It's generally a small enough file
- *             that hashing is unnecessary.
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright 2000  The FreeRADIUS server project.
- * Copyright 1999  Jeff Carneal <jeff@apex.com>, Apex Internet Services, Inc.
- * Copyright 2000  Alan DeKok <aland@ox.org>
- */
-static const char rcsid[] = "$Id$";
-
-#include "autoconf.h"
-#include       "libradius.h"
-#include "config.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <grp.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#ifdef HAVE_SHADOW_H
-#  include <shadow.h>
-#endif
-
-#include "radiusd.h"
-#include "cache.h"
-#include "compat.h"
-
-/*
- *  Static prototypes
- */
-static struct mypasswd *findHashUser(struct pwcache *cache, const char *user);
-static int storeHashUser(struct pwcache *cache, struct mypasswd *new, int idx);
-static int hashUserName(const char *s);
-
-/* Builds the hash table up by storing passwd/shadow fields
- * in memory.  Returns NULL on failure, pointer to the cache on success.
- */
-struct pwcache *unix_buildpwcache(const char *passwd_file,
-                                  const char *shadow_file,
-                                  const char *group_file)
-{
-       FILE *passwd;
-#ifdef HAVE_SHADOW_H
-       FILE *shadow;
-#endif
-       FILE *group;
-       char buffer[BUFSIZE];
-       char idtmp[10];
-       char username[256];
-       char *ptr, *bufptr;
-       int len, hashindex, numread=0;
-       struct mypasswd *new, *cur;
-
-       int len2, idx;
-       struct group *grp;
-       struct mygroup *g_new;
-       char **member;
-
-        struct pwcache *cache;
-
-       if (!passwd_file) {
-               radlog(L_ERR, "rlm_unix:  You MUST specify a password file!");
-               return NULL;
-       }
-
-       if (!group_file) {
-               radlog(L_ERR, "rlm_unix:  You MUST specify a group file!");
-               return NULL;
-       }
-
-#ifdef HAVE_SHADOW_H
-       if (!shadow_file) {
-               radlog(L_ERR, "rlm_unix:  You MUST specify a shadow password file!");
-               return NULL;
-       }
-#endif
-
-       cache = rad_malloc(sizeof(*cache));
-
-       memset(username, 0, sizeof(username));
-
-       /* Init hash array */
-       memset(cache->hashtable, 0, sizeof cache->hashtable);
-       cache->grphead = NULL;
-
-       if ((passwd = fopen(passwd_file, "r")) == NULL) {
-               radlog(L_ERR, "rlm_unix:  Can't open file password file %s: %s",
-                   passwd_file, strerror(errno));
-               unix_freepwcache(cache);
-               return NULL;
-       }
-
-       while(fgets(buffer, BUFSIZE , passwd) != (char *)NULL) {
-               numread++;
-
-               bufptr = buffer;
-               /* Get usernames from password file */
-               for(ptr = bufptr; *ptr!=':'; ptr++);
-               len = ptr - bufptr;
-               if((len+1) > MAX_STRING_LEN) {
-                       radlog(L_ERR, "rlm_unix:  Username too long in line: %s", buffer);
-               }
-               strncpy(username, buffer, len);
-               username[len] = '\0';
-
-               /* Hash the username */
-               hashindex = hashUserName(username);
-               /*printf("%s:%d\n", username, hashindex);*/
-
-               /* Allocate space for structure to go in hashtable */
-               new = (struct mypasswd *)rad_malloc(sizeof(struct mypasswd));
-               memset(new, 0, sizeof(struct mypasswd));
-
-               /* Put username into new structure */
-               new->pw_name = (char *)rad_malloc(strlen(username)+1);
-               strncpy(new->pw_name, username, strlen(username)+1);
-
-               /* Put passwords into array, if not shadowed */
-               /* Get passwords from password file (shadow comes later) */
-               ptr++;
-               bufptr = ptr;
-               while(*ptr!=':')
-                       ptr++;
-
-#if !HAVE_SHADOW_H
-               /* Put passwords into new structure (*/
-               len = ptr - bufptr;
-
-               if (len > 0) {
-                       new->pw_passwd = (char *)rad_malloc(len+1);
-                       strncpy(new->pw_passwd, bufptr, len);
-                       new->pw_passwd[len] = '\0';
-               } else {
-                       new->pw_passwd = NULL;
-               }
-
-#endif /* !HAVE_SHADOW_H */
-
-               /*
-                * Put uid into structure.  Not sure why, but
-                * at least we'll have it later if we need it
-                */
-               ptr++;
-               bufptr = ptr;
-               while(*ptr!=':')
-                       ptr++;
-               len = ptr - bufptr;
-               strncpy(idtmp, bufptr, len);
-               idtmp[len] = '\0';
-               new->pw_uid = (uid_t)atoi(idtmp);
-
-               /*
-                * Put gid into structure.
-                */
-               ptr++;
-               bufptr = ptr;
-               while(*ptr!=':')
-                       ptr++;
-               len = ptr - bufptr;
-               strncpy(idtmp, bufptr, len);
-               idtmp[len] = '\0';
-               new->pw_gid = (gid_t)atoi(idtmp);
-
-               /*
-                * Put name into structure.
-                */
-               ptr++;
-               bufptr = ptr;
-               while(*ptr!=':')
-                       ptr++;
-
-               len = ptr - bufptr;
-               new->pw_gecos = (char *)rad_malloc(len+1);
-               strncpy(new->pw_gecos, bufptr, len);
-               new->pw_gecos[len] = '\0';
-
-               /*
-                * We'll skip home dir and shell
-                * as I can't think of any use for storing them
-                */
-
-               /*printf("User:  %s, UID:  %d, GID:  %d\n", new->pw_name, new->pw_uid, new->pw_gid);*/
-               /* Store user in the hash */
-               storeHashUser(cache, new, hashindex);
-       }       /* End while(fgets(buffer, BUFSIZE , passwd) != (char *)NULL) */
-       fclose(passwd);
-
-#ifdef HAVE_SHADOW_H
-       /*
-        *      FIXME: Check for password expiry!
-        */
-       if ((shadow = fopen(shadow_file, "r")) == NULL) {
-               radlog(L_ERR, "HASH:  Can't open file %s: %s",
-                   shadow_file, strerror(errno));
-               unix_freepwcache(cache);
-               return NULL;
-       } else {
-               while(fgets(buffer, BUFSIZE , shadow) != (char *)NULL) {
-
-                       bufptr = buffer;
-                       /* Get usernames from shadow file */
-                       for(ptr = bufptr; *ptr!=':'; ptr++);
-                       len = ptr - bufptr;
-                       if((len+1) > MAX_STRING_LEN) {
-                               radlog(L_ERR, "HASH:  Username too long in line: %s", buffer);
-                       }
-                       strncpy(username, buffer, len);
-                       username[len] = '\0';
-                       if((new = findHashUser(cache, username)) == NULL) {
-                               radlog(L_ERR, "HASH:  Username %s in shadow but not passwd??", username);
-                               continue;
-                       }
-
-                       /*
-                        * In order to put passwd in correct structure, we have
-                        * to skip any struct that has a passwd already for that
-                        * user
-                        */
-                       cur = new;
-                       while(new && (strcmp(new->pw_name, username)<=0)
-                                               && (new->pw_passwd == NULL)) {
-                               cur = new;
-                               new = new->next;
-                       }
-                       /* Go back one, we passed it in the above loop */
-                       new = cur;
-
-                       /*
-                        * When we get here, we should be at the last duplicate
-                        * user structure in this hash bucket
-                        */
-
-                       /* Put passwords into struct from shadow file */
-                       ptr++;
-                       bufptr = ptr;
-                       while(*ptr!=':')
-                               ptr++;
-                       len = ptr - bufptr;
-
-                       if (len > 0) {
-                               new->pw_passwd = (char *)rad_malloc(len+1);
-                               strncpy(new->pw_passwd, bufptr, len);
-                               new->pw_passwd[len] = '\0';
-                       } else {
-                               new->pw_passwd = NULL;
-                       }
-               }
-       }
-       fclose(shadow);
-#endif
-
-       /* log how many entries we stored from the passwd file */
-       radlog(L_INFO, "HASH:  Stored %d entries from %s", numread, passwd_file);
-
-       /* The remainder of this function caches the /etc/group or equivalent
-        * file, so it's one less thing we have to lookup on disk.  it uses
-        * fgetgrent(), which is quite slow, but the group file is generally
-        * small enough that it won't matter
-        * As a side note, caching the user list per group was a major pain
-        * in the ass, and I won't even need it.  I really hope that somebody
-        * out there needs and appreciates it.
-        */
-
-       if ((group = fopen(group_file, "r")) == NULL) {
-               radlog(L_ERR, "rlm_unix:  Can't open file group file %s: %s",
-                   group_file, strerror(errno));
-               unix_freepwcache(cache);
-               return NULL;
-       }
-       numread = 0;
-
-       /* Get next entry from the group file */
-       while((grp = fgetgrent(group)) != NULL) {
-
-               /* Make new mygroup structure in mem */
-               g_new = (struct mygroup *)rad_malloc(sizeof(struct mygroup));
-               memset(g_new, 0, sizeof(struct mygroup));
-
-               /* copy grp entries to my structure */
-               len = strlen(grp->gr_name);
-               g_new->gr_name = (char *)rad_malloc(len+1);
-               strncpy(g_new->gr_name, grp->gr_name, len);
-               g_new->gr_name[len] = '\0';
-
-               len = strlen(grp->gr_passwd);
-               g_new->gr_passwd= (char *)rad_malloc(len+1);
-               strncpy(g_new->gr_passwd, grp->gr_passwd, len);
-               g_new->gr_passwd[len] = '\0';
-
-               g_new->gr_gid = grp->gr_gid;
-
-               /* Allocate space for user list, as much as I hate doing groups
-                * that way.
-                */
-               for(member = grp->gr_mem; *member!=NULL; member++);
-               len = member - grp->gr_mem;
-               g_new->gr_mem = (char **)rad_malloc((len+1)*sizeof(char **));
-
-               /* Now go back and copy individual users into it */
-               for(member = grp->gr_mem; *member; member++) {
-                       len2 = strlen(*member);
-                       idx = member - grp->gr_mem;
-                       g_new->gr_mem[idx] = (char *)rad_malloc(len2+1);
-                       strncpy(g_new->gr_mem[idx], *member, len2);
-                       g_new->gr_mem[idx][len2] = '\0';
-               }
-               /* Make sure last entry in user list is 0 so we can loop thru it */
-               g_new->gr_mem[len] = 0;
-
-               /* Insert at beginning of list */
-               g_new->next = cache->grphead;
-               cache->grphead = g_new;
-
-               numread++;
-       }
-
-       /* End */
-       fclose(group);
-
-       radlog(L_INFO, "HASH:  Stored %d entries from %s", numread, group_file);
-
-       return cache;
-}
-
-void unix_freepwcache(struct pwcache *cache)
-{
-       int hashindex;
-       struct mypasswd *cur, *next;
-
-       struct mygroup *g_cur, *g_next;
-       char **member;
-
-       for(hashindex=0; hashindex<HASHTABLESIZE; hashindex++) {
-               if(cache->hashtable[hashindex]) {
-                       cur = cache->hashtable[hashindex];
-                       while(cur) {
-                               next = cur->next;
-                               free(cur->pw_name);
-                               if (cur->pw_passwd) free(cur->pw_passwd);
-                               free(cur->pw_gecos);
-                               free(cur);
-                               cur = next;
-                       }
-               }
-       }
-
-       g_cur = cache->grphead;
-
-       while(g_cur) {
-               g_next = g_cur->next;
-
-               /* Free name, name, member list */
-               for(member = g_cur->gr_mem; *member; member++) {
-                       free(*member);
-               }
-               free(g_cur->gr_mem);
-               free(g_cur->gr_name);
-               free(g_cur->gr_passwd);
-               free(g_cur);
-               g_cur = g_next;
-       }
-
-       free(cache);
-}
-
-/*
- * Looks up user in hashtable.  If user can't be found, returns 0.
- * Otherwise returns a pointer to the structure for the user
- */
-static struct mypasswd *findHashUser(struct pwcache *cache, const char *user)
-{
-
-       struct mypasswd *cur;
-       int idx;
-
-       /* first hash the username and get the index into the hashtable */
-       idx = hashUserName(user);
-
-       cur = cache->hashtable[idx];
-
-       while((cur != NULL) && (strcmp(cur->pw_name, user))) {
-               cur = cur->next;
-       }
-
-       if(cur) {
-               DEBUG2("  HASH:  user %s found in hashtable bucket %d", user, idx);
-               return cur;
-       }
-
-       return (struct mypasswd *)0;
-
-}
-
-/* Stores the username sent into the hashtable */
-static int storeHashUser(struct pwcache *cache, struct mypasswd *new, int idx)
-{
-
-       /* store new record at beginning of list */
-       new->next = cache->hashtable[idx];
-       cache->hashtable[idx] = new;
-
-       return 1;
-}
-
-/* Hashes the username sent to it and returns index into hashtable */
-static int hashUserName(const char *s) {
-       unsigned long hash = 0;
-
-       while (*s != '\0') {
-               hash = hash * 7907 + (unsigned char)*s++;
-       }
-
-       return (hash % HASHTABLESIZE);
-}
-
-/*
- *     Emulate the cistron unix_pass function, but do it using
- *     our hashtable (iow, make it blaze).
- * return  0 on success
- * return -1 on failure
- * return -2 on error (let caller fall back to old method)
- */
-int H_unix_pass(struct pwcache *cache, char *name, char *passwd,
-               VALUE_PAIR **reply_items)
-{
-       struct mypasswd *pwd;
-       char *encrypted_pass;
-
-       /*
-        *      Get encrypted password from password file
-        */
-       if ((pwd = findHashUser(cache, name)) == NULL) {
-               /* Default to old way if user isn't hashed */
-               return -2;
-       }
-       encrypted_pass = pwd->pw_passwd;
-
-       /*
-        *      We might have a passwordless account.
-        */
-       if(encrypted_pass == NULL) return 0;
-
-       if(mainconfig.do_usercollide) {
-               while(pwd) {
-                       /*
-                        * Make sure same user still.  If not, return as if
-                        * wrong pass given
-                        */
-                       if(strcmp(name, pwd->pw_name))
-                               return -1;
-
-                       /*
-                        * Could still be null passwd
-                        */
-                       encrypted_pass = pwd->pw_passwd;
-                       if (encrypted_pass == NULL) {
-                               return 0;
-                       }
-
-                       /*
-                        * Check password
-                        */
-                       if(lrad_crypt_check(passwd, encrypted_pass) == 0) {
-                               /*
-                                * Add 'Class' pair here with value of full
-                                * name from passwd
-                                */
-                               if(strlen(pwd->pw_gecos))
-                                       pairadd(reply_items, pairmake("Class", pwd->pw_gecos, T_OP_EQ));
-
-                               return 0;
-                       }
-                       pwd = pwd->next;
-               }
-               /*
-                * If we get here, pwd is null, and no users matched
-                */
-               return -1;
-       } else {
-               /*
-                *      Check encrypted password.
-                */
-               if (lrad_crypt_check(passwd, encrypted_pass))
-                       return -1;
-
-               return 0;
-       }
-}
-
-/*
- * Emulate groupcmp in files.c, but do it (much) faster
- * return -2 on error (let caller fall back to old method),
- * -1 on match fail, or 0 on success
- */
-int H_groupcmp(struct pwcache *cache, VALUE_PAIR *check, char *username)
-{
-       struct mypasswd *pwd;
-       struct mygroup *cur;
-       char **member;
-
-       /* get the user from the hash */
-       if (!(pwd = findHashUser(cache, username)))
-               return -2;
-
-       /* let's find this group */
-       if(cache->grphead) {
-               cur = cache->grphead;
-               while((cur) && (strcmp(cur->gr_name, (char *)check->strvalue))){
-                       cur = cur->next;
-               }
-               /* found the group, now compare it */
-               if(!cur) {
-                       /* Default to old function if we can't find it */
-                       return -2;
-               } else {
-                       if(pwd->pw_gid == cur->gr_gid) {
-                               DEBUG2("  HASH:  matched user %s in group %s", username, cur->gr_name);
-                               return 0;
-                       } else {
-                               for(member = cur->gr_mem; *member; member++) {
-                                       if (strcmp(*member, pwd->pw_name) == 0) {
-                                               DEBUG2("  HASH:  matched user %s in group %s", username, cur->gr_name);
-                                               return 0;
-                                       }
-                               }
-                       }
-               }
-       }
-
-       return -1;
-}
diff --git a/src/modules/rlm_unix/cache.h b/src/modules/rlm_unix/cache.h
deleted file mode 100644 (file)
index 56e0c6d..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * cache.h   Definitions for structures and functions needed in cache.c
- *
- * Version: cache.c  0.99  04-13-1999  jeff@apex.net
- */
-#ifndef _CACHE_H
-#define _CACHE_H
-
-/* Misc definitions */
-#define BUFSIZE  1024
-#define HASHTABLESIZE 100000
-#endif
-
-/* Structure definitions */
-struct mypasswd {
-       char    *pw_name;       /* user name */
-       char    *pw_passwd;     /* user password */
-       uid_t   pw_uid;         /* user id */
-       gid_t   pw_gid;         /* group id */
-       char    *pw_gecos;      /* full name (used for class attr */
-       struct mypasswd *next;  /* next */
-};
-
-struct mygroup {
-       char    *gr_name;        /* group name */
-       char    *gr_passwd;      /* group password */
-       gid_t   gr_gid;          /* group id */
-       char    **gr_mem;        /* group members */
-       struct mygroup *next;    /* next */
-};
-
-struct pwcache {
-  struct mypasswd *hashtable[HASHTABLESIZE];
-  struct mygroup *grphead;
-};
-
-/* Function prototypes */
-struct pwcache *unix_buildpwcache(const char *passwd_file,
-                                  const char *shadow_file,
-                                  const char *group_file);
-int H_unix_pass(struct pwcache *cache, char *name, char *passwd,
-                VALUE_PAIR **reply_items);
-int H_groupcmp(struct pwcache *cache, VALUE_PAIR *check, char *username);
-void unix_freepwcache(struct pwcache *cache);
diff --git a/src/modules/rlm_unix/compat.c b/src/modules/rlm_unix/compat.c
deleted file mode 100644 (file)
index 8d12bca..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * compat.c    Compatibity routines for fgetpwent(), fgetspent(), and fgetgrent()
- *
- *             The code in here was borrowed from the cache.c module
- *             and adapted to be a standalone set of functions.
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * Copyright 2001  The FreeRADIUS server project.
- */
-static const char rcsid[] = "$Id$";
-
-#include       "autoconf.h"
-#include       "libradius.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <grp.h>
-#include <pwd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "config.h"
-
-#ifdef HAVE_SHADOW_H
-#  include <shadow.h>
-#endif
-
-#include "radiusd.h"
-#include "cache.h"
-#include "compat.h"
-
-
-#ifndef HAVE_FGETPWENT
-
-struct passwd *rad_fgetpwent(FILE *pwhandle) {
-       static struct passwd pwbuf;
-       static char username[MAX_STRING_LEN];
-       static char userpwd[64];
-       static char gecostmp[128];
-       static char homedirtmp[128];
-       static char shelltmp[128];
-       char uidtmp[16];
-       char gidtmp[16];
-       char *ptr, *bufptr;
-       char buffer[BUFSIZE];
-       int len;
-
-
-
-#define RAD_EXTRACT_FIELD(txt_field, tmp_buf) \
-       for(bufptr = ptr; (*ptr != '\0') && (*ptr != '\n') && (*ptr != ':'); ptr++); \
-       len = ptr - bufptr; \
-       if((len+1) > sizeof(tmp_buf)) { \
-               radlog(L_ERR, "rlm_unix:  %s too long in line: %s", (txt_field), buffer); \
-               return rad_fgetpwent(pwhandle); \
-       } \
-       strncpy((tmp_buf), bufptr, len); \
-       (tmp_buf)[len] = '\0';
-
-
-
-       if (pwhandle == NULL)
-               return NULL;
-
-       if (fgets(buffer, BUFSIZE , pwhandle) == (char *)NULL)
-               return NULL;
-
-       memset(&pwbuf, 0, sizeof(struct passwd));
-       memset(username, 0, sizeof(username));
-       memset(userpwd, 0, sizeof(userpwd));
-       memset(gecostmp, 0, sizeof(gecostmp));
-       memset(homedirtmp, 0, sizeof(homedirtmp));
-       memset(shelltmp, 0, sizeof(shelltmp));
-       buffer[BUFSIZE] ='\0';
-
-       /* Get usernames from the password file */
-       ptr = buffer;
-       RAD_EXTRACT_FIELD("Username", username);
-       pwbuf.pw_name = username;
-
-       /* Get (encrypted) password from password file (shadow comes later) */
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("Password", userpwd);
-       pwbuf.pw_passwd = userpwd;
-
-       /* Get uid from the password file */
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("UID", uidtmp);
-       pwbuf.pw_uid = atoi(uidtmp);
-
-       /* Get gid from the password file */
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("GID", gidtmp);
-       pwbuf.pw_gid = atoi(gidtmp);
-
-       /* Get the GECOS (name) field from the password file */
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("GECOS", gecostmp);
-       pwbuf.pw_gecos = gecostmp;
-
-       /* Get the home directory from the password file */
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("Home dir", homedirtmp);
-       pwbuf.pw_dir = homedirtmp;
-
-       /* Get the shell from the password file */
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("Shell", shelltmp);
-       pwbuf.pw_shell = shelltmp;
-
-       return(&pwbuf);
-}
-
-#undef RAD_EXTRACT_FIELD
-
-#endif /* HAVE_FGETPWENT */
-
-
-
-
-#ifndef HAVE_FGETSPENT
-
-shadow_pwd_t *rad_fgetspent(FILE *sphandle) {
-       static shadow_pwd_t spbuf;
-       static char username[MAX_STRING_LEN];
-       static char userpwd[64];
-       char lastchgtmp[16];
-       char mintmp[16];
-       char maxtmp[16];
-       char warntmp[16];
-       char inactmp[16];
-       char expiretmp[16];
-       char *ptr, *bufptr;
-       char buffer[BUFSIZE];
-       int len;
-
-#define RAD_EXTRACT_FIELD(txt_field, tmp_buf) \
-       for(bufptr = ptr; (*ptr != '\0') && (*ptr != '\n') && (*ptr != ':'); ptr++); \
-       len = ptr - bufptr; \
-       if((len+1) > sizeof(tmp_buf)) { \
-               radlog(L_ERR, "rlm_unix:  %s too long in line: %s", (txt_field), buffer); \
-               return rad_fgetspent(sphandle); \
-       } \
-       strncpy((tmp_buf), bufptr, len); \
-       (tmp_buf)[len] = '\0';
-
-
-
-       if (sphandle == NULL)
-               return NULL;
-
-       if (fgets(buffer, BUFSIZE, sphandle) == (char *)NULL)
-               return NULL;
-
-       memset(&spbuf, 0, sizeof(shadow_pwd_t));
-       memset(username, 0, sizeof(username));
-       memset(userpwd, 0, sizeof(userpwd));
-       buffer[BUFSIZE] ='\0';
-
-       /* Get usernames from the shadow file */
-       ptr = buffer;
-       RAD_EXTRACT_FIELD("Username", username);
-       GET_SP_NAME(&spbuf) = username;
-
-       /* Get (encrypted) passwords from the shadow file */
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("Password", userpwd);
-       GET_SP_PWD(&spbuf) = userpwd;
-
-       /* Get the 'last change' field from the shadow file */
-#ifdef GET_SP_LSTCHG
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("'Last change'", lastchgtmp);
-       GET_SP_LSTCHG(&spbuf) = atoi(lastchgtmp);
-#endif
-
-       /* Get the 'minimum time between changes' field from the shadow file */
-#ifdef GET_SP_MIN
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("'Min change'", mintmp);
-       GET_SP_MIN(&spbuf) = atoi(mintmp);
-#endif
-
-       /* Get the 'maximum time between changes' field from the shadow file */
-#ifdef GET_SP_MAX
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("'Max change'", maxtmp);
-       GET_SP_MAX(&spbuf) = atoi(maxtmp);
-#endif
-
-       /* Get the 'expire warning time' field from the shadow file */
-#ifdef GET_SP_WARN
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("'Warn time'", warntmp);
-       GET_SP_WARN(&spbuf) = atoi(warntmp);
-#endif
-
-       /* Get the 'account inactivity time' field from the shadow file */
-#ifdef GET_SP_INACT
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("'Inactive time'", inactmp);
-       GET_SP_INACT(&spbuf) = atoi(inactmp);
-#endif
-
-       /* Get the 'expire time' field from the shadow file */
-#ifdef GET_SP_EXPIRE
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("'Expire time'", expiretmp);
-       GET_SP_EXPIRE(&spbuf) = atoi(expiretmp);
-#endif
-       return (&spbuf);
-}
-
-#undef RAD_EXTRACT_FIELD
-
-#endif  /* HAVE_FGETSPENT */
-
-
-
-#ifndef HAVE_FGETGRENT
-
-#define RAD_MAX_GROUP_MEMBERS 500
-
-struct group *rad_fgetgrent(FILE *grhandle) {
-       static struct group grbuf;
-       static char grname[MAX_STRING_LEN];
-       static char grpwd[64];
-       static char *grmem[RAD_MAX_GROUP_MEMBERS];
-       static char grmembuf[2048];
-       char gidtmp[16];
-       char *ptr, *bufptr, *grptr;
-       char buffer[BUFSIZE];
-       int len, gidx;
-
-
-
-#define RAD_EXTRACT_FIELD(txt_field, tmp_buf) \
-       for(bufptr = ptr; (*ptr != '\0') && (*ptr != '\n') && (*ptr != ':'); ptr++); \
-       len = ptr - bufptr; \
-       if((len+1) > sizeof(tmp_buf)) { \
-               radlog(L_ERR, "rlm_unix:  %s too long in line: %s", (txt_field), buffer); \
-               return rad_fgetgrent(grhandle); \
-       } \
-       strncpy((tmp_buf), bufptr, len); \
-       (tmp_buf)[len] = '\0';
-
-
-
-       if (grhandle == NULL)
-               return NULL;
-
-       if (fgets(buffer, BUFSIZE, grhandle) == (char *)NULL)
-               return NULL;
-
-       memset(&grbuf, 0, sizeof(struct group));
-       memset(grname, 0, sizeof(grname));
-       memset(grpwd, 0, sizeof(grpwd));
-       memset(grmem, 0, sizeof(grmem));
-       memset(grmembuf, 0, sizeof(grmembuf));
-       buffer[BUFSIZE] ='\0';
-
-       /* Get the group name */
-       ptr = buffer;
-       RAD_EXTRACT_FIELD("Group name", grname);
-       grbuf.gr_name = grname;
-
-       /* Get the group password */
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("Group password", grpwd);
-       grbuf.gr_passwd = grpwd;
-
-       /* Get the group id */
-       if (*ptr != '\0') ptr++;
-       RAD_EXTRACT_FIELD("Group ID", gidtmp);
-       grbuf.gr_gid = atoi(gidtmp);
-
-       /* Collect all of the group members... */
-       gidx = 0;
-       grbuf.gr_mem = grmem;
-       grbuf.gr_mem[gidx] = NULL;
-       grptr = grmembuf;
-       while (*ptr != '\0') {
-               if (*ptr != '\0') ptr++;
-               for(bufptr = ptr; (*ptr != '\0') && (*ptr != '\n') && (*ptr != ','); ptr++);
-               len = ptr - bufptr;
-
-               /* Ignore "NULL" entries... */
-               if (len == 0) continue;
-
-               if((len+1) > (sizeof(grmembuf) - (grptr - grmembuf))) {
-                       radlog(L_ERR, "rlm_unix:  Some entries dropped.  Group members line too long: %s", buffer);
-                       /* Return a partial list */
-                       return (&grbuf);
-               }
-
-               /* Prevent buffer overflows! */
-               if (gidx+1 >= RAD_MAX_GROUP_MEMBERS) {
-                       radlog(L_ERR, "rlm_unix:  Some entries dropped.  Too many group members: %s", buffer);
-                       /* Return a partial list */
-                       return (&grbuf);
-               }
-
-               strncpy(grptr, bufptr, len);
-               grptr[len] = '\0';
-               grbuf.gr_mem[gidx++] = grptr;
-               grbuf.gr_mem[gidx] = NULL;
-               grptr += len + 1;
-
-       }
-       return (&grbuf);
-}
-
-#undef RAD_EXTRACT_FIELD
-
-#endif /* HAVE_FGETGRENT */
diff --git a/src/modules/rlm_unix/compat.h b/src/modules/rlm_unix/compat.h
deleted file mode 100644 (file)
index 751149b..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * compat.h   Compability library for systems that don't have some
- *              of the routines that we would like to use...
- *
- * Version: cache.c  0.99  04-13-1999  jeff@apex.net
- */
-#ifndef _COMPAT_H
-#define _COMPAT_H
-
-#ifdef HAVE_GETSPNAM
-#if defined(M_UNIX)
-
-       typedef struct passwd shadow_pwd_t;
-#define GET_SP_NAME(sp) ((sp)->pw_name)
-#define GET_SP_PWD(sp) ((sp)->pw_passwd)
-
-#else /* M_UNIX */
-
-       typedef struct spwd shadow_pwd_t;
-#define GET_SP_NAME(sp)  ((sp)->sp_namp)
-#define GET_SP_PWD(sp)    ((sp)->sp_pwdp)
-#define GET_SP_LSTCHG(sp) ((sp)->sp_lstchg)
-#define GET_SP_MIN(sp)    ((sp)->sp_min)
-#define GET_SP_MAX(sp)    ((sp)->sp_max)
-#define GET_SP_WARN(sp)   ((sp)->sp_warn)
-#define GET_SP_INACT(sp)  ((sp)->sp_inact)
-#define GET_SP_EXPIRE(sp) ((sp)->sp_expire)
-
-#endif /* M_UNIX */
-
-#else /* HAVE_GETSPNAM */
-
-typedef struct my_shadow_t {
-       char *sp_namp;
-       char *sp_pwdp;
-       long int sp_lstchg;         /* Date of last change.  */
-       long int sp_min;
-       long int sp_max;
-       long int sp_warn;
-       long int sp_inact;
-       long int sp_expire;
-} shadow_pwd_t;
-#define GET_SP_NAME(sp)  ((sp)->sp_namp)
-#define GET_SP_PWD(sp)    ((sp)->sp_pwdp)
-#define GET_SP_LSTCHG(sp) ((sp)->sp_lstchg)
-#define GET_SP_MIN(sp)    ((sp)->sp_min)
-#define GET_SP_MAX(sp)    ((sp)->sp_max)
-#define GET_SP_WARN(sp)   ((sp)->sp_warn)
-#define GET_SP_INACT(sp)  ((sp)->sp_inact)
-#define GET_SP_EXPIRE(sp) ((sp)->sp_expire)
-
-#endif /* HAVE_GETSPNAM */
-
-
-
-
-#ifndef HAVE_FGETPWENT
-extern struct passwd *rad_fgetpwent(FILE *pwhandle);
-static inline struct passwd *fgetpwent(FILE *pw) {
-       return rad_fgetpwent(pw);
-}
-#endif /* HAVE_FGETPWENT */
-
-#ifndef HAVE_FGETSPENT
-extern shadow_pwd_t *rad_fgetspent(FILE *sphandle);
-static inline shadow_pwd_t *fgetspent(FILE *sp) {
-       return rad_fgetspent(sp);
-}
-#endif /* HAVE_FGETSPENT */
-
-#ifndef HAVE_FGETGRENT
-extern struct group *rad_fgetgrent(FILE *grhandle);
-static inline struct group *fgetgrent(FILE *gr) {
-       return rad_fgetgrent(gr);
-}
-#endif /* HAVE_FGETGRENT */
-
-#endif /* _COMPAT_H */
index 62a75f3..2aaf04b 100644 (file)
@@ -1,33 +1,55 @@
-/* config.h.in.  Generated automatically from configure.in by autoheader 2.13.  */
-/*
+/* config.h.in.  Generated from configure.in by autoheader.  */
 
-acconfig.h - template used by autoheader to create config.h.in
-config.h.in - used by autoconf to create config.h
-config.h - created by autoconf; contains defines generated by autoconf
+/* Define to 1 if you have the `getspnam' function. */
+#undef HAVE_GETSPNAM
 
-*/
+/* Define to 1 if you have the `getusershell' function. */
+#undef HAVE_GETUSERSHELL
 
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
 
-/* Do we have shadow support? */
-#undef HAVE_GETSPNAM
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
 
-/* Define if you have the fgetgrent function.  */
-#undef HAVE_FGETGRENT
+/* Define to 1 if you have the <shadow.h> header file. */
+#undef HAVE_SHADOW_H
 
-/* Define if you have the fgetpwent function.  */
-#undef HAVE_FGETPWENT
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
 
-/* Define if you have the fgetspent function.  */
-#undef HAVE_FGETSPENT
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
 
-/* Define if you have the getspnam function.  */
-#undef HAVE_GETSPNAM
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
 
-/* Define if you have the getusershell function.  */
-#undef HAVE_GETUSERSHELL
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
 
-/* Define if you have the <crypt.h> header file.  */
-#undef HAVE_CRYPT_H
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
 
-/* Define if you have the <shadow.h> header file.  */
-#undef HAVE_SHADOW_H
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
index 79ea2e5..fc4c21f 100755 (executable)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 1.4 .
+# From configure.in Revision: 1.6 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.59.
 #
@@ -938,7 +938,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd $ac_popdir
+    cd "$ac_popdir"
   done
 fi
 
@@ -1858,8 +1858,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1917,8 +1916,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2034,8 +2032,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2089,8 +2086,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2135,8 +2131,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2180,8 +2175,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2477,181 +2471,6 @@ echo "${ECHO_T}no /etc/shadow file." >&6
        fi
 
 
-echo "$as_me:$LINENO: checking for crypt" >&5
-echo $ECHO_N "checking for crypt... $ECHO_C" >&6
-if test "${ac_cv_func_crypt+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-/* Define crypt to an innocuous variant, in case <limits.h> declares crypt.
-   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
-#define crypt innocuous_crypt
-
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char crypt (); below.
-    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-    <limits.h> exists even on freestanding compilers.  */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef crypt
-
-/* Override any gcc2 internal prototype to avoid an error.  */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
-   builtin and then its argument prototype would still apply.  */
-char crypt ();
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined (__stub_crypt) || defined (__stub___crypt)
-choke me
-#else
-char (*f) () = crypt;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != crypt;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_func_crypt=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_func_crypt=no
-fi
-rm -f conftest.err conftest.$ac_objext \
-      conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: $ac_cv_func_crypt" >&5
-echo "${ECHO_T}$ac_cv_func_crypt" >&6
-if test $ac_cv_func_crypt = yes; then
-   cryptlocation=libc
-else
-
-                       #crypt not in libc
-                       echo "$as_me:$LINENO: checking for crypt in -lcrypt" >&5
-echo $ECHO_N "checking for crypt in -lcrypt... $ECHO_C" >&6
-if test "${ac_cv_lib_crypt_crypt+set}" = set; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcrypt  $LIBS"
-cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-
-/* Override any gcc2 internal prototype to avoid an error.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-/* We use char because int might match the return type of a gcc2
-   builtin and then its argument prototype would still apply.  */
-char crypt ();
-int
-main ()
-{
-crypt ();
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  ac_cv_lib_crypt_crypt=yes
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-ac_cv_lib_crypt_crypt=no
-fi
-rm -f conftest.err conftest.$ac_objext \
-      conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-echo "$as_me:$LINENO: result: $ac_cv_lib_crypt_crypt" >&5
-echo "${ECHO_T}$ac_cv_lib_crypt_crypt" >&6
-if test $ac_cv_lib_crypt_crypt = yes; then
-
-                                       cryptlocation=libcrypt
-                                       unix_ldflags="${unix_ldflags} -lcrypt"
-
-
-fi
-
-
-
-fi
-
-       if test x$cryptlocation = x; then
-                fail=$fail" crypt()" ,
-       fi
-
 
 echo "$as_me:$LINENO: checking for egrep" >&5
 echo $ECHO_N "checking for egrep... $ECHO_C" >&6
@@ -2701,8 +2520,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2872,8 +2690,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2907,8 +2724,7 @@ done
 
 
 
-
-for ac_header in crypt.h shadow.h
+for ac_header in shadow.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
 if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -2941,8 +2757,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3127,8 +2942,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3199,8 +3013,7 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
+        { ac_try='test -z "$ac_c_werror_flag"                   || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3237,111 +3050,6 @@ _ACEOF
 fi
 
 
-
-
-
-for ac_func in fgetpwent fgetspent fgetgrent
-do
-as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
-echo "$as_me:$LINENO: checking for $ac_func" >&5
-echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
-if eval "test \"\${$as_ac_var+set}\" = set"; then
-  echo $ECHO_N "(cached) $ECHO_C" >&6
-else
-  cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h.  */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h.  */
-/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
-   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
-#define $ac_func innocuous_$ac_func
-
-/* System header to define __stub macros and hopefully few prototypes,
-    which can conflict with char $ac_func (); below.
-    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
-    <limits.h> exists even on freestanding compilers.  */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $ac_func
-
-/* Override any gcc2 internal prototype to avoid an error.  */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-/* We use char because int might match the return type of a gcc2
-   builtin and then its argument prototype would still apply.  */
-char $ac_func ();
-/* The GNU C library defines this for functions which it implements
-    to always fail with ENOSYS.  Some functions are actually named
-    something starting with __ and the normal name is an alias.  */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-char (*f) () = $ac_func;
-#endif
-#ifdef __cplusplus
-}
-#endif
-
-int
-main ()
-{
-return f != $ac_func;
-  ;
-  return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext conftest$ac_exeext
-if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
-  (eval $ac_link) 2>conftest.er1
-  ac_status=$?
-  grep -v '^ *+' conftest.er1 >conftest.err
-  rm -f conftest.er1
-  cat conftest.err >&5
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); } &&
-        { ac_try='test -z "$ac_c_werror_flag"
-                        || test ! -s conftest.err'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; } &&
-        { ac_try='test -s conftest$ac_exeext'
-  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-  (eval $ac_try) 2>&5
-  ac_status=$?
-  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-  (exit $ac_status); }; }; then
-  eval "$as_ac_var=yes"
-else
-  echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
-eval "$as_ac_var=no"
-fi
-rm -f conftest.err conftest.$ac_objext \
-      conftest$ac_exeext conftest.$ac_ext
-fi
-echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
-echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
-if test `eval echo '${'$as_ac_var'}'` = yes; then
-  cat >>confdefs.h <<_ACEOF
-#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-
        targetname=rlm_unix
 else
        targetname=
@@ -4154,11 +3862,6 @@ esac
 
 
 
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -4197,6 +3900,12 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
         fi;;
       esac
     done` || { (exit 1); exit 1; }
+
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
index a57e7a9..5262f59 100644 (file)
@@ -1,3 +1,4 @@
+AC_PREREQ([2.53])
 AC_INIT(rlm_unix.c)
 AC_REVISION($Revision$)
 AC_DEFUN(modname,[rlm_unix])
@@ -23,23 +24,7 @@ if test x$with_[]modname != xno; then
                AC_MSG_RESULT(no /etc/shadow file.)
        fi
 
-       AC_CHECK_FUNC(crypt, 
-               [ cryptlocation=libc ],
-               [
-                       #crypt not in libc
-                       AC_CHECK_LIB(crypt, crypt, 
-                               [ 
-                                       cryptlocation=libcrypt 
-                                       unix_ldflags="${unix_ldflags} -lcrypt"
-                               ]
-                       )
-               ]
-       )
-       if test x$cryptlocation = x; then
-               [ fail=$fail" crypt()" ],
-       fi
-
-       AC_CHECK_HEADERS(crypt.h shadow.h)
+       AC_CHECK_HEADERS(shadow.h)
        AC_CHECK_FUNCS(getspnam getusershell)
 
        AC_CHECK_LIB(shadow, getspnam, 
@@ -49,8 +34,6 @@ if test x$with_[]modname != xno; then
                ]
        )
 
-       AC_CHECK_FUNCS(fgetpwent fgetspent fgetgrent)
-
        targetname=modname
 else
        targetname=
index 995b3bb..d8d1038 100644 (file)
  *
  *   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * Copyright 2000  The FreeRADIUS server project
+ * Copyright 2000,2006  The FreeRADIUS server project
  * Copyright 2000  Jeff Carneal <jeff@apex.net>
  * Copyright 2000  Alan Curry <pacman@world.std.com>
  */
-static const char rcsid[] = "$Id$";
 
-#include       "autoconf.h"
-#include       "libradius.h"
+#include       <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include       <freeradius-devel/autoconf.h>
 
 #include       <stdlib.h>
 #include       <string.h>
@@ -51,147 +52,30 @@ static const char rcsid[] = "$Id$";
 #  include     <siad.h>
 #endif
 
-#include       "radiusd.h"
-#include       "modules.h"
-#include       "sysutmp.h"
-#include       "cache.h"
-#include       "conffile.h"
-#include       "compat.h"
+#include       <freeradius-devel/radiusd.h>
+#include       <freeradius-devel/modules.h>
+#include       <freeradius-devel/sysutmp.h>
 
 static char trans[64] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 #define ENC(c) trans[c]
 
 struct unix_instance {
-       int cache_passwd;
-       const char *passwd_file;
-       const char *shadow_file;
-       const char *group_file;
        const char *radwtmp;
-       int usegroup;
-       struct pwcache *cache;
-       time_t cache_reload;
-       time_t next_reload;
-       time_t last_reload;
 };
 
-static CONF_PARSER module_config[] = {
-       /*
-        *      Cache the password by default.
-        */
-       { "cache",    PW_TYPE_BOOLEAN,
-         offsetof(struct unix_instance,cache_passwd), NULL, "no" },
-       { "passwd",   PW_TYPE_STRING_PTR,
-         offsetof(struct unix_instance,passwd_file), NULL,  NULL },
-       { "shadow",   PW_TYPE_STRING_PTR,
-         offsetof(struct unix_instance,shadow_file), NULL,  NULL },
-       { "group",    PW_TYPE_STRING_PTR,
-         offsetof(struct unix_instance,group_file), NULL,   NULL },
+static const CONF_PARSER module_config[] = {
        { "radwtmp",  PW_TYPE_STRING_PTR,
          offsetof(struct unix_instance,radwtmp), NULL,   "NULL" },
-       { "usegroup", PW_TYPE_BOOLEAN,
-         offsetof(struct unix_instance,usegroup), NULL,     "no" },
-       { "cache_reload", PW_TYPE_INTEGER,
-         offsetof(struct unix_instance,cache_reload), NULL, "600" },
 
        { NULL, -1, 0, NULL, NULL }             /* end the list */
 };
 
-/*
- * groupcmp is part of autz. But it uses the data from an auth instance. So
- * here is where it gets it. By default this will be the first configured
- * auth instance. That can be changed by putting "usegroup = yes" inside an
- * auth instance to explicitly bind all Group checks to it.
- */
-
-/* binds "Group=" to an instance (a particular passwd file) */
-static struct unix_instance *group_inst;
-
-/* Tells if the above binding was explicit (usegroup=yes specified in config
- * file) or not ("Group=" was bound to the first instance of rlm_unix */
-static int group_inst_explicit;
-
-#ifdef HAVE_GETSPNAM
-#if defined(M_UNIX)
-static inline const char *get_shadow_name(shadow_pwd_t *spwd) {
-       if (spwd == NULL) return NULL;
-       return (spwd->pw_name);
-}
-
-static inline const char *get_shadow_encrypted_pwd(shadow_pwd_t *spwd) {
-       if (spwd == NULL) return NULL;
-       return (spwd->pw_passwd);
-}
-#else /* M_UNIX */
-       static inline const char *get_shadow_name(shadow_pwd_t *spwd) {
-               if (spwd == NULL) return NULL;
-               return (spwd->sp_namp);
-       }
-       static inline const char *get_shadow_encrypted_pwd(shadow_pwd_t *spwd) {
-               if (spwd == NULL) return NULL;
-               return (spwd->sp_pwdp);
-       }
-#endif /* M_UNIX */
-#endif /* HAVE_GETSPNAM */
-
-static struct passwd *fgetpwnam(const char *fname, const char *name) {
-       FILE            *file = fopen(fname, "ro");
-       struct passwd   *pwd = NULL;
-
-       if(file == NULL) return NULL;
-       do {
-               pwd = fgetpwent(file);
-               if(pwd == NULL) {
-                       fclose(file);
-                       return NULL;
-               }
-       } while (strcmp(name, pwd->pw_name) != 0);
-
-       fclose(file);
-       return pwd;
-}
-
-static struct group *fgetgrnam(const char *fname, const char *name) {
-       FILE            *file = fopen(fname, "ro");
-       struct group    *grp = NULL;
-
-       if(file == NULL) return NULL;
-
-       do {
-               grp = fgetgrent(file);
-               if(grp == NULL) {
-                       fclose(file);
-                       return NULL;
-               }
-       } while(strcmp(name, grp->gr_name) != 0);
-       fclose(file);
-       return grp;
-}
-
-#ifdef HAVE_GETSPNAM
-
-static shadow_pwd_t *fgetspnam(const char *fname, const char *name) {
-       FILE            *file = fopen(fname, "ro");
-       shadow_pwd_t    *spwd = NULL;
-
-       if(file == NULL) return NULL;
-       do {
-               spwd = fgetspent(file);
-               if(spwd == NULL) {
-                       fclose(file);
-                       return NULL;
-               }
-       } while(strcmp(name, get_shadow_name(spwd)) != 0);
-       fclose(file);
-       return spwd;
-}
-
-#endif
 
 /*
  *     The Group = handler.
  */
-static int groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request,
+static int groupcmp(void *instance, UNUSED REQUEST *req, VALUE_PAIR *request,
                    VALUE_PAIR *check, VALUE_PAIR *check_pairs,
                    VALUE_PAIR **reply_pairs)
 {
@@ -206,11 +90,6 @@ static int groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request,
        check_pairs = check_pairs;
        reply_pairs = reply_pairs;
 
-       if (!group_inst) {
-               radlog(L_ERR, "groupcmp: no group list known.");
-               return 1;
-       }
-
        /*
         *      No user name, doesn't compare.
         */
@@ -221,23 +100,13 @@ static int groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request,
                        return -1;
                }
        }
-       username = (char *)vp->strvalue;
-
-       if (group_inst->cache_passwd &&
-           (retval = H_groupcmp(group_inst->cache, check, username)) != -2)
-               return retval;
+       username = (char *)vp->vp_strvalue;
 
-       if (group_inst->passwd_file)
-               pwd = fgetpwnam(group_inst->passwd_file, username);
-       else
-               pwd = getpwnam(username);
+       pwd = getpwnam(username);
        if (pwd == NULL)
                return -1;
 
-       if (group_inst->group_file)
-               grp = fgetgrnam(group_inst->group_file, (char *)check->strvalue);
-       else
-               grp = getgrnam((char *)check->strvalue);
+       grp = getgrnam((char *)check->vp_strvalue);
        if (grp == NULL)
                return -1;
 
@@ -253,20 +122,24 @@ static int groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request,
 
 
 /*
- *     FIXME:  We really should have an 'init' which makes
- *     System auth == Unix
+ *     Detach.
  */
-static int unix_init(void)
+static int unix_detach(void *instance)
 {
-       /* FIXME - delay these until a group file has been read so we know
-        * groupcmp can actually do something */
-       paircompare_register(PW_GROUP, PW_USER_NAME, groupcmp, NULL);
-#ifdef PW_GROUP_NAME /* compat */
-       paircompare_register(PW_GROUP_NAME, PW_USER_NAME, groupcmp, NULL);
+#define inst ((struct unix_instance *)instance)
+
+       paircompare_unregister(PW_GROUP, groupcmp);
+#ifdef PW_GROUP_NAME
+       paircompare_unregister(PW_GROUP_NAME, groupcmp);
 #endif
+#undef inst
+       free(instance);
        return 0;
 }
 
+/*
+ *     Read the config
+ */
 static int unix_instantiate(CONF_SECTION *conf, void **instance)
 {
        struct unix_instance *inst;
@@ -284,234 +157,70 @@ static int unix_instantiate(CONF_SECTION *conf, void **instance)
         *      Parse the configuration, failing if we can't do so.
         */
        if (cf_section_parse(conf, inst, module_config) < 0) {
-               free(inst);
+               unix_detach(inst);
                return -1;
        }
 
-       if (inst->cache_passwd) {
-               radlog(L_INFO, "HASH:  Reinitializing hash structures "
-                       "and lists for caching...");
-               if ((inst->cache = unix_buildpwcache(inst->passwd_file,
-                                                    inst->shadow_file,
-                                                    inst->group_file))==NULL)
-                {
-                       radlog(L_ERR, "HASH:  unable to create user "
-                               "hash table.  disable caching and run debugs");
-                       if (inst->passwd_file)
-                               free((char *) inst->passwd_file);
-                       if (inst->shadow_file)
-                               free((char *) inst->shadow_file);
-                       if (inst->group_file)
-                               free((char *) inst->group_file);
-                       if (inst->radwtmp)
-                               free((char *) inst->radwtmp);
-                       free(inst);
-                       return -1;
-               }
-
-               if (inst->cache_reload) {
-                       inst->last_reload = 0;
-                       inst->next_reload = time(NULL) + inst->cache_reload;
-               }
-       } else {
-               inst->cache = NULL;
-       }
-
-       if (inst->usegroup) {
-               if (group_inst_explicit) {
-                       radlog(L_ERR, "Only one group list may be active");
-               } else {
-                       group_inst = inst;
-                       group_inst_explicit = 1;
-               }
-       } else if (!group_inst) {
-               group_inst = inst;
-       }
-#undef inst
-
-       return 0;
-}
+       /* FIXME - delay these until a group file has been read so we know
+        * groupcmp can actually do something */
+       paircompare_register(PW_GROUP, PW_USER_NAME, groupcmp, NULL);
+#ifdef PW_GROUP_NAME /* compat */
+       paircompare_register(PW_GROUP_NAME, PW_USER_NAME, groupcmp, NULL);
+#endif
 
-/*
- *     Detach.
- */
-static int unix_detach(void *instance)
-{
-#define inst ((struct unix_instance *)instance)
-       if (group_inst == inst) {
-               group_inst = NULL;
-               group_inst_explicit = 0;
-       }
-       if (inst->passwd_file)
-               free((char *) inst->passwd_file);
-       if (inst->shadow_file)
-               free((char *) inst->shadow_file);
-       if (inst->group_file)
-               free((char *) inst->group_file);
-       if (inst->radwtmp)
-               free((char *) inst->radwtmp);
-       if (inst->cache) {
-               unix_freepwcache(inst->cache);
-       }
 #undef inst
-       free(instance);
-       return 0;
-}
 
-static int unix_destroy(void)
-{
-       paircompare_unregister(PW_GROUP, groupcmp);
-#ifdef PW_GROUP_NAME
-       paircompare_unregister(PW_GROUP_NAME, groupcmp);
-#endif
        return 0;
 }
 
 
 /*
- *     Check the users password against the standard UNIX
- *     password table.
+ *     Pull the users password from where-ever, and add it to
+ *     the given vp list.
  */
-static int unix_authenticate(void *instance, REQUEST *request)
+static int unix_getpw(UNUSED void *instance, REQUEST *request,
+                     VALUE_PAIR **vp_list)
 {
-#define inst ((struct unix_instance *)instance)
-       char *name, *passwd;
-       struct passwd   *pwd;
+       const char      *name;
        const char      *encrypted_pass;
-       int             ret;
 #ifdef HAVE_GETSPNAM
-       shadow_pwd_t    *spwd = NULL;
+       struct spwd     *spwd = NULL;
 #endif
 #ifdef OSFC2
        struct pr_passwd *pr_pw;
-#endif
-#ifdef OSFSIA
-       char            *info[2];
-       char            *progname = "radius";
-       SIAENTITY       *ent = NULL;
+#else
+       struct passwd   *pwd;
 #endif
 #ifdef HAVE_GETUSERSHELL
        char            *shell;
 #endif
-
-       /* See if we should refresh the cache */
-       if (inst->cache && inst->cache_reload
-        && (inst->next_reload < request->timestamp)) {
-               /* Time to refresh, maybe ? */
-               int must_reload = 0;
-               struct stat statbuf;
-
-               DEBUG2("rlm_users : Time to refresh cache.");
-               /* Check if any of the files has changed */
-               if (inst->passwd_file
-                && (stat(inst->passwd_file, &statbuf) != -1)
-                && (statbuf.st_mtime > inst->last_reload)) {
-                       must_reload++;
-               }
-
-               if (inst->shadow_file
-                && (stat(inst->shadow_file, &statbuf) != -1)
-                && (statbuf.st_mtime > inst->last_reload)) {
-                       must_reload++;
-               }
-
-               if (inst->group_file
-                && (stat(inst->group_file, &statbuf) != -1)
-                && (statbuf.st_mtime > inst->last_reload)) {
-                       must_reload++;
-               }
-
-               if (must_reload) {
-                       /* Build a new cache to replace old one */
-                       struct pwcache *oldcache;
-                       struct pwcache *newcache = unix_buildpwcache(
-                                                       inst->passwd_file,
-                                                       inst->shadow_file,
-                                                       inst->group_file);
-
-                       if (newcache) {
-                               oldcache = inst->cache;
-                               inst->cache = newcache;
-                               unix_freepwcache(oldcache);
-
-                               inst->last_reload = time(NULL);
-                       }
-               } else {
-                       DEBUG2("rlm_users : Files were unchanged. Not reloading.");
-               }
-
-               /* Schedule next refresh */
-               inst->next_reload = time(NULL) + inst->cache_reload;
-       }
+       VALUE_PAIR      *vp;
 
        /*
         *      We can only authenticate user requests which HAVE
         *      a User-Name attribute.
         */
        if (!request->username) {
-               radlog(L_AUTH, "rlm_unix: Attribute \"User-Name\" is required for authentication.");
-               return RLM_MODULE_INVALID;
-       }
-
-       /*
-        *      We can only authenticate user requests which HAVE
-        *      a User-Password attribute.
-        */
-       if (!request->password) {
-               radlog(L_AUTH, "rlm_unix: Attribute \"User-Password\" is required for authentication.");
-               return RLM_MODULE_INVALID;
-       }
-
-       /*
-        *  Ensure that we're being passed a plain-text password,
-        *  and not anything else.
-        */
-       if (request->password->attribute != PW_PASSWORD) {
-               radlog(L_AUTH, "rlm_unix: Attribute \"User-Password\" is required for authentication.  Cannot use \"%s\".", request->password->name);
-               return RLM_MODULE_INVALID;
+               return RLM_MODULE_NOOP;
        }
 
-       name = (char *)request->username->strvalue;
-       passwd = (char *)request->password->strvalue;
-
-       if (inst->cache_passwd &&
-           (ret = H_unix_pass(inst->cache, name, passwd, &request->reply->vps)) != -2)
-               return (ret == 0) ? RLM_MODULE_OK : RLM_MODULE_REJECT;
-
-#ifdef OSFSIA
-       info[0] = progname;
-       info[1] = NULL;
-       if (sia_ses_init (&ent, 1, info, NULL, name, NULL, 0, NULL) !=
-           SIASUCCESS)
-               return RLM_MODULE_NOTFOUND;
-       if ((ret = sia_ses_authent (NULL, passwd, ent)) != SIASUCCESS) {
-               if (ret & SIASTOP)
-                       sia_ses_release (&ent);
-               return RLM_MODULE_NOTFOUND;
-       }
-       if (sia_ses_estab (NULL, ent) == SIASUCCESS) {
-               sia_ses_release (&ent);
-               return RLM_MODULE_OK;
-       }
+       name = (char *)request->username->vp_strvalue;
+       encrypted_pass = NULL;
 
-       return RLM_MODULE_NOTFOUND;
-#else /* OSFSIA */
 #ifdef OSFC2
        if ((pr_pw = getprpwnam(name)) == NULL)
                return RLM_MODULE_NOTFOUND;
        encrypted_pass = pr_pw->ufld.fd_encrypt;
-#else /* OSFC2 */
+
        /*
-        *      Get encrypted password from password file
-        *
-        *      If a password file was explicitly specified, use it,
-        *      otherwise, use the system routines to read the
-        *      system password file
+        *      Check if account is locked.
         */
-       if (inst->passwd_file != NULL) {
-               if ((pwd = fgetpwnam(inst->passwd_file, name)) == NULL)
-                       return RLM_MODULE_NOTFOUND;
-       } else if ((pwd = getpwnam(name)) == NULL) {
+       if (pr_pw->uflg.fg_lock!=1) {
+               radlog(L_AUTH, "rlm_unix: [%s]: account locked", name);
+               return RLM_MODULE_USERLOCK;
+       }
+#else /* OSFC2 */
+       if ((pwd = getpwnam(name)) == NULL) {
                return RLM_MODULE_NOTFOUND;
        }
        encrypted_pass = pwd->pw_passwd;
@@ -521,30 +230,27 @@ static int unix_authenticate(void *instance, REQUEST *request)
        /*
         *      See if there is a shadow password.
         *
-        *      If a shadow file was explicitly specified, use it,
-        *      otherwise, use the system routines to read the
-        *      system shadow file.
-        *
-        *      Also, if we explicitly specify the password file,
-        *      only query the _system_ shadow file if the encrypted
+        *      Only query the _system_ shadow file if the encrypted
         *      password from the passwd file is < 10 characters (i.e.
         *      a valid password would never crypt() to it).  This will
         *      prevents users from using NULL password fields as things
         *      stand right now.
         */
-       if (inst->shadow_file != NULL) {
-               if ((spwd = fgetspnam(inst->shadow_file, name)) != NULL)
-                       encrypted_pass = get_shadow_encrypted_pwd(spwd);
-       } else if ((encrypted_pass == NULL) || (strlen(encrypted_pass) < 10)) {
-               if ((spwd = getspnam(name)) != NULL)
-                       encrypted_pass = get_shadow_encrypted_pwd(spwd);
+       if ((encrypted_pass == NULL) || (strlen(encrypted_pass) < 10)) {
+               if ((spwd = getspnam(name)) == NULL) {
+                       return RLM_MODULE_NOTFOUND;
+               }
+               encrypted_pass = spwd->sp_pwdp;
        }
 #endif /* HAVE_GETSPNAM */
 
+/*
+ *     These require 'pwd != NULL', which isn't true on OSFC2
+ */
+#ifndef OSFC2
 #ifdef DENY_SHELL
        /*
-        *      Undocumented temporary compatibility for iphil.NET
-        *      Users with a certain shell are always denied access.
+        *      Users with a particular shell are denied access
         */
        if (strcmp(pwd->pw_shell, DENY_SHELL) == 0) {
                radlog(L_AUTH, "rlm_unix: [%s]: invalid shell", name);
@@ -566,10 +272,11 @@ static int unix_authenticate(void *instance, REQUEST *request)
        endusershell();
        if (shell == NULL) {
                radlog(L_AUTH, "rlm_unix: [%s]: invalid shell [%s]",
-                       name, pwd->pw_shell);
+                      name, pwd->pw_shell);
                return RLM_MODULE_REJECT;
        }
 #endif
+#endif /* OSFC2 */
 
 #if defined(HAVE_GETSPNAM) && !defined(M_UNIX)
        /*
@@ -593,34 +300,86 @@ static int unix_authenticate(void *instance, REQUEST *request)
        }
 #endif
 
-#ifdef OSFC2
-       /*
-        *      Check if account is locked.
-        */
-       if (pr_pw->uflg.fg_lock!=1) {
-               radlog(L_AUTH, "rlm_unix: [%s]: account locked", name);
-               return RLM_MODULE_USERLOCK;
-       }
-#endif /* OSFC2 */
-
        /*
         *      We might have a passwordless account.
+        *
+        *      FIXME: Maybe add Auth-Type := Accept?
         */
        if (encrypted_pass[0] == 0)
-               return RLM_MODULE_OK;
+               return RLM_MODULE_NOOP;
+
+       vp = pairmake("Crypt-Password", encrypted_pass, T_OP_SET);
+       if (!vp) return RLM_MODULE_FAIL;
+
+       pairmove(vp_list, &vp);
+       pairfree(&vp);          /* might not be NULL; */
+
+       return RLM_MODULE_UPDATED;
+}
+
+
+/*
+ *     Pull the users password from where-ever, and add it to
+ *     the given vp list.
+ */
+static int unix_authorize(void *instance, REQUEST *request)
+{
+       return unix_getpw(instance, request, &request->config_items);
+}
+
+/*
+ *     Pull the users password from where-ever, and add it to
+ *     the given vp list.
+ */
+static int unix_authenticate(void *instance, REQUEST *request)
+{
+#ifdef OSFSIA
+       char            *info[2];
+       char            *progname = "radius";
+       SIAENTITY       *ent = NULL;
+
+       info[0] = progname;
+       info[1] = NULL;
+       if (sia_ses_init (&ent, 1, info, NULL, name, NULL, 0, NULL) !=
+           SIASUCCESS)
+               return RLM_MODULE_NOTFOUND;
+       if ((ret = sia_ses_authent (NULL, passwd, ent)) != SIASUCCESS) {
+               if (ret & SIASTOP)
+                       sia_ses_release (&ent);
+               return RLM_MODULE_NOTFOUND;
+       }
+       if (sia_ses_estab (NULL, ent) != SIASUCCESS) {
+               sia_ses_release (&ent);
+               return RLM_MODULE_NOTFOUND;
+       }
+#else  /* OSFSIA */
+       int rcode;
+       VALUE_PAIR *vp = NULL;
+
+       if (!request->password ||
+           (request->password->attribute != PW_USER_PASSWORD)) {
+               radlog(L_AUTH, "rlm_unix: Attribute \"User-Password\" is required for authentication.");
+               return RLM_MODULE_INVALID;
+       }
+
+       rcode = unix_getpw(instance, request, &vp);
+       if (rcode != RLM_MODULE_UPDATED) return rcode;
 
        /*
-        *      Check encrypted password.
+        *      0 means "ok"
         */
-       if (lrad_crypt_check(passwd, encrypted_pass)) {
-               radlog(L_AUTH, "rlm_unix: [%s]: invalid password", name);
+       if (lrad_crypt_check((char *) request->password->vp_strvalue,
+                            (char *) vp->vp_strvalue) != 0) {
+               radlog(L_AUTH, "rlm_unix: [%s]: invalid password",
+                      request->username->vp_strvalue);
                return RLM_MODULE_REJECT;
        }
+#endif /* OSFFIA */
+
        return RLM_MODULE_OK;
-#endif /* OSFSIA */
-#undef inst
 }
 
+
 /*
  *     UUencode 4 bits base64. We use this to turn a 4 byte field
  *     (an IP address) into 6 bytes of ASCII. This is used for the
@@ -656,7 +415,6 @@ static char *uue(void *in)
 static int unix_accounting(void *instance, REQUEST *request)
 {
        VALUE_PAIR      *vp;
-       RADCLIENT       *cl;
        FILE            *fp;
        struct utmp     ut;
        time_t          t;
@@ -680,6 +438,11 @@ static int unix_accounting(void *instance, REQUEST *request)
                return RLM_MODULE_NOOP;
        }
 
+       if (request->packet->src_ipaddr.af != AF_INET) {
+               DEBUG2("rlm_unix: IPv6 is not supported!");
+               return RLM_MODULE_NOOP;
+       }
+
        /*
         *      Which type is this.
         */
@@ -713,9 +476,9 @@ static int unix_accounting(void *instance, REQUEST *request)
                switch (vp->attribute) {
                        case PW_USER_NAME:
                                if (vp->length >= sizeof(ut.ut_name)) {
-                                       memcpy(ut.ut_name, (char *)vp->strvalue, sizeof(ut.ut_name));
+                                       memcpy(ut.ut_name, (char *)vp->vp_strvalue, sizeof(ut.ut_name));
                                } else {
-                                       strNcpy(ut.ut_name, (char *)vp->strvalue, sizeof(ut.ut_name));
+                                       strlcpy(ut.ut_name, (char *)vp->vp_strvalue, sizeof(ut.ut_name));
                                }
                                break;
                        case PW_LOGIN_IP_HOST:
@@ -748,13 +511,21 @@ static int unix_accounting(void *instance, REQUEST *request)
        if (strncmp(ut.ut_name, "!root", sizeof(ut.ut_name)) == 0 || !port_seen)
                return RLM_MODULE_NOOP;
 
+       s = "";
+
        /*
         *      If we didn't find out the NAS address, use the
         *      originator's IP address.
         */
-       if (nas_address == 0)
-               nas_address = request->packet->src_ipaddr;
-
+       if (nas_address == 0) {
+               RADCLIENT *cl;
+               nas_address = request->packet->src_ipaddr.ipaddr.ip4addr.s_addr;
+               
+               if ((cl = client_find_old(&request->packet->src_ipaddr)) != NULL)
+                       s = cl->shortname;
+       }
+       if (!s || s[0] == 0) s = uue(&(nas_address));
+       
 #ifdef __linux__
        /*
         *      Linux has a field for the client address.
@@ -765,12 +536,8 @@ static int unix_accounting(void *instance, REQUEST *request)
         *      We use the tty field to store the terminal servers' port
         *      and address so that the tty field is unique.
         */
-       s = "";
-       if ((cl = client_find(nas_address)) != NULL)
-               s = cl->shortname;
-       if (s == NULL || s[0] == 0) s = uue(&(nas_address));
        sprintf(buf, "%03d:%s", nas_port, s);
-       strNcpy(ut.ut_line, buf, sizeof(ut.ut_line));
+       strlcpy(ut.ut_line, buf, sizeof(ut.ut_line));
 
        /*
         *      We store the dynamic IP address in the hostname field.
@@ -778,7 +545,7 @@ static int unix_accounting(void *instance, REQUEST *request)
 #ifdef UT_HOSTSIZE
        if (framed_address) {
                ip_ntoa(buf, framed_address);
-               strncpy(ut.ut_host, buf, sizeof(ut.ut_host));
+               strlcpy(ut.ut_host, buf, sizeof(ut.ut_host));
        }
 #endif
 #ifdef HAVE_UTMPX_H
@@ -823,21 +590,19 @@ static int unix_accounting(void *instance, REQUEST *request)
 
 /* globally exported name */
 module_t rlm_unix = {
-  "System",
-  RLM_TYPE_THREAD_UNSAFE,        /* type: reserved */
-  unix_init,                    /* initialization */
-  unix_instantiate,            /* instantiation */
-  {
-         unix_authenticate,    /* authentication */
-         NULL,                 /* authorization */
-         NULL,                 /* preaccounting */
-         unix_accounting,      /* accounting */
-         NULL,                  /* checksimul */
-         NULL,                 /* pre-proxy */
-         NULL,                 /* post-proxy */
-         NULL                  /* post-auth */
-  },
-  unix_detach,                         /* detach */
-  unix_destroy,                  /* destroy */
+       RLM_MODULE_INIT,
+       "System",
+       RLM_TYPE_THREAD_UNSAFE,        /* type */
+       unix_instantiate,               /* instantiation */
+       unix_detach,                    /* detach */
+       {
+               unix_authenticate,    /* authentication */
+               unix_authorize,       /* authorization */
+               NULL,                 /* preaccounting */
+               unix_accounting,      /* accounting */
+               NULL,                  /* checksimul */
+               NULL,                   /* pre-proxy */
+               NULL,                   /* post-proxy */
+               NULL                    /* post-auth */
+       },
 };
-
index 632577d..e09652b 100644 (file)
@@ -42,7 +42,7 @@ all: build-module
 #######################################################################
 LT_OBJS                += $(SRCS:.c=.lo)
 LT_OBJS                += $(SRCS:.cpp=.lo)
-CFLAGS         += -I$(top_builddir)/src/include
+CFLAGS         += -I$(top_builddir)/src
 
 #######################################################################
 #
@@ -146,10 +146,10 @@ reconfig:
        @if [ -f configure.in ]; then \
                [ "x$(AUTOCONF)" != "x" ] && $(AUTOCONF) -I $(top_builddir); \
        fi
-       @if [ -f config.h.in ]; then \
-               [ "x$(AUTOHEADER)" != "x" ] && $(AUTOHEADER); \
+       @[ "x$(AUTOHEADER)" != "x" ] && [ -f ./configure.in ] && \
+       if grep AC_CONFIG_HEADERS configure.in >/dev/null; then\
+               $(AUTOHEADER);\
        fi
-               
 
 #
 #  Do any module-specific installation.
index f71da41..573e49a 100644 (file)
@@ -1,20 +1,25 @@
+rlm_acctlog
 rlm_acct_unique
 rlm_always
 rlm_attr_filter
 rlm_attr_rewrite
 rlm_chap
+rlm_checkval
+rlm_copy_packet
 rlm_counter
 rlm_dbm
 rlm_detail
 rlm_digest
 rlm_eap
 rlm_exec
+rlm_expiration
 rlm_expr
 rlm_fastusers
 rlm_files
 rlm_ippool
 rlm_krb5
 rlm_ldap
+rlm_logintime
 rlm_mschap
 rlm_ns_mta_md5
 rlm_otp
@@ -26,7 +31,7 @@ rlm_preprocess
 rlm_radutmp
 rlm_realm
 rlm_sql
-rlm_sql_log
 rlm_sqlcounter
+rlm_sqlippool
+rlm_sql_log
 rlm_unix
-rlm_checkval
index c3d44a8..53f84b1 100644 (file)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 #( echo 'User-Name = "eapmd5"';
-#  echo 'EAP-MD5-Password = "md5md5"';
+#  echo 'Cleartext-Password = "md5md5"';
 #  echo 'NAS-IP-Address = marajade.sandelman.ottawa.on.ca';
 #  echo 'EAP-Code = Response';
 #  echo 'EAP-Id = 210';
index 2d848b6..d0de5e1 100644 (file)
@@ -1,8 +1,8 @@
 User-Name = "eapmd5"
-EAP-MD5-Password = "md5md5"
+Cleartext-Password = "md5md5"
 NAS-IP-Address = marajade.sandelman.ottawa.on.ca
 EAP-Code = Response
 EAP-Id = 210
-EAP-Type-Identity = "eapsim
+EAP-Type-Identity = "eapsim"
 Message-Authenticator = 0
 NAS-Port = 0
index 1c8fb76..32c5aff 100644 (file)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 ( echo 'User-Name = "eapsim"';
-  echo 'EAP-MD5-Password = "md5md5"';
+  echo 'Cleartext-Password = "md5md5"';
   echo 'NAS-IP-Address = marajade.sandelman.ottawa.on.ca';
   echo 'EAP-Code = Response';
   echo 'EAP-Id = 210';
index 286a591..28226e7 100644 (file)
@@ -1,8 +1,8 @@
 User-Name = "eapsim"
-EAP-MD5-Password = "md5md5"
+Cleartext-Password = "md5md5"
 NAS-IP-Address = marajade.sandelman.ottawa.on.ca
 EAP-Code = Response
 EAP-Id = 210
-EAP-Type-Identify = "eapsim
+EAP-Type-Identity = "eapsim"
 Message-Authenticator = 0
 NAS-Port = 0
index 3ddd70b..2e0a402 100644 (file)
@@ -131,15 +131,6 @@ pidfile = ${run_dir}/radiusd.pid
 #
 max_request_time = 30
 
-#  delete_blocked_requests: If the request takes MORE THAN 'max_request_time'
-#  to be handled, then maybe the server should delete it.
-#
-#  If you're running in threaded, or thread pool mode, this setting
-#  should probably be 'no'.  Setting it to 'yes' when using a threaded
-#  server MAY cause the server to crash!
-#
-delete_blocked_requests = no
-
 #  cleanup_delay: The time to wait (in seconds) before cleaning up
 #  a reply which was sent to the NAS.
 #
diff --git a/suse/dialup_admin.patch b/suse/dialup_admin.patch
deleted file mode 100644 (file)
index 8d86c61..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
---- dialup_admin/bin/clean_radacct
-+++ dialup_admin/bin/clean_radacct
-@@ -6,7 +6,7 @@
- #
- use POSIX;
--$conf=shift||'/usr/local/dialup_admin/conf/admin.conf';
-+$conf=shift||'/usr/share/dialup_admin/conf/admin.conf';
- $back_days = 35;
---- dialup_admin/bin/dialup_admin.cron
-+++ dialup_admin/bin/dialup_admin.cron
-@@ -1,4 +1,4 @@
--1 0 * * * /usr/local/dialup_admin/bin/tot_stats >/dev/null 2>&1
--5 0 * * * /usr/local/dialup_admin/bin/monthly_tot_stats >/dev/null 2>&1
--10 0 1 * * /usr/local/dialup_admin/bin/truncate_radacct >/dev/null 2>&1
--15 0 1 * * /usr/local/dialup_admin/bin/clean_radacct >/dev/null 2>&1
-+1 0 * * * /usr/share/dialup_admin/bin/tot_stats >/dev/null 2>&1
-+5 0 * * * /usr/share/dialup_admin/bin/monthly_tot_stats >/dev/null 2>&1
-+10 0 1 * * /usr/share/dialup_admin/bin/truncate_radacct >/dev/null 2>&1
-+15 0 1 * * /usr/share/dialup_admin/bin/clean_radacct >/dev/null 2>&1
---- dialup_admin/bin/log_badlogins
-+++ dialup_admin/bin/log_badlogins
-@@ -17,7 +17,7 @@
- $|=1;
- $file=shift||'none';
--$conf=shift||'/usr/local/dialup_admin/conf/admin.conf';
-+$conf=shift||'/usr/share/dialup_admin/conf/admin.conf';
- $all_file=shift||'no';
- #
- # Uncomment to force inserts even if there are sql errors. That can
---- dialup_admin/bin/monthly_tot_stats
-+++ dialup_admin/bin/monthly_tot_stats
-@@ -8,7 +8,7 @@
- # Works only with mysql and postgresql
- #
--$conf=shift||'/usr/local/dialup_admin/conf/admin.conf';
-+$conf=shift||'/usr/share/dialup_admin/conf/admin.conf';
- open CONF, "<$conf"
---- dialup_admin/bin/showmodem
-+++ dialup_admin/bin/showmodem
-@@ -7,7 +7,7 @@
- $comm=shift || "public";
- $type=shift|| "xml";
--$conf='/usr/local/dialup_admin/conf/admin.conf';
-+$conf='/usr/share/dialup_admin/conf/admin.conf';
- open CONF, "<$conf"
-       or die "Could not open configuration file\n";
- while(<CONF>){
---- dialup_admin/bin/snmpfinger
-+++ dialup_admin/bin/snmpfinger
-@@ -6,7 +6,7 @@
- $comm=shift || 'public';
- $type=shift || 'cisco';
--$conf='/usr/local/dialup_admin/conf/admin.conf';
-+$conf='/usr/share/dialup_admin/conf/admin.conf';
- open CONF, "<$conf"
-       or die "Could not open configuration file\n";
- while(<CONF>){
---- dialup_admin/bin/tot_stats
-+++ dialup_admin/bin/tot_stats
-@@ -7,7 +7,7 @@
- # Works with mysql and postgresql
- #
--$conf=shift||'/usr/local/dialup_admin/conf/admin.conf';
-+$conf=shift||'/usr/share/dialup_admin/conf/admin.conf';
- open CONF, "<$conf"
---- dialup_admin/bin/truncate_radacct
-+++ dialup_admin/bin/truncate_radacct
-@@ -6,7 +6,7 @@
- #
- use POSIX;
--$conf=shift||'/usr/local/dialup_admin/conf/admin.conf';
-+$conf=shift||'/usr/share/dialup_admin/conf/admin.conf';
- $back_days = 90;
---- dialup_admin/conf/admin.conf
-+++ dialup_admin/conf/admin.conf
-@@ -19,11 +19,11 @@
- #
- # The directory where dialupadmin is installed
- #
--general_base_dir: /usr/local/dialup_admin
-+general_base_dir: /usr/share/dialup_admin
- #
- # The base directory of the freeradius radius installation
- #
--general_radiusd_base_dir: /usr/local/radiusd
-+general_radiusd_base_dir: /
- general_domain: company.com
- #
- # Set it to yes to use sessions and cache the various mappings
-@@ -66,8 +66,8 @@
- general_raddb_dir: %{general_radiusd_base_dir}/etc/raddb
- general_ldap_attrmap: %{general_raddb_dir}/ldap.attrmap
- # Need to fix admin.conf file parser
--#general_clients_conf: %{general_raddb_dir}/clients.conf
--general_clients_conf: /usr/local/etc/raddb/clients.conf
-+general_clients_conf: %{general_raddb_dir}/clients.conf
-+#general_clients_conf: /usr/local/etc/raddb/clients.conf
- general_sql_attrmap: %{general_base_dir}/conf/sql.attrmap
- general_accounting_attrs_file: %{general_base_dir}/conf/accounting.attrs
- general_extra_ldap_attrmap: %{general_base_dir}/conf/extra.ldap-attrmap
-@@ -235,19 +235,19 @@
- # This variable is used by the scripts in the bin folder
- # It should contain the path to the sql binary used to run
- # sql commands (mysql and psql are only supported for now)
--sql_command: /usr/local/bin/mysql
-+sql_command: /usr/bin/mysql
- #
- # This variable is used by the scripts in the bin folder
- # It should contain the snmp type and  path to the binary 
- # used to run snmp commands. 
- # (ucd = UCD-Snmp and net = Net-Snmp are only supported for now)
- general_snmp_type: net
--general_snmpwalk_command: /usr/local/bin/snmpwalk
--general_snmpget_command: /usr/local/bin/snmpget
-+general_snmpwalk_command: /usr/bin/snmpwalk
-+general_snmpget_command: /usr/bin/snmpget
- #
- # Uncomment to enable sql debug
- #
--sql_debug: true
-+#sql_debug: true
- #
- # If set to yes then the HTTP credentials (http authentication)
- # will be used to connect to the sql server instead of sql_username
diff --git a/suse/edir.patch b/suse/edir.patch
deleted file mode 100644 (file)
index de399e1..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- raddb/radiusd.conf.in
-+++ raddb/radiusd.conf.in
-@@ -783,7 +783,7 @@
-               # policy check and intruder detection. This will work *only if*
-               # FreeRADIUS is configured to build with --with-edir option.
-               #
--              # edir_account_policy_check=no
-+              edir_account_policy_check=no
-               #
-               # groupname_attribute = cn
-               # groupmembership_filter = "(|(&(objectClass=GroupOfNames)(member=%{Ldap-UserDn}))(&(objectClass=GroupOfUniqueNames)(uniquemember=%{Ldap-UserDn})))"
index 835c1f4..c143076 100644 (file)
@@ -1,3 +1,7 @@
+#
+# spec file for package freeradius
+#
+
 %define _oracle_support        0
 
 %define distroversion generic
         %define distroversion   sles%{sles_version}
 %endif
 
+# neededforbuild  apache2-devel-packages cyrus-sasl-devel db-devel kerberos-devel-packages mysql-devel mysql-shared openldap2 openldap2-client openldap2-devel openssl openssl-devel pam-devel postgresql-devel postgresql-libs python python-devel unixODBC unixODBC-devel
+
+BuildRequires: aaa_base acl attr bash bind-utils bison bzip2 coreutils cpio cpp cracklib cvs cyrus-sasl db diffutils e2fsprogs file filesystem fillup findutils flex gawk gdbm-devel gettext-devel glibc glibc-devel glibc-locale gpm grep groff gzip info insserv klogd less libacl libattr libcom_err libgcc libnscd libstdc++ libxcrypt libzio m4 make man mktemp module-init-tools ncurses ncurses-devel net-tools netcfg openldap2-client openssl pam pam-modules patch permissions popt procinfo procps psmisc pwdutils rcs readline sed strace sysvinit tar tcpd texinfo timezone unzip util-linux vim zlib zlib-devel apache2 apache2-devel apache2-prefork autoconf automake binutils cyrus-sasl-devel db-devel e2fsprogs-devel expat gcc gdbm gettext krb5 krb5-devel libapr0 libtool mysql-devel mysql-shared openldap2 openldap2-devel openssl-devel pam-devel perl postgresql postgresql-devel postgresql-libs python python-devel rpm unixODBC unixODBC-devel
+
 Name:         freeradius
 License:      GPL, LGPL
 Group:        Productivity/Networking/Radius/Servers
 Provides:     radiusd
 Conflicts:    radiusd-livingston radiusd-cistron icradius
-Version:      1.1.5
+Version:      2.0.0
 Release:      0.%{distroversion}
 URL:          http://www.freeradius.org/
 Summary:      Very highly Configurable Radius-Server
-Conflicts:    freeradius-snapshot
-Source:      %{name}-%{version}.tar.gz
-
-%if 0%{?suse_version} > 800
+Source0:      %{name}-%{version}.tar.gz
+%if %suse_version > 800
 PreReq:       /usr/sbin/useradd /usr/sbin/groupadd
 PreReq:       %insserv_prereq %fillup_prereq
-PreReq:       perl
 %endif
 BuildRoot:    %{_tmppath}/%{name}-%{version}-build
 Autoreqprov:  off
 %define apxs2 apxs2-prefork
 %define apache2_sysconfdir %(%{apxs2} -q SYSCONFDIR)
-Requires: python
-%if %{?suse_version:1}0
-BuildRequires: apache2-devel
-%else
-BuildRequires: httpd-devel
-%endif
-
-%if 0%{?sles_version} < 10
-%else
-BuildRequires: bind-libs
-%endif
-BuildRequires: cyrus-sasl-devel
-BuildRequires: db-devel
-BuildRequires: e2fsprogs-devel
-BuildRequires: gcc-c++
-BuildRequires: gdbm-devel
-BuildRequires: gettext-devel
-BuildRequires: glibc-devel
-BuildRequires: libtool
-BuildRequires: mysql-devel
-BuildRequires: ncurses-devel
-BuildRequires: net-snmp-devel
-BuildRequires: openldap2-devel
-BuildRequires: openssl-devel
-BuildRequires: pam-devel
-BuildRequires: perl
-BuildRequires: postgresql-devel
-BuildRequires: python-devel
-BuildRequires: sed
-BuildRequires: unixODBC-devel
-BuildRequires: zlib-devel
-
-%if 0%{?suse_version} > 910
-BuildRequires: krb5-devel
-%endif
-
-%if 0%{?suse_version} > 930
-
-BuildRequires: libcom_err
-%if %suse_version > 1000
-BuildRequires: libapr1-devel
-%else
-#BuildRequires: libapr0-devel
-%endif
-
-%endif
-
-%if 0%{?fedora_version} > 4
-BuildRequires: syslog-ng
-%endif
-
 
 %description
 The FreeRADIUS server has a number of features found in other servers,
@@ -94,6 +48,7 @@ attributes Selecting a particular configuration Authentication methods
 Accounting methods
 
 
+
 Authors:
 --------
     Miquel van Smoorenburg <miquels@cistron.nl>
@@ -121,25 +76,12 @@ attributes Selecting a particular configuration Authentication methods
 %endif
 
 %package dialupadmin
-Group:          Productivity/Networking/Radius/Servers
-Summary:        Web management for FreeRADIUS
-Requires:       http_daemon
-Requires:       perl-DateManip
-%if 0%{?suse_version} > 1000
-Requires:       apache2-mod_php5
-Requires:       php5
-Requires:       php5-ldap
-Requires:       php5-mysql
-Requires:       php5-pgsql
-%else
-Requires:       apache2-mod_php4
-Requires:       php4
-Requires:       php4-ldap
-Requires:       php4-mysql
-Requires:       php4-pgsql
-Requires:       php4-session
-%endif
-Autoreqprov:    off
+Group:        Productivity/Networking/Radius/Servers
+Summary:      Web management for FreeRADIUS
+Requires:     http_daemon apache2-mod_php4 php4
+Requires:     php4-ldap php4-mysql perl-DateManip
+Requires:     php4-pgsql php4-session
+Autoreqprov:  off
 
 %description dialupadmin
 Dialup Admin supports users either in SQL (MySQL or PostgreSQL are
@@ -177,51 +119,46 @@ Authors:
 %setup -q
 rm -rf `find . -name CVS`
 
-
 %build
 export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing -DLDAP_DEPRECATED"
 %ifarch x86_64
 export CFLAGS="$CFLAGS -fPIC"
 %endif
-%if 0%{?suse_version} > 1000
+%if %suse_version > 1000
 export CFLAGS="$CFLAGS -fstack-protector"
 %endif
+# workaround for SLES9
+%if %suse_version < 920
+ln -sf %{_libdir}/libmysqlclient_r.so.12 %{_libdir}/libmysqlclient_r.so
+ln -sf %{_libdir}/libmysqlclient_r.so.12 %{_libdir}/mysql/libmysqlclient_r.so
+%endif
 ./configure \
-               --prefix=%{_prefix} \
+               --prefix=%{_prefix} \
                 --sysconfdir=%{_sysconfdir} \
                --infodir=%{_infodir} \
                --mandir=%{_mandir} \
                --localstatedir=/var \
-               --libdir=%{_libdir}/freeradius \
+               --libdir=/usr/lib/freeradius \
                --with-threads \
                --with-snmp \
                --with-large-files \
-%if 0%{?suse_version} <= 920 
-               --without-rlm_sql_mysql \
-%endif
-%if %{?suse_version:1}0
-%if %suse_version > 910
+               --disable-ltdl-install \
+               --with-gnu-ld \
 %if %suse_version <= 920
                --enable-heimdal-krb5 \
                --with-rlm-krb5-include-dir=/usr/include/heimdal/ \
 %endif
                --with-rlm-krb5-lib-dir=%{_libdir} \
-%else
-               --without-rlm_krb5 \
-%endif
-%endif
 %if %_oracle_support == 1
                --with-rlm_sql_oracle \
-               --with-oracle-lib-dir=%{_libdir}/oracle/10.1.0.3/client/lib/ \
+               --with-oracle-lib-dir=/usr/lib/oracle/10.1.0.3/client/lib/ \
 %else
                --without-rlm_sql_oracle \
 %endif
                --enable-strict-dependencies \
                --with-edir \
-               --with-modules="rlm_sqlippool" \
-               --disable-ltdl-install \
-               --with-gnu-ld \
                --with-udpfromto
+# no parallel build possible
 make
 
 %install
@@ -233,12 +170,13 @@ make install R=$RPM_BUILD_ROOT
 RADDB=$RPM_BUILD_ROOT%{_sysconfdir}/raddb
 perl -i -pe 's/^#user =.*$/user = radiusd/'   $RADDB/radiusd.conf
 perl -i -pe 's/^#group =.*$/group = radiusd/' $RADDB/radiusd.conf
+ldconfig -n $RPM_BUILD_ROOT/usr/lib/freeradius
 # logs
 touch $RPM_BUILD_ROOT/var/log/radius/radutmp
 # SuSE
 install -d     $RPM_BUILD_ROOT/etc/pam.d
 install -d     $RPM_BUILD_ROOT/etc/logrotate.d
-%if 0%{?suse_version} > 920
+%if %suse_version > 920
 install -m 644 suse/radiusd-pam $RPM_BUILD_ROOT/etc/pam.d/radiusd
 %else
 install -m 644 suse/radiusd-pam-old $RPM_BUILD_ROOT/etc/pam.d/radiusd
@@ -263,7 +201,7 @@ install -m 644 suse/admin-httpd.conf $RPM_BUILD_ROOT%{apache2_sysconfdir}/conf.d
 rm -rf doc/00-OLD
 rm -f $RPM_BUILD_ROOT/etc/raddb/experimental.conf $RPM_BUILD_ROOT/usr/sbin/radwatch $RPM_BUILD_ROOT/usr/sbin/rc.radiusd
 rm -rf $RPM_BUILD_ROOT/usr/share/doc/freeradius*
-rm -rf $RPM_BUILD_ROOT/%{_libdir}/freeradius/*.la
+rm -rf $RPM_BUILD_ROOT/usr/lib/freeradius/*.la
 
 %pre
 /usr/sbin/groupadd -r radiusd 2> /dev/null || :
@@ -271,21 +209,15 @@ rm -rf $RPM_BUILD_ROOT/%{_libdir}/freeradius/*.la
                   /var/lib/radiusd radiusd 2> /dev/null || :
 
 %post
-%ifarch x86_64
-# Modify old installs to look for /usr/lib64/freeradius
-#libdir32=${%{_libdir}%%64}/freeradius
-/usr/bin/perl -i -pe "s:/usr/lib/freeradius:/usr/lib64/freeradius:" /etc/raddb/radiusd.conf
-%endif
-
 %{fillup_and_insserv -s radiusd START_RADIUSD }
-%if 0%{?suse_version} > 820
+%if %suse_version > 820
 
 %preun
 %stop_on_removal radiusd
 %endif
 
 %postun
-%if 0%{?suse_version} > 820
+%if %suse_version > 820
 %restart_on_update radiusd
 %endif
 %{insserv_cleanup}
@@ -333,6 +265,7 @@ rm -rf $RPM_BUILD_ROOT
 %attr(640,-,radiusd) %config(noreplace) /etc/raddb/sql.conf
 %attr(640,-,radiusd) %config(noreplace) /etc/raddb/users
 %config(noreplace) /etc/raddb/otp.conf
+%attr(640,-,radiusd) /etc/raddb/otppasswd.sample
 %attr(640,-,radiusd) %config(noreplace) /etc/raddb/certs
 %attr(640,-,radiusd) %config(noreplace) /etc/raddb/eap.conf
 %attr(640,-,radiusd) /etc/raddb/example.pl
@@ -344,8 +277,8 @@ rm -rf $RPM_BUILD_ROOT
 /usr/sbin/checkrad
 /usr/sbin/radiusd
 # shared libs
-%attr(755,root,root) %dir %{_libdir}/freeradius
-%attr(755,root,root) %{_libdir}/freeradius/*.so*
+%attr(755,root,root) %dir /usr/lib/freeradius
+%attr(755,root,root) /usr/lib/freeradius/*.so*
 # man-pages
 %doc %{_mandir}/man1/*
 %doc %{_mandir}/man5/*
@@ -361,8 +294,8 @@ rm -rf $RPM_BUILD_ROOT
 %if %_oracle_support == 1
 %files oracle
 %defattr(-,root,root)
-%attr(755,root,root) %dir %{_libdir}/freeradius
-%attr(755,root,root) %{_libdir}/freeradius/rlm_sql_oracle*.so*
+%attr(755,root,root) %dir /usr/lib/freeradius
+%attr(755,root,root) /usr/lib/freeradius/rlm_sql_oracle*.so*
 %endif
 
 %files dialupadmin
@@ -382,5 +315,5 @@ rm -rf $RPM_BUILD_ROOT
 
 %files devel
 %defattr(-,root,root)
-%{_libdir}/freeradius/*.a
-#%attr(644,root,root) %{_libdir}/freeradius/*.la
+/usr/lib/freeradius/*.a
+#%attr(644,root,root) /usr/lib/freeradius/*.la
diff --git a/suse/lib64.patch b/suse/lib64.patch
deleted file mode 100644 (file)
index f5103ab..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
---- src/modules/rlm_eap/libeap/Makefile
-+++ src/modules/rlm_eap/libeap/Makefile
-@@ -40,7 +40,7 @@
- $(TARGET).la: $(DYNAMIC_OBJS)
-       $(LIBTOOL) --mode=link $(CC) -release $(RADIUSD_VERSION) \
--      -module $(LINK_MODE) $(CFLAGS) -o $@ -rpath $(libdir) $^ 
-+      -module $(LINK_MODE) $(CFLAGS) -o $@ -rpath $(libdir) -L/lib64 -L/usr/lib64 $^ 
- static: $(TARGET).a
---- src/modules/rlm_sql/drivers/rules.mak
-+++ src/modules/rlm_sql/drivers/rules.mak
-@@ -93,7 +93,7 @@
- $(TARGET).la: $(DYNAMIC_OBJS)
-       $(LIBTOOL) --mode=link $(CC) -release $(RADIUSD_VERSION) \
-       -module $(LINK_MODE) $(CFLAGS) \
--      $(RLM_SQL_CFLAGS) -o $@ -rpath $(libdir) $^ $(RLM_SQL_LIBS)
-+      $(RLM_SQL_CFLAGS) -o $@ -rpath $(libdir) $^ -L/lib64 -L/usr/lib64 $(RLM_SQL_LIBS)
- #######################################################################
- #
---- src/modules/rlm_dbm/Makefile.in
-+++ src/modules/rlm_dbm/Makefile.in
-@@ -3,7 +3,7 @@
- HEADERS     =
- RLM_UTILS   = @dbm_utils@
- RLM_CFLAGS  = @dbm_cflags@
--RLM_LIBS    = @dbm_ldflags@
-+RLM_LIBS    = -lgdbm -lgdbm_compat
- RLM_INSTALL = @dbm_install@
- include ../rules.mak
---- src/modules/rules.mak.orig 2005-09-20 06:36:41.000000000 +0200
-+++ src/modules/rules.mak      2005-09-20 06:36:56.000000000 +0200
-@@ -97,7 +97,7 @@ endif
- $(TARGET).la: $(DYNAMIC_OBJS)
-       $(LIBTOOL) --mode=link $(CC) -release $(RADIUSD_VERSION) \
-       -module $(LINK_MODE) $(LDFLAGS) $(RLM_LDFLAGS) \
--      -o $@ -rpath $(libdir) $^ $(RLM_LIBS) $(LIBS)
-+      -o $@ -rpath $(libdir) $^ -L/lib64 -L/usr/lib64 $(RLM_LIBS) $(LIBS)
- #######################################################################
- #
diff --git a/suse/radiusd-pam-old b/suse/radiusd-pam-old
new file mode 100644 (file)
index 0000000..7a5349d
--- /dev/null
@@ -0,0 +1,7 @@
+#%PAM-1.0
+auth       required    pam_unix2.so nullok
+auth       required    pam_nologin.so
+account    required    pam_unix2.so
+password   required    pam_pwcheck.so nullok use_cracklib
+password   required    pam_unix2.so nullok use_first_pass use_authtok
+session    required    pam_unix2.so none
diff --git a/suse/rcradius-relayd b/suse/rcradius-relayd
new file mode 100644 (file)
index 0000000..4ebe557
--- /dev/null
@@ -0,0 +1,90 @@
+#! /bin/sh
+# Copyright (c) 2001       SuSE GmbH Nuernberg, Germany.
+#               2002, 2003 SuSE Linux AG, Nuernberg, Germany.
+#
+# Author: Wolfgang Rosenauer, 2000-2003
+#
+# /etc/init.d/radius-relayd
+#
+#   and symbolic its link
+#
+# /usr/bin/rcradius-relayd
+#
+### BEGIN INIT INFO
+# Provides:          radius-relayd
+# Required-Start:    $network $syslog $remotefs
+# Required-Stop:
+# Default-Start:     3 5
+# Default-Stop:      0 1 2 6
+# Short-Description: RADIUS Relay Server
+# Description:       Remote Authentication Dialin User Server Relay Service
+### END INIT INFO
+
+RADIUSD_BIN=/usr/sbin/radrelay
+test -x $RADIUSD_BIN || { echo "$RADIUSD_BIN not installed"; \
+       if [ "$1" = "stop" ]; then exit 0;
+       else exit 5; fi; }
+
+. /etc/rc.status
+
+rc_reset
+case "$1" in
+    start)
+       echo -n "Starting RADIUS Relay daemon "
+       startproc $RADIUSD_BIN -s -n radrelay >/dev/null
+       rc_status -v    
+       ;;
+    stop)
+       echo -n "Shutting down RADIUS Relay daemon "
+       killproc -TERM $RADIUSD_BIN 
+       rc_status -v    
+       ;;
+    try-restart|condrestart)
+       ## If first returns OK call the second, if first or
+       ## second command fails, set echo return value.
+       if test "$1" = "condrestart"; then
+               echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}"
+       fi
+       $0 status
+       if test $? = 0; then
+               $0 restart
+       else
+               rc_reset        # Not running is not a failure.
+       fi
+       rc_status
+       ;;
+    restart)
+        ## Stop the service and regardless of whether it was
+        ## running or not, start it again.
+       $0 stop
+       $0 start
+       rc_status
+       ;;
+    force-reload)
+        ## Signal the daemon to reload its config. Most daemons
+        ## do this on signal 1 (SIGHUP).
+        ## If it does not support it, restart.
+
+       echo -n "Reload RADIUS Relay daemon "
+        killproc -HUP $RADIUSD_BIN
+        rc_status -v
+       ;;
+    reload)
+        ## Like force-reload, but if daemon does not support
+        ## signalling, do nothing (!)
+
+       echo -n "Reload RADIUS Relay daemon "
+       killproc -HUP $RADIUSD_BIN 
+       rc_status -v
+       ;;
+    status)
+       echo -n "Checking for service radius-relayd "
+       checkproc $RADIUSD_BIN
+       rc_status -v
+       ;;
+    *)
+       echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload}"
+       exit 1
+       ;;
+esac
+rc_exit
index a22a19d..83e2af0 100644 (file)
@@ -13,9 +13,7 @@
 ### BEGIN INIT INFO
 # Provides:          radiusd
 # Required-Start:    $network $syslog $remotefs
-# Should-Start:      $time postgresql mysql ldap samba krb5kdc
 # Required-Stop:
-# Should-Stop:      $time postgresql mysql ldap
 # Default-Start:     3 5
 # Default-Stop:      0 1 2 6
 # Short-Description: RADIUS-Server
index 4a97631..ae31ac4 100644 (file)
--- a/todo/TODO
+++ b/todo/TODO
@@ -4,9 +4,6 @@ o scan ALL modules, so that they use consistent names for structures
   call rlm_foo_detach() if anything goes wrong, instead of just free()'ing
   'inst'.  The cf_parse_section().. code may have malloc'd memory, and
   that needs to be free'd, too.
-o Add a 'listen' directive, ala Apache, so that we can listen
-  on multiple ports. Hmm... if we do that, we should allow multiple
-  virtual servers, too.
 o Stop unloading modules on HUP so that we can have persistant
   handles/socketc/etc from module_init().  Alan D. and Alan C. had a good
   plan for when to load/reload modules on the list recently...I say
@@ -29,9 +26,6 @@ o Manual pages for the daemon, utilities and conffiles (some done)
 o Fix all FIXME's in the source.
 o better SNMP statistics support, for the auth/acct servers, and for
   each client.
-o fix the proxy receive code, so that we don't have to look through ALL
-  of the requests to find the matching proxy.  This might be hard to do..
-  It would also involve thread locking issues.
 
 WAIT UNTIL NEXT RELEASE:
 o UPDATE accounting requests aren't handled as in 1.5.4.3 for wtmp
@@ -39,9 +33,6 @@ o UPDATE accounting requests aren't handled as in 1.5.4.3 for wtmp
 o New module: rlm_fastradwtmp. with a radutmp-style active session
   database to guarantee wtmp records are always written in matching
   pairs. Because radlast is slow.
-o New module: rlm_attrmap. assigns a single attribute based on a
-  username, with ed-friendly/awk-friendly config file. Because the
-  users file is too complicated.
 o replace the module_t method table with a set of register_* functions
   (so different instances of the same module can offer different
   methods)
@@ -52,7 +43,6 @@ o switch all timers from time() to gettimeofday() so processing is
 o SNMP support for querying users who are on-line.
 o New module: rlm_nsupdate (dyndns). Because dynamic addresses are
   cruel.
-o New module: rlm_perl.
 
 WILL NOT DO:
 o module initialization AFTER forking, not before.
@@ -66,6 +56,10 @@ o there should be a way that radius itself could
        --- This work is for an external process to do ---
 
 DONE:
+o IPv6
+o proxy receive rbtree stuff
+o rlm_perl
+o "listen" directive
 o fix radwho to read modules{radutmp{filename = }}
 o Add 'initialize' list in modules, so explicitely give initialization order.
 o merge OSF/OSFIA patches from Cistron.