Example #1
0
static void
wdctl_reset(int fd, char *arg)
{
	t_client	*node;

	debug(LOG_DEBUG, "Entering wdctl_reset...");

	LOCK_CLIENT_LIST();
	debug(LOG_DEBUG, "Argument: %s (@%x)", arg, arg);

	/* We get the node or return... */
	if ((node = client_list_find_by_ip(arg)) != NULL);
	else if ((node = client_list_find_by_mac(arg)) != NULL);
	else {
		debug(LOG_DEBUG, "Client not found.");
		UNLOCK_CLIENT_LIST();
		write(fd, "No", 2);
		return;
	}

	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);

	UNLOCK_CLIENT_LIST();

	write(fd, "Yes", 3);

	debug(LOG_DEBUG, "Exiting wdctl_reset...");
}
Example #2
0
/** Ping clients to see if they are still active,
 *  refresh their traffic counters,
 *  remove and deny them if timed out
 */
void
fw_refresh_client_list(void)
{
	t_client *cp1, *cp2;
	time_t now, added_time, last_updated;
	s_config *config = config_get_config();

	/* Update all the counters */
	if (-1 == iptables_fw_counters_update()) {
		debug(LOG_ERR, "Could not get counters from firewall!");
		return;
	}

	LOCK_CLIENT_LIST();

	for (cp1 = cp2 = client_get_first_client(); NULL != cp1; cp1 = cp2) {
		cp2 = cp1->next;

		if (!(cp1 = client_list_find(cp1->ip, cp1->mac))) {
			debug(LOG_ERR, "Node %s was freed while being re-validated!", cp1->ip);
		} else {
			now = time(NULL);
			last_updated = cp1->counters.last_updated;
			added_time = cp1->added_time;
			if (last_updated +  (config->checkinterval * config->clienttimeout) <= now) {
				/* Timing out inactive user */
				debug(LOG_NOTICE, "%s %s inactive %d secs. kB in: %llu  kB out: %llu",
					cp1->ip, cp1->mac, config->checkinterval * config->clienttimeout,
					cp1->counters.incoming/1000, cp1->counters.outgoing/1000);
				if (cp1->fw_connection_state == FW_MARK_AUTHENTICATED) {
					iptables_fw_access(AUTH_MAKE_DEAUTHENTICATED, cp1);
				}
				client_list_delete(cp1);
			} else if (added_time +  (config->checkinterval * config->clientforceout) <= now) {
				/* Forcing out user */
				debug(LOG_NOTICE, "%s %s connected %d secs. kB in: %llu kB out: %llu",
					cp1->ip, cp1->mac, config->checkinterval * config->clientforceout,
					cp1->counters.incoming/1000, cp1->counters.outgoing/1000);
				if (cp1->fw_connection_state == FW_MARK_AUTHENTICATED) {
					iptables_fw_access(AUTH_MAKE_DEAUTHENTICATED, cp1);
				}
				client_list_delete(cp1);
			}
		}
	}
	UNLOCK_CLIENT_LIST();
}
Example #3
0
/** See if they are still active,
 *  refresh their traffic counters,
 *  remove and deny them if timed out
 */
