From 2c843ae3d1a1f9a77bf4e906ffb96ef318bb18cc Mon Sep 17 00:00:00 2001
From: Wichert Akkerman <wichert@wiggy.net>
Date: Mon, 28 Apr 2008 17:32:26 +0200
Subject: [PATCH] Refactor logout logic so we can share code

An extra free.. oops
---
 src/client_list.c  |   24 +++++++++++++++++-------
 src/client_list.h  |    8 +++++++-
 src/firewall.c     |   44 +++++++++++++++++++++++++++++++++++---------
 src/firewall.h     |    5 +++++
 src/http.c         |   10 ++--------
 src/wdctl_thread.c |    5 +----
 6 files changed, 67 insertions(+), 29 deletions(-)

diff --git a/src/client_list.c b/src/client_list.c
index 65ab88c..de51975 100644
--- a/src/client_list.c
+++ b/src/client_list.c
@@ -199,7 +199,7 @@ client_list_find_by_token(char *token)
  * @param client Points to the client to be freed
  */
 void
-_client_list_free_node(t_client * client)
+client_free_node(t_client * client)
 {
 
     if (client->mac != NULL)
@@ -224,6 +224,19 @@ _client_list_free_node(t_client * client)
 void
 client_list_delete(t_client * client)
 {
+	client_list_remove(client);
+	client_free_node(client);
+}
+
+
+/**
+ * @brief Removes a client from the connections list
+ *
+ * @param client Points to the client to be deleted
+ */
+void
+client_list_remove(t_client * client)
+{
     t_client         *ptr;
 
     ptr = firstclient;
@@ -232,19 +245,16 @@ client_list_delete(t_client * client)
         debug(LOG_ERR, "Node list empty!");
     } else if (ptr == client) {
         firstclient = ptr->next;
-        _client_list_free_node(client);
     } else {
         /* Loop forward until we reach our point in the list. */
         while (ptr->next != NULL && ptr->next != client) {
             ptr = ptr->next;
         }
         /* If we reach the end before finding out element, complain. */
-        if (ptr->next == NULL) {
+        if (ptr->next == NULL)
             debug(LOG_ERR, "Node to delete could not be found.");
-        /* Free element. */
-        } else {
+        else
             ptr->next = client->next;
-            _client_list_free_node(client);
-        }
     }
 }
+
diff --git a/src/client_list.h b/src/client_list.h
index ad62c9d..fd860a8 100644
--- a/src/client_list.h
+++ b/src/client_list.h
@@ -76,9 +76,15 @@ t_client *client_list_find_by_mac(char *mac); /* needed by wdctl_thread.c */
 /** @brief Finds a client by its token */
 t_client *client_list_find_by_token(char *token);
 
-/** @brief Deletes a client from the connections list */
+/** @brief Deletes a client from the connections list and frees its memoery*/
 void client_list_delete(t_client *client);
 
+/** @brief Removes a client from the connections list */
+void client_list_remove(t_client *client);
+
+/** @brief Free memory associated with a client */
+void client_free_node(t_client *client);
+
 #define LOCK_CLIENT_LIST() do { \
 	debug(LOG_DEBUG, "Locking client list"); \
 	pthread_mutex_lock(&client_list_mutex); \
diff --git a/src/firewall.c b/src/firewall.c
index 9c32f0b..6794998 100644
--- a/src/firewall.c
+++ b/src/firewall.c
@@ -269,15 +269,7 @@ fw_sync_with_authserver(void)
                 /* Timing out user */
                 debug(LOG_INFO, "%s - Inactive for more than %ld seconds, removing client and denying in firewall",
                         p1->ip, config->checkinterval * config->clienttimeout);
-                fw_deny(p1->ip, p1->mac, p1->fw_connection_state);
-                client_list_delete(p1);
-
-                /* Advertise the logout if we have an auth server */
-                if (config->auth_servers != NULL) {
-					UNLOCK_CLIENT_LIST();
-					auth_server_request(&authresponse, REQUEST_TYPE_LOGOUT, ip, mac, token, 0, 0);
-					LOCK_CLIENT_LIST();
-                }
+		logout_client(p1);
             } else {
                 /*
                  * This handles any change in
@@ -348,6 +340,40 @@ fw_sync_with_authserver(void)
     UNLOCK_CLIENT_LIST();
 }
 
+/**
+ * @brief Logout a client and report to auth server.
+ *
+ * This function assumes it is being called with the client lock held! This
+ * function remove the client from the client list and free its memory, so
+ * client is no langer valid when this method returns.
+ *
+ * @param client Points to the client to be logged out
+ */
+void
+logout_client(t_client *client)
+{
+	t_authresponse  authresponse;
+	const s_config *config = config_get_config();
+	fw_deny(client->ip, client->mac, client->fw_connection_state);
+	client_list_remove(client);
+
+	/* Advertise the logout if we have an auth server */
+	if (config->auth_servers != NULL) {
+		UNLOCK_CLIENT_LIST();
+		auth_server_request(&authresponse, REQUEST_TYPE_LOGOUT,
+				client->ip, client->mac, client->token,
+				client->counters.incoming,
+				client->counters.outgoing);
+
+		if (authresponse.authcode==AUTH_ERROR) 
+			debug(LOG_WARNING, "Auth server error when reporting logout");
+		LOCK_CLIENT_LIST();
+	}
+
+	client_free_node(client);
+}
+
+
 void
 icmp_ping(char *host)
 {
diff --git a/src/firewall.h b/src/firewall.h
index 5c59240..03cd128 100644
--- a/src/firewall.h
+++ b/src/firewall.h
@@ -27,6 +27,8 @@
 #ifndef _FIREWALL_H_
 #define _FIREWALL_H_
 
+#include "client_list.h"
+
 int icmp_fd;
 
 /** Used by fw_iptables.c */
@@ -67,4 +69,7 @@ void icmp_ping(char *host);
 /** @brief cheap random */
 unsigned short rand16(void);
 
+/** @brief Logout a client and report to auth server. */
+void logout_client(t_client *client);
+
 #endif /* _FIREWALL_H_ */
diff --git a/src/http.c b/src/http.c
index d10c107..391ddd2 100644
--- a/src/http.c
+++ b/src/http.c
@@ -296,14 +296,8 @@ http_callback_disconnect(httpd *webserver, request *r)
 			return -1;
 		}
 
-		/* TODO: get current firewall counters, set counters to auth server,
-		 * send disconnect to auth server.
-		 *
-		 * XXX: this should share code with wdctl_reset
-		 */
-		fw_deny(client->ip, client->mac, client->fw_connection_state);
-		client_list_delete(client);
-
+		/* TODO: get current firewall counters */
+                logout_client(client);
 		UNLOCK_CLIENT_LIST();
 
 	} else {
diff --git a/src/wdctl_thread.c b/src/wdctl_thread.c
index 0cfadbb..c64b668 100644
--- a/src/wdctl_thread.c
+++ b/src/wdctl_thread.c
@@ -381,10 +381,7 @@ wdctl_reset(int fd, char *arg)
 	debug(LOG_DEBUG, "Got node %x.", node);
 	
 	/* deny.... */
-	/* TODO: maybe just deleting the connection is not best... But this
-	 * is a manual command, I don't anticipate it'll be that useful. */
-	fw_deny(node->ip, node->mac, node->fw_connection_state);
-	client_list_delete(node);
+	logout_client(node);
 	
 	UNLOCK_CLIENT_LIST();
 	
-- 
1.5.5.1


