This indicates how the process supports kicking users.
return TRUE;
}
+static int str_to_kick_type(const char *str, enum kick_type *kick_type_r)
+{
+ switch (str[0]) {
+ case 'N':
+ *kick_type_r = KICK_TYPE_NONE;
+ break;
+ case 'S':
+ *kick_type_r = KICK_TYPE_SIGNAL;
+ break;
+ case 'A':
+ *kick_type_r = KICK_TYPE_ADMIN_SOCKET;
+ break;
+ default:
+ return -1;
+ }
+ return str[1] == '\0' ? 0 : -1;
+}
+
static int
anvil_connection_request(struct anvil_connection *conn,
const char *const *args, const char **error_r)
*error_r = "CONNECT: Invalid ident string";
return -1;
}
- connect_limit_connect(connect_limit, pid, &key, conn_guid);
+ /* extra parameters: */
+ enum kick_type kick_type = KICK_TYPE_NONE;
+ if (args[0] != NULL) {
+ if (str_to_kick_type(args[0], &kick_type) < 0) {
+ *error_r = "CONNECT: Invalid kick_type";
+ return -1;
+ }
+ args++;
+ }
+ connect_limit_connect(connect_limit, pid, &key,
+ conn_guid, kick_type);
} else if (strcmp(cmd, "DISCONNECT") == 0) {
if (args[0] == NULL || args[1] == NULL) {
*error_r = "DISCONNECT: Not enough parameters";
struct process {
pid_t pid;
+ enum kick_type kick_type;
struct session *sessions;
};
static void
session_link_process(struct connect_limit *limit, struct session *session,
- pid_t pid)
+ pid_t pid, enum kick_type kick_type)
{
struct process *process;
session->process = process;
DLLIST_PREPEND_FULL(&process->sessions, session,
process_prev, process_next);
+ /* The kick_type shouldn't change for the process, but keep updating
+ it anyway. */
+ process->kick_type = kick_type;
}
static void
void connect_limit_connect(struct connect_limit *limit, pid_t pid,
const struct connect_limit_key *key,
- const guid_128_t conn_guid)
+ const guid_128_t conn_guid,
+ enum kick_type kick_type)
{
struct session *session, *first_user_session;
struct userip *userip;
session->userip = userip;
guid_128_copy(session->conn_guid, conn_guid);
- session_link_process(limit, session, pid);
+ session_link_process(limit, session, pid, kick_type);
const uint8_t *conn_guid_p = session->conn_guid;
hash_table_insert(limit->session_hash, conn_guid_p, session);
DLLIST_PREPEND_FULL(&first_user_session, session,
while (session != NULL) {
struct connect_limit_iter_result *result =
array_append_space(&iter->results);
+ result->kick_type = session->process->kick_type;
result->pid = session->process->pid;
result->service = session->userip->service;
guid_128_copy(result->conn_guid, session->conn_guid);
#include "net.h"
#include "guid.h"
+enum kick_type {
+ /* This process doesn't support kicking users */
+ KICK_TYPE_NONE,
+ /* User kicking should be done by sending TERM signal */
+ KICK_TYPE_SIGNAL,
+ /* User kicking should be done by sending KICK-USER command to the
+ process's admin socket or the existing anvil connection. */
+ KICK_TYPE_ADMIN_SOCKET,
+};
+
struct connect_limit_key {
/* User's primary username */
const char *username;
};
struct connect_limit_iter_result {
+ enum kick_type kick_type;
pid_t pid;
const char *service;
guid_128_t conn_guid;
const struct connect_limit_key *key);
void connect_limit_connect(struct connect_limit *limit, pid_t pid,
const struct connect_limit_key *key,
- const guid_128_t conn_guid);
+ const guid_128_t conn_guid,
+ enum kick_type kick_type);
void connect_limit_disconnect(struct connect_limit *limit, pid_t pid,
const struct connect_limit_key *key,
const guid_128_t conn_guid);