static void
fw_refresh_client_list(void)
{
	t_client *cp1, *cp2;
	s_config *config = config_get_config();
	const int preauth_idle_timeout_secs = 60 * config->preauth_idle_timeout;
	const int auth_idle_timeout_secs = 60 * config->auth_idle_timeout;
	const time_t now = time(NULL);

	/* Update all the counters */
	if (-1 == iptables_fw_counters_update()) {
		debug(LOG_ERR, "Could not get counters from firewall!");
		return;
	}

	LOCK_CLIENT_LIST();

	for (cp1 = cp2 = client_get_first_client(); NULL != cp1; cp1 = cp2) {
		cp2 = cp1->next;

		if (!(cp1 = client_list_find_by_id(cp1->id))) {
			debug(LOG_ERR, "Client was freed while being re-validated!");
			continue;
		}

		int conn_state = cp1->fw_connection_state;
		int last_updated = cp1->counters.last_updated;

		if (cp1->session_end > 0 && cp1->session_end <= now) {
			/* Session ended (only > 0 for FW_MARK_AUTHENTICATED by binauth) */
			debug(LOG_NOTICE, "Force out user: %s %s, connected: %ds, in: %llukB, out: %llukB",
				cp1->ip, cp1->mac, now - cp1->session_end,
				cp1->counters.incoming / 1000, cp1->counters.outgoing / 1000);

			auth_change_state(cp1, FW_MARK_PREAUTHENTICATED, "timeout_deauth");
		} else if (preauth_idle_timeout_secs > 0
				&& conn_state == FW_MARK_PREAUTHENTICATED
				&& (last_updated + preauth_idle_timeout_secs) <= now) {
			/* Timeout inactive preauthenticated user */
			debug(LOG_NOTICE, "Timeout preauthenticated idle user: %s %s, inactive: %ds, in: %llukB, out: %llukB",
				cp1->ip, cp1->mac, now - last_updated,
				cp1->counters.incoming / 1000, cp1->counters.outgoing / 1000);

			client_list_delete(cp1);
		} else if (auth_idle_timeout_secs > 0
				&& conn_state == FW_MARK_AUTHENTICATED
				&& (last_updated + auth_idle_timeout_secs) <= now) {
			/* Timeout inactive user */
			debug(LOG_NOTICE, "Timeout authenticated idle user: %s %s, inactive: %ds, in: %llukB, out: %llukB",
				cp1->ip, cp1->mac, now - last_updated,
				cp1->counters.incoming / 1000, cp1->counters.outgoing / 1000);

			auth_change_state(cp1, FW_MARK_PREAUTHENTICATED, "idle_deauth");
		}
	}
	UNLOCK_CLIENT_LIST();
}
Example #4
0
void http_callback_logout(httpd *webserver, request *r)
{
	t_client *client;
	s_config *config = config_get_config();

	LOCK_CLIENT_LIST();
	client = client_list_find_by_ip(r->clientAddr);

	/* Send logout to auth server if client is logged in */
	if (client != NULL) {
		t_authresponse authresponse;
		char *ip = strdup(client->ip);
		char *mac = strdup(client->mac);
		char *token = strdup(client->token);
		unsigned long long incoming = client->counters.incoming;
		unsigned long long outgoing = client->counters.outgoing;

		debug(LOG_INFO, "Got manual logout from client ip %s, mac %s, token %s",
			client->ip, client->mac, client->token);

		fw_deny(client->ip, client->mac, client->fw_connection_state);
		client_list_delete(client);

		/* Unlock client list here since auth_server_request may take a while */
		UNLOCK_CLIENT_LIST();

		/* Advertise the logout if we have an auth server */
		if (config->auth_servers != NULL) {
			auth_server_request(&authresponse, REQUEST_TYPE_LOGOUT, ip,
								mac, token, incoming, outgoing);
		}

		free(ip);
		free(mac);
		free(token);
	} else {
		/* Do nothing if the client is not in the client list (i.e. not logged in) */
		debug(LOG_INFO, "Got manual logout from client %s, but client not in list", r->clientAddr);
		UNLOCK_CLIENT_LIST();
	}

	if (config->auth_servers != NULL) {
		/* Re-direct them to auth server */
		char *urlFragment = NULL;
		t_auth_serv	*auth_server = get_auth_server();

		safe_asprintf(&urlFragment, "%smessage=%s",
			auth_server->authserv_msg_script_path_fragment,
			GATEWAY_MESSAGE_ACCOUNT_LOGGED_OUT
		);
		http_send_redirect_to_auth(r, urlFragment, "Redirect to logout message");
		free(urlFragment);
	}
}
Example #5
0
/** Take action on a client.
 * Alter the firewall rules and client list accordingly.
*/
void
auth_client_action(const char ip[], const char mac[], t_authaction action)
{
	t_client *client;

	LOCK_CLIENT_LIST();

	client = client_list_find(ip,mac);

	/* Client should already have hit the server and be on the client list */
	if (client == NULL) {
		debug(LOG_ERR, "Client %s %s action %d is not on client list",
			  ip, mac, action);
		UNLOCK_CLIENT_LIST();
		return;
	}

	switch(action) {

	case AUTH_MAKE_AUTHENTICATED:
		if(client->fw_connection_state != FW_MARK_AUTHENTICATED) {
			client->fw_connection_state = FW_MARK_AUTHENTICATED;
			iptables_fw_access(AUTH_MAKE_AUTHENTICATED, client);
			authenticated_since_start++;
		} else {
			debug(LOG_INFO, "Nothing to do, %s %s already authenticated", client->ip, client->mac);
		}
		break;

	case AUTH_MAKE_DEAUTHENTICATED:
		if(client->fw_connection_state == FW_MARK_AUTHENTICATED) {
			iptables_fw_access(AUTH_MAKE_DEAUTHENTICATED, client);
		}
		client_list_delete(client);
		break;

	default:
		debug(LOG_ERR, "Unknown auth action: %d",action);
	}
	UNLOCK_CLIENT_LIST();
	return;
}
Example #6
0
    void
