int mail_session_connect_parse(const char *const *args, const char **error_r) { struct mail_session *session; const char *session_id; pid_t pid; struct ip_addr ip; unsigned int i; /* <session id> <username> <service> <pid> [key=value ..] */ if (str_array_length(args) < 4) { *error_r = "CONNECT: Too few parameters"; return -1; } session_id = args[0]; if (str_to_pid(args[3], &pid) < 0) { *error_r = t_strdup_printf("CONNECT: Invalid pid %s for session ID %s", args[3], session_id); return -1; } session = hash_table_lookup(mail_sessions_hash, session_id); if (session != NULL) { *error_r = t_strdup_printf( "CONNECT: Duplicate session ID %s for user %s service %s", session_id, args[1], args[2]); return -1; } session = i_malloc(sizeof(struct mail_session) + stats_alloc_size()); session->stats = (void *)(session + 1); session->refcount = 1; /* unrefed at disconnect */ session->id = i_strdup(session_id); session->service = str_table_ref(services, args[2]); session->pid = pid; session->last_update = ioloop_timeval; session->to_idle = timeout_add(MAIL_SESSION_IDLE_TIMEOUT_MSECS, mail_session_idle_timeout, session); session->user = mail_user_login(args[1]); for (i = 3; args[i] != NULL; i++) { if (strncmp(args[i], "rip=", 4) == 0 && net_addr2ip(args[i] + 4, &ip) == 0) session->ip = mail_ip_login(&ip); } hash_table_insert(mail_sessions_hash, session->id, session); DLLIST_PREPEND_FULL(&stable_mail_sessions, session, stable_prev, stable_next); DLLIST2_APPEND_FULL(&mail_sessions_head, &mail_sessions_tail, session, sorted_prev, sorted_next); DLLIST_PREPEND_FULL(&session->user->sessions, session, user_prev, user_next); mail_user_ref(session->user); if (session->ip != NULL) { DLLIST_PREPEND_FULL(&session->ip->sessions, session, ip_prev, ip_next); mail_ip_ref(session->ip); } global_memory_alloc(mail_session_memsize(session)); return 0; }
static int client_export_iter_user(struct client *client) { struct client_export_cmd *cmd = client->cmd_export; struct mail_user *user = client->mail_user_iter; i_assert(cmd->level == MAIL_EXPORT_LEVEL_USER); mail_user_unref(&client->mail_user_iter); if (!cmd->header_sent) { o_stream_nsend_str(client->output, "user\treset_timestamp\tlast_update" "\tnum_logins\tnum_cmds"MAIL_STATS_HEADER); cmd->header_sent = TRUE; } for (; user != NULL; user = user->stable_next) { if (client_is_busy(client)) break; if (!mail_export_filter_match_user(&cmd->filter, user)) continue; str_truncate(cmd->str, 0); str_append_tabescaped(cmd->str, user->name); str_printfa(cmd->str, "\t%ld", (long)user->reset_timestamp); client_export_timeval(cmd->str, &user->last_update); str_printfa(cmd->str, "\t%u\t%u", user->num_logins, user->num_cmds); client_export_mail_stats(cmd->str, &user->stats); str_append_c(cmd->str, '\n'); o_stream_nsend(client->output, str_data(cmd->str), str_len(cmd->str)); } if (user != NULL) { client->mail_user_iter = user; mail_user_ref(user); return 0; } return 1; }
int mail_session_connect_parse(const char *const *args, const char **error_r) { struct mail_session *session; guid_128_t session_guid; uint8_t *guid_p; pid_t pid; struct ip_addr ip; unsigned int i; /* <session guid> <username> <service> <pid> [key=value ..] */ if (str_array_length(args) < 4) { *error_r = "CONNECT: Too few parameters"; return -1; } if (guid_128_from_string(args[0], session_guid) < 0) { *error_r = "CONNECT: Invalid GUID"; return -1; } if (str_to_pid(args[3], &pid) < 0) { *error_r = "CONNECT: Invalid pid"; return -1; } guid_p = session_guid; session = hash_table_lookup(mail_sessions_hash, guid_p); if (session != NULL) { *error_r = "CONNECT: Duplicate session GUID"; return -1; } session = i_new(struct mail_session, 1); session->refcount = 1; /* unrefed at disconnect */ session->service = i_strdup(args[2]); memcpy(session->guid, session_guid, sizeof(session->guid)); session->pid = pid; session->last_update = ioloop_timeval; session->to_idle = timeout_add(MAIL_SESSION_IDLE_TIMEOUT_MSECS, mail_session_idle_timeout, session); session->user = mail_user_login(args[1]); for (i = 3; args[i] != NULL; i++) { if (strncmp(args[i], "rip=", 4) == 0 && net_addr2ip(args[i] + 4, &ip) == 0) session->ip = mail_ip_login(&ip); } guid_p = session->guid; hash_table_insert(mail_sessions_hash, guid_p, session); DLLIST_PREPEND_FULL(&stable_mail_sessions, session, stable_prev, stable_next); DLLIST2_APPEND_FULL(&mail_sessions_head, &mail_sessions_tail, session, sorted_prev, sorted_next); DLLIST_PREPEND_FULL(&session->user->sessions, session, user_prev, user_next); mail_user_ref(session->user); if (session->ip != NULL) { DLLIST_PREPEND_FULL(&session->ip->sessions, session, ip_prev, ip_next); mail_ip_ref(session->ip); } global_memory_alloc(mail_session_memsize(session)); return 0; }
static bool client_export_iter_init(struct client *client) { struct client_export_cmd *cmd = client->cmd_export; if (cmd->filter.user != NULL && strchr(cmd->filter.user, '*') == NULL && (cmd->level == MAIL_EXPORT_LEVEL_USER || cmd->level == MAIL_EXPORT_LEVEL_SESSION)) { /* exact user */ struct mail_user *user = mail_user_lookup(cmd->filter.user); if (user == NULL) return FALSE; if (cmd->level == MAIL_EXPORT_LEVEL_SESSION) { client->mail_session_iter = user->sessions; if (client->mail_session_iter == NULL) return FALSE; mail_session_ref(client->mail_session_iter); cmd->export_iter = client_export_iter_session; } else { client->mail_user_iter = user; mail_user_ref(user); cmd->export_iter = client_export_iter_user; } return TRUE; } if (cmd->filter.ip_bits == IPADDR_BITS(&cmd->filter.ip) && (cmd->level == MAIL_EXPORT_LEVEL_IP || cmd->level == MAIL_EXPORT_LEVEL_SESSION)) { /* exact IP address */ struct mail_ip *ip = mail_ip_lookup(&cmd->filter.ip); if (ip == NULL) return FALSE; if (cmd->level == MAIL_EXPORT_LEVEL_SESSION) { client->mail_session_iter = ip->sessions; if (client->mail_session_iter == NULL) return FALSE; mail_session_ref(client->mail_session_iter); cmd->export_iter = client_export_iter_session; } else { client->mail_ip_iter = ip; mail_ip_ref(ip); cmd->export_iter = client_export_iter_ip; } return TRUE; } if (cmd->filter.domain != NULL && strchr(cmd->filter.domain, '*') == NULL && (cmd->level == MAIL_EXPORT_LEVEL_DOMAIN || cmd->level == MAIL_EXPORT_LEVEL_USER)) { /* exact domain */ struct mail_domain *domain = mail_domain_lookup(cmd->filter.domain); if (domain == NULL) return FALSE; if (cmd->level == MAIL_EXPORT_LEVEL_USER) { client->mail_user_iter = domain->users; mail_user_ref(client->mail_user_iter); cmd->export_iter = client_export_iter_user; } else { client->mail_domain_iter = domain; mail_domain_ref(domain); cmd->export_iter = client_export_iter_domain; } return TRUE; } switch (cmd->level) { case MAIL_EXPORT_LEVEL_COMMAND: client->mail_cmd_iter = stable_mail_commands_head; if (client->mail_cmd_iter == NULL) return FALSE; mail_command_ref(client->mail_cmd_iter); cmd->export_iter = client_export_iter_command; break; case MAIL_EXPORT_LEVEL_SESSION: client->mail_session_iter = stable_mail_sessions; if (client->mail_session_iter == NULL) return FALSE; mail_session_ref(client->mail_session_iter); cmd->export_iter = client_export_iter_session; break; case MAIL_EXPORT_LEVEL_USER: client->mail_user_iter = stable_mail_users; if (client->mail_user_iter == NULL) return FALSE; mail_user_ref(client->mail_user_iter); cmd->export_iter = client_export_iter_user; break; case MAIL_EXPORT_LEVEL_DOMAIN: client->mail_domain_iter = stable_mail_domains; if (client->mail_domain_iter == NULL) return FALSE; mail_domain_ref(client->mail_domain_iter); cmd->export_iter = client_export_iter_domain; break; case MAIL_EXPORT_LEVEL_IP: client->mail_ip_iter = stable_mail_ips; if (client->mail_ip_iter == NULL) return FALSE; mail_ip_ref(client->mail_ip_iter); cmd->export_iter = client_export_iter_ip; break; } i_assert(cmd->export_iter != NULL); return TRUE; }