From 0ea2ec7ca3e563d7d93ab3e45e227483ecc20b1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Arreola=20Rodr=C3=ADguez?= Date: Mon, 13 Jan 2025 17:25:09 -0600 Subject: [PATCH] Reactivo rutas en el manager y primera parte del resolvconf. --- common/utils.c | 2 +- lib/Makefile.am | 3 +- lib/bridge.c | 2 - lib/file_watcher.c | 151 +++++++++++++++++++ lib/file_watcher.h | 54 +++++++ lib/getters.c | 6 +- lib/handle.c | 5 + lib/interfaces.c | 3 +- lib/ip-address.c | 1 - lib/network-inador-private.h | 7 +- lib/network-inador-public.h | 14 ++ lib/resolv_manager.c | 96 ++++++------ lib/resolv_manager.h | 2 +- lib/routes.c | 70 +++++---- lib/routes.h | 4 +- lib/setters.c | 99 +++++++++++++ src/Makefile.am | 3 +- src/manager-interfaces.c | 4 +- src/manager-ip.c | 4 +- src/manager-resolvconf.c | 159 ++++++++++++++++++++ src/manager-resolvconf.h | 37 +++++ src/manager-routes.c | 276 +++++++++++++++++++++++++++++++++++ src/manager-routes.h | 4 + src/manager.c | 20 +-- 24 files changed, 913 insertions(+), 113 deletions(-) create mode 100644 lib/file_watcher.c create mode 100644 lib/file_watcher.h create mode 100644 lib/setters.c create mode 100644 src/manager-resolvconf.c create mode 100644 src/manager-resolvconf.h diff --git a/common/utils.c b/common/utils.c index 2e39407..bcf560c 100644 --- a/common/utils.c +++ b/common/utils.c @@ -40,7 +40,7 @@ void utils_trim (char * s) { void utils_trim_comment (char *s) { char *p = s; - int l = strlen (p); + //int l = strlen (p); while (*p != 0 && *p != '#') { ++p; diff --git a/lib/Makefile.am b/lib/Makefile.am index b5fe72f..906cdde 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -2,11 +2,12 @@ lib_LTLIBRARIES = libnetworkinador.la libnetworkinador_la_SOURCES = network-inador-public.h \ event_notify.c event_notify.h \ - getters.c network-inador-private.h \ + getters.c setters.c network-inador-private.h \ network-inador-link-types.h network-inador-manager.h network-inador-events.h \ struct_addr_union.h wireless_struct.h \ handle.c \ netlink-events.c netlink-events.h \ + file_watcher.c file_watcher.h \ interfaces.c interfaces.h \ ip-address.c ip-address.h \ routes.c routes.h \ diff --git a/lib/bridge.c b/lib/bridge.c index 0de06d0..0cb80d9 100644 --- a/lib/bridge.c +++ b/lib/bridge.c @@ -127,7 +127,6 @@ int interfaces_bridge_create (NetworkInadorHandle *handle, const char *name) { int interfaces_bridge_set_master_interface (NetworkInadorHandle *handle, int master_index, int index) { struct nl_msg * msg; struct ifinfomsg iface_hdr; - struct nlattr *info; int ret, error; Interface *master_iface, *iface; @@ -188,7 +187,6 @@ int interfaces_bridge_set_master_interface (NetworkInadorHandle *handle, int mas int interfaces_bridge_remove_master_interface (NetworkInadorHandle *handle, int index) { struct nl_msg * msg; struct ifinfomsg iface_hdr; - struct nlattr *info; int ret, error; Interface *iface; diff --git a/lib/file_watcher.c b/lib/file_watcher.c new file mode 100644 index 0000000..5c22213 --- /dev/null +++ b/lib/file_watcher.c @@ -0,0 +1,151 @@ +/* + * file_watcher.c + * This file is part of Network-inador + * + * Copyright (C) 2025 - 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 "file_watcher.h" +#include "network-inador-private.h" + +static void network_inador_file_watcher_deliver_event (NetworkInadorHandle *handle, struct inotify_event *event, INotifyWD *inotwd) { + /* Este es el que pidió cierre de escritura */ + if (event->mask & IN_CLOSE_WRITE) { + if (inotwd->close_write_cb != NULL) { + inotwd->close_write_cb (handle, NULL, inotwd->close_write_data); + } + } + + if ((event->mask & IN_IGNORED) || (event->mask & IN_DELETE_SELF) || (event->mask & IN_MOVE_SELF)) { + /* El evento fué eliminado, quitar de la lista de wds */ + handle->file_watcher.wds = f_list_remove (handle->file_watcher.wds, inotwd); + } +} + +static void network_inador_file_watcher_inotify_read_cb (void *data, int fd, int condition) { + NetworkInadorHandle *handle = (NetworkInadorHandle *) data; + int res, g, n; + struct inotify_event events[20]; + FList *p, *next; + INotifyWD *inotwd; + +inotify_read_again: + res = read (handle->file_watcher.inotify_fd, events, sizeof (events)); + + /* Nada que leer */ + if (res < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) return; + + if (res <= 0) { + /* El inotify fué cerrado, cancelar la vigilancia y quitar el source */ + handle->ops.input_remove (handle->file_watcher.inotify_source); + handle->file_watcher.inotify_source = 0; + + f_list_free_full (handle->file_watcher.wds, free); + handle->file_watcher.has_inotify = FALSE; + + close (handle->file_watcher.inotify_fd); + handle->file_watcher.inotify_fd = -1; + return; + } + + n = res / sizeof (events[0]); + + for (g = 0; g < n; g++) { + p = handle->file_watcher.wds; + while (p != NULL) { + next = p->next; + inotwd = (INotifyWD *) p->data; + + if (inotwd->inotify_wd == events[g].wd) { + network_inador_file_watcher_deliver_event (handle, &events[g], inotwd); + break; + } + p = next; + } + } + + if (res == sizeof (events)) goto inotify_read_again; +} + +void network_inador_file_watcher_init (NetworkInadorHandle *handle) { + int fd; + + if (handle->ops.input_add != NULL) { + /* Como tenemos vigilancia de fds, podemos intentar inicializar el inotify */ + fd = inotify_init1 (IN_NONBLOCK | IN_CLOEXEC); + + if (fd < 0) { + handle->file_watcher.has_inotify = FALSE; + handle->file_watcher.inotify_fd = -1; + return; + } + + handle->file_watcher.inotify_source = handle->ops.input_add (fd, POLLIN, network_inador_file_watcher_inotify_read_cb, handle); + + handle->file_watcher.has_inotify = TRUE; + handle->file_watcher.inotify_fd = fd; + } +} + +void network_inador_file_watcher_add_file (NetworkInadorHandle *handle, const char *path, FileWatcherCloseWriteCB close_write_cb, void *close_write_data) { + int res, wd; + INotifyWD *inotwd; + + if (handle->file_watcher.has_inotify == FALSE) return; + + wd = inotify_add_watch (handle->file_watcher.inotify_fd, path, IN_CLOSE_WRITE | IN_DELETE_SELF | IN_MOVE_SELF); + + if (wd < 0) return; /* No lo pude agregar */ + + inotwd = (INotifyWD *) malloc (sizeof (INotifyWD)); + if (inotwd == NULL) { + inotify_rm_watch (handle->file_watcher.inotify_fd, wd); + + return; + } + + memset (inotwd, 0, sizeof (INotifyWD)); + inotwd->inotify_wd = wd; + inotwd->close_write_cb = close_write_cb; + inotwd->close_write_data = close_write_data; + + strncpy (inotwd->path, path, sizeof (inotwd->path)); + + handle->file_watcher.wds = f_list_append (handle->file_watcher.wds, inotwd); +} + +void network_inador_file_watcher_cleanup (NetworkInadorHandle *handle) { + if (handle->file_watcher.has_inotify) { + close (handle->file_watcher.inotify_fd); + handle->file_watcher.inotify_fd = -1; + + if (handle->file_watcher.inotify_source != 0 && handle->ops.input_remove != NULL) { + handle->ops.input_remove (handle->file_watcher.inotify_source); + handle->file_watcher.inotify_source = 0; + } + } +} + diff --git a/lib/file_watcher.h b/lib/file_watcher.h new file mode 100644 index 0000000..b596223 --- /dev/null +++ b/lib/file_watcher.h @@ -0,0 +1,54 @@ +/* + * file_watcher.h + * This file is part of Network-inador + * + * Copyright (C) 2025 - 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 + */ + +#ifndef __FILE_WATCHER_H__ +#define __FILE_WATCHER_H__ + +#include "network-inador-public.h" +#include "flist.h" + +typedef void (*FileWatcherCloseWriteCB) (NetworkInadorHandle *handle, const char *path, void *data); + +typedef struct { + int inotify_wd; + + char path[4096]; + FileWatcherCloseWriteCB close_write_cb; + void *close_write_data; +} INotifyWD; + +typedef struct { + int has_inotify; + + int inotify_fd; + int inotify_source; + + FList *wds; +} NetworkInadorFileWatcher; + +void network_inador_file_watcher_init (NetworkInadorHandle *handle); +void network_inador_file_watcher_add_file (NetworkInadorHandle *handle, const char *path, FileWatcherCloseWriteCB close_write_cb, void *close_write_data); + +void network_inador_file_watcher_cleanup (NetworkInadorHandle *handle); + +#endif /* __FILE_WATCHER_H__ */ + diff --git a/lib/getters.c b/lib/getters.c index 7843abc..9a79ccf 100644 --- a/lib/getters.c +++ b/lib/getters.c @@ -52,7 +52,11 @@ uint32_t *network_inador_list_ifaces (NetworkInadorHandle *handle) { } Interface *network_inador_get_iface (NetworkInadorHandle *handle, uint32_t index) { - _interfaces_locate_by_index (handle->interfaces, index); + return _interfaces_locate_by_index (handle->interfaces, index); +} + +Interface *network_inador_get_iface_by_name (NetworkInadorHandle *handle, const char *name) { + return _interfaces_locate_by_name (handle->interfaces, name); } const unsigned char *network_inador_iface_get_name (Interface *iface) { diff --git a/lib/handle.c b/lib/handle.c index 210bf56..8c02b50 100644 --- a/lib/handle.c +++ b/lib/handle.c @@ -40,6 +40,7 @@ #include "interfaces.h" #include "routes.h" #include "resolv_manager.h" +#include "file_watcher.h" struct _NetworkInadorWatchedPID { unsigned int source; @@ -250,6 +251,8 @@ NetworkInadorHandle * network_inador_init_handle (struct NetworkInadorOps *netwo _network_inador_try_pipe_routes (handle); } + network_inador_file_watcher_init (handle); + /* Inicializar las interfaces (y las direcciones IP) */ interfaces_init (handle); @@ -277,6 +280,8 @@ void network_inador_destroy_handle (NetworkInadorHandle *handle) { network_inador_pipes_child_notify[1] = -1; } + network_inador_file_watcher_cleanup (handle); + if (handle->has_route_events) { /* Quitar la vigilancia */ handle->ops.input_remove (handle->route_events.source); diff --git a/lib/interfaces.c b/lib/interfaces.c index aa4d360..dd45b88 100644 --- a/lib/interfaces.c +++ b/lib/interfaces.c @@ -675,8 +675,7 @@ int interfaces_change_name (NetworkInadorHandle *handle, int index, char * new_n int interfaces_delete (NetworkInadorHandle *handle, int index) { struct nl_msg * msg; struct ifinfomsg iface_hdr; - struct nlattr *info; - int ret, error, len; + int ret, error; Interface *iface; iface = _interfaces_locate_by_index (handle->interfaces, index); diff --git a/lib/ip-address.c b/lib/ip-address.c index aad63a9..40fcbf3 100644 --- a/lib/ip-address.c +++ b/lib/ip-address.c @@ -411,7 +411,6 @@ int ip_address_del_ip (NetworkInadorHandle *handle, int index, uint8_t ip_family struct ifaddrmsg addr_hdr; int ret, error; Interface *iface; - FList *addr_pos; int family_size = 0; /* TODO: Si no tenemos los eventos, podemos ejecutar una lectura de interfaces para refrescar la información */ diff --git a/lib/network-inador-private.h b/lib/network-inador-private.h index e070459..6e92bd3 100644 --- a/lib/network-inador-private.h +++ b/lib/network-inador-private.h @@ -34,6 +34,7 @@ #include "network-inador-public.h" #include "flist.h" #include "network-inador-events.h" +#include "file_watcher.h" /* Para vigilar eventos */ typedef struct { @@ -82,8 +83,6 @@ struct _NetworkInadorHandle { /* Entradas para el resolv conf */ FList *resolver_entries; - int resolver_inotify_fd; - int resolver_inotify_watch; /* Estos sockets ejecutan comandos */ struct nl_sock * nl_sock_route; @@ -100,6 +99,10 @@ struct _NetworkInadorHandle { int pipe_routes[2]; unsigned int source_pipe_routes; + /* Para la vigilancia de cambios en los archivos */ + NetworkInadorFileWatcher file_watcher; + + /* Para notificar los eventos fuera de la librería */ struct _NetworkInadorEventList notify_list; }; diff --git a/lib/network-inador-public.h b/lib/network-inador-public.h index 472ce05..cc1ab97 100644 --- a/lib/network-inador-public.h +++ b/lib/network-inador-public.h @@ -89,9 +89,17 @@ int interfaces_bridge_remove_master_interface (NetworkInadorHandle *handle, int int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type, uint32_t flags); int interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index); +/* Funciones de Rutas */ +int routes_add (NetworkInadorHandle *handle, uint8_t route_family, uint8_t route_prefix, uint8_t route_tos, uint32_t route_table, uint8_t route_protocol, uint8_t route_scope, uint8_t route_type, void *dest, void *prefsrc, uint32_t route_priority, void *route_nexthops); +int routes_del (NetworkInadorHandle *handle, uint8_t route_family, uint8_t route_prefix, uint8_t route_tos, uint32_t route_table, uint32_t route_priority, void *dest); + +/* Funciones de resolvconf */ +void resolv_manager_process_resolvconf_entries (NetworkInadorHandle *handle, void *entries); + /* Lista de getters */ uint32_t *network_inador_list_ifaces (NetworkInadorHandle *handle); Interface * network_inador_get_iface (NetworkInadorHandle *handle, uint32_t index); +Interface *network_inador_get_iface_by_name (NetworkInadorHandle *handle, const char *name); const unsigned char *network_inador_iface_get_name (Interface *iface); uint32_t network_inador_iface_get_index (Interface *iface); uint32_t network_inador_iface_get_link_type (Interface *iface); @@ -136,5 +144,11 @@ uint8_t network_inador_nexthop_get_flags (RouteNH *nexthop); uint8_t network_inador_nexthop_get_weight (RouteNH *nexthop); uint32_t network_inador_nexthop_get_out_index (RouteNH *nexthop); +void *network_inador_route_append_nexthop (void *list, uint8_t family, void *gw, uint32_t out_iface, uint8_t weight, uint8_t flags); +void network_inador_route_free_all_nexthops (void *list); + +void *network_inador_resolvconf_append_ns_entry (void *list, int family, void *addr, int iface_index, const char *owner_prog); +void network_inador_resolvconf_free_all_entries (void *list); + #endif /* __NETWORK_INADOR_H__ */ diff --git a/lib/resolv_manager.c b/lib/resolv_manager.c index a9c1b35..376d11e 100644 --- a/lib/resolv_manager.c +++ b/lib/resolv_manager.c @@ -34,6 +34,7 @@ #include "utils.h" #include "resolv_conf_parser.h" #include "interfaces.h" +#include "file_watcher.h" void resolv_manager_write (NetworkInadorHandle *handle); @@ -111,64 +112,70 @@ void resolv_manager_clear_tag_on_all (NetworkInadorHandle *handle) { } } -void resolv_manager_process_resolvconf_entries (NetworkInadorHandle *handle, ResolvConfEntry *entries, int num_entries) { - int g; - ResolvConfEntry *entry; - FList *pos_entry; +void resolv_manager_process_resolvconf_entries (NetworkInadorHandle *handle, void *entries) { + ResolvConfEntry *new_entry, *found_entry; + FList *g, *pos_searched_entry; int do_write = 0; + int n; resolv_manager_clear_tag_on_all (handle); - for (g = 0; g < num_entries; g++) { - entry = NULL; - while (entry == NULL) { - pos_entry = resolv_parser_search_entry (handle->resolver_entries, entries[g].resolv_type, entries[g].ns_family, &entries[g].nameserver, entries[g].value, 1); - if (pos_entry == NULL) break; + g = entries; + n = 0; + while (g != NULL) { + new_entry = (ResolvConfEntry *) g->data; + + found_entry = NULL; + while (found_entry == NULL) { + pos_searched_entry = resolv_parser_search_entry (handle->resolver_entries, new_entry->resolv_type, new_entry->ns_family, &new_entry->nameserver, new_entry->value, 1); + if (pos_searched_entry == NULL) break; /* De ser posible, hacer conciliación */ - entry = (ResolvConfEntry *) pos_entry->data; + found_entry = (ResolvConfEntry *) pos_searched_entry->data; - if (entry->origin == RESOLV_ORIGIN_FILE) { + if (found_entry->origin == RESOLV_ORIGIN_FILE) { /* Hacer esta entrada nuestra */ - entry->origin = RESOLV_ORIGIN_RESOLVCONF; - entry->owner_interface_index = entries[g].owner_interface_index; - entry->tagged = 1; - strncpy (entry->owner_prog, entries[g].owner_prog, sizeof (entry->owner_prog)); - printf ("/// Asociando una entrada %s existente del archivo al: %s\n", entry->value, entry->owner_prog); + found_entry->origin = RESOLV_ORIGIN_RESOLVCONF; + found_entry->owner_interface_index = new_entry->owner_interface_index; + found_entry->tagged = 1; + strncpy (found_entry->owner_prog, new_entry->owner_prog, sizeof (found_entry->owner_prog)); + printf ("/// Asociando una entrada %s existente del archivo al: %s\n", found_entry->value, found_entry->owner_prog); #if 0 - } else if (entry->origin == RESOLV_ORIGIN_DHCP) { + } else if (found_entry->origin == RESOLV_ORIGIN_DHCP) { /* Una entrada que coincide con la actual solo se puede re-asociar al resolvconf si pertenece a la misma interfaz */ - if (entry->owner_interface_index != entries[g].owner_interface_index) { - entry->tagged = 1; - entry = NULL; + if (found_entry->owner_interface_index != new_entry->owner_interface_index) { + found_entry->tagged = 1; + found_entry = NULL; continue; } #endif } else { /* Existe la entrada, pero no la podemos tomar como nuestra, crear otra */ - entry->tagged = 1; - entry = NULL; + found_entry->tagged = 1; + found_entry = NULL; continue; } } /* Si no existe, crearla */ - if (entry == NULL) { - entry = (ResolvConfEntry *) malloc (sizeof (ResolvConfEntry)); + if (found_entry == NULL) { + found_entry = (ResolvConfEntry *) malloc (sizeof (ResolvConfEntry)); - memcpy (entry, &entries[g], sizeof (ResolvConfEntry)); - entry->file_order = g; /* TODO: Revisar esto del file order */ - entry->tagged = 0; - entry->priority = 0; - entry->for_purge = 0; + memcpy (found_entry, new_entry, sizeof (ResolvConfEntry)); + found_entry->file_order = n; /* TODO: Revisar esto del file order */ + found_entry->tagged = 0; + found_entry->priority = 0; + found_entry->for_purge = 0; /* Anexar al final de la lista */ - handle->resolver_entries = f_list_append (handle->resolver_entries, entry); + handle->resolver_entries = f_list_append (handle->resolver_entries, found_entry); /* TODO: Como creamos una entrada via el resolvconf, regenerar el archivo */ - printf ("/// Nueva entrada %s via resolvconf, programando regeneración.\n", entry->value); + printf ("/// Nueva entrada %s via resolvconf, programando regeneración.\n", found_entry->value); do_write = 1; } + + g = g->next; } /* Si hubo actualización cambios, disparar ahora */ @@ -373,7 +380,7 @@ void resolv_manager_read_local_etc_resolv (NetworkInadorHandle *handle) { /* A la salida, borrar las que ya no siguen en el archivo */ pos = handle->resolver_entries; while (pos != NULL) { - //next = pos->next; + next = pos->next; entry = (ResolvConfEntry *) pos->data; if (entry->origin == RESOLV_ORIGIN_FILE && entry->tagged == 0) { @@ -381,13 +388,13 @@ void resolv_manager_read_local_etc_resolv (NetworkInadorHandle *handle) { printf ("/// La entrada %s del resolv.conf fué eliminada del archivo. Purgando nosotros.\n", entry->value); entry->for_purge = 1; - /*handle->resolver_entries = f_list_delete_link (handle->resolver_entries, pos); + handle->resolver_entries = f_list_delete_link (handle->resolver_entries, pos); free (entry); - entry = NULL;*/ + entry = NULL; } else { printf ("/// La entrada %s del resolv.conf sigue en el archivo.\n", entry->value); } - pos = pos->next; + pos = next; } /* Reordenar las entradas. TODO: Falta leer los ficheros de configuración del resolv.conf */ @@ -464,20 +471,13 @@ void resolv_manager_write (NetworkInadorHandle *handle) { } } +void resolv_manager_notify_close_write_cb (NetworkInadorHandle *handle, const char *path, void *data) { + /* Cuando se nos notifique acerca de un cambio en el resolv.conf re-leer el archivo */ + resolv_manager_read_local_etc_resolv (handle); +} + void resolv_manager_init (NetworkInadorHandle *handle) { - - //handle->resolver_inotify_fd = inotify_init1 (IN_NONBLOCK | IN_CLOEXEC); - - if (handle->resolver_inotify_fd >= 0) { - /* Debemos primero instalar el manejador de eventos de escritura sobre el resolv.conf */ - /* - IN_CLOSE_WRITE Releer archivo. - IN_DELETE_SELF Dejar de hacer watch - IN_MOVE_SELF Dejar de hacer watch - */ - - //handle->resolver_inotify_watch = inotify_add_watch (handle->resolver_inotify_fd, "/etc/resolv.conf", - } + network_inador_file_watcher_add_file (handle, "/etc/resolv.conf", resolv_manager_notify_close_write_cb, NULL); handle->resolver_entries = NULL; /* Luego, leer el resolv.conf */ diff --git a/lib/resolv_manager.h b/lib/resolv_manager.h index b5b1077..85d34cf 100644 --- a/lib/resolv_manager.h +++ b/lib/resolv_manager.h @@ -30,7 +30,7 @@ void resolv_manager_init (NetworkInadorHandle *handle); void resolv_manager_clear_entries_by_prog (NetworkInadorHandle *handle, const int iface_index, const char *prog); -void resolv_manager_process_resolvconf_entries (NetworkInadorHandle *handle, ResolvConfEntry *entries, int num_entries); +void resolv_manager_process_resolvconf_entries (NetworkInadorHandle *handle, void *entries); void resolv_manager_process_dhcp_nameservers (NetworkInadorHandle *handle, Interface *iface); void resolv_manager_clear_dhcp_nameservers (NetworkInadorHandle *handle, Interface *iface); //void resolv_manager_clear_tag_on_all (NetworkInadorHandle *handle); diff --git a/lib/routes.c b/lib/routes.c index 220a20b..9b98e2c 100644 --- a/lib/routes.c +++ b/lib/routes.c @@ -155,13 +155,12 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) { struct nlmsghdr *reply; Route *route = NULL; uint32_t table, prefix; - int remaining, remaining2; + int remaining; int family, family_size = 0; struct rtmsg *rtm_hdr; struct nlattr *attr, *nest_attr_gw; RouteNH *next_hop; struct rtnexthop *nhptr; - int rtnhp_len; int multipath_len; unsigned char *p; uint8_t route_type, tos; @@ -480,7 +479,7 @@ static int _route_wait_error (struct sockaddr_nl *nla, struct nlmsgerr *l_err, v return NL_SKIP; } -int routes_add (NetworkInadorHandle *handle, Route *route) { +int routes_add (NetworkInadorHandle *handle, uint8_t route_family, uint8_t route_prefix, uint8_t route_tos, uint32_t route_table, uint8_t route_protocol, uint8_t route_scope, uint8_t route_type, void *dest, void *prefsrc, uint32_t route_priority, void *route_nexthops) { struct nl_msg * msg, *msg_nh; struct rtmsg route_hdr; int ret, error; @@ -493,14 +492,16 @@ int routes_add (NetworkInadorHandle *handle, Route *route) { char buffer_nexthops[8192]; int size_nexthops; - route_hdr.rtm_family = route->family; - route_hdr.rtm_dst_len = route->prefix; + memset (&empty, 0, sizeof (empty)); + + route_hdr.rtm_family = route_family; + route_hdr.rtm_dst_len = route_prefix; route_hdr.rtm_src_len = 0; - route_hdr.rtm_tos = route->tos; - route_hdr.rtm_table = route->table; - route_hdr.rtm_protocol = route->protocol; - route_hdr.rtm_scope = route->scope; - route_hdr.rtm_type = route->type; + route_hdr.rtm_tos = route_tos; + route_hdr.rtm_table = route_table; + route_hdr.rtm_protocol = route_protocol; + route_hdr.rtm_scope = route_scope; + route_hdr.rtm_type = route_type; route_hdr.rtm_flags = 0; msg = nlmsg_alloc_simple (RTM_NEWROUTE, NLM_F_REQUEST | NLM_F_CREATE); @@ -512,26 +513,27 @@ int routes_add (NetworkInadorHandle *handle, Route *route) { return -1; } - if (route->family == AF_INET) { + if (route_family == AF_INET) { family_size = sizeof (struct in_addr); - } else if (route->family == AF_INET6) { + } else if (route_family == AF_INET6) { family_size = sizeof (struct in6_addr); } - ret = nla_put (msg, RTA_DST, family_size, &route->dest); - if (route->priority != 0) { - ret |= nla_put (msg, RTA_PRIORITY, 4, &route->priority); + ret = nla_put (msg, RTA_DST, family_size, dest); + if (route_priority != 0) { + ret |= nla_put (msg, RTA_PRIORITY, 4, &route_priority); } - memset (&empty, 0, sizeof (empty)); - if (route->has_prefsrc) { - ret |= nla_put (msg, RTA_PREFSRC, family_size, &route->prefsrc); + if (prefsrc != NULL) { + ret |= nla_put (msg, RTA_PREFSRC, family_size, prefsrc); } - hop_count = f_list_length (route->nexthops); - if (hop_count <= 1) { + hop_count = f_list_length ((FList *) route_nexthops); + if (hop_count == 0) { + /* Revisar si no hay nexthops */ + } else if (hop_count == 1) { /* Agregar por el método 1 */ - nh = (RouteNH *) route->nexthops->data; + nh = (RouteNH *) ((FList *) route_nexthops)->data; ret |= nla_put (msg, RTA_OIF, 4, &nh->out_index); @@ -543,7 +545,7 @@ int routes_add (NetworkInadorHandle *handle, Route *route) { //nest = nla_nest_start (msg, RTA_MULTIPATH); size_nexthops = 0; - g = route->nexthops; + g = (FList *) route_nexthops; while (g != NULL) { nh = (RouteNH *) g->data; @@ -606,22 +608,18 @@ int routes_add (NetworkInadorHandle *handle, Route *route) { return 0; } -int routes_del (NetworkInadorHandle *handle, Route *route) { +int routes_del (NetworkInadorHandle *handle, uint8_t route_family, uint8_t route_prefix, uint8_t route_tos, uint32_t route_table, uint32_t route_priority, void *dest) { struct nl_msg * msg; struct rtmsg route_hdr; int ret, error; int family_size = 0; - struct_addr empty; - int hop_count; - RouteNH *nh; - FList *g; memset (&route_hdr, 0, sizeof (route_hdr)); - route_hdr.rtm_family = route->family; - route_hdr.rtm_dst_len = route->prefix; - route_hdr.rtm_tos = route->tos; - route_hdr.rtm_table = route->table; + route_hdr.rtm_family = route_family; + route_hdr.rtm_dst_len = route_prefix; + route_hdr.rtm_tos = route_tos; + route_hdr.rtm_table = route_table; msg = nlmsg_alloc_simple (RTM_DELROUTE, NLM_F_REQUEST); ret = nlmsg_append (msg, &route_hdr, sizeof (route_hdr), NLMSG_ALIGNTO); @@ -632,15 +630,15 @@ int routes_del (NetworkInadorHandle *handle, Route *route) { return -1; } - if (route->family == AF_INET) { + if (route_family == AF_INET) { family_size = sizeof (struct in_addr); - } else if (route->family == AF_INET6) { + } else if (route_family == AF_INET6) { family_size = sizeof (struct in6_addr); } - ret = nla_put (msg, RTA_DST, family_size, &route->dest); - if (route->priority != 0) { - ret |= nla_put (msg, RTA_PRIORITY, 4, &route->priority); + ret = nla_put (msg, RTA_DST, family_size, dest); + if (route_priority != 0) { + ret |= nla_put (msg, RTA_PRIORITY, 4, &route_priority); } if (ret != 0) { diff --git a/lib/routes.h b/lib/routes.h index 2de6393..7204428 100644 --- a/lib/routes.h +++ b/lib/routes.h @@ -77,8 +77,8 @@ void routes_init (NetworkInadorHandle *handle); void routes_ask (NetworkInadorHandle *handle); int routes_receive_message_newroute (struct nl_msg *msg, void *arg); int routes_receive_message_delroute (struct nl_msg *msg, void *arg); -int routes_add (NetworkInadorHandle *handle, Route *route); -int routes_del (NetworkInadorHandle *handle, Route *route); +int routes_add (NetworkInadorHandle *handle, uint8_t route_family, uint8_t route_prefix, uint8_t route_tos, uint32_t route_table, uint8_t route_protocol, uint8_t route_scope, uint8_t route_type, void *dest, void *prefsrc, uint32_t route_priority, void *route_nexthops); +int routes_del (NetworkInadorHandle *handle, uint8_t route_family, uint8_t route_prefix, uint8_t route_tos, uint32_t route_table, uint32_t route_priority, void *dest); void route_ask_delayed_delroute (NetworkInadorHandle *handle); diff --git a/lib/setters.c b/lib/setters.c new file mode 100644 index 0000000..2731978 --- /dev/null +++ b/lib/setters.c @@ -0,0 +1,99 @@ +/* + * setters.c + * This file is part of Network-inador + * + * Copyright (C) 2025 - 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 "network-inador-private.h" +#include "flist.h" +#include "routes.h" +#include "resolv_conf_defs.h" + +void *network_inador_route_append_nexthop (void *list, uint8_t family, void *gw, uint32_t out_iface, uint8_t weight, uint8_t flags) { + RouteNH *nexthop; + int family_size; + + nexthop = (RouteNH *) malloc (sizeof (RouteNH)); + memset (nexthop, 0, sizeof (RouteNH)); + + if (family == AF_INET) { + family_size = sizeof (struct in_addr); + } else if (family == AF_INET6) { + family_size = sizeof (struct in6_addr); + } + + nexthop->family = family; + if (gw != NULL) { + nexthop->has_gw = 1; + + memcpy (&nexthop->gw, gw, family_size); + } + + memcpy (&nexthop->out_index, &out_iface, 4); + nexthop->nh_weight = weight; + nexthop->nh_flags = flags; + + list = f_list_append (list, nexthop); + + return list; +} + +void network_inador_route_free_all_nexthops (void *list) { + f_list_free_full ((FList *) list, free); +} + +void *network_inador_resolvconf_append_ns_entry (void *list, int family, void *addr, int iface_index, const char *owner_prog) { + ResolvConfEntry *entry; + int family_size; + + entry = (ResolvConfEntry *) malloc (sizeof (ResolvConfEntry)); + memset (entry, 0, sizeof (ResolvConfEntry)); + + if (family == AF_INET) { + family_size = sizeof (struct in_addr); + } else if (family == AF_INET6) { + family_size = sizeof (struct in6_addr); + } + + entry->resolv_type = RESOLV_TYPE_NAMESERVER; + entry->origin = RESOLV_ORIGIN_RESOLVCONF; + entry->ns_family = family; + + memcpy (&entry->nameserver, addr, family_size); + inet_ntop (family, addr, entry->value, sizeof (entry->value)); + + entry->owner_interface_index = iface_index; + strncpy (entry->owner_prog, owner_prog, sizeof (entry->owner_prog)); + + list = f_list_append (list, entry); + + return list; +} + +void network_inador_resolvconf_free_all_entries (void *list) { + f_list_free_full ((FList *) list, free); +} + + diff --git a/src/Makefile.am b/src/Makefile.am index 97dbbcf..59dc741 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,7 +6,8 @@ network_inador_SOURCES = main.c \ manager-interfaces.c manager-interfaces.h \ manager-ip.c manager-ip.h \ manager-bridge.c manager-bridge.h \ - manager-routes.c manager-routes.h + manager-routes.c manager-routes.h \ + manager-resolvconf.c manager-resolvconf.h resolvconf_SOURCES = resolv_conf_helper.c \ ../common/flist.c ../common/flist.h \ diff --git a/src/manager-interfaces.c b/src/manager-interfaces.c index 8aecd4a..d9ec941 100644 --- a/src/manager-interfaces.c +++ b/src/manager-interfaces.c @@ -37,7 +37,7 @@ /* Empaquetador de datos */ int _manager_pack_interface_info (unsigned char *buffer, Interface *iface) { const unsigned char *iface_name; - uint32_t u32; uint16_t u16; uint8_t u8; + uint32_t u32; uint16_t u16; int string_len; iface_name = network_inador_iface_get_name (iface); @@ -223,8 +223,6 @@ void _manager_interface_handle_change_mtu (ManagerClientInfo *manager_client, un Interface *iface; uint32_t u32, new_mtu; int ret; - int name_len; - unsigned char name[IFNAMSIZ]; if (buffer_len < 10) { _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_IFACE_CHANGE_MTU); diff --git a/src/manager-ip.c b/src/manager-ip.c index 94de8fa..3c253b5 100644 --- a/src/manager-ip.c +++ b/src/manager-ip.c @@ -143,7 +143,7 @@ void _manager_send_ipaddr_deleted (ManagerClientInfo *manager_client, IPAddr *ip int family; uint32_t index; Interface *iface; - int has_brd, has_local; + int has_local; union { struct in_addr v4; @@ -390,7 +390,7 @@ void _manager_ip_handle_del_ip (ManagerClientInfo *manager_client, unsigned char Interface *iface; int ret; int family_size, wanted_size, family; - uint32_t u32, ip_flags; + uint32_t u32; uint8_t ip_prefix; uint8_t has_local; union { diff --git a/src/manager-resolvconf.c b/src/manager-resolvconf.c new file mode 100644 index 0000000..7c61e24 --- /dev/null +++ b/src/manager-resolvconf.c @@ -0,0 +1,159 @@ +/* + * manager-resolvconf.c + * This file is part of Network-inador + * + * Copyright (C) 2025 - 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 "manager-private.h" +#include "network-inador-public.h" +#include "network-inador-manager.h" + +void _manager_resolvconf_handle_feed (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) { + int name_len, wanted; + unsigned char iface_prog[256]; + unsigned char iface_name[256], prog[256]; + char *point; + void *resolv_entries; + int entries_count; + + int ns_count; + int search_count; + int g, pos, ns_pos; + int family; + uint32_t iface_index; + Interface *iface; + union { + struct in_addr v4; + struct in6_addr v6; + } addr; + + if (buffer_len < 3) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_RESOLVCONF_FEED); + return; + } + + name_len = buffer[2]; + + if (buffer_len < 3 + name_len || name_len == 0) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_RESOLVCONF_FEED); + return; + } + + memcpy (iface_prog, &buffer[3], name_len); + iface_prog[name_len] = 0; + + if (iface_prog[0] == '.') { + /* No permitimos interfaces vacías */ + _manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_VALUE, NET_INADOR_COMMAND_RESOLVCONF_FEED); + + return; + } + + point = strchr (iface_prog, '.'); + if (point == NULL) { + prog[0] = 0; + strncpy (iface_name, iface_prog, sizeof (iface_name)); + } else { + point[0] = 0; + strncpy (iface_name, iface_prog, sizeof (iface_name)); + strncpy (prog, &point[1], sizeof (prog)); + } + + iface = network_inador_get_iface_by_name (manager_client->manager->handle, iface_name); + if (iface == NULL) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_VALUE, NET_INADOR_COMMAND_RESOLVCONF_FEED); + return; + } + iface_index = network_inador_iface_get_index (iface); + + pos = 3 + name_len; + if (buffer_len < pos) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_RESOLVCONF_FEED); + return; + } + + /* Revisar la cantidad de nameservers */ + ns_count = buffer[pos]; + pos++; + + /* TODO: Sumar las otras entradas */ + entries_count = ns_count; + + ns_pos = pos; + /* Los nameserver vienen con un byte de familia y luego los bytes correspondientes a la IP */ + for (g = 0; g < ns_count; g++) { + /* Revisar que en la longitud venga el byte de la familia */ + if (buffer_len < pos + 1) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_RESOLVCONF_FEED); + return; + } + + family = buffer[pos]; + pos++; /* El byte de la familia */ + + if (family != AF_INET && family != AF_INET6) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_FAMILY, NET_INADOR_COMMAND_RESOLVCONF_FEED); + + return; + } + + if (family == AF_INET) { + wanted = 4; + } else if (family == AF_INET6) { + wanted = 16; + } + + if (buffer_len < pos + wanted) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_RESOLVCONF_FEED); + return; + } + pos += wanted; + } + + /* TODO: Validar otro tipo de entradas */ + + /* Notificar al cliente */ + _manager_send_executed (manager_client); + + /* Re-agrupar los datos para enviarlos al resolv_manager */ + pos = ns_pos; + resolv_entries = NULL; + for (g = 0; g < ns_count; g++) { + family = buffer[pos]; + pos++; /* El byte de la familia */ + + wanted = (family == AF_INET) ? 4 : 16; + memcpy (&addr, &buffer[pos], wanted); + pos += wanted; + + resolv_entries = network_inador_resolvconf_append_ns_entry (resolv_entries, family, &addr, iface_index, prog); + } + + resolv_manager_process_resolvconf_entries (manager_client->manager->handle, resolv_entries); + network_inador_resolvconf_free_all_entries (resolv_entries); +} + diff --git a/src/manager-resolvconf.h b/src/manager-resolvconf.h new file mode 100644 index 0000000..abdc154 --- /dev/null +++ b/src/manager-resolvconf.h @@ -0,0 +1,37 @@ +/* + * manager-resolvconf.h + * This file is part of Network-inador + * + * Copyright (C) 2025 - 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 + */ + +#ifndef __MANAGER_RESOLVCONF_H__ +#define __MANAGER_RESOLVCONF_H__ + +#include +#include +#include + +#include "manager-private.h" +#include "network-inador-public.h" +#include "network-inador-manager.h" + +void _manager_resolvconf_handle_feed (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len); + +#endif /* __MANAGER_RESOLVCONF_H__ */ + diff --git a/src/manager-routes.c b/src/manager-routes.c index 251da25..64f94e0 100644 --- a/src/manager-routes.c +++ b/src/manager-routes.c @@ -143,6 +143,43 @@ void _manager_send_route (ManagerClientInfo *manager_client, Route *route, uint8 send (manager_client->fd, buffer, size, 0); } +void _manager_send_route_deleted (ManagerClientInfo *manager_client, Route *route) { + unsigned char buffer[80]; + int family_size = 0; + uint8_t route_family; + uint32_t route_table, route_priority; + union { + struct in_addr v4; + struct in6_addr v6; + } dest; + + buffer[0] = NET_INADOR_TYPE_EVENT; + buffer[1] = NET_INADOR_EVENT_ROUTE_REMOVED; + + route_family = network_inador_route_get_family (route); + /* Familia y máscara */ + if (route_family == AF_INET) { + family_size = sizeof (struct in_addr); + } else if (route_family == AF_INET6) { + family_size = sizeof (struct in6_addr); + } + + route_table = network_inador_route_get_table (route); + route_priority = network_inador_route_get_priority (route); + + buffer[2] = route_family; + buffer[3] = network_inador_route_get_tos (route); + memcpy (&buffer[4], &route_table, 4); + buffer[8] = network_inador_route_get_prefix (route); + memcpy (&buffer[9], &route_priority, 4); + + network_inador_route_get_dest (route, &dest, NULL); + /* Copiar la Ruta de destino */ + memcpy (&buffer[13], &dest, family_size); + + send (manager_client->fd, buffer, 13 + family_size, 0); +} + void _manager_route_handle_list_routes (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) { int family; Route *route; @@ -191,6 +228,183 @@ void _manager_route_handle_list_routes (ManagerClientInfo *manager_client, unsig _manager_send_end_command (manager_client, NET_INADOR_COMMAND_LIST_ROUTES); } +void _manager_route_handle_add_route (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) { + int ret, has_prefsrc, nh_has_gw; + uint8_t family, route_type, route_prefix, route_protocol; + uint8_t route_tos, route_scope; + uint8_t nh_flags, nh_weight; + int family_size, wanted_size; + uint32_t out_iface; + uint32_t route_table, route_priority; + union { + struct in_addr v4; + struct in6_addr v6; + } dest, prefsrc, nh_gw; + int g, rem, pos; + void *nexthops; + + if (buffer_len < 18) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_ADD_ROUTE); + return; + } + + family = buffer[2]; + + if (family != AF_INET && family != AF_INET6) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_FAMILY, NET_INADOR_COMMAND_ADD_ROUTE); + + return; + } + + if (family == AF_INET) { + family_size = sizeof (struct in_addr); + } else if (family == AF_INET6) { + family_size = sizeof (struct in6_addr); + } + + has_prefsrc = 0; + if (buffer[12] & 0x01) { + has_prefsrc = 1; + } + /* Ya puedo revisar el resto de la longitud */ + wanted_size = 18 + family_size + (family_size * has_prefsrc); + if (buffer_len < wanted_size) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_ADD_ROUTE); + return; + } + + /* Revisar los next hops */ + g = buffer[13]; + rem = buffer_len - wanted_size; + pos = wanted_size; + while (g > 0) { + if (rem < 8) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_ADD_ROUTE); + return; + } + + if (buffer[pos] & 0x01 && rem < (8 + family_size)) { + /* Tiene GW */ + _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_ADD_ROUTE); + return; + } + + g--; + if (buffer[pos] & 0x01) { + rem -= (8 + family_size); + pos += (8 + family_size); + } else { + rem -= 8; + pos += 8; + } + } + + /* Ejecutar el parsing */ + route_type = buffer[3]; + memcpy (&route_table, &buffer[4], 4); + route_prefix = buffer[8]; + route_protocol = buffer[9]; + route_tos = buffer[10]; + route_scope = buffer[11]; + memcpy (&route_priority, &buffer[14], 4); + + memcpy (&dest, &buffer[18], family_size); + pos = 18 + family_size; + if (has_prefsrc) { + memcpy (&prefsrc, &buffer[pos], family_size); + pos += family_size; + } + + /* Recorrer cada next-hop */ + g = buffer[13]; + nexthops = NULL; + while (g > 0) { + nh_has_gw = 0; + nh_flags = buffer[pos + 1]; + nh_weight = buffer[pos + 2]; + memcpy (&out_iface, &buffer[pos + 4], 4); + + if (buffer[pos] & 0x01) { + nh_has_gw = 1; + /* Tiene GW */ + memcpy (&nh_gw, &buffer[pos + 8], family_size); + pos += (8 + family_size); + } else { + pos += 8; + } + nexthops = network_inador_route_append_nexthop (nexthops, family, (nh_has_gw == 0 ? NULL : &nh_gw), out_iface, nh_weight, nh_flags); + g--; + } + + ret = routes_add (manager_client->manager->handle, family, route_prefix, route_tos, route_table, route_protocol, route_scope, route_type, &dest, (has_prefsrc == 0 ? NULL : &prefsrc), route_priority, nexthops); + + network_inador_route_free_all_nexthops (nexthops); + nexthops = NULL; + + if (ret == 0) { + /* OK */ + _manager_send_executed (manager_client); + } else { + _manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_ADD_ROUTE); + } +} + +void _manager_route_handle_del_route (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) { + int ret; + uint8_t family, route_prefix; + uint8_t route_tos; + int family_size, wanted_size; + uint32_t route_table, route_priority; + union { + struct in_addr v4; + struct in6_addr v6; + } dest; + + if (buffer_len < 13) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_REMOVE_ROUTE); + return; + } + + family = buffer[2]; + + if (family != AF_INET && family != AF_INET6) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_FAMILY, NET_INADOR_COMMAND_REMOVE_ROUTE); + + return; + } + + if (family == AF_INET) { + family_size = sizeof (struct in_addr); + } else if (family == AF_INET6) { + family_size = sizeof (struct in6_addr); + } + + /* Ya puedo revisar el resto de la longitud */ + wanted_size = 13 + family_size; + if (buffer_len < wanted_size) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_REMOVE_ROUTE); + return; + } + + /* Ejecutar el parsing */ + route_tos = buffer[3]; + memcpy (&route_table, &buffer[4], 4); + route_prefix = buffer[8]; + memcpy (&route_priority, &buffer[9], 4); + + /* Copiar la dirección de destino */ + memcpy (&dest, &buffer[13], family_size); + + ret = routes_del (manager_client->manager->handle, family, route_prefix, route_tos, route_table, route_priority, &dest); + + if (ret == 0) { + /* OK */ + _manager_send_executed (manager_client); + } else { + _manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_REMOVE_ROUTE); + } +} + /* Los eventos que vienen desde la librería */ void _manager_route_added_event_cb (NetworkInadorHandle *handle, Route *route, void *data) { Manager *manager = (Manager *) data; @@ -223,3 +437,65 @@ void _manager_route_added_event_cb (NetworkInadorHandle *handle, Route *route, v } } +void _manager_route_updated_event_cb (NetworkInadorHandle *handle, Route *route, void *data) { + Manager *manager = (Manager *) data; + GList *g; + ManagerClientInfo *manager_client; + uint8_t family, prefix; + union { + struct in_addr v4; + struct in6_addr v6; + } dest; + uint32_t table; + char buffer_ip[200]; + + family = network_inador_route_get_family (route); + table = network_inador_route_get_table (route); + prefix = network_inador_route_get_prefix (route); + network_inador_route_get_dest (route, &dest, NULL); + + inet_ntop (family, &dest, buffer_ip, sizeof (buffer_ip)); + + printf ("___ MANAGER ___ Informando ruta actualizada: %s/%i [Tabla %i]\n", buffer_ip, prefix, table); + + for (g = manager->connected_client_list; g != NULL; g = g->next) { + manager_client = (ManagerClientInfo *) g->data; + + if (manager_client->wanted_events & NET_INADOR_EVENT_MASK_ROUTES) { + printf ("___ MANAGER ___ Informando a la conexión (%i)\n", manager_client->fd); + _manager_send_route (manager_client, route, TRUE); + } + } +} + +void _manager_route_deleted_event_cb (NetworkInadorHandle *handle, Route *route, void *data) { + Manager *manager = (Manager *) data; + GList *g; + ManagerClientInfo *manager_client; + uint8_t family, prefix; + union { + struct in_addr v4; + struct in6_addr v6; + } dest; + uint32_t table; + char buffer_ip[200]; + + family = network_inador_route_get_family (route); + table = network_inador_route_get_table (route); + prefix = network_inador_route_get_prefix (route); + network_inador_route_get_dest (route, &dest, NULL); + + inet_ntop (family, &dest, buffer_ip, sizeof (buffer_ip)); + + printf ("___ MANAGER ___ Informando ruta eliminada: %s/%i [Tabla %i]\n", buffer_ip, prefix, table); + + for (g = manager->connected_client_list; g != NULL; g = g->next) { + manager_client = (ManagerClientInfo *) g->data; + + if (manager_client->wanted_events & NET_INADOR_EVENT_MASK_ROUTES) { + printf ("___ MANAGER ___ Informando a la conexión (%i)\n", manager_client->fd); + _manager_send_route_deleted (manager_client, route); + } + } +} + diff --git a/src/manager-routes.h b/src/manager-routes.h index 3ea7970..044bcd3 100644 --- a/src/manager-routes.h +++ b/src/manager-routes.h @@ -32,8 +32,12 @@ #include "network-inador-manager.h" void _manager_route_handle_list_routes (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len); +void _manager_route_handle_add_route (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len); +void _manager_route_handle_del_route (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len); void _manager_route_added_event_cb (NetworkInadorHandle *handle, Route *route, void *data); +void _manager_route_updated_event_cb (NetworkInadorHandle *handle, Route *route, void *data); +void _manager_route_deleted_event_cb (NetworkInadorHandle *handle, Route *route, void *data); #endif /* __MANAGER_ROUTES_H__ */ diff --git a/src/manager.c b/src/manager.c index f5a186e..31790c0 100644 --- a/src/manager.c +++ b/src/manager.c @@ -48,6 +48,7 @@ #include "manager-ip.h" #include "manager-bridge.h" #include "manager-routes.h" +#include "manager-resolvconf.h" #define COMMAND_SOCKET_PATH "/tmp/network-inador.socket" @@ -104,7 +105,6 @@ static gboolean _manager_on_client_data_recv (GIOChannel *source, GIOCondition c ManagerClientInfo *manager_client = (ManagerClientInfo *) data; Manager *manager = manager_client->manager; int type, command; - Interface *iface; int g; unsigned char buffer[8192]; @@ -202,19 +202,19 @@ static gboolean _manager_on_client_data_recv (GIOChannel *source, GIOCondition c case NET_INADOR_COMMAND_LIST_ROUTES: _manager_route_handle_list_routes (manager_client, buffer, bytes); break; - /*case NET_INADOR_COMMAND_ADD_ROUTE: - _manager_execute_add_route (manager_client, buffer, bytes); + case NET_INADOR_COMMAND_ADD_ROUTE: + _manager_route_handle_add_route (manager_client, buffer, bytes); break; case NET_INADOR_COMMAND_REMOVE_ROUTE: - _manager_execute_del_route (manager_client, buffer, bytes); + _manager_route_handle_del_route (manager_client, buffer, bytes); break; - case NET_INADOR_COMMAND_LIST_ROUTE_TABLES: + /*case NET_INADOR_COMMAND_LIST_ROUTE_TABLES: _manager_send_list_route_tables (manager_client, buffer, bytes); - break; + break;*/ case NET_INADOR_COMMAND_RESOLVCONF_FEED: - _manager_execute_resolvconf_feed (manager_client, buffer, bytes); + _manager_resolvconf_handle_feed (manager_client, buffer, bytes); break; - case NET_INADOR_COMMAND_RESOLVCONF_REMOVE: + /*case NET_INADOR_COMMAND_RESOLVCONF_REMOVE: _manager_execute_resolvconf_remove (manager_client, buffer, bytes); break;*/ default: @@ -330,8 +330,8 @@ Manager * manager_new (NetworkInadorHandle *handle, int type) { network_manager_add_watch_ip_deleted (handle, _manager_ip_deleted_event_cb, manager); network_manager_add_watch_route_added (handle, _manager_route_added_event_cb, manager); - /*network_manager_add_watch_route_updated (handle, manager); - network_manager_add_watch_route_deleted (handle, manager);*/ + network_manager_add_watch_route_updated (handle, _manager_route_updated_event_cb, manager); + network_manager_add_watch_route_deleted (handle, _manager_route_deleted_event_cb, manager); return manager; }