Move socket listening code to plugin modules.
authorAlan T. DeKok <aland@freeradius.org>
Mon, 6 Oct 2008 09:33:41 +0000 (11:33 +0200)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 6 Oct 2008 09:33:41 +0000 (11:33 +0200)
This makes the server core a fair bit simpler, and allows for
the creation of many new kinds of listening sockets.

The next step is to delete the RAD_LISTEN_TYPE_* names, as they're
no longer really needed.

The goal is to move much of src/main/event.c into the plugin modules,
so that the server core isn't are of the underlying protocols.

36 files changed:
src/include/libradius.h
src/include/radiusd.h
src/include/smodule.h [new file with mode: 0644]
src/include/stats.h
src/include/vmps.h [deleted file]
src/lib/Makefile
src/main/Makefile.in
src/main/auth.c
src/main/event.c
src/main/listen.c
src/main/session.c
src/main/stats.c
src/main/threads.c
src/modules/Makefile
src/modules/frs_acct/Makefile [new file with mode: 0644]
src/modules/frs_acct/frs_acct.c [moved from src/main/acct.c with 56% similarity]
src/modules/frs_auth/Makefile [new file with mode: 0644]
src/modules/frs_auth/frs_auth.c [new file with mode: 0644]
src/modules/frs_control/Makefile [new file with mode: 0644]
src/modules/frs_control/frs_control.c [moved from src/main/command.c with 98% similarity]
src/modules/frs_detail/Makefile [new file with mode: 0644]
src/modules/frs_detail/frs_detail.c [moved from src/main/detail.c with 83% similarity]
src/modules/frs_dhcp/Makefile [new file with mode: 0644]
src/modules/frs_dhcp/dhcp.c [moved from src/lib/dhcp.c with 99% similarity]
src/modules/frs_dhcp/dhcp.h [moved from src/include/dhcp.h with 100% similarity]
src/modules/frs_dhcp/frs_dhcp.c [moved from src/main/dhcpd.c with 90% similarity]
src/modules/frs_proxy/Makefile [new file with mode: 0644]
src/modules/frs_proxy/frs_proxy.c [new file with mode: 0644]
src/modules/frs_status/Makefile [new file with mode: 0644]
src/modules/frs_status/frs_status.c [new file with mode: 0644]
src/modules/frs_vmps/Makefile [new file with mode: 0644]
src/modules/frs_vmps/frs_vmps.c [moved from src/main/vmps.c with 79% similarity]
src/modules/frs_vmps/vqp.c [moved from src/lib/vqp.c with 98% similarity]
src/modules/frs_vmps/vqp.h [moved from src/include/vqp.h with 100% similarity]
src/modules/rlm_eap/types/rlm_eap_peap/peap.c
src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c

index e2f0803..12a431a 100644 (file)
@@ -342,13 +342,11 @@ VALUE_PAIR     *readvp2(FILE *fp, int *pfiledone, const char *errprefix);
 /*
  *     Error functions.
  */
-#ifdef _LIBRADIUS
 void           fr_strerror_printf(const char *, ...)
 #ifdef __GNUC__
                __attribute__ ((format (printf, 1, 2)))
 #endif
 ;
-#endif
 void           fr_perror(const char *, ...)
 #ifdef __GNUC__
                __attribute__ ((format (printf, 1, 2)))
index bf126ba..bf707cf 100644 (file)
@@ -95,6 +95,10 @@ typedef struct auth_req REQUEST;
 #include <freeradius-devel/stats.h>
 #include <freeradius-devel/realms.h>
 
+typedef struct radclient_list RADCLIENT_LIST;
+
+#include <freeradius-devel/smodule.h>
+
 
 /*
  *     See util.c
@@ -130,40 +134,10 @@ typedef struct radclient {
 #endif
 } RADCLIENT;
 
-/*
- *     Types of listeners.
- *
- *     Ordered by priority!
- */
-typedef enum RAD_LISTEN_TYPE {
-       RAD_LISTEN_NONE = 0,
-#ifdef WITH_PROXY
-       RAD_LISTEN_PROXY,
-#endif
-       RAD_LISTEN_AUTH,
-#ifdef WITH_ACCOUNTING
-       RAD_LISTEN_ACCT,
-#endif
-#ifdef WITH_DETAIL
-       RAD_LISTEN_DETAIL,
-#endif
-#ifdef WITH_VMPS
-       RAD_LISTEN_VQP,
-#endif
-#ifdef WITH_DHCP
-       RAD_LISTEN_DHCP,
-#endif
-#ifdef WITH_COMMAND_SOCKET
-       RAD_LISTEN_COMMAND,
-#endif
-       RAD_LISTEN_MAX
-} RAD_LISTEN_TYPE;
-
 
 /*
  *     For listening on multiple IP's and ports.
  */
-typedef struct rad_listen_t rad_listen_t;
 typedef                void (*radlog_func_t)(int, int, REQUEST *, const char *, ...);
 
 #define REQUEST_DATA_REGEX (0xadbeef00)
@@ -239,6 +213,7 @@ struct auth_req {
        const char              *server;
        REQUEST                 *parent;
        radlog_func_t           radlog; /* logging function, if set */
+       RAD_REQUEST_FUNP        process;
 };                             /* REQUEST typedef */
 
 #define RAD_REQUEST_OPTION_NONE            (0)
@@ -258,13 +233,6 @@ struct auth_req {
 #define REQUEST_CLEANUP_DELAY  (5)
 #define REQUEST_DONE           (6)
 
-/*
- *  Function handler for requests.
- */
-typedef                int (*RAD_REQUEST_FUNP)(REQUEST *);
-
-typedef struct radclient_list RADCLIENT_LIST;
-
 typedef struct pair_list {
        const char              *name;
        VALUE_PAIR              *check;
@@ -275,42 +243,6 @@ typedef struct pair_list {
        struct pair_list        *lastdefault;
 } PAIR_LIST;
 
-
-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_print_t)(rad_listen_t *, char *, size_t);
-typedef int (*rad_listen_encode_t)(rad_listen_t *, REQUEST *);
-typedef int (*rad_listen_decode_t)(rad_listen_t *, REQUEST *);
-
-struct rad_listen_t {
-       struct rad_listen_t *next; /* should be rbtree stuff */
-
-       /*
-        *      For normal sockets.
-        */
-       RAD_LISTEN_TYPE type;
-       int             fd;
-       const char      *server;
-       int             status;
-
-       rad_listen_recv_t recv;
-       rad_listen_send_t send;
-       rad_listen_encode_t encode;
-       rad_listen_decode_t decode;
-       rad_listen_print_t print;
-
-       void            *data;
-
-#ifdef WITH_STATS
-       fr_stats_t      stats;
-#endif
-};
-
-#define RAD_LISTEN_STATUS_INIT   (0)
-#define RAD_LISTEN_STATUS_KNOWN  (1)
-#define RAD_LISTEN_STATUS_CLOSED (2)
-#define RAD_LISTEN_STATUS_FINISH (3)
-
 typedef enum radlog_dest_t {
   RADLOG_STDOUT = 0,
   RADLOG_FILES,
@@ -443,9 +375,6 @@ void                        radius_signal_self(int flag);
  *     Function prototypes.
  */
 
-/* acct.c */
-int            rad_accounting(REQUEST *);
-
 /* session.c */
 int            rad_check_ts(uint32_t nasaddr, unsigned int port, const char *user,
                             const char *sessionid);
@@ -526,7 +455,6 @@ void radlog_request(int lvl, int priority, REQUEST *request, const char *msg, ..
 
 /* auth.c */
 char   *auth_name(char *buf, size_t buflen, REQUEST *request, int do_cli);
-int            rad_authenticate (REQUEST *);
 int            rad_postauth(REQUEST *);
 
 /* exec.c */
@@ -597,11 +525,6 @@ int listen_init(CONF_SECTION *cs, rad_listen_t **head);
 rad_listen_t *proxy_new_listener(void);
 RADCLIENT *client_listener_find(const rad_listen_t *listener,
                                const fr_ipaddr_t *ipaddr, int src_port);
-#ifdef WITH_STATS
-RADCLIENT_LIST *listener_find_client_list(const fr_ipaddr_t *ipaddr,
-                                         int port);
-rad_listen_t *listener_find_byipaddr(const fr_ipaddr_t *ipaddr, int port);
-#endif
 
 /* event.c */
 int radius_event_init(CONF_SECTION *cs, int spawn_flag);
diff --git a/src/include/smodule.h b/src/include/smodule.h
new file mode 100644 (file)
index 0000000..884d45d
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * smodule.h   Interface to the server-side module system.
+ *
+ * Version:    $Id$
+ *
+ */
+
+#ifndef FR_SMODULE_H
+#define FR_SMODULE_H
+
+#include <freeradius-devel/ident.h>
+RCSIDH(smodules_h, "$Id$")
+
+typedef struct rad_listen_t rad_listen_t;
+typedef                int (*RAD_REQUEST_FUNP)(REQUEST *);
+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_print_t)(rad_listen_t *, char *, size_t);
+typedef int (*rad_listen_encode_t)(rad_listen_t *, REQUEST *);
+typedef int (*rad_listen_decode_t)(rad_listen_t *, REQUEST *);
+typedef int (*rad_listen_parse_t)(CONF_SECTION *, rad_listen_t *);
+typedef void (*rad_listen_free_t)(rad_listen_t *);
+
+/*
+ *     Types of listeners.
+ *
+ *     Ordered by priority!
+ */
+typedef enum RAD_LISTEN_TYPE {
+       RAD_LISTEN_NONE = 0,
+#ifdef WITH_PROXY
+       RAD_LISTEN_PROXY,
+#endif
+       RAD_LISTEN_AUTH,
+#ifdef WITH_ACCOUNTING
+       RAD_LISTEN_ACCT,
+#endif
+#ifdef WITH_DETAIL
+       RAD_LISTEN_DETAIL,
+#endif
+#ifdef WITH_VMPS
+       RAD_LISTEN_VQP,
+#endif
+#ifdef WITH_DHCP
+       RAD_LISTEN_DHCP,
+#endif
+#ifdef WITH_COMMAND_SOCKET
+       RAD_LISTEN_COMMAND,
+#endif
+       RAD_LISTEN_MAX
+} RAD_LISTEN_TYPE;
+
+
+struct rad_listen_t {
+       struct rad_listen_t *next; /* should be rbtree stuff */
+
+       /*
+        *      For normal sockets.
+        */
+       RAD_LISTEN_TYPE type;
+       int             fd;
+       const char      *server;
+       int             status;
+
+       const struct frs_module_t *frs;
+       rad_listen_recv_t recv;
+       rad_listen_send_t send;
+       rad_listen_encode_t encode;
+       rad_listen_decode_t decode;
+       rad_listen_print_t print;
+
+       void            *data;
+
+#ifdef WITH_STATS
+       fr_stats_t      stats;
+#endif
+};
+
+#define RAD_LISTEN_STATUS_INIT   (0)
+#define RAD_LISTEN_STATUS_KNOWN  (1)
+#define RAD_LISTEN_STATUS_CLOSED (2)
+#define RAD_LISTEN_STATUS_FINISH (3)
+
+#define FRS_MODULE_MAGIC_NUMBER ((uint32_t) (0xf5ee4ad2))
+#define FRS_MODULE_INIT FRS_MODULE_MAGIC_NUMBER
+
+typedef struct frs_module_t {
+       uint32_t                magic;
+       RAD_LISTEN_TYPE         type;
+       /*
+        *      FIXME: Add flag for TCP sockets
+        */
+       const char              *name;
+       rad_listen_parse_t      parse;
+       rad_listen_free_t       free;
+       rad_listen_recv_t       recv;
+       rad_listen_send_t       send;
+       rad_listen_print_t      print;
+       rad_listen_encode_t     encode;
+       rad_listen_decode_t     decode;
+} frs_module_t;
+
+extern rad_listen_t *listen_alloc(const char *name);
+extern int listen_socket_parse(CONF_SECTION *cs, rad_listen_t *this);
+
+/*
+ *     FIXME: This should be done in the "parse" routine,
+ *     and it should allocated a fixed buffer..
+ */
+extern int listen_socket_print(rad_listen_t *this,
+                              char *buffer, size_t bufsize);
+
+extern int rad_status_server(REQUEST *request);
+
+/*
+ *     This is pretty bad.
+ */
+typedef struct listen_socket_t {
+       /*
+        *      For normal sockets.
+        */
+       fr_ipaddr_t     ipaddr;
+       int             port;
+#ifdef SO_BINDTODEVICE
+       const char      *interface;
+#endif
+       RADCLIENT_LIST  *clients;
+} listen_socket_t;
+
+#endif /* FR_SMODULE_H */
index 44d17cc..d144b62 100644 (file)
@@ -63,11 +63,14 @@ extern fr_stats_t   proxy_auth_stats;
 extern fr_stats_t      proxy_acct_stats;
 #endif
 
+extern struct timeval  radius_start_time;
+extern struct timeval  radius_hup_time;
+
 void radius_stats_init(int flag);
 void request_stats_final(REQUEST *request);
-void request_stats_reply(REQUEST *request);
 void radius_stats_ema(fr_stats_ema_t *ema,
                      struct timeval *start, struct timeval *end);
+#define EMA_SCALE (100)
 
 #define RAD_STATS_INC(_x) _x++
 #ifdef WITH_ACCOUNTING
diff --git a/src/include/vmps.h b/src/include/vmps.h
deleted file mode 100644 (file)
index fbfee65..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef VMPS_H
-#define VMPS_H
-/*
- *     vmps.h  Routines to handle VMPS sockets.
- *
- * Version:    $Id$
- *
- */
-
-#include <freeradius-devel/ident.h>
-RCSIDH(vmps_h, "$Id$")
-
-int vqp_socket_recv(rad_listen_t *listener,
-                   RAD_REQUEST_FUNP *pfun, REQUEST **prequest);
-int vqp_socket_send(rad_listen_t *listener, REQUEST *request);
-int vqp_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request);
-int vqp_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request);
-int vmps_process(REQUEST *request);
-
-#endif /* VMPS_H */
index 9b800a7..c412780 100644 (file)
@@ -9,8 +9,8 @@ include ../../Make.inc
 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 event.c getaddrinfo.c vqp.c \
-                 heap.c dhcp.c
+                 valuepair.c fifo.c packet.c event.c getaddrinfo.c \
+                 heap.c
 
 LT_OBJS                = $(SRCS:.c=.lo)
 
index a79fbd7..0ad3f12 100644 (file)
@@ -4,11 +4,11 @@
 
 include ../../Make.inc
 
-SERVER_SRCS    = acct.c auth.c client.c conffile.c crypt.c exec.c files.c \
+SERVER_SRCS    = auth.c client.c conffile.c crypt.c exec.c files.c \
                  listen.c log.c mainconfig.c modules.c modcall.c \
                  radiusd.c stats.c \
                  session.c threads.c util.c valuepair.c version.c  \
-                 xlat.c event.c realms.c evaluate.c vmps.c detail.c
+                 xlat.c event.c realms.c evaluate.c
 
 SERVER_OBJS    += $(SERVER_SRCS:.c=.lo)
 
@@ -74,9 +74,6 @@ radiusd.lo: radiusd.c  ../include/modules.h ../include/modcall.h ../include/modp
 %.lo: %.c
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS)  -c $<
 
-acct.lo: acct.c ../include/modules.h
-       $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c acct.c
-
 auth.lo: auth.c ../include/modules.h
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c auth.c
 
@@ -98,10 +95,6 @@ modules.lo: modules.c ../include/modules.h
 session.lo: session.c ../include/modules.h
        $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c session.c
 
-# It's #include'd for simplicity.  This should be fixed...
-listen.lo: dhcpd.c command.c
-       $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(INCLTDL) -c listen.c
-
 #
 # Helper programs
 #
index 0a76aa4..66de138 100644 (file)
@@ -55,339 +55,6 @@ char *auth_name(char *buf, size_t buflen, REQUEST *request, int do_cli)
 }
 
 