http_callback_auth(httpd *webserver, request *r)
{
    t_client	*client;
    httpVar * token;
    char	*mac;
    httpVar *logout = httpdGetVariableByName(r, "logout");
    if ((token = httpdGetVariableByName(r, "token"))) {
        /* They supplied variable "token" */
        if (!(mac = arp_get(r->clientAddr))) {
            /* We could not get their MAC address */
            debug(LOG_ERR, "Failed to retrieve MAC address for ip %s", r->clientAddr);
            send_http_page(r, "WiFiDog Error", "Failed to retrieve your MAC address");
        } else {
            /* We have their MAC address */

            LOCK_CLIENT_LIST();

            if ((client = client_list_find(r->clientAddr, mac)) == NULL) {
                debug(LOG_DEBUG, "New client for %s", r->clientAddr);
                client_list_append(r->clientAddr, mac, token->value);
            } else if (logout) {
                t_authresponse  authresponse;
                s_config *config = config_get_config();
                unsigned long long incoming = client->counters.incoming;
                unsigned long long outgoing = client->counters.outgoing;
                char *ip = safe_strdup(client->ip);
                char *urlFragment = NULL;
                t_auth_serv	*auth_server = get_auth_server();

                fw_deny(client->ip, client->mac, client->fw_connection_state);
                client_list_delete(client);
                debug(LOG_DEBUG, "Got logout from %s", client->ip);

                /* 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->value,
                            incoming, outgoing);
                    LOCK_CLIENT_LIST();

                    /* Re-direct them to auth server */
                    debug(LOG_INFO, "Got manual logout from client ip %s, mac %s, token %s"
                            "- redirecting them to logout message", client->ip, client->mac, client->token);
                    safe_asprintf(&urlFragment, "%smessage=%s",
                            auth_server->authserv_msg_script_path_fragment,
                            GATEWAY_MESSAGE_ACCOUNT_LOGGED_OUT
                            );
                    http_send_redirect_to_auth(r, urlFragment, "Redirect to logout message");
                    free(urlFragment);
                }
                free(ip);
            }
            else {
                debug(LOG_DEBUG, "Client for %s is already in the client list", client->ip);
            }
            UNLOCK_CLIENT_LIST();
            if (!logout) {
                authenticate_client(r);
            }
            free(mac);
        }
    } else {
        /* They did not supply variable "token" */
        send_http_page(r, "WiFiDog error", "Invalid token");
    }
}
/**Probably a misnomer, this function actually refreshes the entire client list's traffic counter, re-authenticates every client with the central server and update's the central servers traffic counters and notifies it if a client has logged-out.
 * @todo Make this function smaller and use sub-fonctions
 */
