Fix bug #45: [Request] Whoip command.
Rewrote patches from Zoltan to support ip ranges and multiple results per IP. Needed to make sure IPv6 mapped IPv4 addresses were converted to proper IPv4 addresses after accept().
This commit is contained in:
parent
041ce7a1fb
commit
6358c7f9cd
@ -307,6 +307,49 @@ static int command_getip(struct hub_info* hub, struct hub_user* user, struct hub
|
|||||||
return command_status(hub, user, cmd, tmp);
|
return command_status(hub, user, cmd, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int command_whoip(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
|
{
|
||||||
|
char* address = list_get_first(cmd->args);
|
||||||
|
struct ip_range range;
|
||||||
|
struct linked_list* users;
|
||||||
|
struct hub_user* u;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = ip_convert_address_to_range(address, &range);
|
||||||
|
if (!ret)
|
||||||
|
return command_status(hub, user, cmd, "Invalid IP address/range/mask");
|
||||||
|
|
||||||
|
users = (struct linked_list*) list_create();
|
||||||
|
ret = uman_get_user_by_addr(hub, users, &range);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
list_destroy(users);
|
||||||
|
return command_status(hub, user, cmd, "No users found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
char tmp[128];
|
||||||
|
snprintf(tmp, 128, "Found %d match%s:", (int) ret, ((ret != 1) ? "es" : ""));
|
||||||
|
|
||||||
|
char* buffer = hub_malloc(((MAX_NICK_LEN + 1) * ret) + strlen(tmp) + 2);
|
||||||
|
buffer[0] = 0;
|
||||||
|
strcat(buffer, tmp);
|
||||||
|
strcat(buffer, "\n");
|
||||||
|
|
||||||
|
u = (struct hub_user*) list_get_first(users);
|
||||||
|
while (u)
|
||||||
|
{
|
||||||
|
strcat(buffer, u->id.nick);
|
||||||
|
strcat(buffer, "\n");
|
||||||
|
u = (struct hub_user*) list_get_next(users);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = command_status(hub, user, cmd, buffer);
|
||||||
|
hub_free(buffer);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef CRASH_DEBUG
|
#ifdef CRASH_DEBUG
|
||||||
static int command_crash(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
static int command_crash(struct hub_info* hub, struct hub_user* user, struct hub_command* cmd)
|
||||||
{
|
{
|
||||||
@ -372,6 +415,7 @@ static struct commands_handler command_handlers[] = {
|
|||||||
{ "shutdown", 8, 0, cred_admin, command_shutdown, "Shutdown hub." },
|
{ "shutdown", 8, 0, cred_admin, command_shutdown, "Shutdown hub." },
|
||||||
{ "myip", 4, 0, cred_guest, command_myip, "Show your own IP." },
|
{ "myip", 4, 0, cred_guest, command_myip, "Show your own IP." },
|
||||||
{ "getip", 5, "n", cred_operator, command_getip, "Show IP address for a user" },
|
{ "getip", 5, "n", cred_operator, command_getip, "Show IP address for a user" },
|
||||||
|
{ "whoip", 5, "a", cred_operator, command_whoip, "Show users matching IP range" },
|
||||||
#ifdef CRASH_DEBUG
|
#ifdef CRASH_DEBUG
|
||||||
{ "crash", 5, 0, cred_admin, command_crash, "Crash the hub (DEBUG)." },
|
{ "crash", 5, 0, cred_admin, command_crash, "Crash the hub (DEBUG)." },
|
||||||
#endif
|
#endif
|
||||||
|
@ -223,6 +223,21 @@ struct hub_user* uman_get_user_by_nick(struct hub_info* hub, const char* nick)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, struct ip_range* range)
|
||||||
|
{
|
||||||
|
size_t num = 0;
|
||||||
|
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list); /* iterate users - only on incoming INF msg */
|
||||||
|
while (user)
|
||||||
|
{
|
||||||
|
if (ip_in_range(&user->net.ipaddr, range))
|
||||||
|
{
|
||||||
|
list_append(users, user);
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
user = (struct hub_user*) list_get_next(hub->users->list);
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
|
int uman_send_user_list(struct hub_info* hub, struct hub_user* target)
|
||||||
{
|
{
|
||||||
|
@ -99,6 +99,13 @@ extern struct hub_user* uman_get_user_by_cid(struct hub_info* hub, const char* c
|
|||||||
*/
|
*/
|
||||||
extern struct hub_user* uman_get_user_by_nick(struct hub_info* hub, const char* nick);
|
extern struct hub_user* uman_get_user_by_nick(struct hub_info* hub, const char* nick);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup users based on an ip address range.
|
||||||
|
*
|
||||||
|
* @return The number of users matching the addressess, or -1 on error (mask is wrong).
|
||||||
|
*/
|
||||||
|
extern size_t uman_get_user_by_addr(struct hub_info* hub, struct linked_list* users, struct ip_range* range);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send the user list of connected clients to 'user'.
|
* Send the user list of connected clients to 'user'.
|
||||||
* Usually part of the login process.
|
* Usually part of the login process.
|
||||||
|
@ -336,9 +336,20 @@ int net_accept(int fd, struct ip_addr_encap* ipaddr)
|
|||||||
memset(ipaddr, 0, sizeof(struct ip_addr_encap));
|
memset(ipaddr, 0, sizeof(struct ip_addr_encap));
|
||||||
ipaddr->af = addr4->sin_family;
|
ipaddr->af = addr4->sin_family;
|
||||||
if (ipaddr->af == AF_INET6)
|
if (ipaddr->af == AF_INET6)
|
||||||
|
{
|
||||||
|
char address[INET6_ADDRSTRLEN+1] = { 0, };
|
||||||
|
net_address_to_string(AF_INET6, (void*) &addr6->sin6_addr, address, INET6_ADDRSTRLEN+1);
|
||||||
|
if (!strncmp(address, "::ffff:", 7))
|
||||||
|
{
|
||||||
|
/* Hack to convert IPv6 mapped IPv4 addresses to true IPv4 addresses */
|
||||||
|
net_string_to_address(AF_INET, address + 7, (void*) &ipaddr->internal_ip_data.in);
|
||||||
|
ipaddr->af = AF_INET;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr));
|
memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr));
|
memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr));
|
||||||
|
Loading…
Reference in New Issue
Block a user