-
-/*
- * Make sure user/pass are clean
- * and then log them
- */
-static int rad_authlog(const char *msg, REQUEST *request, int goodpass) {
-
-       char clean_password[1024];
-       char clean_username[1024];
-       char buf[1024];
-       VALUE_PAIR *username = NULL;
-
-       if (!request->root->log_auth) {
-               return 0;
-       }
-
-       /*
-        * Get the correct username based on the configured value
-        */
-       if (log_stripped_names == 0) {
-               username = pairfind(request->packet->vps, PW_USER_NAME);
-       } else {
-               username = request->username;
-       }
-
-       /*
-        *      Clean up the username
-        */
-       if (username == NULL) {
-               strcpy(clean_username, "<no User-Name attribute>");
-       } else {
-               fr_print_string((char *)username->vp_strvalue,
-                               username->length,
-                               clean_username, sizeof(clean_username));
-       }
-
-       /*
-        *      Clean up the password
-        */
-       if (request->root->log_auth_badpass || request->root->log_auth_goodpass) {
-               if (!request->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 {
-                       fr_print_string((char *)request->password->vp_strvalue,
-                                        request->password->length,
-                                        clean_password, sizeof(clean_password));
-               }
-       }
-
-       if (goodpass) {
-               radlog_request(L_AUTH, 0, request, "%s: [%s%s%s] (%s)",
-                               msg,
-                               clean_username,
-                               request->root->log_auth_goodpass ? "/" : "",
-                               request->root->log_auth_goodpass ? clean_password : "",
-                               auth_name(buf, sizeof(buf), request, 1));
-       } else {
-               radlog_request(L_AUTH, 0, request, "%s: [%s%s%s] (%s)",
-                               msg,
-                               clean_username,
-                               request->root->log_auth_badpass ? "/" : "",
-                               request->root->log_auth_badpass ? clean_password : "",
-                               auth_name(buf, sizeof(buf), request, 1));
-       }
-
-       return 0;
-}
-
-/*
- *     Check password.
- *
- *     Returns:        0  OK
- *                     -1 Password fail
- *                     -2 Rejected (Auth-Type = Reject, send Port-Message back)
- *                     1  End check & return, don't reply
- *
- *     NOTE: NOT the same as the RLM_ values !
- */
-static int rad_check_password(REQUEST *request)
-{
-       VALUE_PAIR *auth_type_pair;
-       VALUE_PAIR *cur_config_item;
-       VALUE_PAIR *password_pair;
-       VALUE_PAIR *auth_item;
-       uint8_t my_chap[MAX_STRING_LEN];
-       int auth_type = -1;
-       int result;
-       int auth_type_count = 0;
-       result = 0;
-
-       /*
-        *      Look for matching check items. We skip the whole lot
-        *      if the authentication type is PW_AUTHTYPE_ACCEPT or
-        *      PW_AUTHTYPE_REJECT.
-        */
-       cur_config_item = request->config_items;
-       while(((auth_type_pair = pairfind(cur_config_item, PW_AUTH_TYPE))) != NULL) {
-               auth_type = auth_type_pair->vp_integer;
-               auth_type_count++;
-               DICT_VALUE *dv = dict_valbyattr(auth_type_pair->attribute,
-                                               auth_type_pair->vp_integer);
-
-               RDEBUG2("Found Auth-Type = %s",
-                       (dv != NULL) ? dv->name : "?");
-               cur_config_item = auth_type_pair->next;
-
-               if (auth_type == PW_AUTHTYPE_REJECT) {
-                       RDEBUG2("Auth-Type = Reject, rejecting user");
-                       return -2;
-               }
-       }
-
-       if (( auth_type_count > 1) && (debug_flag)) {
-               radlog_request(L_ERR, 0, request, "Warning:  Found %d auth-types on request for user '%s'",
-                       auth_type_count, request->username->vp_strvalue);
-       }
-
-       /*
-        *      This means we have a proxy reply or an accept
-        *  and it wasn't rejected in the above loop.  So
-        *  that means it is accepted and we do no further
-        *  authentication
-        */
-       if ((auth_type == PW_AUTHTYPE_ACCEPT)
-#ifdef WITH_PROXY
-           || (request->proxy)
-#endif
-           ) {
-               RDEBUG2("Auth-Type = Accept, accepting the user");
-               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) {
-               DICT_ATTR *da;
-
-               RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
-               RDEBUG("!!!    Replacing User-Password in config items with Cleartext-Password.     !!!");
-               RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
-               RDEBUG("!!! Please update your configuration so that the \"known good\"               !!!");
-               RDEBUG("!!! clear text password is in Cleartext-Password, and not in User-Password. !!!");
-               RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
-               password_pair->attribute = PW_CLEARTEXT_PASSWORD;
-               da = dict_attrbyvalue(PW_CLEARTEXT_PASSWORD);
-               if (!da) {
-                       radlog_request(L_ERR, 0, request, "FATAL: You broke the dictionaries.  Please use the default dictionaries!");
-                       _exit(1);
-               }
-
-               password_pair->name = da->name;
-       }
-
-       /*
-        *      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) {
-               /*
-                *      Re-write Auth-Type, but ONLY if it isn't already
-                *      set.
-                */
-               if (auth_type == -1) auth_type = PW_AUTHTYPE_CRYPT;
-       } else {
-               password_pair = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);
-       }
-
-       if (auth_type < 0) {
-               if (password_pair) {
-                       auth_type = PW_AUTHTYPE_LOCAL;
-               } else {
-                       /*
-                       *       The admin hasn't told us how to
-                       *       authenticate the user, so we reject them!
-                       *
-                       *       This is fail-safe.
-                       */
-                       RDEBUG2("No authenticate method (Auth-Type) configuration found for the request: Rejecting the user");
-                       return -2;
-               }
-       }
-
-       switch(auth_type) {
-               case PW_AUTHTYPE_CRYPT:
-                       RDEBUG2("WARNING: Please update your configuration, and remove 'Auth-Type = Crypt'");
-                       RDEBUG2("WARNING: Use the PAP module instead.");
-
-                       /*
-                        *      Find the password sent by the user. It
-                        *      SHOULD be there, if it's not
-                        *      authentication fails.
-                        */
-                       auth_item = request->password;
-                       if (auth_item == NULL) {
-                               RDEBUG2("No User-Password or CHAP-Password attribute in the request");
-                               return -1;
-                       }
-
-                       if (password_pair == NULL) {
-                               RDEBUG2("No Crypt-Password configured for the user");
-                               rad_authlog("Login incorrect "
-                                       "(No Crypt-Password configured for the user)", request, 0);
-                               return -1;
-                       }
-
-                       switch (fr_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);
-                       case 1:
-                         return -1;
-                       }
-                       break;
-               case PW_AUTHTYPE_LOCAL:
-                       RDEBUG2("WARNING: Please update your configuration, and remove 'Auth-Type = Local'");
-                       RDEBUG2("WARNING: Use the PAP or CHAP modules instead.");
-
-                       /*
-                        *      Find the password sent by the user. It
-                        *      SHOULD be there, if it's not
-                        *      authentication fails.
-                        */
-                       auth_item = request->password;
-                       if (!auth_item)
-                               auth_item = pairfind(request->packet->vps,
-                                                    PW_CHAP_PASSWORD);
-                       if (!auth_item) {
-                               RDEBUG2("No User-Password or CHAP-Password attribute in the request.");
-                               RDEBUG2("Cannot perform authentication.");
-                               return -1;
-                       }
-
-                       /*
-                        *      Plain text password.
-                        */
-                       if (password_pair == NULL) {
-                               RDEBUG2("No \"known good\" password was configured for the user.");
-                               RDEBUG2("As a result, we cannot authenticate the user.");
-                               rad_authlog("Login incorrect "
-                                       "(No password configured for the user)", request, 0);
-                               return -1;
-                       }
-
-                       /*
-                        *      Local password is just plain text.
-                        */
-                       if (auth_item->attribute == PW_USER_PASSWORD) {
-                               if (strcmp((char *)password_pair->vp_strvalue,
-                                          (char *)auth_item->vp_strvalue) != 0) {
-                                       RDEBUG2("User-Password in the request does NOT match \"known good\" password.");
-                                       return -1;
-                               }
-                               RDEBUG2("User-Password in the request is correct.");
-                               break;
-
-                       } else if (auth_item->attribute != PW_CHAP_PASSWORD) {
-                               RDEBUG2("The user did not supply a User-Password or a CHAP-Password attribute");
-                               rad_authlog("Login incorrect "
-                                       "(no User-Password or CHAP-Password attribute)", request, 0);
-                               return -1;
-                       }
-
-                       rad_chap_encode(request->packet, my_chap,
-                                       auth_item->vp_octets[0], password_pair);
-
-                       /*
-                        *      Compare them
-                        */
-                       if (memcmp(my_chap + 1, auth_item->vp_strvalue + 1,
-                                  CHAP_VALUE_LENGTH) != 0) {
-                               RDEBUG2("CHAP-Password is incorrect.");
-                               return -1;
-                       }
-                       RDEBUG2("CHAP-Password is correct.");
-                       break;
-               default:
-                       /*
-                        *      See if there is a module that handles
-                        *      this type, and turn the RLM_ return
-                        *      status into the values as defined at
-                        *      the top of this function.
-                        */
-                       result = module_authenticate(auth_type, request);
-                       switch (result) {
-                               /*
-                                *      An authentication module FAIL
-                                *      return code, or any return code that
-                                *      is not expected from authentication,
-                                *      is the same as an explicit REJECT!
-                                */
-                               case RLM_MODULE_FAIL:
-                               case RLM_MODULE_INVALID:
-                               case RLM_MODULE_NOOP:
-                               case RLM_MODULE_NOTFOUND:
-                               case RLM_MODULE_REJECT:
-                               case RLM_MODULE_UPDATED:
-                               case RLM_MODULE_USERLOCK:
-                               default:
-                                       result = -1;
-                                       break;
-                               case RLM_MODULE_OK:
-                                       result = 0;
-                                       break;
-                               case RLM_MODULE_HANDLED:
-                                       result = 1;
-                                       break;
-                       }
-                       break;
-       }
-
-       return result;
-}
-
 /*
  *     Post-authentication step processes the response before it is
  *     sent to the NAS. It can receive both Access-Accept and Access-Reject
@@ -438,362 +105,3 @@ int rad_postauth(REQUEST *request)
        }
        return result;
 }
-
-/*
- *     Process and reply to an authentication request
- *
- *     The return value of this function isn't actually used right now, so
- *     it's not entirely clear if it is returning the right things. --Pac.
- */
-int rad_authenticate(REQUEST *request)
-{
-       VALUE_PAIR      *namepair;
-#ifdef WITH_SESSION_MGMT
-       VALUE_PAIR      *check_item;
-#endif
-       VALUE_PAIR      *auth_item = NULL;
-       VALUE_PAIR      *module_msg;
-       VALUE_PAIR      *tmp = NULL;
-       int             result;
-       const char      *password;
-       char            autz_retry = 0;
-       int             autz_type = 0;
-
-       password = "";
-
-#ifdef WITH_PROXY
-       /*
-        *      If this request got proxied to another server, we need
-        *      to check whether it authenticated the request or not.
-        */
-       if (request->proxy_reply) {
-               switch (request->proxy_reply->code) {
-               /*
-                *      Reply of ACCEPT means accept, thus set Auth-Type
-                *      accordingly.
-                */
-               case PW_AUTHENTICATION_ACK:
-                       tmp = radius_paircreate(request,
-                                               &request->config_items,
-                                               PW_AUTH_TYPE, PW_TYPE_INTEGER);
-                       if (tmp) tmp->vp_integer = PW_AUTHTYPE_ACCEPT;
-                       goto authenticate;
-
-               /*
-                *      Challenges are punted back to the NAS without any
-                *      further processing.
-                */
-               case PW_ACCESS_CHALLENGE:
-                       request->reply->code = PW_ACCESS_CHALLENGE;
-                       return RLM_MODULE_OK;
-               /*
-                *      ALL other replies mean reject. (this is fail-safe)
-                *
-                *      Do NOT do any authorization or authentication. They
-                *      are being rejected, so we minimize the amount of work
-                *      done by the server, by rejecting them here.
-                */
-               case PW_AUTHENTICATION_REJECT:
-               default:
-                       rad_authlog("Login incorrect (Home Server says so)",
-                                   request, 0);
-                       request->reply->code = PW_AUTHENTICATION_REJECT;
-                       return RLM_MODULE_REJECT;
-               }
-       }
-#endif
-
-       /*
-        *      Get the username from the request.
-        *
-        *      Note that namepair MAY be NULL, in which case there
-        *      is no User-Name attribute in the request.
-        */
-       namepair = request->username;
-
-       /*
-        *      Look for, and cache, passwords.
-        */
-       if (!request->password) {
-               request->password = pairfind(request->packet->vps,
-                                            PW_USER_PASSWORD);
-       }
-
-       /*
-        *      Discover which password we want to use.
-        */
-       auth_item = request->password;
-       if (auth_item) {
-               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) {
-                       password = "<CHAP-PASSWORD>";
-
-               } else {
-                       /*
-                        *      No password we recognize.
-                        */
-                       password = "<NO-PASSWORD>";
-               }
-       }
-       request->password = auth_item;
-
-       /*
-        *      Get the user's authorization information from the database
-        */
-autz_redo:
-       result = module_authorize(autz_type, request);
-       switch (result) {
-               case RLM_MODULE_NOOP:
-               case RLM_MODULE_NOTFOUND:
-               case RLM_MODULE_OK:
-               case RLM_MODULE_UPDATED:
-                       break;
-               case RLM_MODULE_HANDLED:
-                       return result;
-               case RLM_MODULE_FAIL:
-               case RLM_MODULE_INVALID:
-               case RLM_MODULE_REJECT:
-               case RLM_MODULE_USERLOCK:
-               default:
-                       if ((module_msg = pairfind(request->packet->vps,
-                                       PW_MODULE_FAILURE_MESSAGE)) != NULL) {
-                               char msg[MAX_STRING_LEN + 16];
-                               snprintf(msg, sizeof(msg), "Invalid user (%s)",
-                                        module_msg->vp_strvalue);
-                               rad_authlog(msg,request,0);
-                       } else {
-                               rad_authlog("Invalid user", request, 0);
-                       }
-                       request->reply->code = PW_AUTHENTICATION_REJECT;
-                       return result;
-       }
-       if (!autz_retry) {
-               tmp = pairfind(request->config_items, PW_AUTZ_TYPE);
-               if (tmp) {
-                       RDEBUG2("Using Autz-Type %s", tmp->vp_strvalue);
-                       autz_type = tmp->vp_integer;
-                       autz_retry = 1;
-                       goto autz_redo;
-               }
-       }
-
-       /*
-        *      If we haven't already proxied the packet, then check
-        *      to see if we should.  Maybe one of the authorize
-        *      modules has decided that a proxy should be used. If
-        *      so, get out of here and send the packet.
-        */
-       if (
-#ifdef WITH_PROXY
-           (request->proxy == NULL) &&
-#endif
-           ((tmp = pairfind(request->config_items, PW_PROXY_TO_REALM)) != NULL)) {
-               REALM *realm;
-
-               realm = realm_find2(tmp->vp_strvalue);
-
-               /*
-                *      Don't authenticate, as the request is going to
-                *      be proxied.
-                */
-               if (realm && realm->auth_pool) {
-                       return RLM_MODULE_OK;
-               }
-
-               /*
-                *      Catch users who set Proxy-To-Realm to a LOCAL
-                *      realm (sigh).  But don't complain if it is
-                *      *the* LOCAL realm.
-                */
-               if (realm &&(strcmp(realm->name, "LOCAL") != 0)) {
-                       RDEBUG2("WARNING: You set Proxy-To-Realm = %s, but it is a LOCAL realm!  Cancelling proxy request.", realm->name);
-               }
-
-               if (!realm) {
-                       RDEBUG2("WARNING: You set Proxy-To-Realm = %s, but the realm does not exist!  Cancelling invalid proxy request.", tmp->vp_strvalue);
-               }
-       }
-
-#ifdef WITH_PROXY
- authenticate:
-#endif
-
-       /*
-        *      Perhaps there is a Stripped-User-Name now.
-        */
-       namepair = request->username;
-
-       /*
-        *      Validate the user
-        */
-       do {
-               result = rad_check_password(request);
-               if (result > 0) {
-                       /* don't reply! */
-                       return RLM_MODULE_HANDLED;
-               }
-       } while(0);
-
-       /*
-        *      Failed to validate the user.
-        *
-        *      We PRESUME that the code which failed will clean up
-        *      request->reply->vps, to be ONLY the reply items it
-        *      wants to send back.
-        */
-       if (result < 0) {
-               RDEBUG2("Failed to authenticate the user.");
-               request->reply->code = PW_AUTHENTICATION_REJECT;
-
-               if ((module_msg = pairfind(request->packet->vps,PW_MODULE_FAILURE_MESSAGE)) != NULL){
-                       char msg[MAX_STRING_LEN+19];
-
-                       snprintf(msg, sizeof(msg), "Login incorrect (%s)",
-                                module_msg->vp_strvalue);
-                       rad_authlog(msg, request, 0);
-               } else {
-                       rad_authlog("Login incorrect", request, 0);
-               }
-
-               /* double check: maybe the secret is wrong? */
-               if ((debug_flag > 1) && (auth_item != NULL) &&
-                               (auth_item->attribute == PW_USER_PASSWORD)) {
-                       char *p;
-
-                       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!");
-                                       break;
-                               }
-                               p++;
-                       }
-               }
-       }
-
-#ifdef WITH_SESSION_MGMT
-       if (result >= 0 &&
-           (check_item = pairfind(request->config_items, PW_SIMULTANEOUS_USE)) != NULL) {
-               int r, session_type = 0;
-               char            logstr[1024];
-               char            umsg[MAX_STRING_LEN + 1];
-               const char      *user_msg = NULL;
-
-               tmp = pairfind(request->config_items, PW_SESSION_TYPE);
-               if (tmp) {
-                       RDEBUG2("Using Session-Type %s", tmp->vp_strvalue);
-                       session_type = tmp->vp_integer;
-               }
-
-               /*
-                *      User authenticated O.K. Now we have to check
-                *      for the Simultaneous-Use parameter.
-                */
-               if (namepair &&
-                   (r = module_checksimul(session_type, request, check_item->vp_integer)) != 0) {
-                       char mpp_ok = 0;
-
-                       if (r == 2){
-                               /* Multilink attempt. Check if port-limit > simultaneous-use */
-                               VALUE_PAIR *port_limit;
-
-                               if ((port_limit = pairfind(request->reply->vps, PW_PORT_LIMIT)) != NULL &&
-                                       port_limit->vp_integer > check_item->vp_integer){
-                                       RDEBUG2("MPP is OK");
-                                       mpp_ok = 1;
-                               }
-                       }
-                       if (!mpp_ok){
-                               if (check_item->vp_integer > 1) {
-                               snprintf(umsg, sizeof(umsg),
-                                                       "\r\nYou are already logged in %d times  - access denied\r\n\n",
-                                                       (int)check_item->vp_integer);
-                                       user_msg = umsg;
-                               } else {
-                                       user_msg = "\r\nYou are already logged in - access denied\r\n\n";
-                               }
-
-                               request->reply->code = PW_AUTHENTICATION_REJECT;
-
-                               /*
-                                *      They're trying to log in too many times.
-                                *      Remove ALL reply attributes.
-                                */
-                               pairfree(&request->reply->vps);
-                               radius_pairmake(request, &request->reply->vps,
-                                               "Reply-Message",
-                                               user_msg, T_OP_SET);
-
-                               snprintf(logstr, sizeof(logstr), "Multiple logins (max %d) %s",
-                                       check_item->vp_integer,
-                                       r == 2 ? "[MPP attempt]" : "");
-                               rad_authlog(logstr, request, 1);
-
-                               result = -1;
-                       }
-               }
-       }
-#endif
-
-       /*
-        *      Result should be >= 0 here - if not, it means the user
-        *      is rejected, so we just process post-auth and return.
-        */
-       if (result < 0) {
-               return RLM_MODULE_REJECT;
-       }
-
-       /*
-        *      Add the port number to the Framed-IP-Address if
-        *      vp->addport is set.
-        */
-       if (((tmp = pairfind(request->reply->vps,
-                            PW_FRAMED_IP_ADDRESS)) != NULL) &&
-           (tmp->flags.addport != 0)) {
-               VALUE_PAIR *vpPortId;
-
-               /*
-                *  Find the NAS port ID.
-                */
-               if ((vpPortId = pairfind(request->packet->vps,
-                                        PW_NAS_PORT)) != NULL) {
-                 unsigned long tvalue = ntohl(tmp->vp_integer);
-                 tmp->vp_integer = htonl(tvalue + vpPortId->vp_integer);
-                 tmp->flags.addport = 0;
-                 ip_ntoa(tmp->vp_strvalue, tmp->vp_integer);
-               } else {
-                       RDEBUG2("WARNING: No NAS-Port attribute in request.  CANNOT return a Framed-IP-Address + NAS-Port.\n");
-                       pairdelete(&request->reply->vps, PW_FRAMED_IP_ADDRESS);
-               }
-       }
-
-       /*
-        *      Set the reply to Access-Accept, if it hasn't already
-        *      been set to something.  (i.e. Access-Challenge)
-        */
-       if (request->reply->code == 0)
-         request->reply->code = PW_AUTHENTICATION_ACK;
-
-       if ((module_msg = pairfind(request->packet->vps,PW_MODULE_SUCCESS_MESSAGE)) != NULL){
-               char msg[MAX_STRING_LEN+12];
-
-               snprintf(msg, sizeof(msg), "Login OK (%s)",
-                        module_msg->vp_strvalue);
-               rad_authlog(msg, request, 1);
-       } else {
-               rad_authlog("Login OK", request, 1);
-       }
-
-       /*
-        *      Run the modules in the 'post-auth' section.
-        */
-       result = rad_postauth(request);
-
-       return result;
-}
index 2250ec9..67451f9 100644 (file)
@@ -79,6 +79,7 @@ static pthread_t NO_SUCH_CHILD_PID;
 #define PTHREAD_MUTEX_UNLOCK(_x)
 int thread_pool_addrequest(REQUEST *request, RAD_REQUEST_FUNP fun)
 {
+       request->process = fun;
        radius_handle_request(request, fun);
        return 1;
 }
@@ -493,7 +494,7 @@ static void debug_packet(REQUEST *request, RADIUS_PACKET *packet, int direction)
        const fr_ipaddr_t *ip;
        int port;
 
-       if (!packet) return;
+       if (!packet || (packet->code == 0)) return;
 
        if (direction == 0) {
                received = "Received";
@@ -1350,7 +1351,6 @@ static int proxy_request(REQUEST *request)
 static int proxy_to_virtual_server(REQUEST *request)
 {
        REQUEST *fake;
-       RAD_REQUEST_FUNP fun;
 
        if (!request->home_server || !request->home_server->server) return 0;
 
@@ -1368,21 +1368,19 @@ static int proxy_to_virtual_server(REQUEST *request)
        fake->packet->vps = paircopy(request->proxy->vps);
        fake->server = request->home_server->server;
 
-       if (request->proxy->code == PW_AUTHENTICATION_REQUEST) {
-               fun = rad_authenticate;
-
+       if ((request->proxy->code != PW_AUTHENTICATION_REQUEST)
 #ifdef WITH_ACCOUNTING
-       } else if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
-               fun = rad_accounting;
+           && (request->proxy->code == PW_ACCOUNTING_REQUEST)
 #endif
-
-       } else {
+               ) {
                RDEBUG2("Unknown packet type %d", request->proxy->code);
                return 0;
        }
 
+       rad_assert(request->process != NULL);
+
        RDEBUG2(">>> Sending proxied request internally to virtual server.");
-       radius_handle_request(fake, fun);
+       radius_handle_request(fake, request->process);
        RDEBUG2("<<< Received proxied response from internal virtual server.");
 
        request->proxy_reply = fake->reply;
@@ -1391,7 +1389,11 @@ static int proxy_to_virtual_server(REQUEST *request)
        request_free(&fake);
 
        process_proxy_reply(request);
-       fun(request);
+
+       /*
+        *      And do all of this again...
+        */
+       request->process(request);
 
        return 2;               /* success, but NOT '1' !*/
 }
@@ -1835,18 +1837,8 @@ static void request_post_handler(REQUEST *request)
                break;
        }
 
