From 050fa2893a220abf5e586559fe97aae062204c09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Arreola=20Rodr=C3=ADguez?= Date: Fri, 28 Jul 2023 17:01:59 -0600 Subject: [PATCH] Mejoras en el cliente dhcp y el cliente gtk. --- client-gtk/ni-client.c | 6 +- client-gtk/ni-client.h | 2 +- client-gtk/ni-interface.c | 4 +- client-gtk/ni-interface.h | 2 +- client-gtk/ni-window-interface.c | 279 +++++++++++++++++++++++++++---- src/Makefile.am | 1 + src/common.h | 43 +---- src/dhcp_client.c | 57 ++++--- src/dhcpc_defs.h | 77 +++++++++ src/resolv_manager.c | 192 ++++++++++++++++++++- src/resolv_manager.h | 2 + 11 files changed, 554 insertions(+), 111 deletions(-) create mode 100644 src/dhcpc_defs.h diff --git a/client-gtk/ni-client.c b/client-gtk/ni-client.c index 6629636..a815089 100644 --- a/client-gtk/ni-client.c +++ b/client-gtk/ni-client.c @@ -874,10 +874,10 @@ void ni_client_ask_up_down_interface (NIClient *ni_client, NIInterface *ni_inter send (ni_client->priv->client_socket, buffer, 6, 0); } -void ni_client_ask_dhcp_run_interface (NIClient *ni_client, NIInterface *ni_interface, int type) { +void ni_client_ask_dhcp_run_interface (NIClient *ni_client, NIInterface *ni_interface, int type, guint flags) { unsigned char buffer[16]; uint32_t index; - uint32_t flags = 0x1; + uint32_t flags_to_send = flags; if (ni_client->priv->client_socket < 0) { return; @@ -895,7 +895,7 @@ void ni_client_ask_dhcp_run_interface (NIClient *ni_client, NIInterface *ni_inte buffer[6] = AF_INET; buffer[7] = type; - memcpy (&buffer[8], &flags, 4); + memcpy (&buffer[8], &flags_to_send, 4); send (ni_client->priv->client_socket, buffer, 12, 0); } diff --git a/client-gtk/ni-client.h b/client-gtk/ni-client.h index 4c3fc3d..108fca1 100644 --- a/client-gtk/ni-client.h +++ b/client-gtk/ni-client.h @@ -113,7 +113,7 @@ void ni_client_ask_interface_clear_master (NIClient *ni_client, NIInterface *ni_ void ni_client_ask_interface_set_master (NIClient *ni_client, NIInterface *ni_interface, NIInterface *master); void ni_client_ask_dhcp_stop_interface (NIClient *ni_client, NIInterface *ni_interface); -void ni_client_ask_dhcp_run_interface (NIClient *ni_client, NIInterface *ni_interface, int type); +void ni_client_ask_dhcp_run_interface (NIClient *ni_client, NIInterface *ni_interface, int type, guint flags); void ni_client_ask_interface_dhcp_status (NIClient *ni_client, NIInterface *ni_interface); diff --git a/client-gtk/ni-interface.c b/client-gtk/ni-interface.c index 87b2474..a365b3f 100644 --- a/client-gtk/ni-interface.c +++ b/client-gtk/ni-interface.c @@ -828,10 +828,10 @@ void ni_interface_set_up (NIInterface *ni_interface) { ni_client_ask_up_down_interface (ni_interface->priv->ni_client, ni_interface, TRUE); } -void ni_interface_run_dhcp (NIInterface *ni_interface, int type) { +void ni_interface_run_dhcp (NIInterface *ni_interface, int type, guint flags) { g_return_if_fail (NI_IS_INTERFACE (ni_interface)); - ni_client_ask_dhcp_run_interface (ni_interface->priv->ni_client, ni_interface, type); + ni_client_ask_dhcp_run_interface (ni_interface->priv->ni_client, ni_interface, type, flags); } void ni_interface_stop_dhcp (NIInterface *ni_interface) { diff --git a/client-gtk/ni-interface.h b/client-gtk/ni-interface.h index 3de415b..362f7da 100644 --- a/client-gtk/ni-interface.h +++ b/client-gtk/ni-interface.h @@ -79,7 +79,7 @@ const GList *ni_interface_get_ip_list (NIInterface *ni_interface); guint ni_interface_get_flags (NIInterface *ni_interface); void ni_interface_set_down (NIInterface *ni_interface); void ni_interface_set_up (NIInterface *ni_interface); -void ni_interface_run_dhcp (NIInterface *ni_interface, int type); +void ni_interface_run_dhcp (NIInterface *ni_interface, int type, guint flags); void ni_interface_stop_dhcp (NIInterface *ni_interface); guint ni_interface_get_dhcp_type (NIInterface *ni_interface); diff --git a/client-gtk/ni-window-interface.c b/client-gtk/ni-window-interface.c index 2701bda..4b55da7 100644 --- a/client-gtk/ni-window-interface.c +++ b/client-gtk/ni-window-interface.c @@ -57,7 +57,12 @@ struct _NIWindowInterfacePrivate { GtkWidget *tree_ipv4, *tree_ipv6, *tree_bridge_ports; GtkWidget *button_dhcp_run, *button_dhcp_stop; - GtkWidget *dhcpv4_info; + GtkWidget *vbox_dhcpv4_info; + GtkWidget *check_flag_autorestart, *check_flag_no_dns, *check_flag_no_gws, *check_flag_no_ip; + GtkWidget *dhcpv4_process, *dhcpv4_status; + GtkWidget *dhcpv4_ip_label, *dhcpv4_gateway_label; + GtkWidget *dhcpv4_bcast_label, *dhcpv4_dns_label, *dhcpv4_server_label; + GtkWidget *dhcpv4_time_label, *dhcpv4_domain_label; GtkWidget *menu_dhcpv4; int dhcp_type; }; @@ -585,76 +590,110 @@ static void ni_window_interface_update_dhcp_status (NIWindowInterface *window_if type = ni_interface_get_dhcp_type (ni_interface); if (type == 0) { - gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_info), "Información cliente DHCP:\nNo hay proceso corriendo"); + gtk_widget_hide (window_iface->priv->vbox_dhcpv4_info); + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_process), "Ninguno"); + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_status), "No hay proceso corriendo"); } else { if (type == 1) { - pos = g_snprintf (buffer, sizeof (buffer), "Información cliente DHCP: Cliente ISC\n"); + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_process), "Cliente DHCP ISC"); } else if (type == 2) { - pos = g_snprintf (buffer, sizeof (buffer), "Información cliente DHCP: Cliente Busybox UDHCPC\n"); + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_process), "Cliente Busybox UDHCPC"); + } + + status = ni_interface_get_dhcp_status (ni_interface); + if (status == 5) { + /* El proceso murió */ + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_status), "Proceso muerto"); + gtk_widget_hide (window_iface->priv->vbox_dhcpv4_info); + return; + } else if (status == 0 || status == 4) { + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_status), "Buscando..."); + gtk_widget_hide (window_iface->priv->vbox_dhcpv4_info); + return; + } else if (status == 1 || status == 2) { + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_status), "Concesión obtenida"); + } else if (status == 3) { + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_status), "Concesión expirada"); } addr = ni_interface_get_dhcp_addr (ni_interface); prefix = ni_interface_get_dhcp_prefix (ni_interface); inet_ntop (AF_INET, addr, buffer_ip, sizeof (buffer_ip)); - pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "Dirección IP: %s/%i\n", buffer_ip, prefix); + g_snprintf (buffer, sizeof (buffer), "%s/%i", buffer_ip, prefix); + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_ip_label), buffer); c = ni_interface_get_dhcp_gw_count (ni_interface); addr = ni_interface_get_dhcp_gw_addr (ni_interface); - if (c > 0) { - pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "Gateway: "); - } - for (g = 0; g < c; g++) { - inet_ntop (AF_INET, &addr[g], buffer_ip, sizeof (buffer_ip)); - - pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "%s,", buffer_ip); - } - if (c > 0) { - pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "\n"); + if (c == 0) { + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_gateway_label), ""); + } else { + pos = 0; + for (g = 0; g < c; g++) { + inet_ntop (AF_INET, &addr[g], buffer_ip, sizeof (buffer_ip)); + + pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "%s", buffer_ip); + if (g != c - 1) { + pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, ", "); + } + } + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_gateway_label), buffer); } if (ni_interface_has_dhcp_brd_addr (ni_interface)) { addr = ni_interface_get_dhcp_brd_addr (ni_interface); inet_ntop (AF_INET, addr, buffer_ip, sizeof (buffer_ip)); - pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "Broadcast: %s\n", buffer_ip); + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_bcast_label), buffer_ip); + } else { + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_bcast_label), ""); } c = ni_interface_get_dhcp_dns_count (ni_interface); addr = ni_interface_get_dhcp_dns_addr (ni_interface); - if (c > 0) { - pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "DNS: "); - } - for (g = 0; g < c; g++) { - inet_ntop (AF_INET, &addr[g], buffer_ip, sizeof (buffer_ip)); - - pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "%s,", buffer_ip); - } - if (c > 0) { - pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "\n"); + if (c == 0) { + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_dns_label), ""); + } else { + pos = 0; + for (g = 0; g < c; g++) { + inet_ntop (AF_INET, &addr[g], buffer_ip, sizeof (buffer_ip)); + + pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "%s", buffer_ip); + if (g != c - 1) { + pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, ", "); + } + } + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_dns_label), buffer); } if (ni_interface_has_dhcp_server_addr (ni_interface)) { addr = ni_interface_get_dhcp_server_addr (ni_interface); inet_ntop (AF_INET, addr, buffer_ip, sizeof (buffer_ip)); - pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "DHCP Server: %s\n", buffer_ip); + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_server_label), buffer_ip); + } else { + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_server_label), ""); } lease_time = ni_interface_get_dhcp_lease_time (ni_interface); if (lease_time != 0) { - pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "Tiempo de concesión: %i seg(s)\n", lease_time); + g_snprintf (buffer, sizeof (buffer), "%i seg(s)", lease_time); + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_time_label), buffer); + } else { + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_time_label), ""); } domain_name = ni_interface_get_dhcp_domain_name (ni_interface); if (domain_name != NULL) { - pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "Nombre de dominio: %s\n", domain_name); + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_domain_label), domain_name); + } else { + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_domain_label), ""); } - gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_info), buffer); + gtk_widget_show (window_iface->priv->vbox_dhcpv4_info); } } @@ -816,9 +855,27 @@ static void ni_window_interface_aditional_setup_for_bridge (NIWindowInterface *w /* Eventos de los botones de DHCP */ static void ni_window_interface_dhcp_run_cb (GtkWidget *button, gpointer data) { NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data); + guint flags; + + flags = 0; + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (window_iface->priv->check_flag_autorestart))) { + flags |= 0x0001; + } + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (window_iface->priv->check_flag_no_dns))) { + flags |= 0x0002; + } + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (window_iface->priv->check_flag_no_gws))) { + flags |= 0x0004; + } + + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (window_iface->priv->check_flag_no_ip))) { + flags |= 0x0008; + } // Ejecutar el DHCP aquí - ni_interface_run_dhcp (window_iface->priv->ni_interface, window_iface->priv->dhcp_type); + ni_interface_run_dhcp (window_iface->priv->ni_interface, window_iface->priv->dhcp_type, flags); } static void ni_window_interface_dhcp_stop_cb (GtkWidget *button, gpointer data) { @@ -1196,6 +1253,7 @@ static void prepare_bridge_tab (NIWindowInterface *window_iface) { static void prepare_dhcpv4_tab (NIWindowInterface *window_iface) { GtkWidget *vbox, *hbox, *label, *button; GtkSizeGroup *size_l; + GtkWidget *expander; GtkWindow *window = GTK_WINDOW (window_iface); NIWindowInterfacePrivate *priv = window_iface->priv; GtkWidget *item; @@ -1245,11 +1303,162 @@ static void prepare_dhcpv4_tab (NIWindowInterface *window_iface) { g_signal_connect (priv->button_dhcp_run, "clicked", G_CALLBACK (ni_window_interface_dhcp_run_cb), window_iface); gtk_box_pack_end (GTK_BOX (hbox), priv->button_dhcp_run, FALSE, FALSE, 0); + /* Generar un expander para opciones avanzadas */ + expander = gtk_expander_new_with_mnemonic ("_Opciones avanzadas"); + gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4), expander, FALSE, FALSE, 0); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3); + gtk_container_add (GTK_CONTAINER (expander), vbox); + + /* Primera opción, autoreiniciar */ + priv->check_flag_autorestart = gtk_check_button_new_with_label ("Autoreiniciar proceso"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->check_flag_autorestart), TRUE); + gtk_box_pack_start (GTK_BOX (vbox), priv->check_flag_autorestart, FALSE, FALSE, 3); + + /* Segunda opción, no instalar información DNS */ + priv->check_flag_no_dns = gtk_check_button_new_with_label ("No instalar información DNS"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->check_flag_no_dns), FALSE); + gtk_box_pack_start (GTK_BOX (vbox), priv->check_flag_no_dns, FALSE, FALSE, 3); + + /* Tercera opción, no instalar información del gateway */ + priv->check_flag_no_gws = gtk_check_button_new_with_label ("No instalar rutas por defecto"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->check_flag_no_gws), FALSE); + gtk_box_pack_start (GTK_BOX (vbox), priv->check_flag_no_gws, FALSE, FALSE, 3); + + /* Cuarta opción, no instalar información de las ips */ + priv->check_flag_no_ip = gtk_check_button_new_with_label ("No instalar dirección IP adquirida"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->check_flag_no_ip), FALSE); + gtk_box_pack_start (GTK_BOX (vbox), priv->check_flag_no_ip, FALSE, FALSE, 3); + + /* Las labels del estado */ - priv->dhcpv4_info = gtk_label_new ("Información cliente DHCP: "); - gtk_label_set_selectable (GTK_LABEL (priv->dhcpv4_info), TRUE); - gtk_label_set_xalign (GTK_LABEL (priv->dhcpv4_info), 0.0); - gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4), priv->dhcpv4_info, FALSE, FALSE, 0); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4), hbox, FALSE, FALSE, 0); + + label = gtk_label_new ("Tipo de cliente:"); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_size_group_add_widget (size_l, label); + + priv->dhcpv4_process = gtk_label_new (""); + gtk_label_set_xalign (GTK_LABEL (priv->dhcpv4_process), 0.0); + gtk_label_set_selectable (GTK_LABEL (priv->dhcpv4_process), TRUE); + gtk_box_pack_end (GTK_BOX (hbox), priv->dhcpv4_process, FALSE, FALSE, 0); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4), hbox, FALSE, FALSE, 0); + + label = gtk_label_new ("Estado:"); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_size_group_add_widget (size_l, label); + + priv->dhcpv4_status = gtk_label_new (""); + gtk_label_set_xalign (GTK_LABEL (priv->dhcpv4_status), 0.0); + gtk_label_set_selectable (GTK_LABEL (priv->dhcpv4_status), TRUE); + gtk_box_pack_end (GTK_BOX (hbox), priv->dhcpv4_status, FALSE, FALSE, 0); + + /* Un super vbox para ocultar toda la información de DHCP */ + priv->vbox_dhcpv4_info = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); + gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4), priv->vbox_dhcpv4_info, FALSE, FALSE, 10); + + /* Placeholder para la IP */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4_info), hbox, FALSE, FALSE, 0); + + label = gtk_label_new ("Dirección IP:"); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_size_group_add_widget (size_l, label); + + priv->dhcpv4_ip_label = gtk_label_new (""); + gtk_label_set_xalign (GTK_LABEL (priv->dhcpv4_ip_label), 0.0); + gtk_label_set_selectable (GTK_LABEL (priv->dhcpv4_ip_label), TRUE); + gtk_box_pack_end (GTK_BOX (hbox), priv->dhcpv4_ip_label, FALSE, FALSE, 0); + + /* Placeholder para el gateway */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4_info), hbox, FALSE, FALSE, 0); + + label = gtk_label_new ("Gateway:"); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_size_group_add_widget (size_l, label); + + priv->dhcpv4_gateway_label = gtk_label_new (""); + gtk_label_set_xalign (GTK_LABEL (priv->dhcpv4_gateway_label), 0.0); + gtk_label_set_selectable (GTK_LABEL (priv->dhcpv4_gateway_label), TRUE); + gtk_box_pack_end (GTK_BOX (hbox), priv->dhcpv4_gateway_label, FALSE, FALSE, 0); + + /* Placeholder para el broadcast, si está presente */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4_info), hbox, FALSE, FALSE, 0); + + label = gtk_label_new ("Broadcast:"); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_size_group_add_widget (size_l, label); + + priv->dhcpv4_bcast_label = gtk_label_new (""); + gtk_label_set_xalign (GTK_LABEL (priv->dhcpv4_bcast_label), 0.0); + gtk_label_set_selectable (GTK_LABEL (priv->dhcpv4_bcast_label), TRUE); + gtk_box_pack_end (GTK_BOX (hbox), priv->dhcpv4_bcast_label, FALSE, FALSE, 0); + + /* Placer holder para los DNS */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4_info), hbox, FALSE, FALSE, 0); + + label = gtk_label_new ("DNS:"); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_size_group_add_widget (size_l, label); + + priv->dhcpv4_dns_label = gtk_label_new (""); + gtk_label_set_xalign (GTK_LABEL (priv->dhcpv4_dns_label), 0.0); + gtk_label_set_selectable (GTK_LABEL (priv->dhcpv4_dns_label), TRUE); + gtk_box_pack_end (GTK_BOX (hbox), priv->dhcpv4_dns_label, FALSE, FALSE, 0); + + /* Placer holder para el nombre del servidor DHCP */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4_info), hbox, FALSE, FALSE, 0); + + label = gtk_label_new ("Servidor DHCP:"); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_size_group_add_widget (size_l, label); + + priv->dhcpv4_server_label = gtk_label_new (""); + gtk_label_set_xalign (GTK_LABEL (priv->dhcpv4_server_label), 0.0); + gtk_label_set_selectable (GTK_LABEL (priv->dhcpv4_server_label), TRUE); + gtk_box_pack_end (GTK_BOX (hbox), priv->dhcpv4_server_label, FALSE, FALSE, 0); + + /* Placeholder para el tiempo de concesión */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4_info), hbox, FALSE, FALSE, 0); + + label = gtk_label_new ("Tiempo de concesión:"); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_size_group_add_widget (size_l, label); + + priv->dhcpv4_time_label = gtk_label_new (""); + gtk_label_set_xalign (GTK_LABEL (priv->dhcpv4_time_label), 0.0); + gtk_label_set_selectable (GTK_LABEL (priv->dhcpv4_time_label), TRUE); + gtk_box_pack_end (GTK_BOX (hbox), priv->dhcpv4_time_label, FALSE, FALSE, 0); + + /* Placeholder para el dominio */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4_info), hbox, FALSE, FALSE, 0); + + label = gtk_label_new ("Dominio:"); + gtk_label_set_xalign (GTK_LABEL (label), 0.0); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_size_group_add_widget (size_l, label); + + priv->dhcpv4_domain_label = gtk_label_new (""); + gtk_label_set_xalign (GTK_LABEL (priv->dhcpv4_domain_label), 0.0); + gtk_label_set_selectable (GTK_LABEL (priv->dhcpv4_domain_label), TRUE); + gtk_box_pack_end (GTK_BOX (hbox), priv->dhcpv4_domain_label, FALSE, FALSE, 0); } static void ni_window_interface_init (NIWindowInterface *window_iface) { diff --git a/src/Makefile.am b/src/Makefile.am index de70994..fe614bf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,6 +3,7 @@ bin_PROGRAMS = network-inador network_inador_SOURCES = main.c \ common.h link-types.h \ + dhcpc_defs.h \ struct_addr_union.h resolv_conf_defs.h \ netlink-events.c netlink-events.h \ interfaces.c interfaces.h \ diff --git a/src/common.h b/src/common.h index 410fbe9..e232462 100644 --- a/src/common.h +++ b/src/common.h @@ -36,7 +36,7 @@ #include "struct_addr_union.h" #include "resolv_conf_defs.h" - +#include "dhcpc_defs.h" #ifndef FALSE #define FALSE 0 @@ -118,47 +118,6 @@ typedef struct _WirelessInfo { GList *aps; } WirelessInfo; -/* Información del proceso de DHCP */ -enum { - IFACE_NO_DHCP = 0, - IFACE_ISC_DHCLIENT, - IFACE_BUSYBOX_UDHCPC -}; - -/* FIXME: Revisar estos estados */ -enum { - DHCP_CLIENT_SELECTING, - DHCP_CLIENT_BOUND, - DHCP_CLIENT_RENEWED, - - DHCP_CLIENT_EXPIRED, - DHCP_CLIENT_FAILED, - - DHCP_CLIENT_KILLED, -}; - -#define DHCP_CLIENT_FLAG_AUTO_RESTART 0x0001 - -typedef struct _InterfaceDHCPClientInfo { - int type; - - uint32_t flags; - int dhcp_state; - - /* Para vigilar el proceso */ - GPid process_pid; - guint process_watch; - - /* La información obtenida desde el cliente */ - struct_addr ip, broadcast; - struct_addr gateways[7], dns[7]; - char domain_name[256]; - int gw_c, dns_c; - int prefix; - - struct_addr dhcp_server_ip; - uint32_t lease_time; -} InterfaceDHCPClientInfo; struct _Interface { NetworkInadorHandle *handle; diff --git a/src/dhcp_client.c b/src/dhcp_client.c index 7233528..743a4bd 100644 --- a/src/dhcp_client.c +++ b/src/dhcp_client.c @@ -39,6 +39,7 @@ #include "dhcp_client.h" #include "network-inador-manager.h" +#include "resolv_manager.h" static void interfaces_dhcp_clear_info (InterfaceDHCPClientInfo *dhcpc); @@ -96,6 +97,8 @@ void interfaces_dhcp_client_killed_cb (GPid pid, gint status, gpointer data) { } interfaces_dhcp_clear_info (&iface->dhcpc); + resolv_manager_clear_dhcp_nameservers (iface->handle, iface); + /* Enviar actualización de estado aquí */ iface->dhcpc.dhcp_state = DHCP_CLIENT_KILLED; manager_send_event_dhcp_change (iface->handle, &iface->dhcpc); @@ -130,6 +133,7 @@ void interfaces_dhcp_client_killed_cb (GPid pid, gint status, gpointer data) { } else { /* En caso contrario, solo dejar la muerte escrita */ iface->dhcpc.dhcp_state = DHCP_CLIENT_KILLED; + g_source_remove (iface->dhcpc.process_watch); iface->dhcpc.process_watch = 0; } } @@ -230,22 +234,23 @@ int interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index) { } if (iface->dhcpc.type == IFACE_ISC_DHCLIENT || iface->dhcpc.type == IFACE_BUSYBOX_UDHCPC) { - if (iface->dhcpc.dhcp_state == DHCP_CLIENT_KILLED) return -1; - - /* Proceso, matar y reiniciar estado */ - - iface->dhcpc.flags &= (~DHCP_CLIENT_FLAG_AUTO_RESTART); - - g_source_remove (iface->dhcpc.process_watch); - iface->dhcpc.process_watch = 0; - g_child_watch_add (iface->dhcpc.process_pid, interfaces_dhcp_client_ignore_kill, NULL); - - kill (iface->dhcpc.process_pid, SIGTERM); + if (iface->dhcpc.dhcp_state != DHCP_CLIENT_KILLED) { + /* Proceso, matar y reiniciar estado */ + iface->dhcpc.flags &= (~DHCP_CLIENT_FLAG_AUTO_RESTART); + + g_source_remove (iface->dhcpc.process_watch); + iface->dhcpc.process_watch = 0; + g_child_watch_add (iface->dhcpc.process_pid, interfaces_dhcp_client_ignore_kill, NULL); + + kill (iface->dhcpc.process_pid, SIGTERM); + iface->dhcpc.dhcp_state = DHCP_CLIENT_KILLED; + } iface->dhcpc.type = IFACE_NO_DHCP; - iface->dhcpc.dhcp_state = DHCP_CLIENT_KILLED; - /* TODO: Revisar aquí si es pertinente desconfigurar la interfaz y borrar la información obtenida */ interfaces_dhcp_clear_info (&iface->dhcpc); + /* TODO: Revisar aquí si es pertinente desconfigurar la interfaz y borrar la información obtenida */ + resolv_manager_clear_dhcp_nameservers (handle, iface); + /* Enviar actualización de estado aquí */ manager_send_event_dhcp_change (handle, &iface->dhcpc); } @@ -255,10 +260,10 @@ int interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index) { void interfaces_dhcp_client_internal_feed_from_client (NetworkInadorHandle *handle, int index, int status, struct_addr *ip, int prefix, struct_addr *gateways, int gw_c, struct_addr *broadcast, struct_addr *dhcp_server, uint32_t lease_time, struct_addr *dns_list, int dns_count, char *domain_name) { Interface *iface; - struct in_addr empty_v4; int g; struct_addr old_dns[7]; int old_dns_c; + int dns_changed; iface = _interfaces_locate_by_index (handle->interfaces, index); @@ -300,6 +305,7 @@ void interfaces_dhcp_client_internal_feed_from_client (NetworkInadorHandle *hand printf ("----> DHCP status: %i\n", iface->dhcpc.dhcp_state); if (status == NET_INADOR_DHCP_STATUS_BOUND || status == NET_INADOR_DHCP_STATUS_RENEWED) { + dns_changed = 0; /* Copiar la información de DNS para saber si hubo cambios */ old_dns_c = iface->dhcpc.dns_c; if (old_dns_c != dns_count) { @@ -308,8 +314,6 @@ void interfaces_dhcp_client_internal_feed_from_client (NetworkInadorHandle *hand } /* Copiar las variables de estado */ - memset (&empty_v4, 0, sizeof (empty_v4)); - memcpy (&iface->dhcpc.ip, ip, sizeof (iface->dhcpc.ip)); iface->dhcpc.prefix = prefix; @@ -327,13 +331,23 @@ void interfaces_dhcp_client_internal_feed_from_client (NetworkInadorHandle *hand memcpy (&iface->dhcpc.dns[g], &dns_list[g], 4); } + if (strcmp (iface->dhcpc.domain_name, domain_name) != 0) { + /* El nombre de dominio cambió */ + dns_changed = 1; + } + strncpy (iface->dhcpc.domain_name, domain_name, sizeof (iface->dhcpc.domain_name)); + if (iface->dhcpc.dns_c != old_dns_c) { - /* TODO: Tenemos cambio en los DNS, actualizar el resolv.conf */ + /* Tenemos cambio en los DNS, actualizar el resolv.conf */ + dns_changed = 1; } else if (memcmp (iface->dhcpc.dns, old_dns, dns_count * (sizeof (iface->dhcpc.dns[0]))) != 0) { - /* TODO: Tenemos cambio en los DNS, actualizar el resolv.conf */ + /* Tenemos cambio en los DNS, actualizar el resolv.conf */ + dns_changed = 1; } - strncpy (iface->dhcpc.domain_name, domain_name, sizeof (iface->dhcpc.domain_name)); + if (dns_changed) { + resolv_manager_process_dhcp_nameservers (handle, iface); + } /* Esto solo es para impresión */ char buf_a[256], buf_b[256], buf_c[256], buf_d[256]; @@ -354,6 +368,11 @@ void interfaces_dhcp_client_internal_feed_from_client (NetworkInadorHandle *hand } printf (" y domain name <%s>\n", domain_name); + } else if (status == NET_INADOR_DHCP_STATUS_SELECTING || status == NET_INADOR_DHCP_STATUS_EXPIRED || status == NET_INADOR_DHCP_STATUS_FAILED) { + /* Cuando entramos a SELECTING, debemos limpiar los DNS del resolv.conf */ + interfaces_dhcp_clear_info (&iface->dhcpc); + + resolv_manager_clear_dhcp_nameservers (handle, iface); } manager_send_event_dhcp_change (handle, &iface->dhcpc); diff --git a/src/dhcpc_defs.h b/src/dhcpc_defs.h new file mode 100644 index 0000000..d8a5b21 --- /dev/null +++ b/src/dhcpc_defs.h @@ -0,0 +1,77 @@ +/* + * dhcpc_defs.h + * This file is part of Network-inador + * + * Copyright (C) 2023 - 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 __DHCPC_DEFS_H__ +#define __DHCPC_DEFS_H__ + +#include +#include + +#include "struct_addr_union.h" + +/* Información del proceso de DHCP */ +enum { + IFACE_NO_DHCP = 0, + IFACE_ISC_DHCLIENT, + IFACE_BUSYBOX_UDHCPC +}; + +/* FIXME: Revisar estos estados */ +enum { + DHCP_CLIENT_SELECTING, + DHCP_CLIENT_BOUND, + DHCP_CLIENT_RENEWED, + + DHCP_CLIENT_EXPIRED, + DHCP_CLIENT_FAILED, + + DHCP_CLIENT_KILLED, +}; + +#define DHCP_CLIENT_FLAG_AUTO_RESTART 0x0001 +#define DHCP_CLIENT_FLAG_DONT_ADD_DNS_INFO 0x0002 +#define DHCP_CLIENT_FLAG_DONT_ADD_ROUTE_INFO 0x0004 +#define DHCP_CLIENT_FLAG_DONT_ADD_IP_INFO 0x0008 + +typedef struct { + int type; + + uint32_t flags; + int dhcp_state; + + /* Para vigilar el proceso */ + GPid process_pid; + guint process_watch; + + /* La información obtenida desde el cliente */ + struct_addr ip, broadcast; + struct_addr gateways[7], dns[7]; + char domain_name[256]; + int gw_c, dns_c; + int prefix; + + struct_addr dhcp_server_ip; + uint32_t lease_time; +} InterfaceDHCPClientInfo; + +#endif /* __DHCPC_DEFS_H__ */ + diff --git a/src/resolv_manager.c b/src/resolv_manager.c index 007c68a..e4b1c69 100644 --- a/src/resolv_manager.c +++ b/src/resolv_manager.c @@ -26,6 +26,8 @@ #include #include +#include +#include #include "resolv_manager.h" #include "common.h" @@ -70,13 +72,8 @@ void resolv_manager_clear_entries_by_prog (NetworkInadorHandle *handle, const in while (g != NULL) { entry = (ResolvConfEntry *) g->data; - if (entry->origin != RESOLV_ORIGIN_RESOLVCONF) { - /* Solo borramos las entradas creadas via resolvconf */ - g = g->next; - continue; - } - - if (entry->owner_interface_index != iface_index) { + if (entry->origin != RESOLV_ORIGIN_RESOLVCONF || entry->owner_interface_index != iface_index) { + /* Solo borramos las entradas creadas via resolvconf y que pertenezcan a esta interfaz */ g = g->next; continue; } @@ -138,6 +135,7 @@ void resolv_manager_process_resolvconf_entries (NetworkInadorHandle *handle, Res entry->tagged = 1; strncpy (entry->owner_prog, entries[g].owner_prog, sizeof (entry->owner_prog)); printf ("/// Asociando una entrada %s existente del archivo al: %s\n", entry->value, entry->owner_prog); + #if 0 } else if (entry->origin == RESOLV_ORIGIN_DHCP) { /* Una entrada que coincide con la actual solo se puede re-asociar al resolvconf si pertenece a la misma interfaz */ if (entry->owner_interface_index != entries[g].owner_interface_index) { @@ -145,6 +143,7 @@ void resolv_manager_process_resolvconf_entries (NetworkInadorHandle *handle, Res entry = NULL; continue; } + #endif } else { /* Existe la entrada, pero no la podemos tomar como nuestra, crear otra */ entry->tagged = 1; @@ -178,6 +177,183 @@ void resolv_manager_process_resolvconf_entries (NetworkInadorHandle *handle, Res } } +void resolv_manager_process_dhcp_nameservers (NetworkInadorHandle *handle, Interface *iface) { + GList *pos_entry; + int h; + ResolvConfEntry *entry; + int do_write = 0; + + /* Recorrer todas las entradas que sean tipo DHCP y marcar para eliminación */ + resolv_manager_clear_tag_on_all (handle); + + pos_entry = handle->resolver_entries; + while (pos_entry != NULL) { + entry = (ResolvConfEntry *) pos_entry->data; + + if (entry->origin == RESOLV_ORIGIN_DHCP && entry->owner_interface_index == iface->index) { + /* Nos interesa para eliminación */ + entry->for_purge = 1; + } + + pos_entry = pos_entry->next; + } + + /* Ahora, procesar la información de DHCP buscando entradas (viejas o de archivo) para reciclar. + * Si no, crear */ + for (h = 0; h < iface->dhcpc.dns_c; h++) { + entry = NULL; + while (entry == NULL) { + pos_entry = resolv_parser_search_entry (handle->resolver_entries, RESOLV_TYPE_NAMESERVER, AF_INET, &iface->dhcpc.dns[h], "", 1); + if (pos_entry == NULL) break; + + /* De ser posible, hacer conciliación */ + entry = (ResolvConfEntry *) pos_entry->data; + + if (entry->origin == RESOLV_ORIGIN_FILE) { + /* Hacer esta entrada nuestra */ + entry->origin = RESOLV_ORIGIN_DHCP; + entry->owner_interface_index = iface->index; + entry->tagged = 1; + entry->owner_prog[0] = 0; + printf ("/// Asociando una entrada %s existente del archivo al DHCP (%s)\n", entry->value, iface->name); + } else if (entry->origin == RESOLV_ORIGIN_DHCP && entry->owner_interface_index == iface->index) { + /* Una entrada vieja coincide, reciclar */ + entry->tagged = 1; + entry->for_purge = 0; + } else { + /* Existe la entrada, pero no la podemos tomar como nuestra, buscar otra */ + entry->tagged = 1; + entry = NULL; + continue; + } + } + + /* Si la entrada no se pudo conciliar, crear una */ + if (entry == NULL) { + entry = (ResolvConfEntry *) malloc (sizeof (ResolvConfEntry)); + + entry->resolv_type = RESOLV_TYPE_NAMESERVER; + entry->origin = RESOLV_ORIGIN_DHCP; + entry->owner_interface_index = iface->index; + entry->owner_prog[0] = 0; + entry->file_order = h; + entry->tagged = 0; + entry->priority = 0; + entry->for_purge = 0; + entry->ns_family = AF_INET; + memcpy (&entry->nameserver, &iface->dhcpc.dns[h], 4); + inet_ntop (AF_INET, &entry->nameserver, entry->value, sizeof (entry->value)); + + /* Anexar al final de la lista */ + handle->resolver_entries = g_list_append (handle->resolver_entries, entry); + + /* Como creamos una entrada via el dhcp, regenerar el archivo */ + printf ("/// Nueva entrada %s via DHCP (%s), programando regeneración.\n", entry->value, iface->name); + do_write = 1; + } + } + + /* Si tiene un nombre de dominio, agregar como entrada tipo search */ + if (iface->dhcpc.domain_name[0] != 0) { + entry = NULL; + while (entry == NULL) { + pos_entry = resolv_parser_search_entry (handle->resolver_entries, RESOLV_TYPE_SEARCH, AF_INET, NULL, iface->dhcpc.domain_name, 1); + if (pos_entry == NULL) break; + + /* De ser posible, hacer conciliación */ + entry = (ResolvConfEntry *) pos_entry->data; + + if (entry->origin == RESOLV_ORIGIN_FILE) { + /* Hacer esta entrada nuestra */ + entry->origin = RESOLV_ORIGIN_DHCP; + entry->owner_interface_index = iface->index; + entry->tagged = 1; + entry->owner_prog[0] = 0; + printf ("/// Asociando una entrada search %s existente del archivo al DHCP (%s)\n", entry->value, iface->name); + } else if (entry->origin == RESOLV_ORIGIN_DHCP && entry->owner_interface_index == iface->index) { + /* Una entrada vieja coincide, reciclar */ + entry->tagged = 1; + entry->for_purge = 0; + } else { + /* Existe la entrada, pero no la podemos tomar como nuestra, buscar otra */ + entry->tagged = 1; + entry = NULL; + continue; + } + } + + /* Si la entrada no se pudo conciliar, crear una */ + if (entry == NULL) { + entry = (ResolvConfEntry *) malloc (sizeof (ResolvConfEntry)); + + entry->resolv_type = RESOLV_TYPE_SEARCH; + entry->origin = RESOLV_ORIGIN_DHCP; + entry->owner_interface_index = iface->index; + entry->owner_prog[0] = 0; + entry->file_order = h; + entry->tagged = 0; + entry->priority = 0; + entry->for_purge = 0; + entry->ns_family = AF_INET; + memset (&entry->nameserver, 0, sizeof (entry->nameserver)); + strncpy (entry->value, iface->dhcpc.domain_name, sizeof (entry->value)); + + /* Anexar al final de la lista */ + handle->resolver_entries = g_list_append (handle->resolver_entries, entry); + + /* Como creamos una entrada via el dhcp, regenerar el archivo */ + printf ("/// Nueva entrada search %s via DHCP (%s), programando regeneración.\n", entry->value, iface->name); + do_write = 1; + } + } + + /* Después de recorrer las entradas, revisar si quedaron entradas por purgar. + * Si hay entradas por purgar, programar una reescritura de archivo */ + pos_entry = handle->resolver_entries; + while (pos_entry != NULL) { + entry = (ResolvConfEntry *) pos_entry->data; + + if (entry->for_purge == 1) { + do_write = 1; + printf ("/// Entrada %s eliminada via DHCP (%s), programando regeneración.\n", entry->value, iface->name); + //break; + } + pos_entry = pos_entry->next; + } + + if (do_write) { + resolv_manager_write (handle); + } +} + +void resolv_manager_clear_dhcp_nameservers (NetworkInadorHandle *handle, Interface *iface) { + GList *pos_entry; + int h; + ResolvConfEntry *entry; + int do_write = 0; + + /* Recorrer todas las entradas que sean tipo DHCP y marcar para eliminación */ + resolv_manager_clear_tag_on_all (handle); + + pos_entry = handle->resolver_entries; + while (pos_entry != NULL) { + entry = (ResolvConfEntry *) pos_entry->data; + + if (entry->origin == RESOLV_ORIGIN_DHCP && entry->owner_interface_index == iface->index) { + /* Nos interesa para eliminación */ + printf ("/// Entrada %s eliminada via DHCP (%s), programando regeneración.\n", entry->value, iface->name); + entry->for_purge = 1; + do_write = 1; + } + + pos_entry = pos_entry->next; + } + + if (do_write) { + resolv_manager_write (handle); + } +} + void resolv_manager_read_local_etc_resolv (NetworkInadorHandle *handle) { FILE *fd; GList *pos, *next; @@ -248,7 +424,7 @@ void resolv_manager_write (NetworkInadorHandle *handle) { if (entry->origin == RESOLV_ORIGIN_FILE) { fprintf (fd, "# This entry was previously on file, preserving"); } else if (entry->origin == RESOLV_ORIGIN_DHCP) { - fprintf (fd, "# This entry was added via DHCP (on %s) via NetworkInador", (iface != NULL ? iface->name : "unknown")); + fprintf (fd, "# This entry was added via DHCP (on %s) by NetworkInador", (iface != NULL ? iface->name : "unknown")); } else if (entry->origin == RESOLV_ORIGIN_RESOLVCONF) { fprintf (fd, "# This entry was added via resolvconf (%s.%s)", (iface != NULL ? iface->name : "unknown"), entry->owner_prog); } else if (entry->origin == RESOLV_ORIGIN_SLAAC_RDNSS) { diff --git a/src/resolv_manager.h b/src/resolv_manager.h index 4e3b8d9..623e1e4 100644 --- a/src/resolv_manager.h +++ b/src/resolv_manager.h @@ -30,6 +30,8 @@ void resolv_manager_init (NetworkInadorHandle *handle); void resolv_manager_clear_entries_by_prog (NetworkInadorHandle *handle, const int iface_index, const char *prog); void resolv_manager_process_resolvconf_entries (NetworkInadorHandle *handle, ResolvConfEntry *entries, int num_entries); +void resolv_manager_process_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_write (NetworkInadorHandle *handle);