void
fw_sync_with_authserver(void)
{
    t_authresponse authresponse;
    t_client *p1, *p2, *worklist, *tmp;
    s_config *config = config_get_config();

    if (-1 == iptables_fw_counters_update()) {
        debug(LOG_ERR, "Could not get counters from firewall!");
        return;
    }

    LOCK_CLIENT_LIST();

    /* XXX Ideally, from a thread safety PoV, this function should build a list of client pointers,
     * iterate over the list and have an explicit "client still valid" check while list is locked.
     * That way clients can disappear during the cycle with no risk of trashing the heap or getting
     * a SIGSEGV.
     */
    client_list_dup(&worklist);
    UNLOCK_CLIENT_LIST();

    for (p1 = p2 = worklist; NULL != p1; p1 = p2) {
        p2 = p1->next;

        /* Ping the client, if he responds it'll keep activity on the link.
         * However, if the firewall blocks it, it will not help.  The suggested
         * way to deal witht his is to keep the DHCP lease time extremely
         * short:  Shorter than config->checkinterval * config->clienttimeout */
        icmp_ping(p1->ip);
        /* Update the counters on the remote server only if we have an auth server */
        if (config->auth_servers != NULL) {
            auth_server_request(&authresponse, REQUEST_TYPE_COUNTERS, p1->ip, p1->mac, p1->token, p1->counters.incoming,
                                p1->counters.outgoing, p1->counters.incoming_delta, p1->counters.outgoing_delta);
        }

        time_t current_time = time(NULL);
        debug(LOG_INFO,
              "Checking client %s for timeout:  Last updated %ld (%ld seconds ago), timeout delay %ld seconds, current time %ld, ",
              p1->ip, p1->counters.last_updated, current_time - p1->counters.last_updated,
              config->checkinterval * config->clienttimeout, current_time);
        if (p1->counters.last_updated + (config->checkinterval * config->clienttimeout) <= current_time) {
            /* 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);
            LOCK_CLIENT_LIST();
            tmp = client_list_find_by_client(p1);
            if (NULL != tmp) {
                logout_client(tmp);
            } else {
                debug(LOG_NOTICE, "Client was already removed. Not logging out.");
            }
            UNLOCK_CLIENT_LIST();
        } else {
            /*
             * This handles any change in
             * the status this allows us
             * to change the status of a
             * user while he's connected
             *
             * Only run if we have an auth server
             * configured!
             */
            LOCK_CLIENT_LIST();
            tmp = client_list_find_by_client(p1);
            if (NULL == tmp) {
                UNLOCK_CLIENT_LIST();
                debug(LOG_NOTICE, "Client was already removed. Skipping auth processing");
                continue;       /* Next client please */
            }

            if (config->auth_servers != NULL) {
                switch (authresponse.authcode) {
                case AUTH_DENIED:
                    debug(LOG_NOTICE, "%s - Denied. Removing client and firewall rules", tmp->ip);
                    fw_deny(tmp);
                    client_list_delete(tmp);
                    break;

                case AUTH_VALIDATION_FAILED:
                    debug(LOG_NOTICE, "%s - Validation timeout, now denied. Removing client and firewall rules",
                          tmp->ip);
                    fw_deny(tmp);
                    client_list_delete(tmp);
                    break;

                case AUTH_ALLOWED:
                    if (tmp->fw_connection_state != FW_MARK_KNOWN) {
                        debug(LOG_INFO, "%s - Access has changed to allowed, refreshing firewall and clearing counters",
                              tmp->ip);
                        //WHY did we deny, then allow!?!? benoitg 2007-06-21
                        //fw_deny(tmp->ip, tmp->mac, tmp->fw_connection_state); /* XXX this was possibly to avoid dupes. */

                        if (tmp->fw_connection_state != FW_MARK_PROBATION) {
                            tmp->counters.incoming_delta =
                             tmp->counters.outgoing_delta =
                             tmp->counters.incoming =
                             tmp->counters.outgoing = 0;
                        } else {
                            //We don't want to clear counters if the user was in validation, it probably already transmitted data..
                            debug(LOG_INFO,
                                  "%s - Skipped clearing counters after all, the user was previously in validation",
                                  tmp->ip);
                        }
                        fw_allow(tmp, FW_MARK_KNOWN);
                    }
                    break;

                case AUTH_VALIDATION:
                    /*
                     * Do nothing, user
                     * is in validation
                     * period
                     */
                    debug(LOG_INFO, "%s - User in validation period", tmp->ip);
                    break;

                case AUTH_ERROR:
                    debug(LOG_WARNING, "Error communicating with auth server - leaving %s as-is for now", tmp->ip);
                    break;

                default:
                    debug(LOG_ERR, "I do not know about authentication code %d", authresponse.authcode);
                    break;
                }
            }
            UNLOCK_CLIENT_LIST();
        }
    }

    client_list_destroy(worklist);
}
Example #8
0
static int client_thread(SceSize args, void *argp)
{
	char cmd[16];
	cmd_dispatch_func dispatch_func;
	ClientInfo *client = (ClientInfo *)argp;

	DEBUG("Client thread %i started!\n", client->num);

	client_send_ctrl_msg(client, "220 FTPVita Server ready.\n");

	while (1) {

		memset(client->recv_buffer, 0, sizeof(client->recv_buffer));

		client->n_recv = sceNetRecv(client->ctrl_sockfd, client->recv_buffer, sizeof(client->recv_buffer), 0);
		if (client->n_recv > 0) {
			DEBUG("Received %i bytes from client number %i:\n",
				client->n_recv, client->num);

			INFO("\t%i> %s", client->num, client->recv_buffer);

			/* The command are the first chars until the first space */
			sscanf(client->recv_buffer, "%s", cmd);

			/* Wait 1 ms before sending any data */
			sceKernelDelayThread(1*1000);

			if ((dispatch_func = get_dispatch_func(cmd))) {
				dispatch_func(client);
			} else {
				client_send_ctrl_msg(client, "502 Sorry, command not implemented. :(\n");
			}

		} else if (client->n_recv == 0) {
			/* Value 0 means connection closed by the remote peer */
			INFO("Connection closed by the client %i.\n", client->num);
			/* Delete itself from the client list */
			client_list_delete(client);
			break;
		} else if (client->n_recv == PSP2_NET_ERROR_ECANCELED) {
			/* PSP2_NET_ERROR_ECANCELED means socket shutdown */
			DEBUG("Client %i socket shutdown\n", client->num);
			break;
		} else {
			/* Other errors */
			INFO("Socket error client %i.\n", client->num);
			client_list_delete(client);
			break;
		}
	}

	/* Close the client's socket */
	sceNetSocketClose(client->ctrl_sockfd);

	/* If there's an open data connection, close it */
	if (client->data_con_type != FTP_DATA_CONNECTION_NONE) {
		sceNetSocketClose(client->data_sockfd);
		if (client->data_con_type == FTP_DATA_CONNECTION_PASSIVE) {
			sceNetSocketClose(client->pasv_sockfd);
		}
	}

	DEBUG("Client thread %i exiting!\n", client->num);

	/* Temporary newlib thread malloc bug fix */
	// free(client);

	sceKernelExitDeleteThread(0);
	return 0;
}
Example #9
0
/** Authenticates a single client against the central server and returns when done
 * Alters the firewall rules depending on what the auth server says
@param r httpd request struct
*/
void
authenticate_client(request *r, char *gw_id)
{
	t_client	*client;
	t_authresponse	auth_response;
	char	*mac,
		*token;
	char *urlFragment = NULL;
	s_config	*config = NULL;
	t_auth_serv	*auth_server = NULL;

	LOCK_CLIENT_LIST();

	client = client_list_find_by_ip(r->clientAddr);

	if (client == NULL) {
		debug(LOG_ERR, "Could not find client for %s", r->clientAddr);
		UNLOCK_CLIENT_LIST();
		return;
	}
	
	mac = safe_strdup(client->mac);
	token = safe_strdup(client->token);
	
	UNLOCK_CLIENT_LIST();
	
	/* 
	 * At this point we've released the lock while we do an HTTP request since it could
	 * take multiple seconds to do and the gateway would effectively be frozen if we
	 * kept the lock.
	 */
	auth_server_request(&auth_response, REQUEST_TYPE_LOGIN, r->clientAddr, mac, token, 0, 0, gw_id);
	
	LOCK_CLIENT_LIST();
	
	/* can't trust the client to still exist after n seconds have passed */
	client = client_list_find(r->clientAddr, mac);
	
	if (client == NULL) {
		debug(LOG_ERR, "Could not find client node for %s (%s)", r->clientAddr, mac);
		UNLOCK_CLIENT_LIST();
		free(token);
		free(mac);
		return;
	}
	
	free(token);
	free(mac);

	/* Prepare some variables we'll need below */
	config = config_get_config();
	auth_server = get_auth_server();

	switch(auth_response.authcode) {

	case AUTH_ERROR:
		/* Error talking to central server */
		debug(LOG_ERR, "Got %d from central server authenticating token %s from %s at %s", auth_response, client->token, client->ip, client->mac);
		send_http_page(r, "Error!", "Error: We did not get a valid answer from the central server");
		break;

	case AUTH_DENIED:
		/* Central server said invalid token */
		debug(LOG_INFO, "Got DENIED from central server authenticating token %s from %s at %s - redirecting them to denied message", client->token, client->ip, client->mac);
		safe_asprintf(&urlFragment, "%smessage=%s",
			auth_server->authserv_msg_script_path_fragment,
			GATEWAY_MESSAGE_DENIED
		);
		http_send_redirect_to_auth(r, urlFragment, "Redirect to portal", gw_id);
		//set connection logged out (xperimental)
		//snprintf(,client->token, client->ip, client->mac)	
		/*{
			char mysqlCmd[256];
			sprintf(mysqlCmd,"echo \"DELETE FROM connections WHERE token='%s';\"|mysql -uauthpuppy -pauthpuppydev authpuppy > /tmp/wifidog_deauth_mysql_result",client->token);
			debug(LOG_WARNING,"issuing this would help: %s",mysqlCmd);
			//system(mysqlCmd);//kills wifidog somehow *g
		}*/
		free(urlFragment);
		
		//for race conditions, remove from firewall
		fw_deny(client->ip, client->mac, client->fw_connection_state);
		//experimental delete client from list
                client_list_delete(client);

		break;

    case AUTH_VALIDATION:
		/* They just got validated for X minutes to check their email */
		debug(LOG_INFO, "Got VALIDATION from central server authenticating token %s from %s at %s"
				"- adding to firewall and redirecting them to activate message", client->token,
				client->ip, client->mac);
		client->fw_connection_state = FW_MARK_PROBATION;
		fw_allow(client->ip, client->mac, FW_MARK_PROBATION);
		safe_asprintf(&urlFragment, "%smessage=%s",
			auth_server->authserv_msg_script_path_fragment,
			GATEWAY_MESSAGE_ACTIVATE_ACCOUNT
		);
		http_send_redirect_to_auth(r, urlFragment, "Redirect to activate message", gw_id);
		free(urlFragment);
	    break;

    case AUTH_ALLOWED:
		/* Logged in successfully as a regular account */
		debug(LOG_INFO, "Got ALLOWED from central server authenticating token %s from %s at %s - "
				"adding to firewall and redirecting them to portal", client->token, client->ip, client->mac);
		client->fw_connection_state = FW_MARK_KNOWN;
		fw_allow(client->ip, client->mac, FW_MARK_KNOWN);
        served_this_session++;
		safe_asprintf(&urlFragment, "%sgw_id=%s",
			auth_server->authserv_portal_script_path_fragment,
			gw_id
		);
		http_send_redirect_to_auth(r, urlFragment, "Redirect to portal", gw_id);
		free(urlFragment);
	    break;

    case AUTH_VALIDATION_FAILED:
		 /* Client had X minutes to validate account by email and didn't = too late */
		debug(LOG_INFO, "Got VALIDATION_FAILED from central server authenticating token %s from %s at %s "
				"- redirecting them to failed_validation message", client->token, client->ip, client->mac);
		safe_asprintf(&urlFragment, "%smessage=%s",
			auth_server->authserv_msg_script_path_fragment,
			GATEWAY_MESSAGE_ACCOUNT_VALIDATION_FAILED
		);
		http_send_redirect_to_auth(r, urlFragment, "Redirect to failed validation message", gw_id);
		free(urlFragment);
	    break;

    default:
		debug(LOG_WARNING, "I don't know what the validation code %d means for token %s from %s at %s - sending error message", auth_response.authcode, client->token, client->ip, client->mac);
		send_http_page(r, "Internal Error", "We can not validate your request at this time");
	    break;

	}

	UNLOCK_CLIENT_LIST();
	return;
}
Example #10
0
void notify_client_disconnect(char *mac, char *ifname)
{
    t_client *client;
    t_redir_node *node;
    FILE *output;
    char *script, ip[16], rc;
    unsigned long long int counter;
    struct in_addr tempaddr;
    int ifIndex = get_ifIndex(ifname);
    //     printf("Client Disconnected\n");
    LOCK_REDIR();

    node = redir_list_find(mac);
    if (node && node->redir_pending) {
        UNLOCK_REDIR();
        safe_asprintf(&script, "%s %s", "iptables", "-v -n -x -t mangle -L " CHAIN_OUTGOING);
        iptables_insert_gateway_id(&script);
        output = popen(script, "r");
        free(script);
        if (!output) {
            debug(LOG_ERR, "popen(): %s", strerror(errno));
            return -1;
        }

        /* skip the first two lines */
        while (('\n' != fgetc(output)) && !feof(output)) ;
        while (('\n' != fgetc(output)) && !feof(output)) ;
        while (output && !(feof(output))) {
            rc = fscanf(output, "%*s %llu %*s %*s %*s %*s %*s %15[0-9.] %*s %*s %17[0-9a-fA-F:] %*s %*s 0x%*u", &counter, ip, mac);
            if (3 == rc && EOF != rc) {
                /* Sanity */
                if (!inet_aton(ip, &tempaddr)) {
                    debug(LOG_WARNING, "I was supposed to read an IP address but instead got [%s] - ignoring it", ip);
                    continue;
                }
                debug(LOG_DEBUG, "Read outgoing traffic for %s(%s): Bytes=%llu", ip, mac, counter);
                LOCK_CLIENT_LIST();
                if ((client = client_list_find_by_ip(ip))) {
                    client->counters.outgoing = client->counters.outgoing_history + counter;
                    client->counters.last_updated = time(NULL);
                    UNLOCK_CLIENT_LIST();
                    pclose(output);
                    return;
                }
            }
        }
        UNLOCK_CLIENT_LIST();
        pclose(output);
    }

    if(node)
        if(node->ifindex != ifIndex)
            debug(LOG_NOTICE,"%s: %s connected to idx %d, recv'd disconnect evt from idx %d\n",__func__, mac, node->ifindex, ifIndex);

    if (node && (node->ifindex == ifIndex)) {
        if (node->redir_pending) {
            char command[100];
            char fmac[13];
            formatmacaddr(mac, &fmac);
            node->redir_pending = 0;
            debug(LOG_NOTICE,"%s: recv'd disconnect evt for %s from idx %d\n",__func__, mac, node->ifindex);
            snprintf(command,100,"echo %s > /proc/sys/net/bridge/bridge-http-redirect-del-mac",fmac);
            //      printf("%s",command);
            execute(command,0);
            if (node->route_added) {
                memset(command, 0, sizeof(command));
                sprintf(command, "/bin/ip route del %s/32 src %s dev %s", node->host_ip, node->dev_ip, node->dev);
                //printf("\nexecuting %s\n", command);
                execute(command, 0);
            }
            fw_mark_mangle(mac,0);
        }
        debug(LOG_NOTICE,"%s: removing node list for %s from idx %d\n",__func__, mac, node->ifindex);
        redir_list_delete(node);
    }

    UNLOCK_REDIR();

    LOCK_CLIENT_LIST();
    client = client_list_find_by_mac(mac);
    if (client) {
        /*fw_deny_raw(client->ip, client->mac, client->fw_connection_state);*/
        iptables_fw_access(FW_ACCESS_DENY, client->ip, client->mac, client->fw_connection_state);
        client_list_delete(client);
    }
    UNLOCK_CLIENT_LIST();
}
Example #11
0
void notify_client_connect(char *mac, char *ifname)
{
    t_client *client;
    t_redir_node *node;
    s_config *config = config_get_config();
    int ifIndex = get_ifIndex(ifname);

    if( !config->status[ifIndex] ) {
        debug(LOG_NOTICE, "Captive Portal is not enabled for %s", ifname);
        return;
    }
    LOCK_REDIR();
    //  config_cp_auth_status(ifname, mac, 1); /* Updating the cpAuthStatus to 1 */
    node = redir_list_find(mac);
    if (!node) {
        node = redir_list_append(mac);
    }
    if (!node) {
        UNLOCK_REDIR();
        return;
    }
    debug(LOG_NOTICE,"%s recv'd association req from mac %s  %p\n",__func__,mac, node);
    
    /*post_event(ifname, mac, 1 << 0); *//* BIT0 is set which is a session query notification */
    node->ifindex = ifIndex;
    node->wlindex = config->profile[ifIndex];
    if (ifname) strncpy(node->dev, ifname, sizeof(node->dev));
    node->cpAuthstatus = 1;
    node->expiry = time(NULL);

    if (!node->redir_pending) {
        char command[100];
        char fmac[13];
        formatmacaddr(mac, &fmac);
        node->redir_pending = 1;
        snprintf(command,100,"echo %s > /proc/sys/net/bridge/bridge-http-redirect-add-mac",fmac);
        //      printf("%s",command);
        execute(command,0);
        fw_mark_mangle(mac,1);
    }
    if(config->operate_mode){
        if((time(NULL) - timekeeper[0].timestamp) > MAX_HOSTNAME_RESOLVE_TIMEOUT){
            make_proc_entry_for_url(config->portal[0], 0);
            timekeeper[0].timestamp = time(NULL);
        }
    }else{
        if((time(NULL) - timekeeper[ifIndex].timestamp) > MAX_HOSTNAME_RESOLVE_TIMEOUT){
            make_proc_entry_for_url(config->portal[ifIndex], ifIndex);
            timekeeper[ifIndex].timestamp = time(NULL);
        }
    }
    timekeeper[ifIndex].timestamp = time(NULL);

    UNLOCK_REDIR();

    LOCK_CLIENT_LIST();

    client = client_list_find_by_mac(mac);
    if (client) {
        /*fw_deny_raw(client->ip, client->mac, client->fw_connection_state);      *//*PRATIK: Commented so that it doesn't invoke the firewall*/
    iptables_fw_access(FW_ACCESS_DENY, client->ip, client->mac, client->fw_connection_state);    
    client_list_delete(client);
    }

    UNLOCK_CLIENT_LIST();
}