-       /*
-        *      Suppress "no reply" packets here, unless we're reading
-        *      from the "detail" file.  In that case, we've got to
-        *      tell the detail file handler that the request is dead,
-        *      and it should re-send it.
-        *      If configured, encode, sign, and send.
-        */
-       if ((request->reply->code != 0) ||
-           (request->listener->type == RAD_LISTEN_DETAIL)) {
-               DEBUG_PACKET(request, request->reply, 1);
-               request->listener->send(request->listener, request);
-       }
+       DEBUG_PACKET(request, request->reply, 1);
+       request->listener->send(request->listener, request);
 
        /*
         *      Clean up.  These are no longer needed.
@@ -2297,16 +2289,6 @@ REQUEST *received_proxy_response(RADIUS_PACKET *packet)
        home_server     *home;
        REQUEST         *request;
 
-       if (!home_server_find(&packet->src_ipaddr, packet->src_port)) {
-               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 NULL;
-       }
-
        /*
         *      Also removes from the proxy hash if responses == requests
         */
@@ -2561,7 +2543,11 @@ static void handle_signal_self(int flag)
 
                        if (this->type != RAD_LISTEN_DETAIL) continue;
                        
-                       delay = detail_delay(this);
+                       /*
+                        *      FIXME: HORRIBLE hack!  We really need
+                        *      a separate callback for this!
+                        */
+                       delay = this->encode(this, NULL);
                        if (!delay) continue;
 
                        fr_event_now(el, &now);
index 1e07e4f..13c276b 100644 (file)
@@ -26,12 +26,8 @@ RCSID("$Id$")
 
 #include <freeradius-devel/radiusd.h>
 #include <freeradius-devel/modules.h>
+#include <freeradius-devel/modpriv.h>
 #include <freeradius-devel/rad_assert.h>
-#include <freeradius-devel/vqp.h>
-#include <freeradius-devel/dhcp.h>
-
-#include <freeradius-devel/vmps.h>
-#include <freeradius-devel/detail.h>
 
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
@@ -45,37 +41,6 @@ RCSID("$Id$")
 #include <fcntl.h>
 #endif
 
-
-/*
- *     We'll use this below.
- */
-typedef int (*rad_listen_parse_t)(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_print_t      print;
-       rad_listen_encode_t     encode;
-       rad_listen_decode_t     decode;
-} rad_listen_master_t;
-
-typedef struct listen_socket_t {
-       /*
-        *      For normal sockets.
-        */
-       fr_ipaddr_t     ipaddr;
-       int             port;
-#ifdef SO_BINDTODEVICE
-       const char              *interface;
-#endif
-       RADCLIENT_LIST  *clients;
-} listen_socket_t;
-
-static rad_listen_t *listen_alloc(RAD_LISTEN_TYPE type);
-
 /*
  *     Find a per-socket client.
  */
@@ -297,11 +262,11 @@ static int listen_bind(rad_listen_t *this);
 
 
 /*
- *     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.
+ *     Process and reply to a server-status request.  This function
+ *     should likely live in it's own file but it's so small we don't
+ *     bother.
  */
-static int rad_status_server(REQUEST *request)
+int rad_status_server(REQUEST *request)
 {
        int rcode = RLM_MODULE_OK;
        DICT_VALUE *dval;
@@ -362,21 +327,11 @@ static int rad_status_server(REQUEST *request)
                return 0;
        }
 
-#ifdef WITH_STATS
-       /*
-        *      Full statistics are available only on a statistics
-        *      socket.
-        */
-       if (request->listener->type == RAD_LISTEN_NONE) {
-               request_stats_reply(request);
-       }
-#endif
-
        return 0;
 }
 
 
