diff --git a/lib/event_notify.c b/lib/event_notify.c index 8a0c9d5..5f13afa 100644 --- a/lib/event_notify.c +++ b/lib/event_notify.c @@ -65,6 +65,21 @@ void network_manager_add_watch_ip_deleted (NetworkInadorHandle *handle, NetworkI handle->notify_list.ip_del_event_data = data; } +void network_manager_add_watch_route_added (NetworkInadorHandle *handle, NetworkInadorRouteAddEventCB cb, void *data) { + handle->notify_list.route_add_event_cb = cb; + handle->notify_list.route_add_event_data = data; +} + +void network_manager_add_watch_route_updated (NetworkInadorHandle *handle, NetworkInadorRouteUpdateEventCB cb, void *data) { + handle->notify_list.route_update_event_cb = cb; + handle->notify_list.route_update_event_data = data; +} + +void network_manager_add_watch_route_deleted (NetworkInadorHandle *handle, NetworkInadorRouteDelEventCB cb, void *data) { + handle->notify_list.route_del_event_cb = cb; + handle->notify_list.route_del_event_data = data; +} + /* Disparar las vigilancias */ void network_manager_trigger_dhcp_event (NetworkInadorHandle *handle, InterfaceDHCPClientInfo *dhcpc) { Interface *iface = container_of (dhcpc, Interface, dhcpc); @@ -106,3 +121,22 @@ void network_manager_trigger_ip_deleted_event (NetworkInadorHandle *handle, IPAd } } +/* Triggers de rutas */ +void network_manager_trigger_route_added_event (NetworkInadorHandle *handle, Route *route) { + if (handle->notify_list.route_add_event_cb != NULL) { + handle->notify_list.route_add_event_cb (handle, route, handle->notify_list.route_add_event_data); + } +} + +void network_manager_trigger_route_updated_event (NetworkInadorHandle *handle, Route *route) { + if (handle->notify_list.route_update_event_cb != NULL) { + handle->notify_list.route_update_event_cb (handle, route, handle->notify_list.route_update_event_data); + } +} + +void network_manager_trigger_route_deleted_event (NetworkInadorHandle *handle, Route *route) { + if (handle->notify_list.route_del_event_cb != NULL) { + handle->notify_list.route_del_event_cb (handle, route, handle->notify_list.route_del_event_data); + } +} + diff --git a/lib/event_notify.h b/lib/event_notify.h index ba5edf3..93ae7f5 100644 --- a/lib/event_notify.h +++ b/lib/event_notify.h @@ -33,6 +33,9 @@ void network_manager_trigger_interface_updated_event (NetworkInadorHandle *handl void network_manager_trigger_interface_deleted_event (NetworkInadorHandle *handle, uint32_t index); void network_manager_trigger_ip_added_event (NetworkInadorHandle *handle, IPAddr *ip_addr); void network_manager_trigger_ip_deleted_event (NetworkInadorHandle *handle, IPAddr *ip_addr); +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); #endif /* __EVENT_NOTIFY_H__ */ diff --git a/lib/getters.c b/lib/getters.c index d479504..7843abc 100644 --- a/lib/getters.c +++ b/lib/getters.c @@ -27,6 +27,7 @@ #include "network-inador-private.h" #include "interfaces.h" #include "ip-address.h" +#include "routes.h" uint32_t *network_inador_list_ifaces (NetworkInadorHandle *handle) { uint32_t *memory; @@ -195,3 +196,154 @@ const unsigned char *network_inador_ipaddr_get_label (IPAddr *ip_addr) { return ip_addr->label; } +int network_inador_get_routes_count (NetworkInadorHandle *handle, int family) { + if (family == AF_UNSPEC) { + return handle->route_v4_counter + handle->route_v6_counter; + } else if (family == AF_INET) { + return handle->route_v4_counter; + } else if (family == AF_INET6) { + return handle->route_v6_counter; + } + + return 0; +} + +Route *network_inador_get_route_by_index (NetworkInadorHandle *handle, int family, int index) { + if (family == AF_INET) { + return (Route *) f_list_nth_data (f_list_first (handle->route_v4_tables), index); + } else if (family == AF_INET6) { + return (Route *) f_list_nth_data (f_list_first (handle->route_v6_tables), index); + } + + return NULL; +} + +uint8_t network_inador_route_get_family (Route *route) { + return route->family; +} + +uint8_t network_inador_route_get_type (Route *route) { + return route->type; +} + +uint32_t network_inador_route_get_table (Route *route) { + return route->table; +} + +uint8_t network_inador_route_get_prefix (Route *route) { + return route->prefix; +} + +uint8_t network_inador_route_get_protocol (Route *route) { + return route->protocol; +} + +uint8_t network_inador_route_get_tos (Route *route) { + return route->tos; +} + +uint8_t network_inador_route_get_scope (Route *route) { + return route->scope; +} + +uint8_t network_inador_route_has_prefsrc (Route *route) { + return route->has_prefsrc; +} + +uint32_t network_inador_route_get_priority (Route *route) { + return route->priority; +} + +void network_inador_route_get_dest (Route *route, void *dest, int *addr_size) { + int family_size = 0; + + if (route->family == AF_INET) { + family_size = sizeof (struct in_addr); + } else if (route->family == AF_INET6) { + family_size = sizeof (struct in6_addr); + } + + if (addr_size != NULL) { + /* Verificar que no supere el máximo de la dirección */ + if (*addr_size < family_size) { + family_size = *addr_size; + } + } + + memcpy (dest, &route->dest, family_size); + + if (addr_size != NULL) { + *addr_size = family_size; + } +} + +void network_inador_route_get_prefsrc (Route *route, void *prefsrc, int *addr_size) { + int family_size = 0; + + if (route->family == AF_INET) { + family_size = sizeof (struct in_addr); + } else if (route->family == AF_INET6) { + family_size = sizeof (struct in6_addr); + } + + if (addr_size != NULL) { + /* Verificar que no supere el máximo de la dirección */ + if (*addr_size < family_size) { + family_size = *addr_size; + } + } + + memcpy (prefsrc, &route->prefsrc, family_size); + + if (addr_size != NULL) { + *addr_size = family_size; + } +} + +int network_inador_route_get_num_nexthops (Route *route) { + return f_list_length (route->nexthops); +} + +RouteNH *network_inador_route_get_nexthop_by_index (Route *route, int index) { + return (RouteNH *) f_list_nth_data (f_list_first (route->nexthops), index); +} + +uint8_t network_inador_nexthop_has_gw (RouteNH *nexthop) { + return nexthop->has_gw; +} + +void network_inador_nexthop_get_gw (RouteNH *nexthop, void *gw, int *addr_size) { + int family_size = 0; + + if (nexthop->family == AF_INET) { + family_size = sizeof (struct in_addr); + } else if (nexthop->family == AF_INET6) { + family_size = sizeof (struct in6_addr); + } + + if (addr_size != NULL) { + /* Verificar que no supere el máximo de la dirección */ + if (*addr_size < family_size) { + family_size = *addr_size; + } + } + + memcpy (gw, &nexthop->gw, family_size); + + if (addr_size != NULL) { + *addr_size = family_size; + } +} + +uint8_t network_inador_nexthop_get_flags (RouteNH *nexthop) { + return nexthop->nh_flags; +} + +uint8_t network_inador_nexthop_get_weight (RouteNH *nexthop) { + return nexthop->nh_weight; +} + +uint32_t network_inador_nexthop_get_out_index (RouteNH *nexthop) { + return nexthop->out_index; +} + diff --git a/lib/network-inador-events.h b/lib/network-inador-events.h index 94f3264..82495fb 100644 --- a/lib/network-inador-events.h +++ b/lib/network-inador-events.h @@ -29,6 +29,7 @@ typedef struct _NetworkInadorHandle NetworkInadorHandle; typedef struct _Interface Interface; typedef struct _InterfaceDHCPClientInfo InterfaceDHCPClientInfo; 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); @@ -36,6 +37,9 @@ typedef void (*NetworkInadorInterfaceUpdateEventCB) (NetworkInadorHandle *handle 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); /* Pendiente notificar rutas */ void network_manager_add_watch_dhcp (NetworkInadorHandle *handle, NetworkInadorDHCPEventCB cb, void *data); @@ -45,5 +49,9 @@ void network_manager_add_watch_interface_deleted (NetworkInadorHandle *handle, N void network_manager_add_watch_ip_added (NetworkInadorHandle *handle, NetworkInadorIPAddEventCB cb, void *data); void network_manager_add_watch_ip_deleted (NetworkInadorHandle *handle, NetworkInadorIPDelEventCB cb, void *data); +void network_manager_add_watch_route_added (NetworkInadorHandle *handle, NetworkInadorRouteAddEventCB cb, void *data); +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); + #endif /* __NETWORK_INADOR_EVENTS_H__ */ diff --git a/lib/network-inador-private.h b/lib/network-inador-private.h index 4e6d785..e070459 100644 --- a/lib/network-inador-private.h +++ b/lib/network-inador-private.h @@ -56,6 +56,13 @@ typedef struct _NetworkInadorEventList { void *ip_add_event_data; NetworkInadorIPDelEventCB ip_del_event_cb; void *ip_del_event_data; + + NetworkInadorRouteAddEventCB route_add_event_cb; + void *route_add_event_data; + NetworkInadorRouteUpdateEventCB route_update_event_cb; + void *route_update_event_data; + NetworkInadorRouteDelEventCB route_del_event_cb; + void *route_del_event_data; } NetworkInadorEventList; /* La definición principal que engloba todo */ @@ -70,6 +77,8 @@ struct _NetworkInadorHandle { /* Auxiliar contador de la lista ligada de interfaces */ int interfaces_counter; + int route_v4_counter; + int route_v6_counter; /* Entradas para el resolv conf */ FList *resolver_entries; diff --git a/lib/network-inador-public.h b/lib/network-inador-public.h index 558b3f6..472ce05 100644 --- a/lib/network-inador-public.h +++ b/lib/network-inador-public.h @@ -59,6 +59,8 @@ struct NetworkInadorOps { typedef struct _NetworkInadorHandle NetworkInadorHandle; typedef struct _Interface Interface; typedef struct _IPAddr IPAddr; +typedef struct _Route Route; +typedef struct _RouteNH RouteNH; NetworkInadorHandle * network_inador_init_handle (struct NetworkInadorOps *network_inador_ops); void network_inador_destroy_handle (NetworkInadorHandle *handle); @@ -112,5 +114,27 @@ void network_inador_ipaddr_get_local_addr (IPAddr *ip_addr, void *addr, int *add void network_inador_ipaddr_get_brd_addr (IPAddr *ip_addr, void *addr, int *addr_size); const unsigned char *network_inador_ipaddr_get_label (IPAddr *ip_addr); +int network_inador_get_routes_count (NetworkInadorHandle *handle, int family); +Route *network_inador_get_route_by_index (NetworkInadorHandle *handle, int family, int index); + +uint8_t network_inador_route_get_family (Route *route); +uint8_t network_inador_route_get_type (Route *route); +uint32_t network_inador_route_get_table (Route *route); +uint8_t network_inador_route_get_prefix (Route *route); +uint8_t network_inador_route_get_protocol (Route *route); +uint8_t network_inador_route_get_tos (Route *route); +uint8_t network_inador_route_get_scope (Route *route); +uint8_t network_inador_route_has_prefsrc (Route *route); +uint32_t network_inador_route_get_priority (Route *route); +void network_inador_route_get_dest (Route *route, void *dest, int *addr_size); +void network_inador_route_get_prefsrc (Route *route, void *prefsrc, int *addr_size); +int network_inador_route_get_num_nexthops (Route *route); +RouteNH *network_inador_route_get_nexthop_by_index (Route *route, int index); +uint8_t network_inador_nexthop_has_gw (RouteNH *nexthop); +void network_inador_nexthop_get_gw (RouteNH *nexthop, void *gw, int *addr_size); +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); + #endif /* __NETWORK_INADOR_H__ */ diff --git a/lib/routes.c b/lib/routes.c index bf3d8a4..220a20b 100644 --- a/lib/routes.c +++ b/lib/routes.c @@ -37,7 +37,7 @@ #include "flist.h" #include "network-inador-private.h" #include "routes.h" -//#include "manager.h" +#include "event_notify.h" int _route_compare_nexthop_v4 (const void * a, const void * b); int _route_compare_nexthop_v6 (const void * a, const void * b); @@ -165,12 +165,14 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) { int multipath_len; unsigned char *p; uint8_t route_type, tos; - struct_addr dest; + struct_addr dest, empty; uint32_t priority = 0; int was_new = 0, was_update = 0; FList *route_list = NULL; FList *old_next_hops = NULL; + memset (&empty, 0, sizeof (empty)); + reply = nlmsg_hdr (msg); if (reply->nlmsg_type != RTM_NEWROUTE) return NL_SKIP; @@ -244,13 +246,14 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) { if (family == AF_INET) { handle->route_v4_tables = f_list_append (handle->route_v4_tables, route); + handle->route_v4_counter++; } else if (family == AF_INET6) { handle->route_v6_tables = f_list_append (handle->route_v6_tables, route); + handle->route_v6_counter++; } was_new = 1; } else { /* Liberar los next-hops, puesto que volverán a ser creados */ - //f_list_free_full (route->nexthops, free); old_next_hops = route->nexthops; route->nexthops = NULL; route->for_delete = 0; @@ -270,6 +273,8 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) { next_hop = (RouteNH *) malloc (sizeof (RouteNH)); memset (next_hop, 0, sizeof (RouteNH)); + next_hop->family = family; + nlmsg_for_each_attr(attr, reply, sizeof (struct rtmsg), remaining) { switch (nla_type (attr)) { case RTA_PREFSRC: @@ -283,6 +288,7 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) { continue; } memcpy (&next_hop->gw, nla_data (attr), family_size); + next_hop->has_gw = TRUE; break; case RTA_OIF: if (nla_len (attr) != 4) { @@ -307,6 +313,12 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) { if (nest_attr_gw != NULL && nla_len (nest_attr_gw) == family_size) { memcpy (&next_hop->gw, nla_data (nest_attr_gw), family_size); + + if (memcmp (&next_hop->gw, &empty, family_size) == 0) { + next_hop->has_gw = FALSE; + } else { + next_hop->has_gw = TRUE; + } } multipath_len -= nhptr->rtnh_len; @@ -318,12 +330,19 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) { next_hop = (RouteNH *) malloc (sizeof (RouteNH)); memset (next_hop, 0, sizeof (RouteNH)); + next_hop->family = family; } } break; } } + if (memcmp (&empty, &route->prefsrc, family_size) == 0) { + route->has_prefsrc = FALSE; + } else { + route->has_prefsrc = TRUE; + } + route->nexthops = f_list_append (route->nexthops, next_hop); route->nexthops = _route_sort_nexthops (family, route->nexthops); @@ -337,10 +356,10 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) { if (was_new) { /* Enviar aquí evento de ruta agregada */ - //manager_send_event_route_add (handle, route); + network_manager_trigger_route_added_event (handle, route); } else if (was_update) { /* Enviar actualización */ - //manager_send_event_route_update (handle, route); + network_manager_trigger_route_updated_event (handle, route); } return NL_SKIP; } @@ -419,13 +438,15 @@ int routes_receive_message_delroute (struct nl_msg *msg, void *arg) { if (family == AF_INET) { /* Eliminar de la lista ligada */ + handle->route_v4_counter--; handle->route_v4_tables = f_list_remove (handle->route_v4_tables, route); } else if (family == AF_INET6) { + handle->route_v6_counter--; handle->route_v6_tables = f_list_remove (handle->route_v6_tables, route); } /* Notificar del evento */ - //manager_send_event_route_del (handle, route); + network_manager_trigger_route_deleted_event (handle, route); /* Eliminar todos los next-hops primero */ f_list_free_full (route->nexthops, free); @@ -503,7 +524,7 @@ int routes_add (NetworkInadorHandle *handle, Route *route) { } memset (&empty, 0, sizeof (empty)); - if (memcmp (&empty, &route->prefsrc, family_size) != 0) { + if (route->has_prefsrc) { ret |= nla_put (msg, RTA_PREFSRC, family_size, &route->prefsrc); } @@ -703,10 +724,11 @@ void routes_ask (NetworkInadorHandle *handle) { r = (Route *) g->data; if (r->for_delete == 0) continue; + handle->route_v4_counter--; handle->route_v4_tables = f_list_remove (handle->route_v4_tables, r); /* Notificar del evento */ - //manager_send_event_route_del (handle, r); + network_manager_trigger_route_deleted_event (handle, r); /* Eliminar todos los next-hops primero */ f_list_free_full (r->nexthops, free); @@ -720,10 +742,11 @@ void routes_ask (NetworkInadorHandle *handle) { r = (Route *) g->data; if (r->for_delete == 0) continue; + handle->route_v6_counter--; handle->route_v6_tables = f_list_remove (handle->route_v6_tables, r); /* Notificar del evento */ - //manager_send_event_route_del (handle, r); + network_manager_trigger_route_deleted_event (handle, r); /* Eliminar todos los next-hops primero */ f_list_free_full (r->nexthops, free); @@ -888,6 +911,7 @@ void routes_clean_up (NetworkInadorHandle *handle) { f_list_free_full (handle->route_v4_tables, free); handle->route_v4_tables = NULL; + handle->route_v4_counter = 0; for (g = handle->route_v6_tables; g != NULL; g = g->next) { route = (Route *) g->data; @@ -898,6 +922,7 @@ void routes_clean_up (NetworkInadorHandle *handle) { f_list_free_full (handle->route_v6_tables, free); handle->route_v6_tables = NULL; + handle->route_v6_counter = 0; /* FIXME: Falta liberar el nombre de las tablas */ } diff --git a/lib/routes.h b/lib/routes.h index dac075c..2de6393 100644 --- a/lib/routes.h +++ b/lib/routes.h @@ -33,15 +33,17 @@ #include "flist.h" /* Un Next-hop */ -typedef struct { +typedef struct _RouteNH { + sa_family_t family; struct_addr gw; + uint8_t has_gw; uint32_t out_index; uint8_t nh_weight; uint8_t nh_flags; } RouteNH; /* La tabla de ruteo */ -typedef struct { +typedef struct _Route { sa_family_t family; /* AF_INET, AF_INET6 */ uint8_t type; /* Unicast, local, broadcast, etc... */ @@ -53,6 +55,7 @@ typedef struct { uint8_t protocol; uint8_t scope; + uint8_t has_prefsrc; struct_addr prefsrc; uint32_t priority; diff --git a/src/Makefile.am b/src/Makefile.am index e2dea4e..97dbbcf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,7 +5,8 @@ network_inador_SOURCES = main.c \ manager.c manager-private.h \ manager-interfaces.c manager-interfaces.h \ manager-ip.c manager-ip.h \ - manager-bridge.c manager-bridge.h + manager-bridge.c manager-bridge.h \ + manager-routes.c manager-routes.h resolvconf_SOURCES = resolv_conf_helper.c \ ../common/flist.c ../common/flist.h \ diff --git a/src/manager-routes.c b/src/manager-routes.c new file mode 100644 index 0000000..251da25 --- /dev/null +++ b/src/manager-routes.c @@ -0,0 +1,225 @@ +/* + * 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_info (unsigned char *buffer, Route *route) { + uint8_t route_family, route_type, route_prefix; + uint8_t route_protocol, route_tos, route_scope; + uint8_t has_prefsrc, has_gw; + uint32_t route_table, route_priority, out_index; + int family_size = 0; + int num_nexthops, g, pos; + union { + struct in_addr v4; + struct in6_addr v6; + } dest, prefsrc, gw; + RouteNH *nexthop; + + route_family = network_inador_route_get_family (route); + + if (route_family == AF_INET) { + family_size = sizeof (struct in_addr); + } else if (route_family == AF_INET6) { + family_size = sizeof (struct in6_addr); + } + + route_type = network_inador_route_get_type (route); + route_table = network_inador_route_get_table (route); + route_prefix = network_inador_route_get_prefix (route); + route_protocol = network_inador_route_get_protocol (route); + route_tos = network_inador_route_get_tos (route); + route_scope = network_inador_route_get_scope (route); + has_prefsrc = network_inador_route_has_prefsrc (route); + route_priority = network_inador_route_get_priority (route); + + buffer[0] = route_family; + buffer[1] = route_type; + memcpy (&buffer[2], &route_table, 4); + buffer[6] = route_prefix; + buffer[7] = route_protocol; + buffer[8] = route_tos; + buffer[9] = route_scope; + buffer[10] = 0; + if (has_prefsrc) { + /* Tiene pref-src */ + buffer[10] |= 0x01; + } + + num_nexthops = network_inador_route_get_num_nexthops (route); + + buffer[11] = num_nexthops; + memcpy (&buffer[12], &route_priority, 4); + + /* Copiar la Ruta de destino */ + network_inador_route_get_dest (route, &dest, NULL); + memcpy (&buffer[16], &dest, family_size); + pos = 16 + family_size; + + /* Copiar el pref-src, si lo tiene */ + if (has_prefsrc) { + network_inador_route_get_prefsrc (route, &prefsrc, NULL); + memcpy (&buffer[pos], &prefsrc, family_size); + pos += family_size; + } + + /* TODO: Recorrer todos los nexthops */ + for (g = 0; g < num_nexthops; g++) { + nexthop = network_inador_route_get_nexthop_by_index (route, g); + + buffer[pos] = 0; + has_gw = network_inador_nexthop_has_gw (nexthop); + if (has_gw) { + buffer[pos] |= 0x01; + } + pos++; + buffer[pos++] = network_inador_nexthop_get_flags (nexthop); /* Flags next-hop */ + buffer[pos++] = network_inador_nexthop_get_weight (nexthop); /* Weight next-hop */ + + buffer[pos++] = 0; /* Omitimos un byte faltante */ + + /* La interfaz de salida */ + out_index = network_inador_nexthop_get_out_index (nexthop); + memcpy (&buffer[pos], &out_index, 4); + pos += 4; + + if (has_gw) { + network_inador_nexthop_get_gw (nexthop, &gw, NULL); + memcpy (&buffer[pos], &gw, family_size); + pos += family_size; + } + } + + return pos; +} + +/* Los comandos que verdaderamente envian */ +void _manager_send_route (ManagerClientInfo *manager_client, Route *route, uint8_t is_event) { + unsigned char buffer[100]; + int size; + + if (is_event) { + buffer[0] = NET_INADOR_TYPE_EVENT; + buffer[1] = NET_INADOR_EVENT_ROUTE_ADDED; + } else { + buffer[0] = NET_INADOR_TYPE_RESPONSE; + buffer[1] = NET_INADOR_RESPONSE_ROUTE; + } + + size = 2 + _manager_pack_route_info (&buffer[2], route); + + send (manager_client->fd, buffer, size, 0); +} + +void _manager_route_handle_list_routes (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) { + int family; + Route *route; + uint32_t wanted_table, route_table; + int g, route_count; + + if (buffer_len < 7) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_LIST_ROUTES); + 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_ROUTES); + + return; + } + + memcpy (&wanted_table, &buffer[2], 4); + + if (family == AF_UNSPEC || family == AF_INET) { + route_count = network_inador_get_routes_count (manager_client->manager->handle, AF_INET); + for (g = 0; g < route_count; g++) { + route = network_inador_get_route_by_index (manager_client->manager->handle, AF_INET, g); + + route_table = network_inador_route_get_table (route); + if (wanted_table != 0 && route_table != wanted_table) continue; + + _manager_send_route (manager_client, route, FALSE); + } + } + + if (family == AF_UNSPEC || family == AF_INET6) { + route_count = network_inador_get_routes_count (manager_client->manager->handle, AF_INET6); + for (g = 0; g < route_count; g++) { + route = network_inador_get_route_by_index (manager_client->manager->handle, AF_INET6, g); + + route_table = network_inador_route_get_table (route); + if (wanted_table != 0 && route_table != wanted_table) continue; + + _manager_send_route (manager_client, route, FALSE); + } + } + + _manager_send_end_command (manager_client, NET_INADOR_COMMAND_LIST_ROUTES); +} + +/* Los eventos que vienen desde la librería */ +void _manager_route_added_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 agregada: %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); + } + } +} + diff --git a/src/manager-routes.h b/src/manager-routes.h new file mode 100644 index 0000000..3ea7970 --- /dev/null +++ b/src/manager-routes.h @@ -0,0 +1,39 @@ +/* + * manager-routes.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_ROUTES_H__ +#define __MANAGER_ROUTES_H__ + +#include +#include +#include + +#include "manager-private.h" +#include "network-inador-public.h" +#include "network-inador-manager.h" + +void _manager_route_handle_list_routes (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len); + +void _manager_route_added_event_cb (NetworkInadorHandle *handle, Route *route, void *data); + +#endif /* __MANAGER_ROUTES_H__ */ + diff --git a/src/manager.c b/src/manager.c index 92e2ba8..f5a186e 100644 --- a/src/manager.c +++ b/src/manager.c @@ -47,6 +47,7 @@ #include "manager-interfaces.h" #include "manager-ip.h" #include "manager-bridge.h" +#include "manager-routes.h" #define COMMAND_SOCKET_PATH "/tmp/network-inador.socket" @@ -199,9 +200,9 @@ static gboolean _manager_on_client_data_recv (GIOChannel *source, GIOCondition c _manager_execute_dhcp_get_status (manager_client, buffer, bytes); break;*/ case NET_INADOR_COMMAND_LIST_ROUTES: - _manager_send_list_routes (manager_client, buffer, bytes); + _manager_route_handle_list_routes (manager_client, buffer, bytes); break; - case NET_INADOR_COMMAND_ADD_ROUTE: + /*case NET_INADOR_COMMAND_ADD_ROUTE: _manager_execute_add_route (manager_client, buffer, bytes); break; case NET_INADOR_COMMAND_REMOVE_ROUTE: @@ -320,12 +321,18 @@ Manager * manager_new (NetworkInadorHandle *handle, int type) { /* Agregar vigilancias aquí */ network_manager_add_watch_dhcp (handle, _manager_dhcp_event_cb, manager); + network_manager_add_watch_interface_added (handle, _manager_interface_added_event_cb, manager); network_manager_add_watch_interface_updated (handle, _manager_interface_updated_event_cb, manager); network_manager_add_watch_interface_deleted (handle, _manager_interface_deleted_event_cb, manager); + network_manager_add_watch_ip_added (handle, _manager_ip_added_event_cb, manager); 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);*/ + return manager; }