diff --git a/src/manager.c b/src/manager.c new file mode 100644 index 0000000..d0e861e --- /dev/null +++ b/src/manager.c @@ -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 + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#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; +} diff --git a/src/manager.h b/src/manager.h new file mode 100644 index 0000000..b381aac --- /dev/null +++ b/src/manager.h @@ -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 + +#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__ */ + diff --git a/src/network-inador-manager.h b/src/network-inador-manager.h new file mode 100644 index 0000000..e8cb6b9 --- /dev/null +++ b/src/network-inador-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__ */ +