diff --git a/lib/Makefile.am b/lib/Makefile.am index 906cdde..efc41b6 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -11,6 +11,7 @@ libnetworkinador_la_SOURCES = network-inador-public.h \ interfaces.c interfaces.h \ ip-address.c ip-address.h \ routes.c routes.h \ + rtables.c rtables.h \ launch_process.c launch_process.h \ dhcp_client.c dhcp_client.h dhcpc_defs.h \ wireless_if.c wireless_if.h \ diff --git a/lib/event_notify.c b/lib/event_notify.c index 5f13afa..2df4fe9 100644 --- a/lib/event_notify.c +++ b/lib/event_notify.c @@ -80,6 +80,16 @@ void network_manager_add_watch_route_deleted (NetworkInadorHandle *handle, Netwo handle->notify_list.route_del_event_data = data; } +void network_manager_add_watch_route_table_added (NetworkInadorHandle *handle, NetworkInadorRouteTableAddEventCB cb, void *data) { + handle->notify_list.route_table_add_event_cb = cb; + handle->notify_list.route_table_add_event_data = data; +} + +void network_manager_add_watch_route_table_deleted (NetworkInadorHandle *handle, NetworkInadorRouteTableDelEventCB cb, void *data) { + handle->notify_list.route_table_del_event_cb = cb; + handle->notify_list.route_table_del_event_data = data; +} + /* Disparar las vigilancias */ void network_manager_trigger_dhcp_event (NetworkInadorHandle *handle, InterfaceDHCPClientInfo *dhcpc) { Interface *iface = container_of (dhcpc, Interface, dhcpc); @@ -140,3 +150,16 @@ void network_manager_trigger_route_deleted_event (NetworkInadorHandle *handle, R } } +/* Trggers de tablasde ruteo */ +void network_manager_trigger_route_table_added_event (NetworkInadorHandle *handle, uint32_t table_index, const char *table_name) { + if (handle->notify_list.route_table_add_event_cb != NULL) { + handle->notify_list.route_table_add_event_cb (handle, table_index, table_name, handle->notify_list.route_table_add_event_data); + } +} + +void network_manager_trigger_route_table_deleted_event (NetworkInadorHandle *handle, uint32_t table_index) { + if (handle->notify_list.route_table_del_event_cb != NULL) { + handle->notify_list.route_table_del_event_cb (handle, table_index, handle->notify_list.route_table_del_event_data); + } +} + diff --git a/lib/event_notify.h b/lib/event_notify.h index 93ae7f5..07e36c6 100644 --- a/lib/event_notify.h +++ b/lib/event_notify.h @@ -36,6 +36,8 @@ void network_manager_trigger_ip_deleted_event (NetworkInadorHandle *handle, IPAd void network_manager_trigger_route_added_event (NetworkInadorHandle *handle, Route *route); void network_manager_trigger_route_updated_event (NetworkInadorHandle *handle, Route *route); void network_manager_trigger_route_deleted_event (NetworkInadorHandle *handle, Route *route); +void network_manager_trigger_route_table_added_event (NetworkInadorHandle *handle, uint32_t table_index, const char *table_name); +void network_manager_trigger_route_table_deleted_event (NetworkInadorHandle *handle, uint32_t table_index); #endif /* __EVENT_NOTIFY_H__ */ diff --git a/lib/file_watcher.c b/lib/file_watcher.c index 5c22213..bb74c9c 100644 --- a/lib/file_watcher.c +++ b/lib/file_watcher.c @@ -32,10 +32,18 @@ #include "network-inador-private.h" static void network_inador_file_watcher_deliver_event (NetworkInadorHandle *handle, struct inotify_event *event, INotifyWD *inotwd) { + char path[4096]; + + if (event->name[0] == 0) { + snprintf (path, sizeof (path), "%s", inotwd->path); + } else { + snprintf (path, sizeof (path), "%s/%s", inotwd->path, event->name); + } + /* 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); + inotwd->close_write_cb (handle, path, inotwd->close_write_data); } } diff --git a/lib/getters.c b/lib/getters.c index 9a79ccf..f57d8bf 100644 --- a/lib/getters.c +++ b/lib/getters.c @@ -28,6 +28,7 @@ #include "interfaces.h" #include "ip-address.h" #include "routes.h" +#include "rtables.h" uint32_t *network_inador_list_ifaces (NetworkInadorHandle *handle) { uint32_t *memory; @@ -351,3 +352,21 @@ uint32_t network_inador_nexthop_get_out_index (RouteNH *nexthop) { return nexthop->out_index; } +int network_inador_rtables_get_count_tables (NetworkInadorHandle *handle) { + return handle->rtables_counter; +} + +void network_inador_rtables_get_table_by_index (NetworkInadorHandle *handle, uint32_t nth, uint32_t *table_index, unsigned char *table_name, size_t table_name_size) { + RouteTable *table; + + table = (RouteTable *) f_list_nth_data (f_list_first (handle->route_tables_names), nth); + + if (table_index != NULL) { + *table_index = table->table; + } + + if (table_name != NULL) { + strncpy (table_name, table->name, table_name_size); + } +} + diff --git a/lib/handle.c b/lib/handle.c index 8c02b50..2076155 100644 --- a/lib/handle.c +++ b/lib/handle.c @@ -41,6 +41,7 @@ #include "routes.h" #include "resolv_manager.h" #include "file_watcher.h" +#include "rtables.h" struct _NetworkInadorWatchedPID { unsigned int source; @@ -259,6 +260,9 @@ NetworkInadorHandle * network_inador_init_handle (struct NetworkInadorOps *netwo /* Inicializar las rutas */ routes_init (handle); + /* Inicializar los nombres de las tablas de ruteo */ + rtables_init (handle); + /* Inicializar el resolv.conf */ resolv_manager_init (handle); @@ -308,6 +312,7 @@ void network_inador_destroy_handle (NetworkInadorHandle *handle) { } /* TODO: Liberar las listas ligadas aquí */ + rtables_clean_up (handle); routes_clean_up (handle); interfaces_clean_up (handle); diff --git a/lib/network-inador-events.h b/lib/network-inador-events.h index 82495fb..afa06be 100644 --- a/lib/network-inador-events.h +++ b/lib/network-inador-events.h @@ -32,15 +32,21 @@ typedef struct _IPAddr IPAddr; typedef struct _Route Route; typedef void (*NetworkInadorDHCPEventCB) (NetworkInadorHandle *handle, Interface *iface, InterfaceDHCPClientInfo *dhcp_info, void *data); + typedef void (*NetworkInadorInterfaceAddEventCB) (NetworkInadorHandle *handle, Interface *iface, void *data); typedef void (*NetworkInadorInterfaceUpdateEventCB) (NetworkInadorHandle *handle, Interface *iface, void *data); typedef void (*NetworkInadorInterfaceDeleteEventCB) (NetworkInadorHandle *handle, uint32_t index, void *data); + typedef void (*NetworkInadorIPAddEventCB) (NetworkInadorHandle *handle, IPAddr *addr, void *data); typedef void (*NetworkInadorIPDelEventCB) (NetworkInadorHandle *handle, IPAddr *addr, void *data); + typedef void (*NetworkInadorRouteAddEventCB) (NetworkInadorHandle *handle, Route *route, void *data); typedef void (*NetworkInadorRouteUpdateEventCB) (NetworkInadorHandle *handle, Route *route, void *data); typedef void (*NetworkInadorRouteDelEventCB) (NetworkInadorHandle *handle, Route *route, void *data); +typedef void (*NetworkInadorRouteTableAddEventCB) (NetworkInadorHandle *handle, uint32_t table_index, const char *table_name, void *data); +typedef void (*NetworkInadorRouteTableDelEventCB) (NetworkInadorHandle *handle, uint32_t table_index, void *data); + /* Pendiente notificar rutas */ void network_manager_add_watch_dhcp (NetworkInadorHandle *handle, NetworkInadorDHCPEventCB cb, void *data); void network_manager_add_watch_interface_added (NetworkInadorHandle *handle, NetworkInadorInterfaceAddEventCB cb, void *data); @@ -53,5 +59,8 @@ void network_manager_add_watch_route_added (NetworkInadorHandle *handle, Network void network_manager_add_watch_route_updated (NetworkInadorHandle *handle, NetworkInadorRouteUpdateEventCB cb, void *data); void network_manager_add_watch_route_deleted (NetworkInadorHandle *handle, NetworkInadorRouteDelEventCB cb, void *data); +void network_manager_add_watch_route_table_added (NetworkInadorHandle *handle, NetworkInadorRouteTableAddEventCB cb, void *data); +void network_manager_add_watch_route_table_deleted (NetworkInadorHandle *handle, NetworkInadorRouteTableDelEventCB cb, void *data); + #endif /* __NETWORK_INADOR_EVENTS_H__ */ diff --git a/lib/network-inador-private.h b/lib/network-inador-private.h index 6e92bd3..fcda2b3 100644 --- a/lib/network-inador-private.h +++ b/lib/network-inador-private.h @@ -64,6 +64,11 @@ typedef struct _NetworkInadorEventList { void *route_update_event_data; NetworkInadorRouteDelEventCB route_del_event_cb; void *route_del_event_data; + + NetworkInadorRouteTableAddEventCB route_table_add_event_cb; + void *route_table_add_event_data; + NetworkInadorRouteTableDelEventCB route_table_del_event_cb; + void *route_table_del_event_data; } NetworkInadorEventList; /* La definición principal que engloba todo */ @@ -80,6 +85,7 @@ struct _NetworkInadorHandle { int interfaces_counter; int route_v4_counter; int route_v6_counter; + int rtables_counter; /* Entradas para el resolv conf */ FList *resolver_entries; diff --git a/lib/network-inador-public.h b/lib/network-inador-public.h index cc1ab97..b838f64 100644 --- a/lib/network-inador-public.h +++ b/lib/network-inador-public.h @@ -93,8 +93,12 @@ int interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index); 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 tablas de ruteo */ + + /* Funciones de resolvconf */ void resolv_manager_process_resolvconf_entries (NetworkInadorHandle *handle, void *entries); +void resolv_manager_clear_entries_by_prog (NetworkInadorHandle *handle, const uint32_t iface_index, const char *prog); /* Lista de getters */ uint32_t *network_inador_list_ifaces (NetworkInadorHandle *handle); @@ -144,6 +148,9 @@ 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); +int network_inador_rtables_get_count_tables (NetworkInadorHandle *handle); +void network_inador_rtables_get_table_by_index (NetworkInadorHandle *handle, uint32_t nth, uint32_t *table_index, unsigned char *table_name, size_t table_name_size); + 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); diff --git a/lib/resolv_manager.c b/lib/resolv_manager.c index b454387..1cd2906 100644 --- a/lib/resolv_manager.c +++ b/lib/resolv_manager.c @@ -64,7 +64,7 @@ int resolv_manager_sort_entries (const void *a, const void *b, void * data) { return 0; } -void resolv_manager_clear_entries_by_prog (NetworkInadorHandle *handle, const int iface_index, const char *prog) { +void resolv_manager_clear_entries_by_prog (NetworkInadorHandle *handle, uint32_t iface_index, const char *prog) { FList *g; ResolvConfEntry *entry; int do_write = 0; diff --git a/lib/resolv_manager.h b/lib/resolv_manager.h index 85d34cf..00a0dd2 100644 --- a/lib/resolv_manager.h +++ b/lib/resolv_manager.h @@ -29,7 +29,7 @@ #include "interfaces.h" 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_clear_entries_by_prog (NetworkInadorHandle *handle, const uint32_t iface_index, const char *prog); 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); diff --git a/lib/routes.c b/lib/routes.c index 9b98e2c..8bf5bec 100644 --- a/lib/routes.c +++ b/lib/routes.c @@ -753,147 +753,9 @@ void routes_ask (NetworkInadorHandle *handle) { } } -int _routes_table_find_by_number (const void * left, const void * right) { - RouteTable *a, *b; - - a = (RouteTable *) left; - b = (RouteTable *) right; - - return a->table != b->table; -} - -void _routes_table_parse_file (NetworkInadorHandle *handle, FILE *fd) { - FList *g; - int ret; - RouteTable *rtable, temp_table; - char buffer[2048]; - - while (fgets (buffer, sizeof (buffer), fd), feof (fd) == 0) { - if (buffer[0] == '#') continue; /* Ignorar las lineas con comentarios */ - - ret = sscanf (buffer, "%d %s", &(temp_table.table), temp_table.name); - - if (ret < 2) { - continue; - } - - g = f_list_find_custom (handle->route_tables_names, &temp_table, _routes_table_find_by_number); - - if (g != NULL) { - /* El número de tabla ya existe, marcar y actualizar el nombre */ - rtable = (RouteTable *) g->data; - - rtable->for_delete = 0; - rtable->was_new = 0; - } else { - /* No existe, crear nueva */ - rtable = (RouteTable *) malloc (sizeof (RouteTable)); - rtable->table = temp_table.table; - rtable->for_delete = 0; - rtable->was_new = 1; - } - /* En cualquier caso actualizar el nombre */ - strncpy (rtable->name, temp_table.name, sizeof (rtable->name)); - - handle->route_tables_names = f_list_append (handle->route_tables_names, rtable); - } -} - -void routes_tables_read (NetworkInadorHandle *handle, int do_notify) { - FILE *fd; - FList *g, *h; - RouteTable *rtable; - DIR *dir; - struct dirent *direntry; - int len; - char buffer[4096]; - - g = handle->route_tables_names; - while (g != NULL) { - rtable = (RouteTable *) g->data; - - rtable->for_delete = 1; - rtable->was_new = 0; - g = g->next; - } - - //f_list_free_full (handle->route_tables_names, g_free); - //handle->route_tables_names = NULL; - - /* Intentar abrir /etc/iproute2/rt_tables */ - fd = fopen ("/etc/iproute2/rt_tables", "r"); - if (fd != NULL) { - _routes_table_parse_file (handle, fd); - - fclose (fd); - } - - /* Ahora leer todo el directorio /etc/iproute2/rt_tables.d/ y buscar archivos *.conf */ - dir = opendir ("/etc/iproute2/rt_tables.d"); - if (dir != NULL) { - - while (direntry = readdir (dir), direntry != NULL) { - len = strlen (direntry->d_name); - - /* Buscar por archivos que terminen en .conf */ - if (len > 5 && strcmp (&(direntry->d_name[len - 5]), ".conf") == 0) { - /* Intentar abrir este archivo y parsearlo */ - snprintf (buffer, sizeof (buffer), "/etc/iproute2/rt_tables.d/%s", direntry->d_name); - fd = fopen (buffer, "r"); - - if (fd != NULL) { - _routes_table_parse_file (handle, fd); - - fclose (fd); - } - } - } - - closedir (dir); - } - - /* Ahora, todas las tablas que están marcadas para eliminar, eliminarlas */ - g = handle->route_tables_names; - - while (g != NULL) { - h = g->next; - - rtable = (RouteTable *) g->data; - - if (rtable->for_delete) { - handle->route_tables_names = f_list_delete_link (handle->route_tables_names, g); - - if (do_notify) { - //manager_send_event_route_table_del (handle, rtable); - } - - free (rtable); - } - - g = h; - } - - g = handle->route_tables_names; - while (g != NULL) { - rtable = (RouteTable *) g->data; - - if (rtable->was_new) { - if (do_notify) { - //manager_send_event_route_table_add (handle, rtable); - } - rtable->was_new = 0; - } - - g = g->next; - } -} - void routes_init (NetworkInadorHandle *handle) { /* Si es la primera vez que nos llaman, descargar una primera lista de interfaces */ routes_ask (handle); - - /* Inicializar los nombres de las tablas de ruteo */ - routes_tables_read (handle, FALSE); } void routes_clean_up (NetworkInadorHandle *handle) { diff --git a/lib/routes.h b/lib/routes.h index 7204428..d88e2cb 100644 --- a/lib/routes.h +++ b/lib/routes.h @@ -66,13 +66,6 @@ typedef struct _Route { int for_delete; } Route; -typedef struct { - uint32_t table; - char name[256]; - - int for_delete, was_new; -} RouteTable; - void routes_init (NetworkInadorHandle *handle); void routes_ask (NetworkInadorHandle *handle); int routes_receive_message_newroute (struct nl_msg *msg, void *arg); diff --git a/lib/rtables.c b/lib/rtables.c new file mode 100644 index 0000000..b455efc --- /dev/null +++ b/lib/rtables.c @@ -0,0 +1,218 @@ +/* + * rtables.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 + +#include + +#include +#include + +#include "flist.h" +#include "network-inador-private.h" +#include "rtables.h" +#include "event_notify.h" +#include "file_watcher.h" + +static int _routes_table_find_by_number (const void * left, const void * right) { + RouteTable *a, *b; + + a = (RouteTable *) left; + b = (RouteTable *) right; + + return a->table != b->table; +} + +static void _routes_table_parse_file (NetworkInadorHandle *handle, FILE *fd) { + FList *g; + int ret; + RouteTable *rtable, temp_table; + char buffer[2048]; + + while (fgets (buffer, sizeof (buffer), fd), feof (fd) == 0) { + if (buffer[0] == '#') continue; /* Ignorar las lineas con comentarios */ + + ret = sscanf (buffer, "%d %s", &(temp_table.table), temp_table.name); + + if (ret < 2) { + continue; + } + + if (temp_table.table == 0) continue; /* Omitir la tabla número 0 */ + + g = f_list_find_custom (handle->route_tables_names, &temp_table, _routes_table_find_by_number); + + if (g != NULL) { + /* El número de tabla ya existe, marcar y actualizar el nombre */ + rtable = (RouteTable *) g->data; + + printf ("Tabla ya existe en la lista ligada: %d\n", temp_table.table); + rtable->for_delete = 0; + rtable->was_new = 0; + } else { + printf ("Creando tabla en la lista ligada: %i, %s\n", temp_table.table, temp_table.name); + /* No existe, crear nueva */ + rtable = (RouteTable *) malloc (sizeof (RouteTable)); + rtable->table = temp_table.table; + rtable->for_delete = 0; + rtable->was_new = 1; + + handle->route_tables_names = f_list_append (handle->route_tables_names, rtable); + handle->rtables_counter++; + } + /* En cualquier caso actualizar el nombre */ + strncpy (rtable->name, temp_table.name, sizeof (rtable->name)); + } +} + +static void routes_tables_read_all (NetworkInadorHandle *handle, int do_notify) { + FILE *fd; + FList *g, *h; + RouteTable *rtable; + DIR *dir; + struct dirent *direntry; + int len; + char buffer[4096]; + + g = handle->route_tables_names; + while (g != NULL) { + rtable = (RouteTable *) g->data; + + rtable->for_delete = 1; + rtable->was_new = 0; + g = g->next; + } + + /* Intentar abrir /etc/iproute2/rt_tables */ + fd = fopen ("/etc/iproute2/rt_tables", "r"); + if (fd != NULL) { + printf ("Parsing main rt_tables file\n"); + _routes_table_parse_file (handle, fd); + + fclose (fd); + } + + /* Ahora leer todo el directorio /etc/iproute2/rt_tables.d/ y buscar archivos *.conf */ + dir = opendir ("/etc/iproute2/rt_tables.d"); + if (dir != NULL) { + + while (direntry = readdir (dir), direntry != NULL) { + len = strlen (direntry->d_name); + + /* Buscar por archivos que terminen en .conf */ + if (len > 5 && strcmp (&(direntry->d_name[len - 5]), ".conf") == 0) { + /* Intentar abrir este archivo y parsearlo */ + snprintf (buffer, sizeof (buffer), "/etc/iproute2/rt_tables.d/%s", direntry->d_name); + printf ("Parsing %s secundary\n", buffer); + fd = fopen (buffer, "r"); + + if (fd != NULL) { + _routes_table_parse_file (handle, fd); + + fclose (fd); + } + } + } + + closedir (dir); + } + + /* Ahora, todas las tablas que están marcadas para eliminar, eliminarlas */ + g = handle->route_tables_names; + + while (g != NULL) { + h = g->next; + + rtable = (RouteTable *) g->data; + + if (rtable->for_delete) { + handle->route_tables_names = f_list_delete_link (handle->route_tables_names, g); + handle->rtables_counter--; + + if (do_notify) { + network_manager_trigger_route_table_deleted_event (handle, rtable->table); + } + + free (rtable); + } + + g = h; + } + + g = handle->route_tables_names; + while (g != NULL) { + rtable = (RouteTable *) g->data; + + if (rtable->was_new) { + if (do_notify) { + network_manager_trigger_route_table_added_event (handle, rtable->table, rtable->name); + } + rtable->was_new = 0; + } + + g = g->next; + } +} + +static void rtables_notify_close_write_cb (NetworkInadorHandle *handle, const char *path, void *data) { + /* Cuando se nos notifique acerca de un cambio en el /etc/iproute2/rt_tables re-leer el archivo */ + routes_tables_read_all (handle, TRUE); +} + +static void rtables_notify_directory_close_write_cb (NetworkInadorHandle *handle, const char *path, void *data) { + int path_len; + + path_len = strlen (path); + + if (path_len < 5) { + /* Si ni siquiera tiene 5 letras ".conf", este archivo no nos interesa */ + return; + } + + if (strcmp (&path[path_len - 5], ".conf") != 0) return; + + /* Cuando se nos notifique acerca de un cambio en el resolv.conf re-leer el archivo */ + routes_tables_read_all (handle, TRUE); +} + +void rtables_init (NetworkInadorHandle *handle) { + network_inador_file_watcher_add_file (handle, "/etc/iproute2/rt_tables", rtables_notify_close_write_cb, NULL); + + /* TODO: La vigilancia de directorios necesita vigilar eliminar archivos y archivos movidos */ + network_inador_file_watcher_add_file (handle, "/etc/iproute2/rt_tables.d/", rtables_notify_directory_close_write_cb, NULL); + + routes_tables_read_all (handle, FALSE); +} + +void rtables_clean_up (NetworkInadorHandle *handle) { + f_list_free_full (handle->route_tables_names, free); + handle->route_tables_names = NULL; + handle->rtables_counter = 0; +} + diff --git a/lib/rtables.h b/lib/rtables.h new file mode 100644 index 0000000..e0f136f --- /dev/null +++ b/lib/rtables.h @@ -0,0 +1,44 @@ +/* + * rtables.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 __RTABLES_H__ +#define __RTABLES_H__ + +#include + +#include +#include + +#include "network-inador-private.h" + +typedef struct { + uint32_t table; + char name[256]; + + int for_delete, was_new; +} RouteTable; + +void rtables_init (NetworkInadorHandle *handle); +void rtables_clean_up (NetworkInadorHandle *handle); + +#endif /* __RTABLES_H__ */ + diff --git a/src/Makefile.am b/src/Makefile.am index 59dc741..a2d4291 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,7 @@ network_inador_SOURCES = main.c \ manager-ip.c manager-ip.h \ manager-bridge.c manager-bridge.h \ manager-routes.c manager-routes.h \ + manager-rtables.c manager-rtables.h \ manager-resolvconf.c manager-resolvconf.h resolvconf_SOURCES = resolv_conf_helper.c \ diff --git a/src/manager-rtables.c b/src/manager-rtables.c new file mode 100644 index 0000000..be9b437 --- /dev/null +++ b/src/manager-rtables.c @@ -0,0 +1,137 @@ +/* + * manager-routes.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 + +#include "manager-private.h" +#include "network-inador-public.h" +#include "network-inador-manager.h" + +/* Empaquetador de datos */ +int _manager_pack_route_table_info (unsigned char *buffer, uint32_t table_index, const char *table_name) { + int name_len; + + memcpy (&buffer[0], &table_index, 4); + + name_len = strlen (table_name); + buffer[4] = name_len; + memcpy (&buffer[5], table_name, name_len); + + return 5 + name_len; +} + +/* Los comandos que verdaderamente envian */ +void _manager_send_route_table (ManagerClientInfo *manager_client, uint32_t table_index, const char *table_name, uint8_t is_event) { + unsigned char buffer[300]; + int size; + + if (is_event) { + buffer[0] = NET_INADOR_TYPE_EVENT; + buffer[1] = NET_INADOR_EVENT_ROUTE_TABLE_ADDED; + } else { + buffer[0] = NET_INADOR_TYPE_RESPONSE; + buffer[1] = NET_INADOR_RESPONSE_ROUTE_TABLE; + } + + size = 2 + _manager_pack_route_table_info (&buffer[2], table_index, table_name); + + send (manager_client->fd, buffer, size, 0); +} + +void _manager_send_route_table_deleted (ManagerClientInfo *manager_client, uint32_t table_index) { + unsigned char buffer[80]; + + buffer[0] = NET_INADOR_TYPE_EVENT; + buffer[1] = NET_INADOR_EVENT_ROUTE_TABLE_REMOVED; + + memcpy (&buffer[2], &table_index, 4); + + send (manager_client->fd, buffer, 6, 0); +} + +void _manager_route_table_handle_list_tables (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) { + int g, table_count; + uint32_t table, table_wanted; + char table_name[256]; + + if (buffer_len < 6) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_LIST_ROUTE_TABLES); + return; + } + + memcpy (&table_wanted, &buffer[2], 4); + + table_count = network_inador_rtables_get_count_tables (manager_client->manager->handle); + for (g = 0; g < table_count; g++) { + network_inador_rtables_get_table_by_index (manager_client->manager->handle, g, &table, table_name, sizeof (table_name)); + + if (table_wanted != 0 && table_wanted != table) continue; + + _manager_send_route_table (manager_client, table, table_name, FALSE); + } + + _manager_send_end_command (manager_client, NET_INADOR_COMMAND_LIST_ROUTE_TABLES); +} + +/* Los eventos que vienen desde la librería */ +void _manager_route_table_added_event_cb (NetworkInadorHandle *handle, uint32_t table_index, const char *table_name, void *data) { + Manager *manager = (Manager *) data; + GList *g; + ManagerClientInfo *manager_client; + + printf ("___ MANAGER ___ Informando tabla de ruteo agregada: %s (%i)\n", table_name, table_index); + + 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_ROUTE_TABLES) { + printf ("___ MANAGER ___ Informando a la conexión (%i)\n", manager_client->fd); + _manager_send_route_table (manager_client, table_index, table_name, TRUE); + } + } +} + +void _manager_route_table_deleted_event_cb (NetworkInadorHandle *handle, uint32_t table_index, void *data) { + Manager *manager = (Manager *) data; + GList *g; + ManagerClientInfo *manager_client; + + printf ("___ MANAGER ___ Informando tabla de ruteo eliminada: %i\n", table_index); + + 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_ROUTE_TABLES) { + printf ("___ MANAGER ___ Informando a la conexión (%i)\n", manager_client->fd); + _manager_send_route_table_deleted (manager_client, table_index); + } + } +} + diff --git a/src/manager-rtables.h b/src/manager-rtables.h new file mode 100644 index 0000000..f2fb810 --- /dev/null +++ b/src/manager-rtables.h @@ -0,0 +1,40 @@ +/* + * manager-rtables.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_RTABLES_H__ +#define __MANAGER_RTABLES_H__ + +#include +#include +#include + +#include "manager-private.h" +#include "network-inador-public.h" +#include "network-inador-manager.h" + +void _manager_route_table_handle_list_tables (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len); + +void _manager_route_table_added_event_cb (NetworkInadorHandle *handle, uint32_t table_index, const char *table_name, void *data); +void _manager_route_table_deleted_event_cb (NetworkInadorHandle *handle, uint32_t table_index, void *data); + +#endif /* __MANAGER_RTABLES_H__ */ + diff --git a/src/manager.c b/src/manager.c index 5d5b1b4..483dfb8 100644 --- a/src/manager.c +++ b/src/manager.c @@ -49,6 +49,7 @@ #include "manager-bridge.h" #include "manager-routes.h" #include "manager-resolvconf.h" +#include "manager-rtables.h" #define COMMAND_SOCKET_PATH "/tmp/network-inador.socket" @@ -208,9 +209,9 @@ static gboolean _manager_on_client_data_recv (GIOChannel *source, GIOCondition c case NET_INADOR_COMMAND_REMOVE_ROUTE: _manager_route_handle_del_route (manager_client, buffer, bytes); break; - /*case NET_INADOR_COMMAND_LIST_ROUTE_TABLES: - _manager_send_list_route_tables (manager_client, buffer, bytes); - break;*/ + case NET_INADOR_COMMAND_LIST_ROUTE_TABLES: + _manager_route_table_handle_list_tables (manager_client, buffer, bytes); + break; case NET_INADOR_COMMAND_RESOLVCONF_FEED: _manager_resolvconf_handle_feed (manager_client, buffer, bytes); break; @@ -333,6 +334,9 @@ Manager * manager_new (NetworkInadorHandle *handle, int type) { 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); + network_manager_add_watch_route_table_added (handle, _manager_route_table_added_event_cb, manager); + network_manager_add_watch_route_table_deleted (handle, _manager_route_table_deleted_event_cb, manager); + return manager; }