Agrego manager para enviar eventos.
parent
9dac3ca7ed
commit
715dfeddf7
|
@ -0,0 +1,725 @@
|
||||||
|
/*
|
||||||
|
* manager.c
|
||||||
|
* This file is part of Network-inador
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 - Félix Arreola Rodríguez
|
||||||
|
*
|
||||||
|
* Network-inador is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Network-inador is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Network-inador; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
#include <linux/if_addr.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "interfaces.h"
|
||||||
|
#include "ip-address.h"
|
||||||
|
#include "network-inador-manager.h"
|
||||||
|
|
||||||
|
#define COMMAND_SOCKET_PATH "/tmp/network-inador.socket"
|
||||||
|
|
||||||
|
static void _manager_send_error (ManagerClientInfo *manager_client, int error, int orig_cmd) {
|
||||||
|
unsigned char buffer[8];
|
||||||
|
|
||||||
|
buffer[0] = NET_INADOR_TYPE_RESPONSE_ERROR;
|
||||||
|
buffer[1] = orig_cmd;
|
||||||
|
buffer[2] = error;
|
||||||
|
|
||||||
|
send (manager_client->fd, buffer, 3, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _manager_send_executed (ManagerClientInfo *manager_client) {
|
||||||
|
unsigned char buffer[8];
|
||||||
|
|
||||||
|
buffer[0] = NET_INADOR_TYPE_RESPONSE;
|
||||||
|
buffer[1] = NET_INADOR_RESPONSE_EXECUTED;
|
||||||
|
|
||||||
|
send (manager_client->fd, buffer, 2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _manager_send_end_command (ManagerClientInfo *manager_client, int orig_cmd) {
|
||||||
|
unsigned char buffer[8];
|
||||||
|
|
||||||
|
buffer[0] = NET_INADOR_TYPE_RESPONSE_LISTING_END;
|
||||||
|
buffer[1] = orig_cmd;
|
||||||
|
|
||||||
|
send (manager_client->fd, buffer, 2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Interface * _manager_fetch_interface (ManagerClientInfo *manager_client, unsigned char *buffer, int orig_cmd) {
|
||||||
|
Interface *iface;
|
||||||
|
uint32_t index;
|
||||||
|
|
||||||
|
memcpy (&index, buffer, 4);
|
||||||
|
|
||||||
|
/* TODO: Revisar el ntohl */
|
||||||
|
iface = _interfaces_locate_by_index (manager_client->manager->handle->interfaces, index);
|
||||||
|
|
||||||
|
if (iface == NULL) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_IFACE_INDEX, orig_cmd);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _manager_send_interface (ManagerClientInfo *manager_client, Interface *iface, gboolean is_event) {
|
||||||
|
unsigned char buffer[32 + IFNAMSIZ + IFNAMSIZ];
|
||||||
|
int name_len = strlen (iface->name);
|
||||||
|
|
||||||
|
if (is_event) {
|
||||||
|
buffer[0] = NET_INADOR_TYPE_EVENT;
|
||||||
|
buffer[1] = NET_INADOR_EVENT_IFACE_ADDED;
|
||||||
|
} else {
|
||||||
|
buffer[0] = NET_INADOR_TYPE_RESPONSE;
|
||||||
|
buffer[1] = NET_INADOR_RESPONSE_IFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (&buffer[2], &iface->index, 4);
|
||||||
|
memcpy (&buffer[6], &iface->link_type, 4);
|
||||||
|
memcpy (&buffer[10], &iface->master_index, 4);
|
||||||
|
memcpy (&buffer[14], &iface->mtu, 4);
|
||||||
|
memcpy (&buffer[18], &iface->flags, 2);
|
||||||
|
buffer[20] = iface->is_wireless;
|
||||||
|
buffer[21] = name_len;
|
||||||
|
memcpy (&buffer[22], iface->name, name_len);
|
||||||
|
|
||||||
|
send (manager_client->fd, buffer, 22 + name_len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _manager_send_interface_del (ManagerClientInfo *manager_client, uint32_t index) {
|
||||||
|
unsigned char buffer[8];
|
||||||
|
|
||||||
|
buffer[0] = NET_INADOR_TYPE_EVENT;
|
||||||
|
buffer[1] = NET_INADOR_EVENT_IFACE_REMOVED;
|
||||||
|
|
||||||
|
memcpy (&buffer[2], &index, 4);
|
||||||
|
|
||||||
|
send (manager_client->fd, buffer, 6, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _manager_send_ip (ManagerClientInfo *manager_client, IPAddr *ip_addr, gboolean is_event) {
|
||||||
|
unsigned char buffer[80];
|
||||||
|
int family_size = 0;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
if (is_event) {
|
||||||
|
buffer[0] = NET_INADOR_TYPE_EVENT;
|
||||||
|
buffer[1] = NET_INADOR_EVENT_IPADDR_ADDED;
|
||||||
|
} else {
|
||||||
|
buffer[0] = NET_INADOR_TYPE_RESPONSE;
|
||||||
|
buffer[1] = NET_INADOR_RESPONSE_IPADDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ip_addr->family == AF_INET) {
|
||||||
|
family_size = sizeof (struct in_addr);
|
||||||
|
} else if (ip_addr->family == AF_INET6) {
|
||||||
|
family_size = sizeof (struct in6_addr);
|
||||||
|
}
|
||||||
|
memcpy (&buffer[2], &ip_addr->iface->index, 4);
|
||||||
|
buffer[6] = ip_addr->family;
|
||||||
|
buffer[7] = ip_addr->prefix;
|
||||||
|
|
||||||
|
buffer[8] = 0;
|
||||||
|
if (ip_addr->has_local) {
|
||||||
|
buffer[8] |= 0x01;
|
||||||
|
}
|
||||||
|
if (ip_addr->has_brd) {
|
||||||
|
buffer[8] |= 0x02;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[9] = ip_addr->scope;
|
||||||
|
memcpy (&buffer[10], &ip_addr->flags, 4);
|
||||||
|
|
||||||
|
memcpy (&buffer[14], &ip_addr->addr, family_size);
|
||||||
|
pos = 14 + family_size;
|
||||||
|
if (ip_addr->has_local) {
|
||||||
|
memcpy (&buffer[pos], &ip_addr->local_addr, family_size);
|
||||||
|
pos += family_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ip_addr->has_brd) {
|
||||||
|
memcpy (&buffer[pos], &ip_addr->brd_addr, family_size);
|
||||||
|
pos += family_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
send (manager_client->fd, buffer, pos, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _manager_send_ip_del (ManagerClientInfo *manager_client, IPAddr *ip_addr) {
|
||||||
|
unsigned char buffer[80];
|
||||||
|
int family_size = 0;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
buffer[0] = NET_INADOR_TYPE_EVENT;
|
||||||
|
buffer[1] = NET_INADOR_EVENT_IPADDR_REMOVED;
|
||||||
|
|
||||||
|
if (ip_addr->family == AF_INET) {
|
||||||
|
family_size = sizeof (struct in_addr);
|
||||||
|
} else if (ip_addr->family == AF_INET6) {
|
||||||
|
family_size = sizeof (struct in6_addr);
|
||||||
|
}
|
||||||
|
memcpy (&buffer[2], &ip_addr->iface->index, 4);
|
||||||
|
buffer[6] = ip_addr->family;
|
||||||
|
buffer[7] = ip_addr->prefix;
|
||||||
|
|
||||||
|
buffer[8] = 0;
|
||||||
|
if (ip_addr->has_local) {
|
||||||
|
buffer[8] |= 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[9] = 0;
|
||||||
|
|
||||||
|
memcpy (&buffer[10], &ip_addr->addr, family_size);
|
||||||
|
pos = 10 + family_size;
|
||||||
|
if (ip_addr->has_local) {
|
||||||
|
memcpy (&buffer[pos], &ip_addr->local_addr, family_size);
|
||||||
|
pos += family_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
send (manager_client->fd, buffer, pos, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _manager_send_list_interfaces (ManagerClientInfo *manager_client) {
|
||||||
|
GList *g;
|
||||||
|
Interface *iface;
|
||||||
|
|
||||||
|
g = manager_client->manager->handle->interfaces;
|
||||||
|
while (g != NULL) {
|
||||||
|
iface = (Interface *) g->data;
|
||||||
|
|
||||||
|
_manager_send_interface (manager_client, iface, FALSE);
|
||||||
|
g = g->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
_manager_send_end_command (manager_client, NET_INADOR_COMMAND_LIST_IFACES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _manager_send_iface (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
|
||||||
|
Interface *iface;
|
||||||
|
|
||||||
|
if (buffer_len < 6) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_GET_IFACE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = _manager_fetch_interface (manager_client, &buffer[2], NET_INADOR_COMMAND_GET_IFACE);
|
||||||
|
if (iface == NULL) return;
|
||||||
|
|
||||||
|
_manager_send_interface (manager_client, iface, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _manager_send_list_ips (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
|
||||||
|
int family;
|
||||||
|
GList *g;
|
||||||
|
IPAddr *ip_addr;
|
||||||
|
Interface *iface;
|
||||||
|
|
||||||
|
if (buffer_len < 7) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_LIST_IP);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
family = buffer[6];
|
||||||
|
|
||||||
|
if (family != AF_UNSPEC && family != AF_INET && family != AF_INET6) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_FAMILY, NET_INADOR_COMMAND_LIST_IP);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = _manager_fetch_interface (manager_client, &buffer[2], NET_INADOR_COMMAND_LIST_IP);
|
||||||
|
if (iface == NULL) return;
|
||||||
|
|
||||||
|
for (g = iface->address; g != NULL; g = g->next) {
|
||||||
|
ip_addr = (IPAddr *) g->data;
|
||||||
|
|
||||||
|
if (family != AF_UNSPEC && family != ip_addr->family) continue;
|
||||||
|
|
||||||
|
_manager_send_ip (manager_client, ip_addr, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
_manager_send_end_command (manager_client, NET_INADOR_COMMAND_LIST_IP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _manager_execute_iface_down_up (ManagerClientInfo *manager_client, int is_up, unsigned char *buffer, int buffer_len) {
|
||||||
|
Interface *iface;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (buffer_len < 6) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, (is_up ? NET_INADOR_COMMAND_IFACE_UP : NET_INADOR_COMMAND_IFACE_DOWN));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = _manager_fetch_interface (manager_client, &buffer[2], (is_up ? NET_INADOR_COMMAND_IFACE_UP : NET_INADOR_COMMAND_IFACE_DOWN));
|
||||||
|
if (iface == NULL) return;
|
||||||
|
|
||||||
|
if (is_up) {
|
||||||
|
ret = interfaces_change_set_up (manager_client->manager->handle, iface->index);
|
||||||
|
} else {
|
||||||
|
ret = interfaces_change_set_down (manager_client->manager->handle, iface->index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
/* OK */
|
||||||
|
_manager_send_executed (manager_client);
|
||||||
|
} else {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, (is_up ? NET_INADOR_COMMAND_IFACE_UP : NET_INADOR_COMMAND_IFACE_DOWN));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _manager_execute_iface_change_name (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
|
||||||
|
Interface *iface;
|
||||||
|
int ret;
|
||||||
|
int name_len;
|
||||||
|
unsigned char name[IFNAMSIZ];
|
||||||
|
|
||||||
|
if (buffer_len < 7) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_IFACE_CHANGE_NAME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = _manager_fetch_interface (manager_client, &buffer[2], NET_INADOR_COMMAND_IFACE_CHANGE_NAME);
|
||||||
|
if (iface == NULL) return;
|
||||||
|
|
||||||
|
name_len = buffer[6];
|
||||||
|
if (name_len == 0 || name_len >= IFNAMSIZ) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_BAD_STRING, NET_INADOR_COMMAND_IFACE_CHANGE_NAME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name_len + 7 < buffer_len) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_IFACE_CHANGE_NAME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (name, &buffer[7], name_len);
|
||||||
|
if (name[0] == 0) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_BAD_STRING, NET_INADOR_COMMAND_IFACE_CHANGE_NAME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = interfaces_change_name (manager_client->manager->handle, iface->index, name);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
/* OK */
|
||||||
|
_manager_send_executed (manager_client);
|
||||||
|
} else {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_IFACE_CHANGE_NAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _manager_execute_clear_ips (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
|
||||||
|
int family;
|
||||||
|
Interface *iface;
|
||||||
|
IPAddr *ip_addr;
|
||||||
|
GList *g;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (buffer_len < 7) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_CLEAR_IP);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
family = buffer[6];
|
||||||
|
|
||||||
|
if (family != AF_UNSPEC && family != AF_INET && family != AF_INET6) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_FAMILY, NET_INADOR_COMMAND_CLEAR_IP);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = _manager_fetch_interface (manager_client, &buffer[2], NET_INADOR_COMMAND_CLEAR_IP);
|
||||||
|
if (iface == NULL) return;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
for (g = iface->address; g != NULL; g = g->next) {
|
||||||
|
ip_addr = (IPAddr *) g->data;
|
||||||
|
|
||||||
|
if (family != AF_UNSPEC && family != ip_addr->family) continue;
|
||||||
|
|
||||||
|
ret |= ip_address_del_ip (manager_client->manager->handle, iface->index, ip_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
/* OK */
|
||||||
|
_manager_send_executed (manager_client);
|
||||||
|
} else {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_CLEAR_IP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _manager_execute_add_ip (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
|
||||||
|
Interface *iface;
|
||||||
|
IPAddr ip_addr;
|
||||||
|
GList *g;
|
||||||
|
int ret;
|
||||||
|
int family_size, wanted_size, family;
|
||||||
|
int has_local, has_brd;
|
||||||
|
|
||||||
|
if (buffer_len < 14) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_ADD_IP);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
family = ip_addr.family = buffer[6];
|
||||||
|
|
||||||
|
if (family != AF_INET && family != AF_INET6) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_FAMILY, NET_INADOR_COMMAND_ADD_IP);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface = _manager_fetch_interface (manager_client, &buffer[2], NET_INADOR_COMMAND_ADD_IP);
|
||||||
|
if (iface == NULL) return;
|
||||||
|
|
||||||
|
ip_addr.prefix = buffer[7];
|
||||||
|
if (ip_addr.family == AF_INET && (ip_addr.prefix > 32 || ip_addr.prefix < 1)) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_VALUE, NET_INADOR_COMMAND_ADD_IP);
|
||||||
|
return;
|
||||||
|
} else if (ip_addr.family == AF_INET6 && (ip_addr.prefix > 128 || ip_addr.prefix < 1)) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_VALUE, NET_INADOR_COMMAND_ADD_IP);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
has_local = buffer[8] & 0x01;
|
||||||
|
has_brd = (buffer[8] & 0x02) >> 1;
|
||||||
|
|
||||||
|
if (ip_addr.family == AF_INET) {
|
||||||
|
family_size = sizeof (struct in_addr);
|
||||||
|
} else if (ip_addr.family == AF_INET6) {
|
||||||
|
family_size = sizeof (struct in6_addr);
|
||||||
|
}
|
||||||
|
/* Ya puedo revisar el resto de la longitud */
|
||||||
|
wanted_size = 14 + family_size + (family_size * has_local) + (family_size * has_brd);
|
||||||
|
if (buffer_len < wanted_size) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_ADD_IP);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ip_addr.scope = buffer[9];
|
||||||
|
memcpy (&ip_addr.flags, &buffer[10], 4);
|
||||||
|
|
||||||
|
memcpy (&ip_addr.addr, &buffer[14], family_size);
|
||||||
|
wanted_size = 14 + family_size;
|
||||||
|
|
||||||
|
if (has_local) {
|
||||||
|
memcpy (&ip_addr.local_addr, &buffer[wanted_size], family_size);
|
||||||
|
wanted_size += family_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_brd) {
|
||||||
|
memcpy (&ip_addr.brd_addr, &buffer[wanted_size], family_size);
|
||||||
|
wanted_size += family_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ip_address_add_ip (manager_client->manager->handle, iface->index, &ip_addr);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
/* OK */
|
||||||
|
_manager_send_executed (manager_client);
|
||||||
|
} else {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_ADD_IP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _manager_handle_set_event_mask (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
|
||||||
|
uint32_t events;
|
||||||
|
|
||||||
|
if (buffer_len < 6) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_SET_EVENT_MASK);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (&events, &buffer[2], 4);
|
||||||
|
printf ("___ MANAGER __ Set events de un cliente (%i), eventos: %u\n", manager_client->fd, events);
|
||||||
|
|
||||||
|
manager_client->wanted_events = events;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean _manager_client_data (GIOChannel *source, GIOCondition condition, gpointer data) {
|
||||||
|
ManagerClientInfo *manager_client = (ManagerClientInfo *) data;
|
||||||
|
NetworkInadorManager *manager = manager_client->manager;
|
||||||
|
int type, command;
|
||||||
|
Interface *iface;
|
||||||
|
int g;
|
||||||
|
|
||||||
|
unsigned char buffer[8192];
|
||||||
|
int bytes;
|
||||||
|
|
||||||
|
bytes = recv (manager_client->fd, buffer, sizeof (buffer), 0);
|
||||||
|
|
||||||
|
if (bytes <= 0) {
|
||||||
|
printf ("___ MANAGER ___ Conexión cerrada manager (%i)\n", manager_client->fd);
|
||||||
|
/* Error de lectura o cierre */
|
||||||
|
close (manager_client->fd);
|
||||||
|
|
||||||
|
manager->connected_client_list = g_list_remove (manager->connected_client_list, manager_client);
|
||||||
|
free (manager_client);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf ("___ MANAGER ___ Data arrival (%i):\n", manager_client->fd);
|
||||||
|
for (g = 0; g < bytes; g++) {
|
||||||
|
printf ("%02hhx ", buffer[g]);
|
||||||
|
}
|
||||||
|
printf ("\n");
|
||||||
|
|
||||||
|
/* Comando incompleto */
|
||||||
|
if (bytes < 2) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, 0);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Procesar los datos del cliente */
|
||||||
|
type = buffer[0];
|
||||||
|
if (type != NET_INADOR_TYPE_COMMAND) {
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_WRONG_COMMAND, 0);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
command = buffer[1];
|
||||||
|
switch (command) {
|
||||||
|
case NET_INADOR_COMMAND_LIST_IFACES:
|
||||||
|
_manager_send_list_interfaces (manager_client);
|
||||||
|
break;
|
||||||
|
case NET_INADOR_COMMAND_GET_IFACE:
|
||||||
|
_manager_send_iface (manager_client, buffer, bytes);
|
||||||
|
break;
|
||||||
|
case NET_INADOR_COMMAND_IFACE_UP:
|
||||||
|
case NET_INADOR_COMMAND_IFACE_DOWN:
|
||||||
|
_manager_execute_iface_down_up (manager_client, (command == NET_INADOR_COMMAND_IFACE_UP), buffer, bytes);
|
||||||
|
break;
|
||||||
|
case NET_INADOR_COMMAND_IFACE_CHANGE_NAME:
|
||||||
|
_manager_execute_iface_change_name (manager_client, buffer, bytes);
|
||||||
|
break;
|
||||||
|
case NET_INADOR_COMMAND_LIST_IP:
|
||||||
|
_manager_send_list_ips (manager_client, buffer, bytes);
|
||||||
|
break;
|
||||||
|
case NET_INADOR_COMMAND_CLEAR_IP:
|
||||||
|
_manager_execute_clear_ips (manager_client, buffer, bytes);
|
||||||
|
break;
|
||||||
|
case NET_INADOR_COMMAND_ADD_IP:
|
||||||
|
_manager_execute_add_ip (manager_client, buffer, bytes);
|
||||||
|
break;
|
||||||
|
/*case NET_INADOR_COMMAND_REMOVE_IP:
|
||||||
|
|
||||||
|
break;*/
|
||||||
|
case NET_INADOR_COMMAND_SET_EVENT_MASK:
|
||||||
|
_manager_handle_set_event_mask (manager_client, buffer, bytes);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_manager_send_error (manager_client, NET_INADOR_ERROR_WRONG_COMMAND, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean _manager_client_connect (GIOChannel *source, GIOCondition condition, gpointer data) {
|
||||||
|
NetworkInadorManager *manager = (NetworkInadorManager *) data;
|
||||||
|
ManagerClientInfo *manager_client;
|
||||||
|
int fd;
|
||||||
|
GIOChannel *channel;
|
||||||
|
|
||||||
|
fd = accept (manager->socket, NULL, NULL);
|
||||||
|
printf ("___ MANAGER ___ Nueva conexión (%i)\n", fd);
|
||||||
|
|
||||||
|
manager_client = malloc (sizeof (ManagerClientInfo));
|
||||||
|
|
||||||
|
if (manager_client == NULL) {
|
||||||
|
close (fd);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (manager_client, 0, sizeof (*manager_client));
|
||||||
|
|
||||||
|
manager_client->fd = fd;
|
||||||
|
|
||||||
|
/* Generar el vigilador */
|
||||||
|
channel = g_io_channel_unix_new (fd);
|
||||||
|
manager_client->source = g_io_add_watch (channel, G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP, _manager_client_data, manager_client);
|
||||||
|
g_io_channel_unref (channel);
|
||||||
|
manager_client->manager = manager;
|
||||||
|
|
||||||
|
manager->connected_client_list = g_list_prepend (manager->connected_client_list, manager_client);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void manager_send_event_interface_add (NetworkInadorHandle *handle, Interface *iface) {
|
||||||
|
printf ("___ MANAGER ___ Informando interfaz agregada: %s (%i)\n", iface->name, iface->index);
|
||||||
|
GList *g;
|
||||||
|
ManagerClientInfo *manager_client;
|
||||||
|
|
||||||
|
if (handle->manager == NULL) return;
|
||||||
|
|
||||||
|
for (g = handle->manager->connected_client_list; g != NULL; g = g->next) {
|
||||||
|
manager_client = (ManagerClientInfo *) g->data;
|
||||||
|
|
||||||
|
if (manager_client->wanted_events & NET_INADOR_EVENT_MASK_INTERFACES) {
|
||||||
|
printf ("___ MANAGER ___ Informando a la conexión (%i)\n", manager_client->fd);
|
||||||
|
_manager_send_interface (manager_client, iface, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void manager_send_event_interface_del (NetworkInadorHandle *handle, uint32_t index) {
|
||||||
|
printf ("___ MANAGER ___ Informando interfaz eliminada: %i\n", index);
|
||||||
|
GList *g;
|
||||||
|
ManagerClientInfo *manager_client;
|
||||||
|
|
||||||
|
if (handle->manager == NULL) return;
|
||||||
|
|
||||||
|
for (g = handle->manager->connected_client_list; g != NULL; g = g->next) {
|
||||||
|
manager_client = (ManagerClientInfo *) g->data;
|
||||||
|
|
||||||
|
if (manager_client->wanted_events & NET_INADOR_EVENT_MASK_INTERFACES) {
|
||||||
|
printf ("___ MANAGER ___ Informando a la conexión (%i)\n", manager_client->fd);
|
||||||
|
_manager_send_interface_del (manager_client, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void manager_send_event_interface_update (NetworkInadorHandle *handle, Interface *iface) {
|
||||||
|
printf ("___ MANAGER ___ Informando interfaz actualizada: %s (%i)\n", iface->name, iface->index);
|
||||||
|
GList *g;
|
||||||
|
ManagerClientInfo *manager_client;
|
||||||
|
|
||||||
|
if (handle->manager == NULL) return;
|
||||||
|
|
||||||
|
for (g = handle->manager->connected_client_list; g != NULL; g = g->next) {
|
||||||
|
manager_client = (ManagerClientInfo *) g->data;
|
||||||
|
|
||||||
|
if (manager_client->wanted_events & NET_INADOR_EVENT_MASK_INTERFACES) {
|
||||||
|
printf ("___ MANAGER ___ Informando a la conexión (%i)\n", manager_client->fd);
|
||||||
|
_manager_send_interface (manager_client, iface, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void manager_send_event_ip_add (NetworkInadorHandle *handle, IPAddr *ip_addr) {
|
||||||
|
printf ("___ MANAGER ___ Informando ip agregada: %s (%i)\n", ip_addr->iface->name, ip_addr->iface->index);
|
||||||
|
GList *g;
|
||||||
|
ManagerClientInfo *manager_client;
|
||||||
|
|
||||||
|
if (handle->manager == NULL) return;
|
||||||
|
|
||||||
|
for (g = handle->manager->connected_client_list; g != NULL; g = g->next) {
|
||||||
|
manager_client = (ManagerClientInfo *) g->data;
|
||||||
|
|
||||||
|
if (manager_client->wanted_events & NET_INADOR_EVENT_MASK_IP) {
|
||||||
|
printf ("___ MANAGER ___ Informando a la conexión (%i)\n", manager_client->fd);
|
||||||
|
_manager_send_ip (manager_client, ip_addr, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void manager_send_event_ip_del (NetworkInadorHandle *handle, IPAddr *ip_addr) {
|
||||||
|
printf ("___ MANAGER ___ Informando ip eliminada: %s (%i)\n", ip_addr->iface->name, ip_addr->iface->index);
|
||||||
|
GList *g;
|
||||||
|
ManagerClientInfo *manager_client;
|
||||||
|
|
||||||
|
if (handle->manager == NULL) return;
|
||||||
|
|
||||||
|
for (g = handle->manager->connected_client_list; g != NULL; g = g->next) {
|
||||||
|
manager_client = (ManagerClientInfo *) g->data;
|
||||||
|
|
||||||
|
if (manager_client->wanted_events & NET_INADOR_EVENT_MASK_IP) {
|
||||||
|
printf ("___ MANAGER ___ Informando a la conexión (%i)\n", manager_client->fd);
|
||||||
|
_manager_send_ip_del (manager_client, ip_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int manager_init (NetworkInadorHandle *handle) {
|
||||||
|
NetworkInadorManager *manager;
|
||||||
|
struct sockaddr_un socket_name;
|
||||||
|
GIOChannel *channel;
|
||||||
|
|
||||||
|
manager = malloc (sizeof (NetworkInadorManager));
|
||||||
|
if (manager == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (manager, 0, sizeof (*manager));
|
||||||
|
|
||||||
|
manager->socket = socket (AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
|
||||||
|
|
||||||
|
if (manager->socket < 0) {
|
||||||
|
perror ("Failed to create AF_UNIX socket");
|
||||||
|
|
||||||
|
free (manager);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (&socket_name, 0, sizeof (struct sockaddr_un));
|
||||||
|
|
||||||
|
socket_name.sun_family = AF_UNIX;
|
||||||
|
strncpy (socket_name.sun_path, COMMAND_SOCKET_PATH, sizeof (socket_name.sun_path) - 1);
|
||||||
|
|
||||||
|
unlink (COMMAND_SOCKET_PATH);
|
||||||
|
|
||||||
|
if (bind (manager->socket, (struct sockaddr *) &socket_name, sizeof (struct sockaddr_un)) < 0) {
|
||||||
|
perror ("bind");
|
||||||
|
|
||||||
|
close (manager->socket);
|
||||||
|
manager->socket = -1;
|
||||||
|
free (manager);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listen (manager->socket, 10) < 0) {
|
||||||
|
perror ("listen");
|
||||||
|
|
||||||
|
close (manager->socket);
|
||||||
|
manager->socket = -1;
|
||||||
|
free (manager);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Aplicar permisos aquí */
|
||||||
|
chmod (COMMAND_SOCKET_PATH, 0666);
|
||||||
|
|
||||||
|
channel = g_io_channel_unix_new (manager->socket);
|
||||||
|
|
||||||
|
manager->source = g_io_add_watch (channel, G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP, _manager_client_connect, manager);
|
||||||
|
g_io_channel_unref (channel);
|
||||||
|
manager->handle = handle;
|
||||||
|
|
||||||
|
handle->manager = manager;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* manager.h
|
||||||
|
* This file is part of Network Inador
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 - Gatuno
|
||||||
|
*
|
||||||
|
* Network Inador is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Network Inador is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Network Inador; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MANAGER_H__
|
||||||
|
#define __MANAGER_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
int manager_init (NetworkInadorHandle *handle);
|
||||||
|
void manager_send_event_interface_add (NetworkInadorHandle *handle, Interface *iface);
|
||||||
|
void manager_send_event_interface_del (NetworkInadorHandle *handle, uint32_t index);
|
||||||
|
void manager_send_event_interface_update (NetworkInadorHandle *handle, Interface *iface);
|
||||||
|
void manager_send_event_ip_add (NetworkInadorHandle *handle, IPAddr *ip_addr);
|
||||||
|
void manager_send_event_ip_del (NetworkInadorHandle *handle, IPAddr *ip_addr);
|
||||||
|
|
||||||
|
#endif /* __MANAGER_H__ */
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
#ifndef __NETWOR_INADOR_MANAGER_H__
|
||||||
|
#define __NETWOR_INADOR_MANAGER_H__
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NET_INADOR_TYPE_COMMAND = 1,
|
||||||
|
NET_INADOR_TYPE_RESPONSE = 2,
|
||||||
|
NET_INADOR_TYPE_RESPONSE_ERROR = 3,
|
||||||
|
NET_INADOR_TYPE_RESPONSE_LISTING_END = 4,
|
||||||
|
NET_INADOR_TYPE_EVENT = 16
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Lista de eventos */
|
||||||
|
#define NET_INADOR_EVENT_MASK_INTERFACES 0x01
|
||||||
|
#define NET_INADOR_EVENT_MASK_IP 0x02
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NET_INADOR_COMMAND_LIST_IFACES = 1,
|
||||||
|
|
||||||
|
NET_INADOR_COMMAND_GET_IFACE,
|
||||||
|
|
||||||
|
NET_INADOR_COMMAND_IFACE_UP,
|
||||||
|
NET_INADOR_COMMAND_IFACE_DOWN,
|
||||||
|
|
||||||
|
NET_INADOR_COMMAND_IFACE_CHANGE_NAME,
|
||||||
|
|
||||||
|
NET_INADOR_COMMAND_LIST_IP = 32,
|
||||||
|
NET_INADOR_COMMAND_CLEAR_IP,
|
||||||
|
NET_INADOR_COMMAND_ADD_IP,
|
||||||
|
NET_INADOR_COMMAND_REMOVE_IP,
|
||||||
|
|
||||||
|
NET_INADOR_COMMAND_SET_EVENT_MASK = 192,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NET_INADOR_ERROR_UNKNOWN = 0,
|
||||||
|
|
||||||
|
NET_INADOR_ERROR_WRONG_COMMAND,
|
||||||
|
NET_INADOR_ERROR_INCOMPLETE_REQUEST,
|
||||||
|
NET_INADOR_ERROR_INVALID_IFACE_INDEX,
|
||||||
|
NET_INADOR_ERROR_INVALID_FAMILY,
|
||||||
|
NET_INADOR_ERROR_INVALID_VALUE,
|
||||||
|
NET_INADOR_ERROR_NOT_EXECUTED,
|
||||||
|
NET_INADOR_ERROR_BAD_STRING,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NET_INADOR_EVENT_IFACE_ADDED = 2,
|
||||||
|
NET_INADOR_EVENT_IPADDR_ADDED,
|
||||||
|
NET_INADOR_EVENT_IFACE_REMOVED,
|
||||||
|
NET_INADOR_EVENT_IPADDR_REMOVED
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
NET_INADOR_RESPONSE_EXECUTED = 1,
|
||||||
|
|
||||||
|
NET_INADOR_RESPONSE_IFACE = 2,
|
||||||
|
NET_INADOR_RESPONSE_IPADDR,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __NETWOR_INADOR_MANAGER_H__ */
|
||||||
|
|
Loading…
Reference in New Issue