Reactivo rutas en el manager y primera parte del resolvconf.

master
Félix Arreola Rodríguez 2025-01-13 17:25:09 -06:00
parent ed22081f6a
commit 0ea2ec7ca3
24 changed files with 913 additions and 113 deletions

View File

@ -40,7 +40,7 @@ void utils_trim (char * s) {
void utils_trim_comment (char *s) { void utils_trim_comment (char *s) {
char *p = s; char *p = s;
int l = strlen (p); //int l = strlen (p);
while (*p != 0 && *p != '#') { while (*p != 0 && *p != '#') {
++p; ++p;

View File

@ -2,11 +2,12 @@
lib_LTLIBRARIES = libnetworkinador.la lib_LTLIBRARIES = libnetworkinador.la
libnetworkinador_la_SOURCES = network-inador-public.h \ libnetworkinador_la_SOURCES = network-inador-public.h \
event_notify.c event_notify.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 \ network-inador-link-types.h network-inador-manager.h network-inador-events.h \
struct_addr_union.h wireless_struct.h \ struct_addr_union.h wireless_struct.h \
handle.c \ handle.c \
netlink-events.c netlink-events.h \ netlink-events.c netlink-events.h \
file_watcher.c file_watcher.h \
interfaces.c interfaces.h \ interfaces.c interfaces.h \
ip-address.c ip-address.h \ ip-address.c ip-address.h \
routes.c routes.h \ routes.c routes.h \

View File

@ -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) { int interfaces_bridge_set_master_interface (NetworkInadorHandle *handle, int master_index, int index) {
struct nl_msg * msg; struct nl_msg * msg;
struct ifinfomsg iface_hdr; struct ifinfomsg iface_hdr;
struct nlattr *info;
int ret, error; int ret, error;
Interface *master_iface, *iface; 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) { int interfaces_bridge_remove_master_interface (NetworkInadorHandle *handle, int index) {
struct nl_msg * msg; struct nl_msg * msg;
struct ifinfomsg iface_hdr; struct ifinfomsg iface_hdr;
struct nlattr *info;
int ret, error; int ret, error;
Interface *iface; Interface *iface;

151
lib/file_watcher.c 100644
View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/inotify.h>
#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;
}
}
}

54
lib/file_watcher.h 100644
View File

@ -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__ */

View File

@ -52,7 +52,11 @@ uint32_t *network_inador_list_ifaces (NetworkInadorHandle *handle) {
} }
Interface *network_inador_get_iface (NetworkInadorHandle *handle, uint32_t index) { 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) { const unsigned char *network_inador_iface_get_name (Interface *iface) {

View File

@ -40,6 +40,7 @@
#include "interfaces.h" #include "interfaces.h"
#include "routes.h" #include "routes.h"
#include "resolv_manager.h" #include "resolv_manager.h"
#include "file_watcher.h"
struct _NetworkInadorWatchedPID { struct _NetworkInadorWatchedPID {
unsigned int source; unsigned int source;
@ -250,6 +251,8 @@ NetworkInadorHandle * network_inador_init_handle (struct NetworkInadorOps *netwo
_network_inador_try_pipe_routes (handle); _network_inador_try_pipe_routes (handle);
} }
network_inador_file_watcher_init (handle);
/* Inicializar las interfaces (y las direcciones IP) */ /* Inicializar las interfaces (y las direcciones IP) */
interfaces_init (handle); interfaces_init (handle);
@ -277,6 +280,8 @@ void network_inador_destroy_handle (NetworkInadorHandle *handle) {
network_inador_pipes_child_notify[1] = -1; network_inador_pipes_child_notify[1] = -1;
} }
network_inador_file_watcher_cleanup (handle);
if (handle->has_route_events) { if (handle->has_route_events) {
/* Quitar la vigilancia */ /* Quitar la vigilancia */
handle->ops.input_remove (handle->route_events.source); handle->ops.input_remove (handle->route_events.source);

View File

@ -675,8 +675,7 @@ int interfaces_change_name (NetworkInadorHandle *handle, int index, char * new_n
int interfaces_delete (NetworkInadorHandle *handle, int index) { int interfaces_delete (NetworkInadorHandle *handle, int index) {
struct nl_msg * msg; struct nl_msg * msg;
struct ifinfomsg iface_hdr; struct ifinfomsg iface_hdr;
struct nlattr *info; int ret, error;
int ret, error, len;
Interface *iface; Interface *iface;
iface = _interfaces_locate_by_index (handle->interfaces, index); iface = _interfaces_locate_by_index (handle->interfaces, index);

View File

@ -411,7 +411,6 @@ int ip_address_del_ip (NetworkInadorHandle *handle, int index, uint8_t ip_family
struct ifaddrmsg addr_hdr; struct ifaddrmsg addr_hdr;
int ret, error; int ret, error;
Interface *iface; Interface *iface;
FList *addr_pos;
int family_size = 0; int family_size = 0;
/* TODO: Si no tenemos los eventos, podemos ejecutar una lectura de interfaces para refrescar la información */ /* TODO: Si no tenemos los eventos, podemos ejecutar una lectura de interfaces para refrescar la información */

View File

@ -34,6 +34,7 @@
#include "network-inador-public.h" #include "network-inador-public.h"
#include "flist.h" #include "flist.h"
#include "network-inador-events.h" #include "network-inador-events.h"
#include "file_watcher.h"
/* Para vigilar eventos */ /* Para vigilar eventos */
typedef struct { typedef struct {
@ -82,8 +83,6 @@ struct _NetworkInadorHandle {
/* Entradas para el resolv conf */ /* Entradas para el resolv conf */
FList *resolver_entries; FList *resolver_entries;
int resolver_inotify_fd;
int resolver_inotify_watch;
/* Estos sockets ejecutan comandos */ /* Estos sockets ejecutan comandos */
struct nl_sock * nl_sock_route; struct nl_sock * nl_sock_route;
@ -100,6 +99,10 @@ struct _NetworkInadorHandle {
int pipe_routes[2]; int pipe_routes[2];
unsigned int source_pipe_routes; 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; struct _NetworkInadorEventList notify_list;
}; };

View File

@ -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_run (NetworkInadorHandle *handle, int index, int type, uint32_t flags);
int interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index); 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 */ /* Lista de getters */
uint32_t *network_inador_list_ifaces (NetworkInadorHandle *handle); uint32_t *network_inador_list_ifaces (NetworkInadorHandle *handle);
Interface * network_inador_get_iface (NetworkInadorHandle *handle, uint32_t index); 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); 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_index (Interface *iface);
uint32_t network_inador_iface_get_link_type (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); uint8_t network_inador_nexthop_get_weight (RouteNH *nexthop);
uint32_t network_inador_nexthop_get_out_index (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__ */ #endif /* __NETWORK_INADOR_H__ */

View File

@ -34,6 +34,7 @@
#include "utils.h" #include "utils.h"
#include "resolv_conf_parser.h" #include "resolv_conf_parser.h"
#include "interfaces.h" #include "interfaces.h"
#include "file_watcher.h"
void resolv_manager_write (NetworkInadorHandle *handle); 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) { void resolv_manager_process_resolvconf_entries (NetworkInadorHandle *handle, void *entries) {
int g; ResolvConfEntry *new_entry, *found_entry;
ResolvConfEntry *entry; FList *g, *pos_searched_entry;
FList *pos_entry;
int do_write = 0; int do_write = 0;
int n;
resolv_manager_clear_tag_on_all (handle); resolv_manager_clear_tag_on_all (handle);
for (g = 0; g < num_entries; g++) { g = entries;
entry = NULL; n = 0;
while (entry == NULL) { while (g != 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); new_entry = (ResolvConfEntry *) g->data;
if (pos_entry == NULL) break;
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 */ /* 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 */ /* Hacer esta entrada nuestra */
entry->origin = RESOLV_ORIGIN_RESOLVCONF; found_entry->origin = RESOLV_ORIGIN_RESOLVCONF;
entry->owner_interface_index = entries[g].owner_interface_index; found_entry->owner_interface_index = new_entry->owner_interface_index;
entry->tagged = 1; found_entry->tagged = 1;
strncpy (entry->owner_prog, entries[g].owner_prog, sizeof (entry->owner_prog)); 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", entry->value, entry->owner_prog); printf ("/// Asociando una entrada %s existente del archivo al: %s\n", found_entry->value, found_entry->owner_prog);
#if 0 #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 */ /* 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) { if (found_entry->owner_interface_index != new_entry->owner_interface_index) {
entry->tagged = 1; found_entry->tagged = 1;
entry = NULL; found_entry = NULL;
continue; continue;
} }
#endif #endif
} else { } else {
/* Existe la entrada, pero no la podemos tomar como nuestra, crear otra */ /* Existe la entrada, pero no la podemos tomar como nuestra, crear otra */
entry->tagged = 1; found_entry->tagged = 1;
entry = NULL; found_entry = NULL;
continue; continue;
} }
} }
/* Si no existe, crearla */ /* Si no existe, crearla */
if (entry == NULL) { if (found_entry == NULL) {
entry = (ResolvConfEntry *) malloc (sizeof (ResolvConfEntry)); found_entry = (ResolvConfEntry *) malloc (sizeof (ResolvConfEntry));
memcpy (entry, &entries[g], sizeof (ResolvConfEntry)); memcpy (found_entry, new_entry, sizeof (ResolvConfEntry));
entry->file_order = g; /* TODO: Revisar esto del file order */ found_entry->file_order = n; /* TODO: Revisar esto del file order */
entry->tagged = 0; found_entry->tagged = 0;
entry->priority = 0; found_entry->priority = 0;
entry->for_purge = 0; found_entry->for_purge = 0;
/* Anexar al final de la lista */ /* 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 */ /* 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; do_write = 1;
} }
g = g->next;
} }
/* Si hubo actualización cambios, disparar ahora */ /* 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 */ /* A la salida, borrar las que ya no siguen en el archivo */
pos = handle->resolver_entries; pos = handle->resolver_entries;
while (pos != NULL) { while (pos != NULL) {
//next = pos->next; next = pos->next;
entry = (ResolvConfEntry *) pos->data; entry = (ResolvConfEntry *) pos->data;
if (entry->origin == RESOLV_ORIGIN_FILE && entry->tagged == 0) { 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); printf ("/// La entrada %s del resolv.conf fué eliminada del archivo. Purgando nosotros.\n", entry->value);
entry->for_purge = 1; 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); free (entry);
entry = NULL;*/ entry = NULL;
} else { } else {
printf ("/// La entrada %s del resolv.conf sigue en el archivo.\n", entry->value); 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 */ /* 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) { void resolv_manager_init (NetworkInadorHandle *handle) {
network_inador_file_watcher_add_file (handle, "/etc/resolv.conf", resolv_manager_notify_close_write_cb, NULL);
//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",
}
handle->resolver_entries = NULL; handle->resolver_entries = NULL;
/* Luego, leer el resolv.conf */ /* Luego, leer el resolv.conf */

View File

@ -30,7 +30,7 @@
void resolv_manager_init (NetworkInadorHandle *handle); 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 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_process_dhcp_nameservers (NetworkInadorHandle *handle, Interface *iface);
void resolv_manager_clear_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); //void resolv_manager_clear_tag_on_all (NetworkInadorHandle *handle);

View File

@ -155,13 +155,12 @@ int routes_receive_message_newroute (struct nl_msg *msg, void *arg) {
struct nlmsghdr *reply; struct nlmsghdr *reply;
Route *route = NULL; Route *route = NULL;
uint32_t table, prefix; uint32_t table, prefix;
int remaining, remaining2; int remaining;
int family, family_size = 0; int family, family_size = 0;
struct rtmsg *rtm_hdr; struct rtmsg *rtm_hdr;
struct nlattr *attr, *nest_attr_gw; struct nlattr *attr, *nest_attr_gw;
RouteNH *next_hop; RouteNH *next_hop;
struct rtnexthop *nhptr; struct rtnexthop *nhptr;
int rtnhp_len;
int multipath_len; int multipath_len;
unsigned char *p; unsigned char *p;
uint8_t route_type, tos; 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; 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 nl_msg * msg, *msg_nh;
struct rtmsg route_hdr; struct rtmsg route_hdr;
int ret, error; int ret, error;
@ -493,14 +492,16 @@ int routes_add (NetworkInadorHandle *handle, Route *route) {
char buffer_nexthops[8192]; char buffer_nexthops[8192];
int size_nexthops; int size_nexthops;
route_hdr.rtm_family = route->family; memset (&empty, 0, sizeof (empty));
route_hdr.rtm_dst_len = route->prefix;
route_hdr.rtm_family = route_family;
route_hdr.rtm_dst_len = route_prefix;
route_hdr.rtm_src_len = 0; route_hdr.rtm_src_len = 0;
route_hdr.rtm_tos = route->tos; route_hdr.rtm_tos = route_tos;
route_hdr.rtm_table = route->table; route_hdr.rtm_table = route_table;
route_hdr.rtm_protocol = route->protocol; route_hdr.rtm_protocol = route_protocol;
route_hdr.rtm_scope = route->scope; route_hdr.rtm_scope = route_scope;
route_hdr.rtm_type = route->type; route_hdr.rtm_type = route_type;
route_hdr.rtm_flags = 0; route_hdr.rtm_flags = 0;
msg = nlmsg_alloc_simple (RTM_NEWROUTE, NLM_F_REQUEST | NLM_F_CREATE); 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; return -1;
} }
if (route->family == AF_INET) { if (route_family == AF_INET) {
family_size = sizeof (struct in_addr); family_size = sizeof (struct in_addr);
} else if (route->family == AF_INET6) { } else if (route_family == AF_INET6) {
family_size = sizeof (struct in6_addr); family_size = sizeof (struct in6_addr);
} }
ret = nla_put (msg, RTA_DST, family_size, &route->dest); ret = nla_put (msg, RTA_DST, family_size, dest);
if (route->priority != 0) { if (route_priority != 0) {
ret |= nla_put (msg, RTA_PRIORITY, 4, &route->priority); ret |= nla_put (msg, RTA_PRIORITY, 4, &route_priority);
} }
memset (&empty, 0, sizeof (empty)); if (prefsrc != NULL) {
if (route->has_prefsrc) { ret |= nla_put (msg, RTA_PREFSRC, family_size, prefsrc);
ret |= nla_put (msg, RTA_PREFSRC, family_size, &route->prefsrc);
} }
hop_count = f_list_length (route->nexthops); hop_count = f_list_length ((FList *) route_nexthops);
if (hop_count <= 1) { if (hop_count == 0) {
/* Revisar si no hay nexthops */
} else if (hop_count == 1) {
/* Agregar por el método 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); 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); //nest = nla_nest_start (msg, RTA_MULTIPATH);
size_nexthops = 0; size_nexthops = 0;
g = route->nexthops; g = (FList *) route_nexthops;
while (g != NULL) { while (g != NULL) {
nh = (RouteNH *) g->data; nh = (RouteNH *) g->data;
@ -606,22 +608,18 @@ int routes_add (NetworkInadorHandle *handle, Route *route) {
return 0; 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 nl_msg * msg;
struct rtmsg route_hdr; struct rtmsg route_hdr;
int ret, error; int ret, error;
int family_size = 0; int family_size = 0;
struct_addr empty;
int hop_count;
RouteNH *nh;
FList *g;
memset (&route_hdr, 0, sizeof (route_hdr)); memset (&route_hdr, 0, sizeof (route_hdr));
route_hdr.rtm_family = route->family; route_hdr.rtm_family = route_family;
route_hdr.rtm_dst_len = route->prefix; route_hdr.rtm_dst_len = route_prefix;
route_hdr.rtm_tos = route->tos; route_hdr.rtm_tos = route_tos;
route_hdr.rtm_table = route->table; route_hdr.rtm_table = route_table;
msg = nlmsg_alloc_simple (RTM_DELROUTE, NLM_F_REQUEST); msg = nlmsg_alloc_simple (RTM_DELROUTE, NLM_F_REQUEST);
ret = nlmsg_append (msg, &route_hdr, sizeof (route_hdr), NLMSG_ALIGNTO); ret = nlmsg_append (msg, &route_hdr, sizeof (route_hdr), NLMSG_ALIGNTO);
@ -632,15 +630,15 @@ int routes_del (NetworkInadorHandle *handle, Route *route) {
return -1; return -1;
} }
if (route->family == AF_INET) { if (route_family == AF_INET) {
family_size = sizeof (struct in_addr); family_size = sizeof (struct in_addr);
} else if (route->family == AF_INET6) { } else if (route_family == AF_INET6) {
family_size = sizeof (struct in6_addr); family_size = sizeof (struct in6_addr);
} }
ret = nla_put (msg, RTA_DST, family_size, &route->dest); ret = nla_put (msg, RTA_DST, family_size, dest);
if (route->priority != 0) { if (route_priority != 0) {
ret |= nla_put (msg, RTA_PRIORITY, 4, &route->priority); ret |= nla_put (msg, RTA_PRIORITY, 4, &route_priority);
} }
if (ret != 0) { if (ret != 0) {

View File

@ -77,8 +77,8 @@ void routes_init (NetworkInadorHandle *handle);
void routes_ask (NetworkInadorHandle *handle); void routes_ask (NetworkInadorHandle *handle);
int routes_receive_message_newroute (struct nl_msg *msg, void *arg); int routes_receive_message_newroute (struct nl_msg *msg, void *arg);
int routes_receive_message_delroute (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_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, 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);
void route_ask_delayed_delroute (NetworkInadorHandle *handle); void route_ask_delayed_delroute (NetworkInadorHandle *handle);

99
lib/setters.c 100644
View File

@ -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 <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <arpa/inet.h>
#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);
}

View File

@ -6,7 +6,8 @@ network_inador_SOURCES = main.c \
manager-interfaces.c manager-interfaces.h \ manager-interfaces.c manager-interfaces.h \
manager-ip.c manager-ip.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 manager-routes.c manager-routes.h \
manager-resolvconf.c manager-resolvconf.h
resolvconf_SOURCES = resolv_conf_helper.c \ resolvconf_SOURCES = resolv_conf_helper.c \
../common/flist.c ../common/flist.h \ ../common/flist.c ../common/flist.h \

View File

@ -37,7 +37,7 @@
/* Empaquetador de datos */ /* Empaquetador de datos */
int _manager_pack_interface_info (unsigned char *buffer, Interface *iface) { int _manager_pack_interface_info (unsigned char *buffer, Interface *iface) {
const unsigned char *iface_name; const unsigned char *iface_name;
uint32_t u32; uint16_t u16; uint8_t u8; uint32_t u32; uint16_t u16;
int string_len; int string_len;
iface_name = network_inador_iface_get_name (iface); iface_name = network_inador_iface_get_name (iface);
@ -223,8 +223,6 @@ void _manager_interface_handle_change_mtu (ManagerClientInfo *manager_client, un
Interface *iface; Interface *iface;
uint32_t u32, new_mtu; uint32_t u32, new_mtu;
int ret; int ret;
int name_len;
unsigned char name[IFNAMSIZ];
if (buffer_len < 10) { if (buffer_len < 10) {
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_IFACE_CHANGE_MTU); _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_IFACE_CHANGE_MTU);

View File

@ -143,7 +143,7 @@ void _manager_send_ipaddr_deleted (ManagerClientInfo *manager_client, IPAddr *ip
int family; int family;
uint32_t index; uint32_t index;
Interface *iface; Interface *iface;
int has_brd, has_local; int has_local;
union { union {
struct in_addr v4; struct in_addr v4;
@ -390,7 +390,7 @@ void _manager_ip_handle_del_ip (ManagerClientInfo *manager_client, unsigned char
Interface *iface; Interface *iface;
int ret; int ret;
int family_size, wanted_size, family; int family_size, wanted_size, family;
uint32_t u32, ip_flags; uint32_t u32;
uint8_t ip_prefix; uint8_t ip_prefix;
uint8_t has_local; uint8_t has_local;
union { union {

View File

@ -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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#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);
}

View File

@ -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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#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__ */

View File

@ -143,6 +143,43 @@ void _manager_send_route (ManagerClientInfo *manager_client, Route *route, uint8
send (manager_client->fd, buffer, size, 0); 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) { void _manager_route_handle_list_routes (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
int family; int family;
Route *route; 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); _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 */ /* Los eventos que vienen desde la librería */
void _manager_route_added_event_cb (NetworkInadorHandle *handle, Route *route, void *data) { void _manager_route_added_event_cb (NetworkInadorHandle *handle, Route *route, void *data) {
Manager *manager = (Manager *) 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);
}
}
}

View File

@ -32,8 +32,12 @@
#include "network-inador-manager.h" #include "network-inador-manager.h"
void _manager_route_handle_list_routes (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len); 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_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__ */ #endif /* __MANAGER_ROUTES_H__ */

View File

@ -48,6 +48,7 @@
#include "manager-ip.h" #include "manager-ip.h"
#include "manager-bridge.h" #include "manager-bridge.h"
#include "manager-routes.h" #include "manager-routes.h"
#include "manager-resolvconf.h"
#define COMMAND_SOCKET_PATH "/tmp/network-inador.socket" #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; ManagerClientInfo *manager_client = (ManagerClientInfo *) data;
Manager *manager = manager_client->manager; Manager *manager = manager_client->manager;
int type, command; int type, command;
Interface *iface;
int g; int g;
unsigned char buffer[8192]; 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: case NET_INADOR_COMMAND_LIST_ROUTES:
_manager_route_handle_list_routes (manager_client, buffer, bytes); _manager_route_handle_list_routes (manager_client, buffer, bytes);
break; break;
/*case NET_INADOR_COMMAND_ADD_ROUTE: case NET_INADOR_COMMAND_ADD_ROUTE:
_manager_execute_add_route (manager_client, buffer, bytes); _manager_route_handle_add_route (manager_client, buffer, bytes);
break; break;
case NET_INADOR_COMMAND_REMOVE_ROUTE: case NET_INADOR_COMMAND_REMOVE_ROUTE:
_manager_execute_del_route (manager_client, buffer, bytes); _manager_route_handle_del_route (manager_client, buffer, bytes);
break; break;
case NET_INADOR_COMMAND_LIST_ROUTE_TABLES: /*case NET_INADOR_COMMAND_LIST_ROUTE_TABLES:
_manager_send_list_route_tables (manager_client, buffer, bytes); _manager_send_list_route_tables (manager_client, buffer, bytes);
break; break;*/
case NET_INADOR_COMMAND_RESOLVCONF_FEED: case NET_INADOR_COMMAND_RESOLVCONF_FEED:
_manager_execute_resolvconf_feed (manager_client, buffer, bytes); _manager_resolvconf_handle_feed (manager_client, buffer, bytes);
break; break;
case NET_INADOR_COMMAND_RESOLVCONF_REMOVE: /*case NET_INADOR_COMMAND_RESOLVCONF_REMOVE:
_manager_execute_resolvconf_remove (manager_client, buffer, bytes); _manager_execute_resolvconf_remove (manager_client, buffer, bytes);
break;*/ break;*/
default: 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_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_added (handle, _manager_route_added_event_cb, manager);
/*network_manager_add_watch_route_updated (handle, manager); network_manager_add_watch_route_updated (handle, _manager_route_updated_event_cb, manager);
network_manager_add_watch_route_deleted (handle, manager);*/ network_manager_add_watch_route_deleted (handle, _manager_route_deleted_event_cb, manager);
return manager; return manager;
} }