-static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
+int listen_socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
 {
        size_t len;
        listen_socket_t *sock = this->data;
@@ -463,7 +418,7 @@ static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
 /*
  *     Parse an authentication or accounting socket.
  */
-static int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
+int listen_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
 {
        int             rcode;
        int             listen_port;
@@ -612,479 +567,6 @@ static int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
        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);
-
-       return rad_send(request->reply, request->packet,
-                       request->client->secret);
-}
-
-
-#ifdef WITH_ACCOUNTING
-/*
- *     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->client->secret);
-}
-#endif
-
-#ifdef WITH_PROXY
-/*
- *     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->home_server->secret);
-}
-#endif
-
-#ifdef WITH_STATS
-/*
- *     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 stats_socket_recv(rad_listen_t *listener,
-                           RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
-{
-       ssize_t         rcode;
-       int             code, src_port;
-       RADIUS_PACKET   *packet;
-       RADCLIENT       *client;
-       fr_ipaddr_t     src_ipaddr;
-
-       rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
-       if (rcode < 0) return 0;
-
-       RAD_STATS_TYPE_INC(listener, total_requests);
-
-       if (rcode < 20) {       /* AUTH_HDR_LEN */
-               RAD_STATS_TYPE_INC(listener, total_malformed_requests);
-               return 0;
-       }
-
-       if ((client = client_listener_find(listener,
-                                          &src_ipaddr, src_port)) == NULL) {
-               rad_recv_discard(listener->fd);
-               RAD_STATS_TYPE_INC(listener, total_invalid_requests);
-               return 0;
-       }
-
-       /*
-        *      We only understand Status-Server on this socket.
-        */
-       if (code != PW_STATUS_SERVER) {
-               DEBUG("Ignoring packet code %d sent to Status-Server port",
-                     code);
-               rad_recv_discard(listener->fd);
-               RAD_STATS_TYPE_INC(listener, total_unknown_types);
-               RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
-               return 0;
-       }
-
-       /*
-        *      Now that we've sanity checked everything, receive the
-        *      packet.
-        */
-       packet = rad_recv(listener->fd, 1); /* require message authenticator */
-       if (!packet) {
-               RAD_STATS_TYPE_INC(listener, total_malformed_requests);
-               DEBUG("%s", fr_strerror());
-               return 0;
-       }
-
-       if (!received_request(listener, packet, prequest, client)) {
-               RAD_STATS_TYPE_INC(listener, total_packets_dropped);
-               RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
-               rad_free(&packet);
-               return 0;
-       }
-
-       *pfun = rad_status_server;
-       return 1;
-}
-#endif
-
-
-/*
- *     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)
-{
-       ssize_t         rcode;
-       int             code, src_port;
-       RADIUS_PACKET   *packet;
-       RAD_REQUEST_FUNP fun = NULL;
-       RADCLIENT       *client;
-       fr_ipaddr_t     src_ipaddr;
-
-       rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
-       if (rcode < 0) return 0;
-
-       RAD_STATS_TYPE_INC(listener, total_requests);
-
-       if (rcode < 20) {       /* AUTH_HDR_LEN */
-               RAD_STATS_TYPE_INC(listener, total_malformed_requests);
-               return 0;
-       }
-
-       if ((client = client_listener_find(listener,
-                                          &src_ipaddr, src_port)) == NULL) {
-               rad_recv_discard(listener->fd);
-               RAD_STATS_TYPE_INC(listener, total_invalid_requests);
-               return 0;
-       }
-
-       /*
-        *      Some sanity checks, based on the packet code.
-        */
-       switch(code) {
-       case PW_AUTHENTICATION_REQUEST:
-               RAD_STATS_CLIENT_INC(listener, client, total_requests);
-               fun = rad_authenticate;
-               break;
-
-       case PW_STATUS_SERVER:
-               if (!mainconfig.status_server) {
-                       rad_recv_discard(listener->fd);
-                       RAD_STATS_TYPE_INC(listener, total_packets_dropped);
-                       RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
-                       DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
-                       return 0;
-               }
-               fun = rad_status_server;
-               break;
-
-       default:
-               rad_recv_discard(listener->fd);
-               RAD_STATS_INC(radius_auth_stats.total_unknown_types);
-               RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
-
-               DEBUG("Invalid packet code %d sent to authentication port from client %s port %d : IGNORED",
-                     code, client->shortname, src_port);
-               return 0;
-               break;
-       } /* switch over packet types */
-
-       /*
-        *      Now that we've sanity checked everything, receive the
-        *      packet.
-        */
-       packet = rad_recv(listener->fd, client->message_authenticator);
-       if (!packet) {
-               RAD_STATS_TYPE_INC(listener, total_malformed_requests);
-               DEBUG("%s", fr_strerror());
-               return 0;
-       }
-
-       if (!received_request(listener, packet, prequest, client)) {
-               RAD_STATS_TYPE_INC(listener, total_packets_dropped);
-               RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
-               rad_free(&packet);
-               return 0;
-       }
-
-       *pfun = fun;
-       return 1;
-}
-
-
-#ifdef WITH_ACCOUNTING
-/*
- *     Receive packets from an accounting socket
- */
-static int acct_socket_recv(rad_listen_t *listener,
-                           RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
-{
-       ssize_t         rcode;
-       int             code, src_port;
-       RADIUS_PACKET   *packet;
-       RAD_REQUEST_FUNP fun = NULL;
-       RADCLIENT       *client;
-       fr_ipaddr_t     src_ipaddr;
-
-       rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
-       if (rcode < 0) return 0;
-
-       RAD_STATS_TYPE_INC(listener, total_requests);
-
-       if (rcode < 20) {       /* AUTH_HDR_LEN */
-               RAD_STATS_TYPE_INC(listener, total_malformed_requests);
-               return 0;
-       }
-
-       if ((client = client_listener_find(listener,
-                                          &src_ipaddr, src_port)) == NULL) {
-               rad_recv_discard(listener->fd);
-               RAD_STATS_TYPE_INC(listener, total_invalid_requests);
-               return 0;
-       }
-
-       /*
-        *      Some sanity checks, based on the packet code.
-        */
-       switch(code) {
-       case PW_ACCOUNTING_REQUEST:
-               RAD_STATS_CLIENT_INC(listener, client, total_requests);
-               fun = rad_accounting;
-               break;
-
-       case PW_STATUS_SERVER:
-               if (!mainconfig.status_server) {
-                       rad_recv_discard(listener->fd);
-                       RAD_STATS_TYPE_INC(listener, total_packets_dropped);
-                       RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
-
-                       DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
-                       return 0;
-               }
-               fun = rad_status_server;
-               break;
-
-       default:
-               rad_recv_discard(listener->fd);
-               RAD_STATS_TYPE_INC(listener, total_unknown_types);
-               RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
-
-               DEBUG("Invalid packet code %d sent to a accounting port from client %s port %d : IGNORED",
-                     code, client->shortname, src_port);
-               return 0;
-       } /* switch over packet types */
-
-       /*
-        *      Now that we've sanity checked everything, receive the
-        *      packet.
-        */
-       packet = rad_recv(listener->fd, 0);
-       if (!packet) {
-               RAD_STATS_TYPE_INC(listener, total_malformed_requests);
-               radlog(L_ERR, "%s", fr_strerror());
-               return 0;
-       }
-
-       /*
-        *      There can be no duplicate accounting packets.
-        */
-       if (!received_request(listener, packet, prequest, client)) {
-               RAD_STATS_TYPE_INC(listener, total_packets_dropped);
-               RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
-               rad_free(&packet);
-               return 0;
-       }
-
-       *pfun = fun;
-       return 1;
-}
-#endif
-
-#ifdef WITH_PROXY
-/*
- *     Recieve packets from a proxy socket.
- */
-static int proxy_socket_recv(rad_listen_t *listener,
-                             RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
-{
-       REQUEST         *request;
-       RADIUS_PACKET   *packet;
-       RAD_REQUEST_FUNP fun = NULL;
-       char            buffer[128];
-
-       packet = rad_recv(listener->fd, 0);
-       if (!packet) {
-               radlog(L_ERR, "%s", fr_strerror());
-               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;
-
-#ifdef WITH_ACCOUNTING
-       case PW_ACCOUNTING_RESPONSE:
-               fun = rad_accounting;
-               break;
-#endif
-
-       default:
-               /*
-                *      FIXME: Update MIB for packet types?
-                */
-               radlog(L_ERR, "Invalid packet code %d sent to a proxy port "
-                      "from home server %s port %d - ID %d : IGNORED",
-                      packet->code,
-                      ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
-                      packet->src_port, packet->id);
-               rad_free(&packet);
-               return 0;
-       }
-
-       request = received_proxy_response(packet);
-       if (!request) {
-               return 0;
-       }
-
-       rad_assert(fun != NULL);
-       *pfun = fun;
-       *prequest = request;
-
-       return 1;
-}
-#endif
-
-
-static int client_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
-{
-       if (!request->reply->code) return 0;
-
-       rad_encode(request->reply, request->packet,
-                  request->client->secret);
-       rad_sign(request->reply, request->packet,
-                request->client->secret);
-
-       return 0;
-}
-
-
-static int client_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
-{
-       if (rad_verify(request->packet, NULL,
-                      request->client->secret) < 0) {
-               return -1;
-       }
-
-       return rad_decode(request->packet, NULL,
-                         request->client->secret);
-}
-
-#ifdef WITH_PROXY
-static int proxy_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
-{
-       rad_encode(request->proxy, NULL, request->home_server->secret);
-       rad_sign(request->proxy, NULL, request->home_server->secret);
-
-       return 0;
-}
-
-
-static int proxy_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
-{
-       if (rad_verify(request->proxy_reply, request->proxy,
-                      request->home_server->secret) < 0) {
-               return -1;
-       }
-
-       return rad_decode(request->proxy_reply, request->proxy,
-                          request->home_server->secret);
-}
-#endif
-
-#include "dhcpd.c"
-
-#include "command.c"
-
-static const rad_listen_master_t master_listen[RAD_LISTEN_MAX] = {
-#ifdef WITH_STATS
-       { common_socket_parse, NULL,
-         stats_socket_recv, auth_socket_send,
-         socket_print, client_socket_encode, client_socket_decode },
-#else
-       /*
-        *      This always gets defined.
-        */
-       { NULL, NULL, NULL, NULL, NULL, NULL, NULL},    /* RAD_LISTEN_NONE */
-#endif
-
-#ifdef WITH_PROXY
-       /* proxying */
-       { common_socket_parse, NULL,
-         proxy_socket_recv, proxy_socket_send,
-         socket_print, proxy_socket_encode, proxy_socket_decode },
-#endif
-
-       /* authentication */
-       { common_socket_parse, NULL,
-         auth_socket_recv, auth_socket_send,
-         socket_print, client_socket_encode, client_socket_decode },
-
-#ifdef WITH_ACCOUNTING
-       /* accounting */
-       { common_socket_parse, NULL,
-         acct_socket_recv, acct_socket_send,
-         socket_print, client_socket_encode, client_socket_decode},
-#endif
-
-#ifdef WITH_DETAIL
-       /* detail */
-       { detail_parse, detail_free,
-         detail_recv, detail_send,
-         detail_print, detail_encode, detail_decode },
-#endif
-
-#ifdef WITH_VMPS
-       /* vlan query protocol */
-       { common_socket_parse, NULL,
-         vqp_socket_recv, vqp_socket_send,
-         socket_print, vqp_socket_encode, vqp_socket_decode },
-#endif
-
-#ifdef WITH_DHCP
-       /* dhcp query protocol */
-       { dhcp_socket_parse, NULL,
-         dhcp_socket_recv, dhcp_socket_send,
-         socket_print, dhcp_socket_encode, dhcp_socket_decode },
-#endif
-
-#ifdef WITH_COMMAND_SOCKET
-       /* TCP command socket */
-       { command_socket_parse, NULL,
-         command_domain_accept, command_domain_send,
-         command_socket_print, command_socket_encode, command_socket_decode },
-#endif
-
-};
-
-
 
 /*
  *     Binds a listener to a socket.
@@ -1263,21 +745,51 @@ static int listen_bind(rad_listen_t *this)
 /*
  *     Allocate & initialize a new listener.
  */
-static rad_listen_t *listen_alloc(RAD_LISTEN_TYPE type)
+rad_listen_t *listen_alloc(const char *type_name)
 {
        rad_listen_t *this;
+       const frs_module_t *frs;
+       lt_dlhandle handle;
+       char buffer[256];
 
        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->print = master_listen[this->type].print;
-       this->encode = master_listen[this->type].encode;
-       this->decode = master_listen[this->type].decode;
+       snprintf(buffer, sizeof(buffer), "frs_%s", type_name);
+       
+       handle = lt_dlopenext(buffer);
+       if (!handle) {
+               radlog(L_ERR, "Failed opening %s: %s",
+                      type_name, lt_dlerror());
+               return NULL;
+       }
+       
+       frs = lt_dlsym(handle, buffer);
+       if (!frs) {
+               radlog(L_ERR, "Failed linking to %s: %s",
+                      type_name, lt_dlerror());
+               return NULL;
+       }
+       
+       if (frs->magic != FRS_MODULE_MAGIC_NUMBER) {
+               radlog(L_ERR, "Invalid version in %s\n",
+                      type_name);
+               return NULL;
+       }
+       
+       /*
+        *      FIXME: handle is leaked.
+        */
+
+       this->type = frs->type;
+       this->frs = frs;
+       this->recv = frs->recv;
+       this->send = frs->send;
+       this->print = frs->print;
+       this->encode = frs->encode;
+       this->decode = frs->decode;
 
-       switch (type) {
+       switch (this->type) {
 #ifdef WITH_STATS
        case RAD_LISTEN_NONE:
 #endif
@@ -1305,9 +817,10 @@ static rad_listen_t *listen_alloc(RAD_LISTEN_TYPE type)
 #endif
 
 #ifdef WITH_COMMAND_SOCKET
+       /*
+        *      The data here is allocate in the "parse" section.
+        */
        case RAD_LISTEN_COMMAND:
-               this->data = rad_malloc(sizeof(fr_command_socket_t));
-               memset(this->data, 0, sizeof(fr_command_socket_t));
                break;
 #endif
 
@@ -1335,7 +848,8 @@ rad_listen_t *proxy_new_listener()
        rad_listen_t *this, *tmp, **last;
        listen_socket_t *sock, *old;
 
-       this = listen_alloc(RAD_LISTEN_PROXY);
+       this = listen_alloc("proxy");
+       if (!this) return NULL;
 
        /*
         *      Find an existing proxy socket to copy.
@@ -1391,36 +905,10 @@ rad_listen_t *proxy_new_listener()
 }
 #endif
 
-static const FR_NAME_NUMBER listen_compare[] = {
-#ifdef WITH_STATS
-       { "status",     RAD_LISTEN_NONE },
-#endif
-       { "auth",       RAD_LISTEN_AUTH },
-#ifdef WITH_ACCOUNTING
-       { "acct",       RAD_LISTEN_ACCT },
-#endif
-#ifdef WITH_DETAIL
-       { "detail",     RAD_LISTEN_DETAIL },
-#endif
-#ifdef WITH_PROXY
-       { "proxy",      RAD_LISTEN_PROXY },
-#endif
-#ifdef WITH_VMPS
-       { "vmps",       RAD_LISTEN_VQP },
-#endif
-#ifdef WITH_DHCP
-       { "dhcp",       RAD_LISTEN_DHCP },
-#endif
-#ifdef WITH_COMMAND_SOCKET
-       { "control",    RAD_LISTEN_COMMAND },
-#endif
-       { NULL, 0 },
-};
-
 
 static rad_listen_t *listen_parse(CONF_SECTION *cs, const char *server)
 {
-       int             type, rcode;
+       int             rcode;
        char            *listen_type;
        rad_listen_t    *this;
 
@@ -1438,16 +926,6 @@ static rad_listen_t *listen_parse(CONF_SECTION *cs, const char *server)
                return NULL;
        }
 
-       type = fr_str2int(listen_compare, listen_type, -1);
-       if (type < 0) {
-               cf_log_err(cf_sectiontoitem(cs),
-                          "Invalid type \"%s\" in listen section.",
-                          listen_type);
-               free(listen_type);
-               return NULL;
-       }
-       free(listen_type);
-       
        /*
         *      Allow listen sections in the default config to
         *      refer to a server.
@@ -1459,20 +937,26 @@ static rad_listen_t *listen_parse(CONF_SECTION *cs, const char *server)
                        rcode = cf_item_parse(cs, "server", PW_TYPE_STRING_PTR,
                                              &server, NULL);
                }
-               if (rcode < 0) return NULL;
+               if (rcode < 0) {
+                       free(listen_type);
+                       return NULL;
+               }
        }
 
        /*
         *      Set up cross-type data.
         */
-       this = listen_alloc(type);
+       this = listen_alloc(listen_type);
+       if (!this) return NULL;
+
+       free(listen_type);
        this->server = server;
        this->fd = -1;
 
        /*
         *      Call per-type parser.
         */
-       if (master_listen[type].parse(cs, this) < 0) {
+       if (this->frs->parse(cs, this) < 0) {
                listen_free(&this);
                return NULL;
        }
@@ -1544,11 +1028,15 @@ int listen_init(CONF_SECTION *config, rad_listen_t **head)
        bind_it:
 #ifdef WITH_VMPS
                if (strcmp(progname, "vmpsd") == 0) {
-                       this = listen_alloc(RAD_LISTEN_VQP);
+                       this = listen_alloc("vmps");
+                       if (!this) return 0;    /* FIXME: memleak? */
                        if (!auth_port) auth_port = 1589;
                } else
 #endif
-                       this = listen_alloc(RAD_LISTEN_AUTH);
+               {
+                       this = listen_alloc("auth");
+                       if (!this) return 0;    /* FIXME: memleak? */
+               }
 
                sock = this->data;
 
@@ -1592,7 +1080,8 @@ int listen_init(CONF_SECTION *config, rad_listen_t **head)
                 *      If we haven't already gotten acct_port from
                 *      /etc/services, then make it auth_port + 1.
                 */
-               this = listen_alloc(RAD_LISTEN_ACCT);
+               this = listen_alloc("acct");
+               if (!this) return 0;    /* FIXME: memleak? */
                sock = this->data;
 
                /*
@@ -1772,7 +1261,8 @@ int listen_init(CONF_SECTION *config, rad_listen_t **head)
                        server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
                }
 
-               this = listen_alloc(RAD_LISTEN_PROXY);
+               this = listen_alloc("proxy");
+               if (!this) return 0;    /* FIXME: memleak? */
                sock = this->data;
 
                /*
@@ -1825,8 +1315,8 @@ void listen_free(rad_listen_t **head)
                 */
                if (this->fd >= 0) close(this->fd);
 
-               if (master_listen[this->type].free) {
-                       master_listen[this->type].free(this);
+               if (this->frs->free) {
+                       this->frs->free(this);
                }
                free(this->data);
                free(this);
@@ -1836,48 +1326,3 @@ void listen_free(rad_listen_t **head)
 
        *head = NULL;
 }
-
-#ifdef WITH_STATS
-RADCLIENT_LIST *listener_find_client_list(const fr_ipaddr_t *ipaddr,
-                                         int port)
-{
-       rad_listen_t *this;
-
-       for (this = mainconfig.listen; this != NULL; this = this->next) {
-               listen_socket_t *sock;
-
-               if ((this->type != RAD_LISTEN_AUTH) &&
-                   (this->type != RAD_LISTEN_ACCT)) continue;
-               
-               sock = this->data;
-
-               if ((sock->port == port) &&
-                   (fr_ipaddr_cmp(ipaddr, &sock->ipaddr) == 0)) {
-                       return sock->clients;
-               }
-       }
-
-       return NULL;
-}
-
-rad_listen_t *listener_find_byipaddr(const fr_ipaddr_t *ipaddr, int port)
-{
-       rad_listen_t *this;
-
-       for (this = mainconfig.listen; this != NULL; this = this->next) {
-               listen_socket_t *sock;
-
-               if ((this->type != RAD_LISTEN_AUTH) &&
-                   (this->type != RAD_LISTEN_ACCT)) continue;
-               
-               sock = this->data;
-
-               if ((sock->port == port) &&
-                   (fr_ipaddr_cmp(ipaddr, &sock->ipaddr) == 0)) {
-                       return this;
-               }
-       }
-
-       return NULL;
-}
-#endif
index 5d49861..d516d79 100644 (file)
@@ -33,6 +33,57 @@ RCSID("$Id$")
 
 #ifdef WITH_SESSION_MGMT
 /*
+ *     Copied from rad_accounting, with edits.  i.e. We don't proxy
+ *     these packets.
+ */
+static int session_accounting(REQUEST *request)
+{
+       int result = RLM_MODULE_OK;
+       VALUE_PAIR      *vp;
+       int             acct_type = 0;
+
+       result = module_preacct(request);
+       switch (result) {
+               /*
+                *      The module has a number of OK return codes.
+                */
+       case RLM_MODULE_NOOP:
+       case RLM_MODULE_OK:
+       case RLM_MODULE_UPDATED:
+               break;
+
+               /*
+                *      Something went wrong: stop.
+                */
+       case RLM_MODULE_FAIL:
+       case RLM_MODULE_INVALID:
+       case RLM_MODULE_NOTFOUND:
+       case RLM_MODULE_REJECT:
+       case RLM_MODULE_USERLOCK:
+       case RLM_MODULE_HANDLED:
+       default:
+               return result;
+       }
+       
+       /*
+        *      Run Acct-Type.
+        */
+       vp = pairfind(request->config_items, PW_ACCT_TYPE);
+       if (vp) {
+               DEBUG2("  Found Acct-Type %s", vp->vp_strvalue);
+               acct_type = vp->vp_integer;
+       }
+       result = module_accounting(acct_type, request);
+
+       /*
+        *      Don't bother setting reply code: it's a fake packet.
+        *      Don't bother proxying it.  It's a fake packet.
+        */
+       
+       return result;
+}
+
+/*
  *     End a session by faking a Stop packet to all accounting modules.
  */
 int session_zap(REQUEST *request, uint32_t nasaddr, unsigned int port,
@@ -101,7 +152,7 @@ int session_zap(REQUEST *request, uint32_t nasaddr, unsigned int port,
        stopreq->username = userpair;
        stopreq->password = NULL;
 
-       ret = rad_accounting(stopreq);
+       ret = session_accounting(stopreq);
 
        /*
         *  We've got to clean it up by hand, because no one else will.
index a99a43b..208e32e 100644 (file)
@@ -30,13 +30,12 @@ RCSID("$Id$")
 #ifdef WITH_STATS
 
 #define USEC (1000000)
-#define EMA_SCALE (100)
 #define PREC (USEC * EMA_SCALE)
 
 #define F_EMA_SCALE (1000000)
 
-static struct timeval  start_time;
-static struct timeval  hup_time;
+struct timeval radius_start_time;
+struct timeval radius_hup_time;
 
 fr_stats_t radius_auth_stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 #ifdef WITH_ACCOUNTING
@@ -189,449 +188,13 @@ void request_stats_final(REQUEST *request)
        request->master_state = REQUEST_COUNTED;
 }
 
-typedef struct fr_stats2vp {
-       int     attribute;
-       size_t  offset;
-} fr_stats2vp;
-
-/*
- *     Authentication
- */
-static fr_stats2vp authvp[] = {
-       { 128, offsetof(fr_stats_t, total_requests) },
-       { 129, offsetof(fr_stats_t, total_access_accepts) },
-       { 130, offsetof(fr_stats_t, total_access_rejects) },
-       { 131, offsetof(fr_stats_t, total_access_challenges) },
-       { 132, offsetof(fr_stats_t, total_responses) },
-       { 133, offsetof(fr_stats_t, total_dup_requests) },
-       { 134, offsetof(fr_stats_t, total_malformed_requests) },
-       { 135, offsetof(fr_stats_t, total_bad_authenticators) },
-       { 136, offsetof(fr_stats_t, total_packets_dropped) },
-       { 137, offsetof(fr_stats_t, total_unknown_types) },
-       { 0, 0 }
-};
-
-
-#ifdef WITH_PROXY
-/*
- *     Proxied authentication requests.
- */
-static fr_stats2vp proxy_authvp[] = {
-       { 138, offsetof(fr_stats_t, total_requests) },
-       { 139, offsetof(fr_stats_t, total_access_accepts) },
-       { 140, offsetof(fr_stats_t, total_access_rejects) },
-       { 141, offsetof(fr_stats_t, total_access_challenges) },
-       { 142, offsetof(fr_stats_t, total_responses) },
-       { 143, offsetof(fr_stats_t, total_dup_requests) },
-       { 144, offsetof(fr_stats_t, total_malformed_requests) },
-       { 145, offsetof(fr_stats_t, total_bad_authenticators) },
-       { 146, offsetof(fr_stats_t, total_packets_dropped) },
-       { 147, offsetof(fr_stats_t, total_unknown_types) },
-       { 0, 0 }
-};
-#endif
-
-
-#ifdef WITH_ACCOUNTING
-/*
- *     Accounting
- */
-static fr_stats2vp acctvp[] = {
-       { 148, offsetof(fr_stats_t, total_requests) },
-       { 149, offsetof(fr_stats_t, total_responses) },
-       { 150, offsetof(fr_stats_t, total_dup_requests) },
-       { 151, offsetof(fr_stats_t, total_malformed_requests) },
-       { 152, offsetof(fr_stats_t, total_bad_authenticators) },
-       { 153, offsetof(fr_stats_t, total_packets_dropped) },
-       { 154, offsetof(fr_stats_t, total_unknown_types) },
-       { 0, 0 }
-};
-
-#ifdef WITH_PROXY
-static fr_stats2vp proxy_acctvp[] = {
-       { 155, offsetof(fr_stats_t, total_requests) },
-       { 156, offsetof(fr_stats_t, total_responses) },
-       { 157, offsetof(fr_stats_t, total_dup_requests) },
-       { 158, offsetof(fr_stats_t, total_malformed_requests) },
-       { 159, offsetof(fr_stats_t, total_bad_authenticators) },
-       { 160, offsetof(fr_stats_t, total_packets_dropped) },
-       { 161, offsetof(fr_stats_t, total_unknown_types) },
-       { 0, 0 }
-};
-#endif
-#endif
-
-static fr_stats2vp client_authvp[] = {
-       { 128, offsetof(fr_stats_t, total_requests) },
-       { 129, offsetof(fr_stats_t, total_access_accepts) },
-       { 130, offsetof(fr_stats_t, total_access_rejects) },
-       { 131, offsetof(fr_stats_t, total_access_challenges) },
-       { 132, offsetof(fr_stats_t, total_responses) },
-       { 133, offsetof(fr_stats_t, total_dup_requests) },
-       { 134, offsetof(fr_stats_t, total_malformed_requests) },
-       { 135, offsetof(fr_stats_t, total_bad_authenticators) },
-       { 136, offsetof(fr_stats_t, total_packets_dropped) },
-       { 137, offsetof(fr_stats_t, total_unknown_types) },
-       { 0, 0 }
-};
-
-#ifdef WITH_ACCOUNTING
-static fr_stats2vp client_acctvp[] = {
-       { 155, offsetof(fr_stats_t, total_requests) },
-       { 156, offsetof(fr_stats_t, total_responses) },
-       { 157, offsetof(fr_stats_t, total_dup_requests) },
-       { 158, offsetof(fr_stats_t, total_malformed_requests) },
-       { 159, offsetof(fr_stats_t, total_bad_authenticators) },
-       { 160, offsetof(fr_stats_t, total_packets_dropped) },
-       { 161, offsetof(fr_stats_t, total_unknown_types) },
-       { 0, 0 }
-};
-#endif
-
-#define FR2ATTR(x) ((11344 << 16) | (x))
-
-static void request_stats_addvp(REQUEST *request,
-                               fr_stats2vp *table, fr_stats_t *stats)
-{
-       int i;
-       VALUE_PAIR *vp;
-
-       for (i = 0; table[i].attribute != 0; i++) {
-               vp = radius_paircreate(request, &request->reply->vps,
-                                      FR2ATTR(table[i].attribute),
-                                      PW_TYPE_INTEGER);
-               if (!vp) continue;
-
-               vp->vp_integer = *(int *)(((char *) stats) + table[i].offset);
-       }
-}
-
-
-void request_stats_reply(REQUEST *request)
-{
-       VALUE_PAIR *flag, *vp;
-
-       /*
-        *      Statistics are available ONLY on a "status" port.
-        */
-       rad_assert(request->packet->code == PW_STATUS_SERVER);
-       rad_assert(request->listener->type == RAD_LISTEN_NONE);
-               
-       flag = pairfind(request->packet->vps, FR2ATTR(127));
-       if (!flag || (flag->vp_integer == 0)) return;
-
-       /*
-        *      Authentication.
-        */
-       if (((flag->vp_integer & 0x01) != 0) &&
-           ((flag->vp_integer & 0xc0) == 0)) {
-               request_stats_addvp(request, authvp, &radius_auth_stats);
-       }
-               
-#ifdef WITH_ACCOUNTING
-       /*
-        *      Accounting
-        */
-       if (((flag->vp_integer & 0x02) != 0) &&
-           ((flag->vp_integer & 0xc0) == 0)) {
-               request_stats_addvp(request, acctvp, &radius_acct_stats);
-       }
-#endif
-
-#ifdef WITH_PROXY
-       /*
-        *      Proxied authentication requests.
-        */
-       if (((flag->vp_integer & 0x04) != 0) &&
-           ((flag->vp_integer & 0x20) == 0)) {
-               request_stats_addvp(request, proxy_authvp, &proxy_auth_stats);
-       }
-
-#ifdef WITH_ACCOUNTING
-       /*
-        *      Proxied accounting requests.
-        */
-       if (((flag->vp_integer & 0x08) != 0) &&
-           ((flag->vp_integer & 0x20) == 0)) {
-               request_stats_addvp(request, proxy_acctvp, &proxy_acct_stats);
-       }
-#endif
-#endif
-
-       /*
-        *      Internal server statistics
-        */
-       if ((flag->vp_integer & 0x10) != 0) {
-               vp = radius_paircreate(request, &request->reply->vps,
-                                      FR2ATTR(176), PW_TYPE_DATE);
-               if (vp) vp->vp_date = start_time.tv_sec;
-               vp = radius_paircreate(request, &request->reply->vps,
-                                      FR2ATTR(177), PW_TYPE_DATE);
-               if (vp) vp->vp_date = hup_time.tv_sec;
-               
-#ifdef HAVE_PTHREAD_H
-               int i, array[RAD_LISTEN_MAX];
-
-               thread_pool_queue_stats(array);
-
-               for (i = 0; i <= RAD_LISTEN_DETAIL; i++) {
-                       vp = radius_paircreate(request, &request->reply->vps,
-                                              FR2ATTR(162 + i),
-                                              PW_TYPE_INTEGER);
-                       
-                       if (!vp) continue;
-                       vp->vp_integer = array[i];
-               }
-#endif
-       }
-
-       /*
-        *      For a particular client.
-        */
-       if ((flag->vp_integer & 0x20) != 0) {
-               fr_ipaddr_t ipaddr;
-               VALUE_PAIR *server_ip, *server_port = NULL;
-               RADCLIENT *client = NULL;
-               RADCLIENT_LIST *cl = NULL;
-
-               /*
-                *      See if we need to look up the client by server
-                *      socket.
-                */
-               server_ip = pairfind(request->packet->vps, FR2ATTR(170));
-               if (server_ip) {
-                       server_port = pairfind(request->packet->vps,
-                                              FR2ATTR(171));
-
-                       if (server_port) {
-                               ipaddr.af = AF_INET;
-                               ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
-                               cl = listener_find_client_list(&ipaddr, server_port->vp_integer);
-                                                              
-                               /*
-                                *      Not found: don't do anything
-                                */
-                               if (!cl) return;
-                       }
-               }
-
-
-               vp = pairfind(request->packet->vps, FR2ATTR(167));
-               if (vp) {
-                       ipaddr.af = AF_INET;
-                       ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
-                       client = client_find(cl, &ipaddr);
-
-                       /*
-                        *      Else look it up by number.
-                        */
-               } else if ((vp = pairfind(request->packet->vps,
-                                          FR2ATTR(168))) != NULL) {
-                       client = client_findbynumber(cl, vp->vp_integer);
-               }
-
-               if (client) {
-                       /*
-                        *      If found, echo it back, along with
-                        *      the requested statistics.
-                        */
-                       pairadd(&request->reply->vps, paircopyvp(vp));
-
-                       /*
-                        *      When retrieving client by number, also
-                        *      echo back it's IP address.
-                        */
-                       if ((vp->type == PW_TYPE_INTEGER) &&
-                           (client->ipaddr.af == AF_INET)) {
-                               vp = radius_paircreate(request,
-                                                      &request->reply->vps,
-                                                      FR2ATTR(167),
-                                                      PW_TYPE_IPADDR);
-                               if (vp) {
-                                       vp->vp_ipaddr = client->ipaddr.ipaddr.ip4addr.s_addr;
-                               }
-
-                               if (client->prefix != 32) {
-                                       vp = radius_paircreate(request,
-                                                              &request->reply->vps,
-                                                              FR2ATTR(169),
-                                                              PW_TYPE_INTEGER);
-                                       if (vp) {
-                                               vp->vp_integer = client->prefix;
-                                       }
-                               }
-                       }
-                       
-                       if (server_ip) {
-                               pairadd(&request->reply->vps,
-                                       paircopyvp(server_ip));
-                               pairadd(&request->reply->vps,
-                                       paircopyvp(server_port));
-                       }
-
-                       if (client->auth &&
-                           ((flag->vp_integer & 0x01) != 0)) {
-                               request_stats_addvp(request, client_authvp,
-                                                   client->auth);
-                       }
-#ifdef WITH_ACCOUNTING
-                       if (client->acct &&
-                           ((flag->vp_integer & 0x01) != 0)) {
-                               request_stats_addvp(request, client_acctvp,
-                                                   client->acct);
-                       }
-#endif
-               } /* else client wasn't found, don't echo it back */
-       }
-
-       /*
-        *      For a particular "listen" socket.
-        */
-       if (((flag->vp_integer & 0x40) != 0) &&
-           ((flag->vp_integer & 0x03) != 0)) {
-               rad_listen_t *this;
-               VALUE_PAIR *server_ip, *server_port;
-               fr_ipaddr_t ipaddr;
-
-               /*
-                *      See if we need to look up the server by socket
-                *      socket.
-                */
-               server_ip = pairfind(request->packet->vps, FR2ATTR(170));
-               if (!server_ip) return;
-
-               server_port = pairfind(request->packet->vps,
-                                      FR2ATTR(171));
-               if (!server_port) return;
-               
-               ipaddr.af = AF_INET;
-               ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
-               this = listener_find_byipaddr(&ipaddr,
-                                             server_port->vp_integer);
-               
-               /*
-                *      Not found: don't do anything
-                */
-               if (!this) return;
-               
-               pairadd(&request->reply->vps,
-                       paircopyvp(server_ip));
-               pairadd(&request->reply->vps,
-                       paircopyvp(server_port));
-
-               if (((flag->vp_integer & 0x01) != 0) &&
-                   ((request->listener->type == RAD_LISTEN_AUTH) ||
-                    (request->listener->type == RAD_LISTEN_NONE))) {
-                       request_stats_addvp(request, authvp, &this->stats);
-               }
-               
-#ifdef WITH_ACCOUNTING
-               if (((flag->vp_integer & 0x02) != 0) &&
-                   ((request->listener->type == RAD_LISTEN_ACCT) ||
-                    (request->listener->type == RAD_LISTEN_NONE))) {
-                       request_stats_addvp(request, acctvp, &this->stats);
-               }
-#endif
-       }
-
-       /*
-        *      Home servers.
-        */
-       if (((flag->vp_integer & 0x80) != 0) &&
-           ((flag->vp_integer & 0x03) != 0)) {
-               home_server *home;
-               VALUE_PAIR *server_ip, *server_port;
-               fr_ipaddr_t ipaddr;
-
-               /*
-                *      See if we need to look up the server by socket
-                *      socket.
-                */
-               server_ip = pairfind(request->packet->vps, FR2ATTR(170));
-               if (!server_ip) return;
-
-               server_port = pairfind(request->packet->vps,
-                                      FR2ATTR(171));
-               if (!server_port) return;
-               
-               ipaddr.af = AF_INET;
-               ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
-               home = home_server_find(&ipaddr, server_port->vp_integer);
-
-               /*
-                *      Not found: don't do anything
-                */
-               if (!home) return;
-               
-               pairadd(&request->reply->vps,
-                       paircopyvp(server_ip));
-               pairadd(&request->reply->vps,
-                       paircopyvp(server_port));
-
-               vp = radius_paircreate(request, &request->reply->vps,
-                                      FR2ATTR(172), PW_TYPE_INTEGER);
-               if (vp) vp->vp_integer = home->currently_outstanding;
-
-               vp = radius_paircreate(request, &request->reply->vps,
-                                      FR2ATTR(173), PW_TYPE_INTEGER);
-               if (vp) vp->vp_integer = home->state;
-
-               if ((home->state == HOME_STATE_ALIVE) &&
-                   (home->revive_time.tv_sec != 0)) {
-                       vp = radius_paircreate(request, &request->reply->vps,
-                                              FR2ATTR(175), PW_TYPE_DATE);
-                       if (vp) vp->vp_date = home->revive_time.tv_sec;
-               }
-
-               if ((home->state == HOME_STATE_ALIVE) &&
-                   (home->ema.window > 0)) {
-                               vp = radius_paircreate(request,
-                                                      &request->reply->vps,
-                                                      FR2ATTR(178),
-                                                      PW_TYPE_INTEGER);
-                               if (vp) vp->vp_integer = home->ema.window;
-                               vp = radius_paircreate(request,
-                                                      &request->reply->vps,
-                                                      FR2ATTR(179),
-                                                      PW_TYPE_INTEGER);
-                               if (vp) vp->vp_integer = home->ema.ema1 / EMA_SCALE;
-                               vp = radius_paircreate(request,
-                                                      &request->reply->vps,
-                                                      FR2ATTR(180),
-                                                      PW_TYPE_INTEGER);
-                               if (vp) vp->vp_integer = home->ema.ema10 / EMA_SCALE;
-
-               }
-
-               if (home->state == HOME_STATE_IS_DEAD) {
-                       vp = radius_paircreate(request, &request->reply->vps,
-                                              FR2ATTR(174), PW_TYPE_DATE);
-                       if (vp) vp->vp_date = home->zombie_period_start.tv_sec + home->zombie_period;
-               }
-
-               if (((flag->vp_integer & 0x01) != 0) &&
-                   (home->type == HOME_TYPE_AUTH)) {
-                       request_stats_addvp(request, proxy_authvp,
-                                           &home->stats);
-               }
-
-#ifdef WITH_ACCOUNTING
-               if (((flag->vp_integer & 0x02) != 0) &&
-                   (home->type == HOME_TYPE_ACCT)) {
-                       request_stats_addvp(request, proxy_acctvp,
-                                           &home->stats);
-               }
-#endif
-       }
-}
-
 void radius_stats_init(int flag)
 {
        if (!flag) {
-               gettimeofday(&start_time, NULL);
-               hup_time = start_time; /* it's just nicer this way */
+               gettimeofday(&radius_start_time, NULL);
+               radius_hup_time = radius_start_time; /* it's just nicer this way */
        } else {
-               gettimeofday(&hup_time, NULL);
+               gettimeofday(&radius_hup_time, NULL);
        }
 }
 
index 8d15a36..4fe9ce6 100644 (file)
@@ -96,14 +96,6 @@ typedef struct THREAD_HANDLE {
        REQUEST              *request;
 } THREAD_HANDLE;
 
-/*
- *     For the request queue.
- */
-typedef struct request_queue_t {
-       REQUEST           *request;
-       RAD_REQUEST_FUNP  fun;
-} request_queue_t;
-
 typedef struct thread_fork_t {
        pid_t           pid;
        int             status;
@@ -288,8 +280,7 @@ static void reap_children(void)
  */
 static int request_enqueue(REQUEST *request, RAD_REQUEST_FUNP fun)
 {
-       request_queue_t *entry;
-
+       rad_assert(request->process == fun);
        pthread_mutex_lock(&thread_pool.queue_mutex);
 
        thread_pool.request_count++;
@@ -305,15 +296,10 @@ static int request_enqueue(REQUEST *request, RAD_REQUEST_FUNP fun)
                return 0;
        }
 
-       entry = rad_malloc(sizeof(*entry));
-       entry->request = request;
-       entry->fun = fun;
-
        /*
         *      Push the request onto the appropriate fifo for that
         */
-       if (!fr_fifo_push(thread_pool.fifo[request->priority],
-                           entry)) {
+       if (!fr_fifo_push(thread_pool.fifo[request->priority], request)) {
                pthread_mutex_unlock(&thread_pool.queue_mutex);
                radlog(L_ERR, "!!! ERROR !!! Failed inserting request %d into the queue", request->number);
                request->child_state = REQUEST_DONE;
@@ -341,10 +327,10 @@ static int request_enqueue(REQUEST *request, RAD_REQUEST_FUNP fun)
 /*
  *     Remove a request from the queue.
  */
-static int request_dequeue(REQUEST **request, RAD_REQUEST_FUNP *fun)
+static int request_dequeue(REQUEST **prequest, RAD_REQUEST_FUNP *fun)
 {
        RAD_LISTEN_TYPE i, start;
-       request_queue_t *entry;
+       REQUEST *request = NULL;
 
        reap_children();
 
@@ -359,19 +345,18 @@ static int request_dequeue(REQUEST **request, RAD_REQUEST_FUNP *fun)
         *      requests will be quickly cleared.
         */
        for (i = 0; i < RAD_LISTEN_MAX; i++) {
-               entry = fr_fifo_peek(thread_pool.fifo[i]);
-               if (!entry ||
-                   (entry->request->master_state != REQUEST_STOP_PROCESSING)) {
+               request = fr_fifo_peek(thread_pool.fifo[i]);
+               if (!request ||
+                   (request->master_state != REQUEST_STOP_PROCESSING)) {
                        continue;
 }
                /*
                 *      This entry was marked to be stopped.  Acknowledge it.
                 */
-               entry = fr_fifo_pop(thread_pool.fifo[i]);
-               rad_assert(entry != NULL);
-               entry->request->child_state = REQUEST_DONE;
+               request = fr_fifo_pop(thread_pool.fifo[i]);
+               rad_assert(request != NULL);
+               request->child_state = REQUEST_DONE;
                thread_pool.num_queued--;
-               free(entry);
        }
 
        start = 0;
@@ -380,28 +365,26 @@ static int request_dequeue(REQUEST **request, RAD_REQUEST_FUNP *fun)
         *      Pop results from the top of the queue
         */
        for (i = start; i < RAD_LISTEN_MAX; i++) {
-               entry = fr_fifo_pop(thread_pool.fifo[i]);
-               if (entry) {
+               request = fr_fifo_pop(thread_pool.fifo[i]);
+               if (request) {
                        start = i;
                        break;
                }
        }
 
-       if (!entry) {
+       if (!request) {
                pthread_mutex_unlock(&thread_pool.queue_mutex);
-               *request = NULL;
+               *prequest = NULL;
                *fun = NULL;
                return 0;
        }
 
        rad_assert(thread_pool.num_queued > 0);
        thread_pool.num_queued--;
-       *request = entry->request;
-       *fun = entry->fun;
-       free(entry);
+       *prequest = request;
+       *fun = request->process;
 
-       rad_assert(*request != NULL);
-       rad_assert((*request)->magic == REQUEST_MAGIC);
+       rad_assert(request->magic == REQUEST_MAGIC);
        rad_assert(*fun != NULL);
 
        /*
@@ -412,8 +395,8 @@ static int request_dequeue(REQUEST **request, RAD_REQUEST_FUNP *fun)
         *      the queue, and therefore won't clean it up until we
         *      have acknowledged it as "done".
         */
-       if ((*request)->master_state == REQUEST_STOP_PROCESSING) {
-               (*request)->child_state = REQUEST_DONE;
+       if (request->master_state == REQUEST_STOP_PROCESSING) {
+               request->child_state = REQUEST_DONE;
                goto retry;
        }
 
@@ -836,6 +819,8 @@ int thread_pool_addrequest(REQUEST *request, RAD_REQUEST_FUNP fun)
 {
        time_t now = request->timestamp;
 
+       request->process = fun;
+
        /*
         *      We've been told not to spawn threads, so don't.
         */
index 5f5a582..c02c399 100644 (file)
@@ -7,6 +7,7 @@
 include ../../Make.inc
 
 WHAT_TO_MAKE   = all
+FRS_MODULES    = $(shell echo frs_*/Makefile | sed 's,/Makefile,,g')
 
 all:
        @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
@@ -43,7 +44,7 @@ reconfig:
 
 common:
        @[ -d lib/ ] || mkdir lib
-       @for mod in $(MODULES); do \
+       @for mod in $(FRS_MODULES) $(MODULES); do \
                if [ -d $$mod ] && [ -f $$mod/Makefile ]; then \
                        echo "Making $(WHAT_TO_MAKE) in $$mod..."; \
                        $(MAKE) $(MFLAGS) -C $$mod $(WHAT_TO_MAKE) || exit $$?; \
diff --git a/src/modules/frs_acct/Makefile b/src/modules/frs_acct/Makefile
new file mode 100644 (file)
index 0000000..4ebbe52
--- /dev/null
@@ -0,0 +1,11 @@
+TARGET         = frs_acct
+SRCS           = frs_acct.c
+HEADERS                = 
+RLM_CFLAGS     =
+RLM_LIBS       = 
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
similarity index 56%
rename from src/main/acct.c
rename to src/modules/frs_acct/frs_acct.c
index 104850b..a611795 100644 (file)
 RCSID("$Id$")
 
 #include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
 #include <freeradius-devel/modules.h>
 
-#ifdef WITH_ACCOUNTING
+
 /*
  *     rad_accounting: call modules.
  *
  *     The return value of this function isn't actually used right now, so
  *     it's not entirely clear if it is returning the right things. --Pac.
  */
-int rad_accounting(REQUEST *request)
+static int rad_accounting(REQUEST *request)
 {
        int result = RLM_MODULE_OK;
 
@@ -180,4 +181,144 @@ int rad_accounting(REQUEST *request)
        }
        return result;
 }
-#endif
+
+
+/*
+ *     Receive packets from an accounting socket
+ */
+static int acct_socket_recv(rad_listen_t *listener,
+                           RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+{
+       ssize_t         rcode;
+       int             code, src_port;
+       RADIUS_PACKET   *packet;
+       RAD_REQUEST_FUNP fun = NULL;
+       RADCLIENT       *client;
+       fr_ipaddr_t     src_ipaddr;
+
+       rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
+       if (rcode < 0) return 0;
+
+       RAD_STATS_TYPE_INC(listener, total_requests);
+
+       if (rcode < 20) {       /* AUTH_HDR_LEN */
+               RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+               return 0;
+       }
+
+       if ((client = client_listener_find(listener,
+                                          &src_ipaddr, src_port)) == NULL) {
+               rad_recv_discard(listener->fd);
+               RAD_STATS_TYPE_INC(listener, total_invalid_requests);
+               return 0;
+       }
+
+       /*
+        *      Some sanity checks, based on the packet code.
+        */
+       switch(code) {
+       case PW_ACCOUNTING_REQUEST:
+               RAD_STATS_CLIENT_INC(listener, client, total_requests);
+               fun = rad_accounting;
+               break;
+
+       case PW_STATUS_SERVER:
+               if (!mainconfig.status_server) {
+                       rad_recv_discard(listener->fd);
+                       RAD_STATS_TYPE_INC(listener, total_packets_dropped);
+                       RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
+
+                       DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
+                       return 0;
+               }
+               fun = rad_status_server;
+               break;
+
+       default:
+               rad_recv_discard(listener->fd);
+               RAD_STATS_TYPE_INC(listener, total_unknown_types);
+               RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
+
+               DEBUG("Invalid packet code %d sent to a accounting port from client %s port %d : IGNORED",
+                     code, client->shortname, src_port);
+               return 0;
+       } /* switch over packet types */
+
+       /*
+        *      Now that we've sanity checked everything, receive the
+        *      packet.
+        */
+       packet = rad_recv(listener->fd, 0);
+       if (!packet) {
+               RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+               radlog(L_ERR, "%s", fr_strerror());
+               return 0;
+       }
+
+       /*
+        *      There can be no duplicate accounting packets.
+        */
+       if (!received_request(listener, packet, prequest, client)) {
+               RAD_STATS_TYPE_INC(listener, total_packets_dropped);
+               RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
+               rad_free(&packet);
+               return 0;
+       }
+
+       *pfun = fun;
+       return 1;
+}
+
+
+/*
+ *     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->client->secret);
+}
+
+
+static int acct_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+       if (!request->reply->code) return 0;
+
+       rad_encode(request->reply, request->packet,
+                  request->client->secret);
+       rad_sign(request->reply, request->packet,
+                request->client->secret);
+
+       return 0;
+}
+
+
+static int acct_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+       if (rad_verify(request->packet, NULL,
+                      request->client->secret) < 0) {
+               return -1;
+       }
+
+       return rad_decode(request->packet, NULL,
+                         request->client->secret);
+}
+
+
+frs_module_t frs_acct = {
+  FRS_MODULE_INIT, RAD_LISTEN_ACCT, "acct",
+  listen_socket_parse, NULL,
+  acct_socket_recv, acct_socket_send,
+  listen_socket_print, acct_socket_encode, acct_socket_decode
+};
diff --git a/src/modules/frs_auth/Makefile b/src/modules/frs_auth/Makefile
new file mode 100644 (file)
index 0000000..f44b4d6
--- /dev/null
@@ -0,0 +1,11 @@
+TARGET         = frs_auth
+SRCS           = frs_auth.c
+HEADERS                = 
+RLM_CFLAGS     =
+RLM_LIBS       = 
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
diff --git a/src/modules/frs_auth/frs_auth.c b/src/modules/frs_auth/frs_auth.c
new file mode 100644 (file)
index 0000000..a63f760
--- /dev/null
@@ -0,0 +1,857 @@
+/*
+ * auth.c      User authentication.
+ *
+ * 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  Jeff Carneal <jeff@apex.net>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/rad_assert.h>
+
+#include <ctype.h>
+
+
+/*
+ * Make sure user/pass are clean
+ * and then log them
+ */
+static int rad_authlog(const char *msg, REQUEST *request, int goodpass) {
+
+       char clean_password[1024];
+       char clean_username[1024];
+       char buf[1024];
+       VALUE_PAIR *username = NULL;
+
+       if (!request->root->log_auth) {
+               return 0;
+       }
+
+       /*
+        * Get the correct username based on the configured value
+        */
+       if (log_stripped_names == 0) {
+               username = pairfind(request->packet->vps, PW_USER_NAME);
+       } else {
+               username = request->username;
+       }
+
+       /*
+        *      Clean up the username
+        */
+       if (username == NULL) {
+               strcpy(clean_username, "<no User-Name attribute>");
+       } else {
+               fr_print_string((char *)username->vp_strvalue,
+                               username->length,
+                               clean_username, sizeof(clean_username));
+       }
+
+       /*
+        *      Clean up the password
+        */
+       if (request->root->log_auth_badpass || request->root->log_auth_goodpass) {
+               if (!request->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 {
+                       fr_print_string((char *)request->password->vp_strvalue,
+                                        request->password->length,
+                                        clean_password, sizeof(clean_password));
+               }
+       }
+
+       if (goodpass) {
+               radlog_request(L_AUTH, 0, request, "%s: [%s%s%s] (%s)",
+                               msg,
+                               clean_username,
+                               request->root->log_auth_goodpass ? "/" : "",
+                               request->root->log_auth_goodpass ? clean_password : "",
+                               auth_name(buf, sizeof(buf), request, 1));
+       } else {
+               radlog_request(L_AUTH, 0, request, "%s: [%s%s%s] (%s)",
+                               msg,
+                               clean_username,
+                               request->root->log_auth_badpass ? "/" : "",
+                               request->root->log_auth_badpass ? clean_password : "",
+                               auth_name(buf, sizeof(buf), request, 1));
+       }
+
+       return 0;
+}
+
+/*
+ *     Check password.
+ *
+ *     Returns:        0  OK
+ *                     -1 Password fail
+ *                     -2 Rejected (Auth-Type = Reject, send Port-Message back)
+ *                     1  End check & return, don't reply
+ *
+ *     NOTE: NOT the same as the RLM_ values !
+ */
+static int rad_check_password(REQUEST *request)
+{
+       VALUE_PAIR *auth_type_pair;
+       VALUE_PAIR *cur_config_item;
+       VALUE_PAIR *password_pair;
+       VALUE_PAIR *auth_item;
+       uint8_t my_chap[MAX_STRING_LEN];
+       int auth_type = -1;
+       int result;
+       int auth_type_count = 0;
+       result = 0;
+
+       /*
+        *      Look for matching check items. We skip the whole lot
+        *      if the authentication type is PW_AUTHTYPE_ACCEPT or
+        *      PW_AUTHTYPE_REJECT.
+        */
+       cur_config_item = request->config_items;
+       while(((auth_type_pair = pairfind(cur_config_item, PW_AUTH_TYPE))) != NULL) {
+               auth_type = auth_type_pair->vp_integer;
+               auth_type_count++;
+               DICT_VALUE *dv = dict_valbyattr(auth_type_pair->attribute,
+                                               auth_type_pair->vp_integer);
+
+               RDEBUG2("Found Auth-Type = %s",
+                       (dv != NULL) ? dv->name : "?");
+               cur_config_item = auth_type_pair->next;
+
+               if (auth_type == PW_AUTHTYPE_REJECT) {
+                       RDEBUG2("Auth-Type = Reject, rejecting user");
+                       return -2;
+               }
+       }
+
+       if (( auth_type_count > 1) && (debug_flag)) {
+               radlog_request(L_ERR, 0, request, "Warning:  Found %d auth-types on request for user '%s'",
+                       auth_type_count, request->username->vp_strvalue);
+       }
+
+       /*
+        *      This means we have a proxy reply or an accept
+        *  and it wasn't rejected in the above loop.  So
+        *  that means it is accepted and we do no further
+        *  authentication
+        */
+       if ((auth_type == PW_AUTHTYPE_ACCEPT)
+#ifdef WITH_PROXY
+           || (request->proxy)
+#endif
+           ) {
+               RDEBUG2("Auth-Type = Accept, accepting the user");
+               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) {
+               DICT_ATTR *da;
+
+               RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+               RDEBUG("!!!    Replacing User-Password in config items with Cleartext-Password.     !!!");
+               RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+               RDEBUG("!!! Please update your configuration so that the \"known good\"               !!!");
+               RDEBUG("!!! clear text password is in Cleartext-Password, and not in User-Password. !!!");
+               RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+               password_pair->attribute = PW_CLEARTEXT_PASSWORD;
+               da = dict_attrbyvalue(PW_CLEARTEXT_PASSWORD);
+               if (!da) {
+                       radlog_request(L_ERR, 0, request, "FATAL: You broke the dictionaries.  Please use the default dictionaries!");
+                       _exit(1);
+               }
+
+               password_pair->name = da->name;
+       }
+
+       /*
+        *      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) {
+               /*
+                *      Re-write Auth-Type, but ONLY if it isn't already
+                *      set.
+                */
+               if (auth_type == -1) auth_type = PW_AUTHTYPE_CRYPT;
+       } else {
+               password_pair = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);
+       }
+
+       if (auth_type < 0) {
+               if (password_pair) {
+                       auth_type = PW_AUTHTYPE_LOCAL;
+               } else {
+                       /*
+                       *       The admin hasn't told us how to
+                       *       authenticate the user, so we reject them!
+                       *
+                       *       This is fail-safe.
+                       */
+                       RDEBUG2("No authenticate method (Auth-Type) configuration found for the request: Rejecting the user");
+                       return -2;
+               }
+       }
+
+       switch(auth_type) {
+               case PW_AUTHTYPE_CRYPT:
+                       RDEBUG2("WARNING: Please update your configuration, and remove 'Auth-Type = Crypt'");
+                       RDEBUG2("WARNING: Use the PAP module instead.");
+
+                       /*
+                        *      Find the password sent by the user. It
+                        *      SHOULD be there, if it's not
+                        *      authentication fails.
+                        */
+                       auth_item = request->password;
+                       if (auth_item == NULL) {
+                               RDEBUG2("No User-Password or CHAP-Password attribute in the request");
+                               return -1;
+                       }
+
+                       if (password_pair == NULL) {
+                               RDEBUG2("No Crypt-Password configured for the user");
+                               rad_authlog("Login incorrect "
+                                       "(No Crypt-Password configured for the user)", request, 0);
+                               return -1;
+                       }
+
+                       switch (fr_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);
+                       case 1:
+                         return -1;
+                       }
+                       break;
+               case PW_AUTHTYPE_LOCAL:
+                       RDEBUG2("WARNING: Please update your configuration, and remove 'Auth-Type = Local'");
+                       RDEBUG2("WARNING: Use the PAP or CHAP modules instead.");
+
+                       /*
+                        *      Find the password sent by the user. It
+                        *      SHOULD be there, if it's not
+                        *      authentication fails.
+                        */
+                       auth_item = request->password;
+                       if (!auth_item)
+                               auth_item = pairfind(request->packet->vps,
+                                                    PW_CHAP_PASSWORD);
+                       if (!auth_item) {
+                               RDEBUG2("No User-Password or CHAP-Password attribute in the request.");
+                               RDEBUG2("Cannot perform authentication.");
+                               return -1;
+                       }
+
+                       /*
+                        *      Plain text password.
+                        */
+                       if (password_pair == NULL) {
+                               RDEBUG2("No \"known good\" password was configured for the user.");
+                               RDEBUG2("As a result, we cannot authenticate the user.");
+                               rad_authlog("Login incorrect "
+                                       "(No password configured for the user)", request, 0);
+                               return -1;
+                       }
+
+                       /*
+                        *      Local password is just plain text.
+                        */
+                       if (auth_item->attribute == PW_USER_PASSWORD) {
+                               if (strcmp((char *)password_pair->vp_strvalue,
+                                          (char *)auth_item->vp_strvalue) != 0) {
+                                       RDEBUG2("User-Password in the request does NOT match \"known good\" password.");
+                                       return -1;
+                               }
+                               RDEBUG2("User-Password in the request is correct.");
+                               break;
+
+                       } else if (auth_item->attribute != PW_CHAP_PASSWORD) {
+                               RDEBUG2("The user did not supply a User-Password or a CHAP-Password attribute");
+                               rad_authlog("Login incorrect "
+                                       "(no User-Password or CHAP-Password attribute)", request, 0);
+                               return -1;
+                       }
+
+                       rad_chap_encode(request->packet, my_chap,
+                                       auth_item->vp_octets[0], password_pair);
+
+                       /*
+                        *      Compare them
+                        */
+                       if (memcmp(my_chap + 1, auth_item->vp_strvalue + 1,
+                                  CHAP_VALUE_LENGTH) != 0) {
+                               RDEBUG2("CHAP-Password is incorrect.");
+                               return -1;
+                       }
+                       RDEBUG2("CHAP-Password is correct.");
+                       break;
+               default:
+                       /*
+                        *      See if there is a module that handles
+                        *      this type, and turn the RLM_ return
+                        *      status into the values as defined at
+                        *      the top of this function.
+                        */
+                       result = module_authenticate(auth_type, request);
+                       switch (result) {
+                               /*
+                                *      An authentication module FAIL
+                                *      return code, or any return code that
+                                *      is not expected from authentication,
+                                *      is the same as an explicit REJECT!
+                                */
+                               case RLM_MODULE_FAIL:
+                               case RLM_MODULE_INVALID:
+                               case RLM_MODULE_NOOP:
+                               case RLM_MODULE_NOTFOUND:
+                               case RLM_MODULE_REJECT:
+                               case RLM_MODULE_UPDATED:
+                               case RLM_MODULE_USERLOCK:
+                               default:
+                                       result = -1;
+                                       break;
+                               case RLM_MODULE_OK:
+                                       result = 0;
+                                       break;
+                               case RLM_MODULE_HANDLED:
+                                       result = 1;
+                                       break;
+                       }
+                       break;
+       }
+
+       return result;
+}
+
+
+/*
+ *     Process and reply to an authentication request
+ *
+ *     The return value of this function isn't actually used right now, so
+ *     it's not entirely clear if it is returning the right things. --Pac.
+ */
+static int rad_authenticate(REQUEST *request)
+{
+       VALUE_PAIR      *namepair;
+#ifdef WITH_SESSION_MGMT
+       VALUE_PAIR      *check_item;
+#endif
+       VALUE_PAIR      *auth_item = NULL;
+       VALUE_PAIR      *module_msg;
+       VALUE_PAIR      *tmp = NULL;
+       int             result;
+       const char      *password;
+       char            autz_retry = 0;
+       int             autz_type = 0;
+
+       password = "";
+
+#ifdef WITH_PROXY
+       /*
+        *      If this request got proxied to another server, we need
+        *      to check whether it authenticated the request or not.
+        */
+       if (request->proxy_reply) {
+               switch (request->proxy_reply->code) {
+               /*
+                *      Reply of ACCEPT means accept, thus set Auth-Type
+                *      accordingly.
+                */
+               case PW_AUTHENTICATION_ACK:
+                       tmp = radius_paircreate(request,
+                                               &request->config_items,
+                                               PW_AUTH_TYPE, PW_TYPE_INTEGER);
+                       if (tmp) tmp->vp_integer = PW_AUTHTYPE_ACCEPT;
+                       goto authenticate;
+
+               /*
+                *      Challenges are punted back to the NAS without any
+                *      further processing.
+                */
+               case PW_ACCESS_CHALLENGE:
+                       request->reply->code = PW_ACCESS_CHALLENGE;
+                       return RLM_MODULE_OK;
+               /*
+                *      ALL other replies mean reject. (this is fail-safe)
+                *
+                *      Do NOT do any authorization or authentication. They
+                *      are being rejected, so we minimize the amount of work
+                *      done by the server, by rejecting them here.
+                */
+               case PW_AUTHENTICATION_REJECT:
+               default:
+                       rad_authlog("Login incorrect (Home Server says so)",
+                                   request, 0);
+                       request->reply->code = PW_AUTHENTICATION_REJECT;
+                       return RLM_MODULE_REJECT;
+               }
+       }
+#endif
+
+       /*
+        *      Get the username from the request.
+        *
+        *      Note that namepair MAY be NULL, in which case there
+        *      is no User-Name attribute in the request.
+        */
+       namepair = request->username;
+
+       /*
+        *      Look for, and cache, passwords.
+        */
+       if (!request->password) {
+               request->password = pairfind(request->packet->vps,
+                                            PW_USER_PASSWORD);
+       }
+
+       /*
+        *      Discover which password we want to use.
+        */
+       auth_item = request->password;
+       if (auth_item) {
+               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) {
+                       password = "<CHAP-PASSWORD>";
+
+               } else {
+                       /*
+                        *      No password we recognize.
+                        */
+                       password = "<NO-PASSWORD>";
+               }
+       }
+       request->password = auth_item;
+
+       /*
+        *      Get the user's authorization information from the database
+        */
+autz_redo:
+       result = module_authorize(autz_type, request);
+       switch (result) {
+               case RLM_MODULE_NOOP:
+               case RLM_MODULE_NOTFOUND:
+               case RLM_MODULE_OK:
+               case RLM_MODULE_UPDATED:
+                       break;
+               case RLM_MODULE_HANDLED:
+                       return result;
+               case RLM_MODULE_FAIL:
+               case RLM_MODULE_INVALID:
+               case RLM_MODULE_REJECT:
+               case RLM_MODULE_USERLOCK:
+               default:
+                       if ((module_msg = pairfind(request->packet->vps,
+                                       PW_MODULE_FAILURE_MESSAGE)) != NULL) {
+                               char msg[MAX_STRING_LEN + 16];
+                               snprintf(msg, sizeof(msg), "Invalid user (%s)",
+                                        module_msg->vp_strvalue);
+                               rad_authlog(msg,request,0);
+                       } else {
+                               rad_authlog("Invalid user", request, 0);
+                       }
+                       request->reply->code = PW_AUTHENTICATION_REJECT;
+                       return result;
+       }
+       if (!autz_retry) {
+               tmp = pairfind(request->config_items, PW_AUTZ_TYPE);
+               if (tmp) {
+                       RDEBUG2("Using Autz-Type %s", tmp->vp_strvalue);
+                       autz_type = tmp->vp_integer;
+                       autz_retry = 1;
+                       goto autz_redo;
+               }
+       }
+
+       /*
+        *      If we haven't already proxied the packet, then check
+        *      to see if we should.  Maybe one of the authorize
+        *      modules has decided that a proxy should be used. If
+        *      so, get out of here and send the packet.
+        */
+       if (
+#ifdef WITH_PROXY
+           (request->proxy == NULL) &&
+#endif
+           ((tmp = pairfind(request->config_items, PW_PROXY_TO_REALM)) != NULL)) {
+               REALM *realm;
+
+               realm = realm_find2(tmp->vp_strvalue);
+
+               /*
+                *      Don't authenticate, as the request is going to
+                *      be proxied.
+                */
+               if (realm && realm->auth_pool) {
+                       return RLM_MODULE_OK;
+               }
+
+               /*
+                *      Catch users who set Proxy-To-Realm to a LOCAL
+                *      realm (sigh).  But don't complain if it is
+                *      *the* LOCAL realm.
+                */
+               if (realm &&(strcmp(realm->name, "LOCAL") != 0)) {
+                       RDEBUG2("WARNING: You set Proxy-To-Realm = %s, but it is a LOCAL realm!  Cancelling proxy request.", realm->name);
+               }
+
+               if (!realm) {
+                       RDEBUG2("WARNING: You set Proxy-To-Realm = %s, but the realm does not exist!  Cancelling invalid proxy request.", tmp->vp_strvalue);
+               }
+       }
+
+#ifdef WITH_PROXY
+ authenticate:
+#endif
+
+       /*
+        *      Perhaps there is a Stripped-User-Name now.
+        */
+       namepair = request->username;
+
+       /*
+        *      Validate the user
+        */
+       do {
+               result = rad_check_password(request);
+               if (result > 0) {
+                       /* don't reply! */
+                       return RLM_MODULE_HANDLED;
+               }
+       } while(0);
+
+       /*
+        *      Failed to validate the user.
+        *
+        *      We PRESUME that the code which failed will clean up
+        *      request->reply->vps, to be ONLY the reply items it
+        *      wants to send back.
+        */
+       if (result < 0) {
+               RDEBUG2("Failed to authenticate the user.");
+               request->reply->code = PW_AUTHENTICATION_REJECT;
+
+               if ((module_msg = pairfind(request->packet->vps,PW_MODULE_FAILURE_MESSAGE)) != NULL){
+                       char msg[MAX_STRING_LEN+19];
+
+                       snprintf(msg, sizeof(msg), "Login incorrect (%s)",
+                                module_msg->vp_strvalue);
+                       rad_authlog(msg, request, 0);
+               } else {
+                       rad_authlog("Login incorrect", request, 0);
+               }
+
+               /* double check: maybe the secret is wrong? */
+               if ((debug_flag > 1) && (auth_item != NULL) &&
+                               (auth_item->attribute == PW_USER_PASSWORD)) {
+                       char *p;
+
+                       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!");
+                                       break;
+                               }
+                               p++;
+                       }
+               }
+       }
+
+#ifdef WITH_SESSION_MGMT
+       if (result >= 0 &&
+           (check_item = pairfind(request->config_items, PW_SIMULTANEOUS_USE)) != NULL) {
+               int r, session_type = 0;
+               char            logstr[1024];
+               char            umsg[MAX_STRING_LEN + 1];
+               const char      *user_msg = NULL;
+
+               tmp = pairfind(request->config_items, PW_SESSION_TYPE);
+               if (tmp) {
+                       RDEBUG2("Using Session-Type %s", tmp->vp_strvalue);
+                       session_type = tmp->vp_integer;
+               }
+
+               /*
+                *      User authenticated O.K. Now we have to check
+                *      for the Simultaneous-Use parameter.
+                */
+               if (namepair &&
+                   (r = module_checksimul(session_type, request, check_item->vp_integer)) != 0) {
+                       char mpp_ok = 0;
+
+                       if (r == 2){
+                               /* Multilink attempt. Check if port-limit > simultaneous-use */
+                               VALUE_PAIR *port_limit;
+
+                               if ((port_limit = pairfind(request->reply->vps, PW_PORT_LIMIT)) != NULL &&
+                                       port_limit->vp_integer > check_item->vp_integer){
+                                       RDEBUG2("MPP is OK");
+                                       mpp_ok = 1;
+                               }
+                       }
+                       if (!mpp_ok){
+                               if (check_item->vp_integer > 1) {
+                               snprintf(umsg, sizeof(umsg),
+                                                       "\r\nYou are already logged in %d times  - access denied\r\n\n",
+                                                       (int)check_item->vp_integer);
+                                       user_msg = umsg;
+                               } else {
+                                       user_msg = "\r\nYou are already logged in - access denied\r\n\n";
+                               }
+
+                               request->reply->code = PW_AUTHENTICATION_REJECT;
+
+                               /*
+                                *      They're trying to log in too many times.
+                                *      Remove ALL reply attributes.
+                                */
+                               pairfree(&request->reply->vps);
+                               radius_pairmake(request, &request->reply->vps,
+                                               "Reply-Message",
+                                               user_msg, T_OP_SET);
+
+                               snprintf(logstr, sizeof(logstr), "Multiple logins (max %d) %s",
+                                       check_item->vp_integer,
+                                       r == 2 ? "[MPP attempt]" : "");
+                               rad_authlog(logstr, request, 1);
+
+                               result = -1;
+                       }
+               }
+       }
+#endif
+
+       /*
+        *      Result should be >= 0 here - if not, it means the user
+        *      is rejected, so we just process post-auth and return.
+        */
+       if (result < 0) {
+               return RLM_MODULE_REJECT;
+       }
+
+       /*
+        *      Add the port number to the Framed-IP-Address if
+        *      vp->addport is set.
+        */
+       if (((tmp = pairfind(request->reply->vps,
+                            PW_FRAMED_IP_ADDRESS)) != NULL) &&
+           (tmp->flags.addport != 0)) {
+               VALUE_PAIR *vpPortId;
+
+               /*
+                *  Find the NAS port ID.
+                */
+               if ((vpPortId = pairfind(request->packet->vps,
+                                        PW_NAS_PORT)) != NULL) {
+                 unsigned long tvalue = ntohl(tmp->vp_integer);
+                 tmp->vp_integer = htonl(tvalue + vpPortId->vp_integer);
+                 tmp->flags.addport = 0;
+                 ip_ntoa(tmp->vp_strvalue, tmp->vp_integer);
+               } else {
+                       RDEBUG2("WARNING: No NAS-Port attribute in request.  CANNOT return a Framed-IP-Address + NAS-Port.\n");
+                       pairdelete(&request->reply->vps, PW_FRAMED_IP_ADDRESS);
+               }
+       }
+
+       /*
+        *      Set the reply to Access-Accept, if it hasn't already
+        *      been set to something.  (i.e. Access-Challenge)
+        */
+       if (request->reply->code == 0)
+         request->reply->code = PW_AUTHENTICATION_ACK;
+
+       if ((module_msg = pairfind(request->packet->vps,PW_MODULE_SUCCESS_MESSAGE)) != NULL){
+               char msg[MAX_STRING_LEN+12];
+
+               snprintf(msg, sizeof(msg), "Login OK (%s)",
+                        module_msg->vp_strvalue);
+               rad_authlog(msg, request, 1);
+       } else {
+               rad_authlog("Login OK", request, 1);
+       }
+
+       /*
+        *      Run the modules in the 'post-auth' section.
+        */
+       result = rad_postauth(request);
+
+       return result;
+}
+
+
+/*
+ *     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);
+
+       return rad_send(request->reply, request->packet,
+                       request->client->secret);
+}
+
+
+/*
+ *     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)
+{
+       ssize_t         rcode;
+       int             code, src_port;
+       RADIUS_PACKET   *packet;
+       RAD_REQUEST_FUNP fun = NULL;
+       RADCLIENT       *client;
+       fr_ipaddr_t     src_ipaddr;
+
+       rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
+       if (rcode < 0) return 0;
+
+       RAD_STATS_TYPE_INC(listener, total_requests);
+
+       if (rcode < 20) {       /* AUTH_HDR_LEN */
+               RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+               return 0;
+       }
+
+       if ((client = client_listener_find(listener,
+                                          &src_ipaddr, src_port)) == NULL) {
+               rad_recv_discard(listener->fd);
+               RAD_STATS_TYPE_INC(listener, total_invalid_requests);
+               return 0;
+       }
+
+       /*
+        *      Some sanity checks, based on the packet code.
+        */
+       switch(code) {
+       case PW_AUTHENTICATION_REQUEST:
+               RAD_STATS_CLIENT_INC(listener, client, total_requests);
+               fun = rad_authenticate;
+               break;
+
+       case PW_STATUS_SERVER:
+               if (!mainconfig.status_server) {
+                       rad_recv_discard(listener->fd);
+                       RAD_STATS_TYPE_INC(listener, total_packets_dropped);
+                       RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
+                       DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
+                       return 0;
+               }
+               fun = rad_status_server;
+               break;
+
+       default:
+               rad_recv_discard(listener->fd);
+               RAD_STATS_INC(radius_auth_stats.total_unknown_types);
+               RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
+
+               DEBUG("Invalid packet code %d sent to authentication port from client %s port %d : IGNORED",
+                     code, client->shortname, src_port);
+               return 0;
+               break;
+       } /* switch over packet types */
+
+       /*
+        *      Now that we've sanity checked everything, receive the
+        *      packet.
+        */
+       packet = rad_recv(listener->fd, client->message_authenticator);
+       if (!packet) {
+               RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+               DEBUG("%s", fr_strerror());
+               return 0;
+       }
+
+       if (!received_request(listener, packet, prequest, client)) {
+               RAD_STATS_TYPE_INC(listener, total_packets_dropped);
+               RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
+               rad_free(&packet);
+               return 0;
+       }
+
+       *pfun = fun;
+       return 1;
+}
+
+
+static int auth_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+       if (!request->reply->code) return 0;
+
+       rad_encode(request->reply, request->packet,
+                  request->client->secret);
+       rad_sign(request->reply, request->packet,
+                request->client->secret);
+
+       return 0;
+}
+
+
+static int auth_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+       if (rad_verify(request->packet, NULL,
+                      request->client->secret) < 0) {
+               return -1;
+       }
+
+       return rad_decode(request->packet, NULL,
+                         request->client->secret);
+}
+
+frs_module_t frs_auth =        {
+       FRS_MODULE_INIT, RAD_LISTEN_AUTH, "auth",
+       listen_socket_parse, NULL,
+       auth_socket_recv, auth_socket_send,
+       listen_socket_print, auth_socket_encode, auth_socket_decode
+};
diff --git a/src/modules/frs_control/Makefile b/src/modules/frs_control/Makefile
new file mode 100644 (file)
index 0000000..2918cec
--- /dev/null
@@ -0,0 +1,11 @@
+TARGET         = frs_control
+SRCS           = frs_control.c
+HEADERS                = 
+RLM_CFLAGS     =
+RLM_LIBS       = 
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
similarity index 98%
rename from src/main/command.c
rename to src/modules/frs_control/frs_control.c
index 13b8c9e..d1480a6 100644 (file)
@@ -21,8 +21,8 @@
  * Copyright 2008 Alan DeKok <aland@deployingradius.com>
  */
 
-#ifdef WITH_COMMAND_SOCKET
-
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
 #include <freeradius-devel/modpriv.h>
 #include <freeradius-devel/conffile.h>
 #include <freeradius-devel/stats.h>
@@ -1363,6 +1363,8 @@ static int command_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
 {
        fr_command_socket_t *sock;
 
+       this->data = rad_malloc(sizeof(fr_command_socket_t));
+       memset(this->data, 0, sizeof(fr_command_socket_t));
        sock = this->data;
 
        if (cf_section_parse(cs, sock, command_config) < 0) {
@@ -1720,7 +1722,6 @@ static int command_domain_recv(rad_listen_t *listener,
        return 0;
 }
 
-
 static int command_domain_accept(rad_listen_t *listener,
                                 UNUSED RAD_REQUEST_FUNP *pfun,
                                 UNUSED REQUEST **prequest)
@@ -1796,17 +1797,18 @@ static int command_domain_accept(rad_listen_t *listener,
                return -1;
        }
 
-
        /*
         *      Add the new listener.
         */
-       this = listen_alloc(listener->type);
+       this = listen_alloc(listener->frs->name);
        if (!this) return -1;
 
        /*
         *      Copy everything, including the pointer to the socket
         *      information.
         */
+       this->data = rad_malloc(sizeof(fr_command_socket_t));
+       memset(this->data, 0, sizeof(fr_command_socket_t));
        sock = this->data;
        memcpy(this, listener, sizeof(*this));
        this->status = RAD_LISTEN_STATUS_INIT;
@@ -1853,4 +1855,9 @@ static int command_socket_decode(UNUSED rad_listen_t *listener,
        return 0;
 }
 
-#endif /* WITH_COMMAND_SOCKET */
+frs_module_t frs_control = {
+  FRS_MODULE_INIT, RAD_LISTEN_COMMAND, "control",
+  command_socket_parse, NULL,
+  command_domain_accept, command_domain_send,
+  command_socket_print, command_socket_encode, command_socket_decode
+};
diff --git a/src/modules/frs_detail/Makefile b/src/modules/frs_detail/Makefile
new file mode 100644 (file)
index 0000000..d0ced71
--- /dev/null
@@ -0,0 +1,11 @@
+TARGET         = frs_detail
+SRCS           = frs_detail.c
+HEADERS                = 
+RLM_CFLAGS     =
+RLM_LIBS       = 
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
similarity index 83%
rename from src/main/detail.c
rename to src/modules/frs_detail/frs_detail.c
index 3e9c3f9..27b3112 100644 (file)
@@ -28,6 +28,8 @@ RCSID("$Id$")
 #include <freeradius-devel/modules.h>
 #include <freeradius-devel/detail.h>
 #include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/detail.h>
+
 
 #ifdef HAVE_SYS_STAT_H
 #include <sys/stat.h>
@@ -39,8 +41,6 @@ RCSID("$Id$")
 
 #include <fcntl.h>
 
-#ifdef WITH_DETAIL
-
 #define USEC (1000000)
 
 typedef struct listen_detail_t {
@@ -73,6 +73,157 @@ typedef struct listen_detail_t {
 #define STATE_REPLIED  (7)
 
 /*
+ *     Copied from rad_accounting without any changes.
+ *
+ *     This isn't perfect, but it helps with modularization
+ */
+static int detail_accounting(REQUEST *request)
+{
+       int result = RLM_MODULE_OK;
+
+
+#ifdef WITH_PROXY
+#define WAS_PROXIED (request->proxy)
+#else
+#define WAS_PROXIED (0)
+#endif
+
+       /*
+        *      Run the modules only once, before proxying.
+        */
+       if (!WAS_PROXIED) {
+               VALUE_PAIR      *vp;
+               int             acct_type = 0;
+
+               result = module_preacct(request);
+               switch (result) {
+                       /*
+                        *      The module has a number of OK return codes.
+                        */
+                       case RLM_MODULE_NOOP:
+                       case RLM_MODULE_OK:
+                       case RLM_MODULE_UPDATED:
+                               break;
+                       /*
+                        *      The module handled the request, stop here.
+                        */
+                       case RLM_MODULE_HANDLED:
+                               return result;
+                       /*
+                        *      The module failed, or said the request is
+                        *      invalid, therefore we stop here.
+                        */
+                       case RLM_MODULE_FAIL:
+                       case RLM_MODULE_INVALID:
+                       case RLM_MODULE_NOTFOUND:
+                       case RLM_MODULE_REJECT:
+                       case RLM_MODULE_USERLOCK:
+                       default:
+                               return result;
+               }
+
+               /*
+                *      Do the data storage before proxying. This is to ensure
+                *      that we log the packet, even if the proxy never does.
+                */
+               vp = pairfind(request->config_items, PW_ACCT_TYPE);
+               if (vp) {
+                       DEBUG2("  Found Acct-Type %s", vp->vp_strvalue);
+                       acct_type = vp->vp_integer;
+               }
+               result = module_accounting(acct_type, request);
+               switch (result) {
+                       /*
+                        *      In case the accounting module returns FAIL,
+                        *      it's still useful to send the data to the
+                        *      proxy.
+                        */
+                       case RLM_MODULE_FAIL:
+                       case RLM_MODULE_NOOP:
+                       case RLM_MODULE_OK:
+                       case RLM_MODULE_UPDATED:
+                               break;
+                       /*
+                        *      The module handled the request, don't reply.
+                        */
+                       case RLM_MODULE_HANDLED:
+                               return result;
+                       /*
+                        *      Neither proxy, nor reply to invalid requests.
+                        */
+                       case RLM_MODULE_INVALID:
+                       case RLM_MODULE_NOTFOUND:
+                       case RLM_MODULE_REJECT:
+                       case RLM_MODULE_USERLOCK:
+                       default:
+                               return result;
+               }
+
+               /*
+                *      Maybe one of the preacct modules has decided
+                *      that a proxy should be used.
+                */
+               if ((vp = pairfind(request->config_items, PW_PROXY_TO_REALM))) {
+                       REALM *realm;
+
+                       /*
+                        *      Check whether Proxy-To-Realm is
+                        *      a LOCAL realm.
+                        */
+                       realm = realm_find2(vp->vp_strvalue);
+                       if (realm && !realm->acct_pool) {
+                               DEBUG("rad_accounting: Cancelling proxy to realm %s, as it is a LOCAL realm.", realm->name);
+                               pairdelete(&request->config_items, PW_PROXY_TO_REALM);
+                       } else {
+                               /*
+                                *      Don't reply to the NAS now because
+                                *      we have to send the proxied packet
+                                *      before that.
+                                */
+                               return result;
+                       }
+               }
+       }
+
+       /*
+        *      We get here IF we're not proxying, OR if we've
+        *      received the accounting reply from the end server,
+        *      THEN we can reply to the NAS.
+        *      If the accounting module returns NOOP, the data
+        *      storage did not succeed, so radiusd should not send
+        *      Accounting-Response.
+        */
+       switch (result) {
+               /*
+                *      Send back an ACK to the NAS.
+                */
+               case RLM_MODULE_OK:
+               case RLM_MODULE_UPDATED:
+                       request->reply->code = PW_ACCOUNTING_RESPONSE;
+                       break;
+               /*
+                *      The module handled the request, don't reply.
+                */
+               case RLM_MODULE_HANDLED:
+                       break;
+               /*
+                *      Failed to log or to proxy the accounting data,
+                *      therefore don't reply to the NAS.
+                */
+               case RLM_MODULE_FAIL:
+               case RLM_MODULE_INVALID:
+               case RLM_MODULE_NOOP:
+               case RLM_MODULE_NOTFOUND:
+               case RLM_MODULE_REJECT:
+               case RLM_MODULE_USERLOCK:
+               default:
+                       break;
+       }
+       return result;
+}
+
+
+/*
  *     If we're limiting outstanding packets, then mark the response
  *     as being sent.
  */
@@ -176,17 +327,6 @@ int detail_send(rad_listen_t *listener, REQUEST *request)
        return 0;
 }
 
-int detail_delay(rad_listen_t *listener)
-{
-       listen_detail_t *data = listener->data;
-
-       if (!data->signal) return 0;
-
-       data->signal = 0;
-
-       return data->delay_time;
-}
-
 
 /*
  *     Open the detail file, if we can.
@@ -672,7 +812,7 @@ int detail_recv(rad_listen_t *listener,
                vp->vp_integer += time(NULL) - data->timestamp;
        }
 
-       *pfun = rad_accounting;
+       *pfun = detail_accounting;
 
        if (debug_flag) {
                fr_printf_log("detail_recv: Read packet from %s\n", data->filename_work);
@@ -726,18 +866,25 @@ int detail_print(rad_listen_t *this, char *buffer, size_t bufsize)
                        this->server);
 }
 
-int detail_encode(UNUSED rad_listen_t *this, UNUSED REQUEST *request)
+/*
+ *     FIXME: src/main/event.c doesn't ever call encode, so
+ *     we overload it here.
+ */
+int detail_encode(rad_listen_t *this, UNUSED REQUEST *request)
 {
-       /*
-        *      We never encode responses "sent to" the detail file.
-        */
-       return 0;
+       listen_detail_t *data = this->data;
+
+       if (!data->signal) return 0;
+
+       data->signal = 0;
+
+       return data->delay_time;
 }
 
 int detail_decode(UNUSED rad_listen_t *this, UNUSED REQUEST *request)
 {
        /*
-        *      We never decode responses read from the detail file.
+        *      We never decode responses "sent to" the detail file.
         */
        return 0;
 }
@@ -833,4 +980,10 @@ int detail_parse(CONF_SECTION *cs, rad_listen_t *this)
 
        return 0;
 }
-#endif
+
+frs_module_t frs_detail = {
+  FRS_MODULE_INIT, RAD_LISTEN_DETAIL, "detail",
+  detail_parse, detail_free,
+  detail_recv, detail_send,
+  detail_print, detail_encode, detail_decode
+};
diff --git a/src/modules/frs_dhcp/Makefile b/src/modules/frs_dhcp/Makefile
new file mode 100644 (file)
index 0000000..b020096
--- /dev/null
@@ -0,0 +1,11 @@
+TARGET         = frs_dhcp
+SRCS           = frs_dhcp.c dhcp.c
+HEADERS                = 
+RLM_CFLAGS     =
+RLM_LIBS       = 
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
similarity index 99%
rename from src/lib/dhcp.c
rename to src/modules/frs_dhcp/dhcp.c
index cc78947..d16d2be 100644 (file)
@@ -24,9 +24,9 @@
 #include       <freeradius-devel/ident.h>
 RCSID("$Id$")
 
-#include <freeradius-devel/libradius.h>
+#include <freeradius-devel/radiusd.h>
 #include <freeradius-devel/udpfromto.h>
-#include <freeradius-devel/dhcp.h>
+#include "dhcp.h"
 
 #ifdef WITH_DHCP
 #define DHCP_CHADDR_LEN        (16)
similarity index 90%
rename from src/main/dhcpd.c
rename to src/modules/frs_dhcp/frs_dhcp.c
index 8b38569..0282dc2 100644 (file)
  * Copyright 2008 Alan DeKok <aland@deployingradius.com>
  */
 
-#ifdef WITH_DHCP
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/conffile.h>
+#include <freeradius-devel/rad_assert.h>
+#include "dhcp.h"
 
 static int dhcp_process(REQUEST *request)
 {
@@ -83,7 +87,7 @@ static int dhcp_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
        int on = 1;
        listen_socket_t *sock;
 
-       rcode = common_socket_parse(cs, this);
+       rcode = listen_socket_parse(cs, this);
        if (rcode != 0) return rcode;
 
        sock = this->data;
@@ -173,5 +177,12 @@ static int dhcp_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
 {
        return fr_dhcp_decode(request->packet);
 }
-#endif /* WITH_DCHP */
+
+
+frs_module_t frs_dhcp = {
+  FRS_MODULE_INIT, RAD_LISTEN_DHCP, "dhcp",
+  dhcp_socket_parse, NULL,
+  dhcp_socket_recv, dhcp_socket_send,
+  listen_socket_print, dhcp_socket_encode, dhcp_socket_decode
+};
 
diff --git a/src/modules/frs_proxy/Makefile b/src/modules/frs_proxy/Makefile
new file mode 100644 (file)
index 0000000..02c4902
--- /dev/null
@@ -0,0 +1,11 @@
+TARGET         = frs_proxy
+SRCS           = frs_proxy.c
+HEADERS                = 
+RLM_CFLAGS     =
+RLM_LIBS       = 
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
diff --git a/src/modules/frs_proxy/frs_proxy.c b/src/modules/frs_proxy/frs_proxy.c
new file mode 100644 (file)
index 0000000..4d6910c
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * proxy.c     Handle PROXY traffic.
+ *
+ * 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 2007  The FreeRADIUS server project
+ * Copyright 2007  Alan DeKok <aland@deployingradius.com>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/rad_assert.h>
+
+
+/*
+ *     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->home_server->secret);
+}
+
+/*
+ *     Recieve packets from a proxy socket.
+ */
+static int proxy_socket_recv(rad_listen_t *listener,
+                             RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+{
+       REQUEST         *request;
+       RADIUS_PACKET   *packet;
+       char            buffer[128];
+
+       packet = rad_recv(listener->fd, 0);
+       if (!packet) {
+               radlog(L_ERR, "%s", fr_strerror());
+               return 0;
+       }
+
+       /*
+        *      FIXME: Client MIB updates?
+        */
+       switch(packet->code) {
+       case PW_AUTHENTICATION_ACK:
+       case PW_ACCESS_CHALLENGE:
+       case PW_AUTHENTICATION_REJECT:
+#ifdef WITH_ACCOUNTING
+       case PW_ACCOUNTING_RESPONSE:
+#endif
+               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;
+       }
+
+       request = received_proxy_response(packet);
+       if (!request) {
+               return 0;
+       }
+
+       rad_assert(request->process != NULL);
+
+       *pfun = request->process;
+       *prequest = request;
+
+       return 1;
+}
+
+static int proxy_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+       rad_encode(request->proxy, NULL, request->home_server->secret);
+       rad_sign(request->proxy, NULL, request->home_server->secret);
+
+       return 0;
+}
+
+
+static int proxy_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+       if (rad_verify(request->proxy_reply, request->proxy,
+                      request->home_server->secret) < 0) {
+               return -1;
+       }
+
+       return rad_decode(request->proxy_reply, request->proxy,
+                          request->home_server->secret);
+}
+
+frs_module_t frs_proxy = {
+       FRS_MODULE_INIT, RAD_LISTEN_PROXY, "proxy",
+       listen_socket_parse, NULL,
+       proxy_socket_recv, proxy_socket_send,
+       listen_socket_print, proxy_socket_encode, proxy_socket_decode
+};
diff --git a/src/modules/frs_status/Makefile b/src/modules/frs_status/Makefile
new file mode 100644 (file)
index 0000000..5694335
--- /dev/null
@@ -0,0 +1,11 @@
+TARGET         = frs_status
+SRCS           = frs_status.c
+HEADERS                = 
+RLM_CFLAGS     =
+RLM_LIBS       = 
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
diff --git a/src/modules/frs_status/frs_status.c b/src/modules/frs_status/frs_status.c
new file mode 100644 (file)
index 0000000..28c8615
--- /dev/null
@@ -0,0 +1,628 @@
+/*
+ * status.c    Statistics processing
+ *
+ * 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 2008 The FreeRADIUS server project
+ * Copyright 2008 Alan DeKok <aland@deployingradius.com>
+ */
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/stats.h>
+
+#ifdef WITH_STATS
+typedef struct fr_stats2vp {
+       int     attribute;
+       size_t  offset;
+} fr_stats2vp;
+
+/*
+ *     Authentication
+ */
+static fr_stats2vp authvp[] = {
+       { 128, offsetof(fr_stats_t, total_requests) },
+       { 129, offsetof(fr_stats_t, total_access_accepts) },
+       { 130, offsetof(fr_stats_t, total_access_rejects) },
+       { 131, offsetof(fr_stats_t, total_access_challenges) },
+       { 132, offsetof(fr_stats_t, total_responses) },
+       { 133, offsetof(fr_stats_t, total_dup_requests) },
+       { 134, offsetof(fr_stats_t, total_malformed_requests) },
+       { 135, offsetof(fr_stats_t, total_bad_authenticators) },
+       { 136, offsetof(fr_stats_t, total_packets_dropped) },
+       { 137, offsetof(fr_stats_t, total_unknown_types) },
+       { 0, 0 }
+};
+
+
+#ifdef WITH_PROXY
+/*
+ *     Proxied authentication requests.
+ */
+static fr_stats2vp proxy_authvp[] = {
+       { 138, offsetof(fr_stats_t, total_requests) },
+       { 139, offsetof(fr_stats_t, total_access_accepts) },
+       { 140, offsetof(fr_stats_t, total_access_rejects) },
+       { 141, offsetof(fr_stats_t, total_access_challenges) },
+       { 142, offsetof(fr_stats_t, total_responses) },
+       { 143, offsetof(fr_stats_t, total_dup_requests) },
+       { 144, offsetof(fr_stats_t, total_malformed_requests) },
+       { 145, offsetof(fr_stats_t, total_bad_authenticators) },
+       { 146, offsetof(fr_stats_t, total_packets_dropped) },
+       { 147, offsetof(fr_stats_t, total_unknown_types) },
+       { 0, 0 }
+};
+#endif
+
+
+#ifdef WITH_ACCOUNTING
+/*
+ *     Accounting
+ */
+static fr_stats2vp acctvp[] = {
+       { 148, offsetof(fr_stats_t, total_requests) },
+       { 149, offsetof(fr_stats_t, total_responses) },
+       { 150, offsetof(fr_stats_t, total_dup_requests) },
+       { 151, offsetof(fr_stats_t, total_malformed_requests) },
+       { 152, offsetof(fr_stats_t, total_bad_authenticators) },
+       { 153, offsetof(fr_stats_t, total_packets_dropped) },
+       { 154, offsetof(fr_stats_t, total_unknown_types) },
+       { 0, 0 }
+};
+
+#ifdef WITH_PROXY
+static fr_stats2vp proxy_acctvp[] = {
+       { 155, offsetof(fr_stats_t, total_requests) },
+       { 156, offsetof(fr_stats_t, total_responses) },
+       { 157, offsetof(fr_stats_t, total_dup_requests) },
+       { 158, offsetof(fr_stats_t, total_malformed_requests) },
+       { 159, offsetof(fr_stats_t, total_bad_authenticators) },
+       { 160, offsetof(fr_stats_t, total_packets_dropped) },
+       { 161, offsetof(fr_stats_t, total_unknown_types) },
+       { 0, 0 }
+};
+#endif
+#endif
+
+static fr_stats2vp client_authvp[] = {
+       { 128, offsetof(fr_stats_t, total_requests) },
+       { 129, offsetof(fr_stats_t, total_access_accepts) },
+       { 130, offsetof(fr_stats_t, total_access_rejects) },
+       { 131, offsetof(fr_stats_t, total_access_challenges) },
+       { 132, offsetof(fr_stats_t, total_responses) },
+       { 133, offsetof(fr_stats_t, total_dup_requests) },
+       { 134, offsetof(fr_stats_t, total_malformed_requests) },
+       { 135, offsetof(fr_stats_t, total_bad_authenticators) },
+       { 136, offsetof(fr_stats_t, total_packets_dropped) },
+       { 137, offsetof(fr_stats_t, total_unknown_types) },
+       { 0, 0 }
+};
+
+#ifdef WITH_ACCOUNTING
+static fr_stats2vp client_acctvp[] = {
+       { 155, offsetof(fr_stats_t, total_requests) },
+       { 156, offsetof(fr_stats_t, total_responses) },
+       { 157, offsetof(fr_stats_t, total_dup_requests) },
+       { 158, offsetof(fr_stats_t, total_malformed_requests) },
+       { 159, offsetof(fr_stats_t, total_bad_authenticators) },
+       { 160, offsetof(fr_stats_t, total_packets_dropped) },
+       { 161, offsetof(fr_stats_t, total_unknown_types) },
+       { 0, 0 }
+};
+#endif
+
+#define FR2ATTR(x) ((11344 << 16) | (x))
+
+static void request_stats_addvp(REQUEST *request,
+                               fr_stats2vp *table, fr_stats_t *stats)
+{
+       int i;
+       VALUE_PAIR *vp;
+
+       for (i = 0; table[i].attribute != 0; i++) {
+               vp = radius_paircreate(request, &request->reply->vps,
+                                      FR2ATTR(table[i].attribute),
+                                      PW_TYPE_INTEGER);
+               if (!vp) continue;
+
+               vp->vp_integer = *(int *)(((char *) stats) + table[i].offset);
+       }
+}
+
+
+/*
+ *     Find a listener by IP address && port.
+ */
+static rad_listen_t *listener_find_byipaddr(const fr_ipaddr_t *ipaddr,
+                                           int port)
+{
+       rad_listen_t *this;
+
+       for (this = mainconfig.listen; this != NULL; this = this->next) {
+               listen_socket_t *sock;
+
+               if ((this->type != RAD_LISTEN_AUTH) &&
+                   (this->type != RAD_LISTEN_ACCT)) continue;
+               
+               sock = this->data;
+
+               if ((sock->port == port) &&
+                   (fr_ipaddr_cmp(ipaddr, &sock->ipaddr) == 0)) {
+                       return this;
+               }
+       }
+
+       return NULL;
+}
+
+
+/*
+ *     Find a RADCLIENT_LIST based on listening IP address && port
+ */
+static RADCLIENT_LIST *listener_find_client_list(const fr_ipaddr_t *ipaddr,
+                                                int port)
+{
+       listen_socket_t *sock;
+       rad_listen_t *this;
+
+       this = listener_find_byipaddr(ipaddr, port);
+       if (!this) return NULL;
+
+       sock = this->data;
+       return sock->clients;
+}
+
+static void request_stats_reply(REQUEST *request)
+{
+       VALUE_PAIR *flag, *vp;
+
+       /*
+        *      Statistics are available ONLY on a "status" port.
+        */
+       rad_assert(request->packet->code == PW_STATUS_SERVER);
+       rad_assert(request->listener->type == RAD_LISTEN_NONE);
+               
+       flag = pairfind(request->packet->vps, FR2ATTR(127));
+       if (!flag || (flag->vp_integer == 0)) return;
+
+       /*
+        *      Authentication.
+        */
+       if (((flag->vp_integer & 0x01) != 0) &&
+           ((flag->vp_integer & 0xc0) == 0)) {
+               request_stats_addvp(request, authvp, &radius_auth_stats);
+       }
+               
+#ifdef WITH_ACCOUNTING
+       /*
+        *      Accounting
+        */
+       if (((flag->vp_integer & 0x02) != 0) &&
+           ((flag->vp_integer & 0xc0) == 0)) {
+               request_stats_addvp(request, acctvp, &radius_acct_stats);
+       }
+#endif
+
+#ifdef WITH_PROXY
+       /*
+        *      Proxied authentication requests.
+        */
+       if (((flag->vp_integer & 0x04) != 0) &&
+           ((flag->vp_integer & 0x20) == 0)) {
+               request_stats_addvp(request, proxy_authvp, &proxy_auth_stats);
+       }
+
+#ifdef WITH_ACCOUNTING
+       /*
+        *      Proxied accounting requests.
+        */
+       if (((flag->vp_integer & 0x08) != 0) &&
+           ((flag->vp_integer & 0x20) == 0)) {
+               request_stats_addvp(request, proxy_acctvp, &proxy_acct_stats);
+       }
+#endif
+#endif
+
+       /*
+        *      Internal server statistics
+        */
+       if ((flag->vp_integer & 0x10) != 0) {
+               vp = radius_paircreate(request, &request->reply->vps,
+                                      FR2ATTR(176), PW_TYPE_DATE);
+               if (vp) vp->vp_date = radius_start_time.tv_sec;
+               vp = radius_paircreate(request, &request->reply->vps,
+                                      FR2ATTR(177), PW_TYPE_DATE);
+               if (vp) vp->vp_date = radius_hup_time.tv_sec;
+               
+#ifdef HAVE_PTHREAD_H
+               int i, array[RAD_LISTEN_MAX];
+
+               thread_pool_queue_stats(array);
+
+               for (i = 0; i <= RAD_LISTEN_DETAIL; i++) {
+                       vp = radius_paircreate(request, &request->reply->vps,
+                                              FR2ATTR(162 + i),
+                                              PW_TYPE_INTEGER);
+                       
+                       if (!vp) continue;
+                       vp->vp_integer = array[i];
+               }
+#endif
+       }
+
+       /*
+        *      For a particular client.
+        */
+       if ((flag->vp_integer & 0x20) != 0) {
+               fr_ipaddr_t ipaddr;
+               VALUE_PAIR *server_ip, *server_port = NULL;
+               RADCLIENT *client = NULL;
+               RADCLIENT_LIST *cl = NULL;
+
+               /*
+                *      See if we need to look up the client by server
+                *      socket.
+                */
+               server_ip = pairfind(request->packet->vps, FR2ATTR(170));
+               if (server_ip) {
+                       server_port = pairfind(request->packet->vps,
+                                              FR2ATTR(171));
+
+                       if (server_port) {
+                               ipaddr.af = AF_INET;
+                               ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
+                               cl = listener_find_client_list(&ipaddr, server_port->vp_integer);
+                                                              
+                               /*
+                                *      Not found: don't do anything
+                                */
+                               if (!cl) return;
+                       }
+               }
+
+
+               vp = pairfind(request->packet->vps, FR2ATTR(167));
+               if (vp) {
+                       ipaddr.af = AF_INET;
+                       ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
+                       client = client_find(cl, &ipaddr);
+
+                       /*
+                        *      Else look it up by number.
+                        */
+               } else if ((vp = pairfind(request->packet->vps,
+                                          FR2ATTR(168))) != NULL) {
+                       client = client_findbynumber(cl, vp->vp_integer);
+               }
+
+               if (client) {
+                       /*
+                        *      If found, echo it back, along with
+                        *      the requested statistics.
+                        */
+                       pairadd(&request->reply->vps, paircopyvp(vp));
+
+                       /*
+                        *      When retrieving client by number, also
+                        *      echo back it's IP address.
+                        */
+                       if ((vp->type == PW_TYPE_INTEGER) &&
+                           (client->ipaddr.af == AF_INET)) {
+                               vp = radius_paircreate(request,
+                                                      &request->reply->vps,
+                                                      FR2ATTR(167),
+                                                      PW_TYPE_IPADDR);
+                               if (vp) {
+                                       vp->vp_ipaddr = client->ipaddr.ipaddr.ip4addr.s_addr;
+                               }
+
+                               if (client->prefix != 32) {
+                                       vp = radius_paircreate(request,
+                                                              &request->reply->vps,
+                                                              FR2ATTR(169),
+                                                              PW_TYPE_INTEGER);
+                                       if (vp) {
+                                               vp->vp_integer = client->prefix;
+                                       }
+                               }
+                       }
+                       
+                       if (server_ip) {
+                               pairadd(&request->reply->vps,
+                                       paircopyvp(server_ip));
+                               pairadd(&request->reply->vps,
+                                       paircopyvp(server_port));
+                       }
+
+                       if (client->auth &&
+                           ((flag->vp_integer & 0x01) != 0)) {
+                               request_stats_addvp(request, client_authvp,
+                                                   client->auth);
+                       }
+#ifdef WITH_ACCOUNTING
+                       if (client->acct &&
+                           ((flag->vp_integer & 0x01) != 0)) {
+                               request_stats_addvp(request, client_acctvp,
+                                                   client->acct);
+                       }
+#endif
+               } /* else client wasn't found, don't echo it back */
+       }
+
+       /*
+        *      For a particular "listen" socket.
+        */
+       if (((flag->vp_integer & 0x40) != 0) &&
+           ((flag->vp_integer & 0x03) != 0)) {
+               rad_listen_t *this;
+               VALUE_PAIR *server_ip, *server_port;
+               fr_ipaddr_t ipaddr;
+
+               /*
+                *      See if we need to look up the server by socket
+                *      socket.
+                */
+               server_ip = pairfind(request->packet->vps, FR2ATTR(170));
+               if (!server_ip) return;
+
+               server_port = pairfind(request->packet->vps,
+                                      FR2ATTR(171));
+               if (!server_port) return;
+               
+               ipaddr.af = AF_INET;
+               ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
+               this = listener_find_byipaddr(&ipaddr,
+                                             server_port->vp_integer);
+               
+               /*
+                *      Not found: don't do anything
+                */
+               if (!this) return;
+               
+               pairadd(&request->reply->vps,
+                       paircopyvp(server_ip));
+               pairadd(&request->reply->vps,
+                       paircopyvp(server_port));
+
+               if (((flag->vp_integer & 0x01) != 0) &&
+                   ((request->listener->type == RAD_LISTEN_AUTH) ||
+                    (request->listener->type == RAD_LISTEN_NONE))) {
+                       request_stats_addvp(request, authvp, &this->stats);
+               }
+               
+#ifdef WITH_ACCOUNTING
+               if (((flag->vp_integer & 0x02) != 0) &&
+                   ((request->listener->type == RAD_LISTEN_ACCT) ||
+                    (request->listener->type == RAD_LISTEN_NONE))) {
+                       request_stats_addvp(request, acctvp, &this->stats);
+               }
+#endif
+       }
+
+       /*
+        *      Home servers.
+        */
+       if (((flag->vp_integer & 0x80) != 0) &&
+           ((flag->vp_integer & 0x03) != 0)) {
+               home_server *home;
+               VALUE_PAIR *server_ip, *server_port;
+               fr_ipaddr_t ipaddr;
+
+               /*
+                *      See if we need to look up the server by socket
+                *      socket.
+                */
+               server_ip = pairfind(request->packet->vps, FR2ATTR(170));
+               if (!server_ip) return;
+
+               server_port = pairfind(request->packet->vps,
+                                      FR2ATTR(171));
+               if (!server_port) return;
+               
+               ipaddr.af = AF_INET;
+               ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
+               home = home_server_find(&ipaddr, server_port->vp_integer);
+
+               /*
+                *      Not found: don't do anything
+                */
+               if (!home) return;
+               
+               pairadd(&request->reply->vps,
+                       paircopyvp(server_ip));
+               pairadd(&request->reply->vps,
+                       paircopyvp(server_port));
+
+               vp = radius_paircreate(request, &request->reply->vps,
+                                      FR2ATTR(172), PW_TYPE_INTEGER);
+               if (vp) vp->vp_integer = home->currently_outstanding;
+
+               vp = radius_paircreate(request, &request->reply->vps,
+                                      FR2ATTR(173), PW_TYPE_INTEGER);
+               if (vp) vp->vp_integer = home->state;
+
+               if ((home->state == HOME_STATE_ALIVE) &&
+                   (home->revive_time.tv_sec != 0)) {
+                       vp = radius_paircreate(request, &request->reply->vps,
+                                              FR2ATTR(175), PW_TYPE_DATE);
+                       if (vp) vp->vp_date = home->revive_time.tv_sec;
+               }
+
+               if ((home->state == HOME_STATE_ALIVE) &&
+                   (home->ema.window > 0)) {
+                               vp = radius_paircreate(request,
+                                                      &request->reply->vps,
+                                                      FR2ATTR(178),
+                                                      PW_TYPE_INTEGER);
+                               if (vp) vp->vp_integer = home->ema.window;
+                               vp = radius_paircreate(request,
+                                                      &request->reply->vps,
+                                                      FR2ATTR(179),
+                                                      PW_TYPE_INTEGER);
+                               if (vp) vp->vp_integer = home->ema.ema1 / EMA_SCALE;
+                               vp = radius_paircreate(request,
+                                                      &request->reply->vps,
+                                                      FR2ATTR(180),
+                                                      PW_TYPE_INTEGER);
+                               if (vp) vp->vp_integer = home->ema.ema10 / EMA_SCALE;
+
+               }
+
+               if (home->state == HOME_STATE_IS_DEAD) {
+                       vp = radius_paircreate(request, &request->reply->vps,
+                                              FR2ATTR(174), PW_TYPE_DATE);
+                       if (vp) vp->vp_date = home->zombie_period_start.tv_sec + home->zombie_period;
+               }
+
+               if (((flag->vp_integer & 0x01) != 0) &&
+                   (home->type == HOME_TYPE_AUTH)) {
+                       request_stats_addvp(request, proxy_authvp,
+                                           &home->stats);
+               }
+
+#ifdef WITH_ACCOUNTING
+               if (((flag->vp_integer & 0x02) != 0) &&
+                   (home->type == HOME_TYPE_ACCT)) {
+                       request_stats_addvp(request, proxy_acctvp,
+                                           &home->stats);
+               }
+#endif
+       }
+}
+
+static int status_process(REQUEST *request)
+{
+       rad_status_server(request);
+
+       request_stats_reply(request);
+
+       return 0;
+}
+
+/*
+ *     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 status_socket_recv(rad_listen_t *listener,
+                           RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+{
+       ssize_t         rcode;
+       int             code, src_port;
+       RADIUS_PACKET   *packet;
+       RADCLIENT       *client;
+       fr_ipaddr_t     src_ipaddr;
+
+       rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
+       if (rcode < 0) return 0;
+
+       RAD_STATS_TYPE_INC(listener, total_requests);
+
+       if (rcode < 20) {       /* AUTH_HDR_LEN */
+               RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+               return 0;
+       }
+
+       if ((client = client_listener_find(listener,
+                                          &src_ipaddr, src_port)) == NULL) {
+               rad_recv_discard(listener->fd);
+               RAD_STATS_TYPE_INC(listener, total_invalid_requests);
+               return 0;
+       }
+
+       /*
+        *      We only understand Status-Server on this socket.
+        */
+       if (code != PW_STATUS_SERVER) {
+               DEBUG("Ignoring packet code %d sent to Status-Server port",
+                     code);
+               rad_recv_discard(listener->fd);
+               RAD_STATS_TYPE_INC(listener, total_unknown_types);
+               RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
+               return 0;
+       }
+
+       /*
+        *      Now that we've sanity checked everything, receive the
+        *      packet.
+        */
+       packet = rad_recv(listener->fd, 1); /* require message authenticator */
+       if (!packet) {
+               RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+               DEBUG("%s", fr_strerror());
+               return 0;
+       }
+
+       if (!received_request(listener, packet, prequest, client)) {
+               RAD_STATS_TYPE_INC(listener, total_packets_dropped);
+               RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
+               rad_free(&packet);
+               return 0;
+       }
+
+       *pfun = status_process;
+       return 1;
+}
+
+
+/*
+ *     Send an authentication response packet
+ */
+static int status_socket_send(rad_listen_t *listener, REQUEST *request)
+{
+       rad_assert(request->listener == listener);
+       rad_assert(listener->send == status_socket_send);
+
+       return rad_send(request->reply, request->packet,
+                       request->client->secret);
+}
+
+
+static int status_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+       if (!request->reply->code) return 0;
+
+       rad_encode(request->reply, request->packet,
+                  request->client->secret);
+       rad_sign(request->reply, request->packet,
+                request->client->secret);
+
+       return 0;
+}
+
+
+static int status_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+       if (rad_verify(request->packet, NULL,
+                      request->client->secret) < 0) {
+               return -1;
+       }
+
+       return rad_decode(request->packet, NULL,
+                         request->client->secret);
+}
+
+
+frs_module_t frs_status = {
+       FRS_MODULE_INIT, RAD_LISTEN_NONE,
+       "status", listen_socket_parse, NULL,
+       status_socket_recv, status_socket_send,
+       listen_socket_print, status_socket_encode, status_socket_decode
+};
+#endif
diff --git a/src/modules/frs_vmps/Makefile b/src/modules/frs_vmps/Makefile
new file mode 100644 (file)
index 0000000..d99ef0d
--- /dev/null
@@ -0,0 +1,11 @@
+TARGET         = frs_vmps
+SRCS           = frs_vmps.c vqp.c
+HEADERS                = vqp.h
+RLM_CFLAGS     =
+RLM_LIBS       = 
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
similarity index 79%
rename from src/main/vmps.c
rename to src/modules/frs_vmps/frs_vmps.c
index b88b11a..42af29f 100644 (file)
@@ -26,19 +26,30 @@ RCSID("$Id$")
 
 #include <freeradius-devel/radiusd.h>
 #include <freeradius-devel/modules.h>
-#include <freeradius-devel/vqp.h>
-#include <freeradius-devel/vmps.h>
 #include <freeradius-devel/rad_assert.h>
+#include "vqp.h"
 
 #ifdef WITH_VMPS
+static int vmps_process(REQUEST *request)
+{
+       DEBUG2("Doing VMPS");
+       module_post_auth(0, request);
+       DEBUG2("Done VMPS");
+
+       request->reply->code = PW_AUTHENTICATION_ACK;
+
+       return 0;
+}
+
+
 /*
  *     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.
  */
-int vqp_socket_recv(rad_listen_t *listener,
-                   RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+static int vqp_socket_recv(rad_listen_t *listener,
+                          RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
 {
        RADIUS_PACKET   *packet;
        RAD_REQUEST_FUNP fun = NULL;
@@ -76,7 +87,7 @@ int vqp_socket_recv(rad_listen_t *listener,
 /*
  *     Send an authentication response packet
  */
-int vqp_socket_send(rad_listen_t *listener, REQUEST *request)
+static int vqp_socket_send(rad_listen_t *listener, REQUEST *request)
 {
        rad_assert(request->listener == listener);
        rad_assert(listener->send == vqp_socket_send);
@@ -90,26 +101,22 @@ int vqp_socket_send(rad_listen_t *listener, REQUEST *request)
 }
 
 
-int vqp_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
+static int vqp_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
 {
        return vqp_encode(request->reply, request->packet);
 }
 
 
-int vqp_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
+static int vqp_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
 {
        return vqp_decode(request->packet);
 }
 
 
-int vmps_process(REQUEST *request)
-{
-       DEBUG2("Doing VMPS");
-       module_post_auth(0, request);
-       DEBUG2("Done VMPS");
-
-       request->reply->code = PW_AUTHENTICATION_ACK;
-
-       return 0;
-}
-#endif
+frs_module_t frs_vmps = {
+  FRS_MODULE_INIT, RAD_LISTEN_VQP, "vmps",
+  listen_socket_parse, NULL,
+  vqp_socket_recv, vqp_socket_send,
+  listen_socket_print, vqp_socket_encode, vqp_socket_decode
+};
+#endif /* WITH_VMPS */
similarity index 98%
rename from src/lib/vqp.c
rename to src/modules/frs_vmps/vqp.c
index f7ae1c0..bd67fb4 100644 (file)
 #include       <freeradius-devel/ident.h>
 RCSID("$Id$");
 
-#include       <freeradius-devel/libradius.h>
+#include       <freeradius-devel/radiusd.h>
 #include       <freeradius-devel/udpfromto.h>
-#include       <freeradius-devel/vqp.h>
+#include       "vqp.h"
 
 #ifdef WITH_VMPS
 
+#  define debug_pair(vp)       do { if (fr_debug_flag && fr_log_fp) { \
+                                       fputc('\t', fr_log_fp); \
+                                       vp_print(fr_log_fp, vp); \
+                                       fputc('\n', fr_log_fp); \
+                                    } \
+                               } while(0)
+
 /*
  *  http://www.openbsd.org/cgi-bin/cvsweb/src/usr.sbin/tcpdump/print-vqp.c
  *
similarity index 100%
rename from src/include/vqp.h
rename to src/modules/frs_vmps/vqp.h
index ddad07f..4bb36fe 100644 (file)
@@ -814,7 +814,7 @@ int eappeap_process(EAP_HANDLER *handler, tls_session_t *tls_session)
         *      Call authentication recursively, which will
         *      do PAP, CHAP, MS-CHAP, etc.
         */
-       rad_authenticate(fake);
+       request->process(fake);(fake);
 
        /*
         *      Note that we don't do *anything* with the reply
index 3f0bad6..024bb5c 100644 (file)
@@ -1180,7 +1180,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
         *      Call authentication recursively, which will
         *      do PAP, CHAP, MS-CHAP, etc.
         */
-       rad_authenticate(fake);
+       request->process(fake);
 
        /*
         *      Note that we don't do *anything* with the reply