From 0ff00a8b9ccd741306dd972e90974dc27d9825f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Arreola=20Rodr=C3=ADguez?= Date: Sun, 2 Jan 2022 23:07:39 -0600 Subject: [PATCH] Agrego eventos del estado del DHCP --- client-gtk/ni-client.c | 88 ++++++++++- client-gtk/ni-client.h | 6 +- client-gtk/ni-interface.c | 256 ++++++++++++++++++++++++++----- client-gtk/ni-interface.h | 16 ++ client-gtk/ni-marshal.list | 1 + client-gtk/ni-window-interface.c | 183 +++++++++++++++++++++- src/common.h | 1 - src/dhcp_client.c | 25 ++- src/interfaces.c | 2 +- src/manager.c | 25 ++- src/manager.h | 1 + 11 files changed, 550 insertions(+), 54 deletions(-) diff --git a/client-gtk/ni-client.c b/client-gtk/ni-client.c index 9956eac..5856d17 100644 --- a/client-gtk/ni-client.c +++ b/client-gtk/ni-client.c @@ -230,6 +230,19 @@ static gboolean ni_client_data_read (NIClient *ni_client, gpointer data, guint s } return TRUE; break; + case NET_INADOR_EVENT_DHCP_STATUS: + memcpy (&index, &buffer[2], 4); + + /* Si la interfaz no existe, proccesarla yo, para que se cree el objeto, si la interfaz ya existe, dejar pasar el mensaje */ + ni_interface = (NIInterface *) g_hash_table_lookup (ni_client->priv->interfaces, GINT_TO_POINTER(index)); + if (ni_interface == NULL) { + /* Esta es una condición de error interesante. No debería ocurrir. Absorber el evento */ + return TRUE; + } + + /* Dejar pasar el evento para que la propia interfaz lo procese */ + return FALSE; + break; } } else if (buffer[0] == NET_INADOR_TYPE_RESPONSE) { switch (buffer[1]) { @@ -246,6 +259,19 @@ static gboolean ni_client_data_read (NIClient *ni_client, gpointer data, guint s return FALSE; } break; + case NET_INADOR_RESPONSE_DHCP_STATUS: + memcpy (&index, &buffer[2], 4); + + /* Si la interfaz no existe, proccesarla yo, para que se cree el objeto, si la interfaz ya existe, dejar pasar el mensaje */ + ni_interface = (NIInterface *) g_hash_table_lookup (ni_client->priv->interfaces, GINT_TO_POINTER(index)); + if (ni_interface == NULL) { + /* Esta es una condición de error interesante. No debería ocurrir. Absorber el evento */ + return TRUE; + } + + /* Dejar pasar el evento para que la propia interfaz lo procese */ + return FALSE; + break; } } @@ -349,7 +375,7 @@ static void ni_client_init (NIClient *ni_client) { priv->client_socket = -1; priv->socket_path = NULL; priv->source = 0; - priv->events = NET_INADOR_EVENT_MASK_INTERFACES | NET_INADOR_EVENT_MASK_IP; + priv->events = NET_INADOR_EVENT_MASK_INTERFACES | NET_INADOR_EVENT_MASK_IP | NET_INADOR_EVENT_MASK_DHCP_STATUS; priv->interfaces = g_hash_table_new (g_direct_hash, g_direct_equal); } @@ -554,6 +580,49 @@ 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) { + unsigned char buffer[16]; + uint32_t index; + uint32_t flags = 0x1; + + if (ni_client->priv->client_socket < 0) { + return; + } + + if (type < 1 || type > 2) { + /* Solo se permite tipo 1 o tipo 2 */ + return; + } + + index = ni_interface_get_index (ni_interface); + buffer[0] = NET_INADOR_TYPE_COMMAND; + buffer[1] = NET_INADOR_COMMAND_RUN_DHCP; + memcpy (&buffer[2], &index, 4); + buffer[6] = AF_INET; + buffer[7] = type; + + memcpy (&buffer[8], &flags, 4); + + send (ni_client->priv->client_socket, buffer, 12, 0); +} + +void ni_client_ask_dhcp_stop_interface (NIClient *ni_client, NIInterface *ni_interface) { + unsigned char buffer[8]; + uint32_t index; + + if (ni_client->priv->client_socket < 0) { + return; + } + + index = ni_interface_get_index (ni_interface); + buffer[0] = NET_INADOR_TYPE_COMMAND; + buffer[1] = NET_INADOR_COMMAND_STOP_DHCP; + memcpy (&buffer[2], &index, 4); + buffer[6] = AF_INET; + + send (ni_client->priv->client_socket, buffer, 7, 0); +} + void ni_client_ask_create_bridge (NIClient *ni_client, const gchar *name) { unsigned char buffer[128]; int n_len; @@ -607,6 +676,23 @@ void ni_client_ask_interface_set_master (NIClient *ni_client, NIInterface *ni_in send (ni_client->priv->client_socket, buffer, 10, 0); } +void ni_client_ask_interface_dhcp_status (NIClient *ni_client, NIInterface *ni_interface) { + unsigned char buffer[8]; + uint32_t index; + + if (ni_client->priv->client_socket < 0) { + return; + } + + index = ni_interface_get_index (ni_interface); + buffer[0] = NET_INADOR_TYPE_COMMAND; + buffer[1] = NET_INADOR_COMMAND_GET_DHCP_STATUS; + memcpy (&buffer[2], &index, 4); + buffer[6] = AF_INET; + + send (ni_client->priv->client_socket, buffer, 7, 0); +} + static void ni_client_foreach_has_table (gpointer key, gpointer value, gpointer data) { GList **lista = (GList **) data; diff --git a/client-gtk/ni-client.h b/client-gtk/ni-client.h index 84f4f90..faab229 100644 --- a/client-gtk/ni-client.h +++ b/client-gtk/ni-client.h @@ -77,7 +77,6 @@ NIClient *ni_client_new (void); NIClient *ni_client_new_with_path (const char *path); gboolean ni_client_connect (NIClient *ni_client); void ni_client_ask_ip_interface (NIClient *ni_client, NIInterface *ni_interface, int family); -void ni_client_ask_ips (NIClient *ni_client, NIInterface *ni_interface); void ni_client_ask_ip_new (NIClient *ni_client, NIInterface *ni_interface, int family, int prefix, struct_addr *addr, uint32_t flags, unsigned char scope, int has_local, struct_addr *local_addr, int has_brd, struct_addr *brd_addr, uint32_t *cacheinfo); void ni_client_ask_ip_delete (NIClient *ni_client, NIInterface *ni_interface, NIIP *ni_ip); void ni_client_ask_change_iface_name (NIClient *ni_client, NIInterface *ni_interface, const gchar *new_name); @@ -90,6 +89,11 @@ NIInterface *ni_client_get_interface_by_index (NIClient *ni_client, guint index) void ni_client_ask_interface_clear_master (NIClient *ni_client, NIInterface *ni_interface); 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_interface_dhcp_status (NIClient *ni_client, NIInterface *ni_interface); + G_END_DECLS #endif /* __NI_CLIENT_H__ */ diff --git a/client-gtk/ni-interface.c b/client-gtk/ni-interface.c index cef4909..f32eaf3 100644 --- a/client-gtk/ni-interface.c +++ b/client-gtk/ni-interface.c @@ -27,6 +27,7 @@ #include "ni-client.h" #include "ni-interface.h" #include "ni-ip.h" +#include "ni-marshal.h" #include "../src/network-inador-manager.h" @@ -43,6 +44,16 @@ struct _NIInterfacePrivate { gboolean is_wireless; GList *ip_list; + + /* Información del DHCP */ + gboolean dhcp_type_first_time; + int dhcp_type, dhcp_status; + uint32_t dhcp_lease_time; + gboolean has_dhcp_broadcast, has_dhcp_gw, has_dhcp_server; + struct_addr dhcp_addr, dhcp_broadcast, dhcp_gateway, dhcp_server; + guint dhcp_prefix; + + /* TODO: Falta procesar la información del DNS */ }; enum { @@ -73,6 +84,9 @@ enum { ADDED_TO_BRIDGE, REMOVED_FROM_BRIDGE, + DHCP_TYPE_CHANGED, + DHCP_STATUS_UPDATED, + LAST_SIGNAL }; @@ -138,6 +152,9 @@ static void ni_interface_constructed (GObject *obj) { /* Solicitar listado de IP's */ ni_client_ask_ip_interface (ni_interface->priv->ni_client, ni_interface, AF_UNSPEC); + + /* Solicitar la información del estado del DHCP */ + ni_client_ask_interface_dhcp_status (ni_interface->priv->ni_client, ni_interface); } } @@ -344,6 +361,28 @@ static void ni_interface_class_init (NIInterfaceClass *klass) { G_TYPE_NONE, 1, G_TYPE_UINT); + + signals[DHCP_TYPE_CHANGED] = g_signal_new ("dhcp-type-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + _ni_marshal_VOID__UINT_UINT, + G_TYPE_NONE, + 2, + G_TYPE_UINT, + G_TYPE_UINT); + + signals[DHCP_STATUS_UPDATED] = g_signal_new ("dhcp-status-updated", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); } static gint ni_interface_locate_ip (gconstpointer *a, gconstpointer *b) { @@ -487,7 +526,6 @@ static void ni_interface_process_ip_added (NIInterface *ni_interface, gpointer d ni_interface->priv->ip_list = g_list_append (ni_interface->priv->ip_list, ni_ip); - printf ("Emitiendo signal de IP-addr\n"); g_signal_emit (ni_interface, signals[NEW_IP], 0, ni_ip); } @@ -535,6 +573,74 @@ static void ni_interface_process_ip_removed (NIInterface *ni_interface, gpointer } } +static void ni_interface_process_dhcp_status (NIInterface *ni_interface, gpointer data, guint size) { + unsigned char *buffer = (unsigned char *) data; + gint family_size = 0; + guint bits, pos; + int old_type; + + if (buffer[6] != AF_INET) { + return; + } + + old_type = ni_interface->priv->dhcp_type; + + family_size = sizeof (struct in_addr); + + ni_interface->priv->dhcp_type = buffer[7]; + ni_interface->priv->dhcp_status = buffer[8]; + ni_interface->priv->dhcp_prefix = buffer[9]; + + ni_interface->priv->has_dhcp_gw = FALSE; + if (buffer[10] & 0x01) { + /* Hay un DHCP gateway */ + ni_interface->priv->has_dhcp_gw = TRUE; + } + + ni_interface->priv->has_dhcp_broadcast = FALSE; + if (buffer[10] & 0x02) { + /* Hay una IP broadcast de DHCP */ + ni_interface->priv->has_dhcp_broadcast = TRUE; + } + + ni_interface->priv->has_dhcp_server = FALSE; + if (buffer[10] & 0x04) { + /* Hay un servidor DHCP */ + ni_interface->priv->has_dhcp_server = TRUE; + } + + /* TODO: Procesar aquí la información de DNS */ + + memcpy (&ni_interface->priv->dhcp_lease_time, &buffer[12], 4); + + memcpy (&ni_interface->priv->dhcp_addr, &buffer[16], family_size); + pos = 16 + family_size; + + if (ni_interface->priv->has_dhcp_gw) { + memcpy (&ni_interface->priv->dhcp_gateway, &buffer[pos], family_size); + pos += family_size; + } + + if (ni_interface->priv->has_dhcp_broadcast) { + memcpy (&ni_interface->priv->dhcp_broadcast, &buffer[pos], family_size); + pos += family_size; + } + + if (ni_interface->priv->has_dhcp_server) { + memcpy (&ni_interface->priv->dhcp_server, &buffer[pos], family_size); + pos += family_size; + } + + /* TODO: Procesar la información de los DNS */ + if (old_type != ni_interface->priv->dhcp_type || ni_interface->priv->dhcp_type_first_time) { + /* Es una actualizacion de tipo */ + g_signal_emit (ni_interface, signals[DHCP_TYPE_CHANGED], 0, old_type, ni_interface->priv->dhcp_type); + ni_interface->priv->dhcp_type_first_time = FALSE; + } else { + g_signal_emit (ni_interface, signals[DHCP_STATUS_UPDATED], 0); + } +} + static gboolean ni_interface_process_interface_response (NIClient *ni_client, unsigned char *buffer, guint size, gpointer user_data) { NIInterface *ni_interface = (NIInterface *) user_data; uint32_t index; @@ -575,6 +681,17 @@ static gboolean ni_interface_process_interface_response (NIClient *ni_client, un ni_interface_process_ip_removed (ni_interface, buffer, size); return TRUE; break; + case NET_INADOR_EVENT_DHCP_STATUS: + memcpy (&index, &buffer[2], 4); + + if (index != ni_interface->priv->index) { + /* Mensaje de la interfaz, pero no para mí, dejar pasar */ + return FALSE; + } + + ni_interface_process_dhcp_status (ni_interface, buffer, size); + return TRUE; + break; } } else if (buffer[0] == NET_INADOR_TYPE_RESPONSE) { switch (buffer[1]) { @@ -585,7 +702,6 @@ static gboolean ni_interface_process_interface_response (NIClient *ni_client, un /* Mensaje de IP, pero no para mí, dejar pasar */ return FALSE; } - printf ("Response IP addr sobre interfaz\n"); ni_interface_process_ip_added (ni_interface, buffer, size); return TRUE; @@ -601,6 +717,17 @@ static gboolean ni_interface_process_interface_response (NIClient *ni_client, un ni_interface_process_interface_update (ni_interface, buffer, size); return TRUE; break; + case NET_INADOR_RESPONSE_DHCP_STATUS: + memcpy (&index, &buffer[2], 4); + + if (index != ni_interface->priv->index) { + /* Mensaje de la interfaz, pero no para mí, dejar pasar */ + return FALSE; + } + + ni_interface_process_dhcp_status (ni_interface, buffer, size); + return TRUE; + break; } } @@ -694,44 +821,83 @@ void ni_interface_set_up (NIInterface *ni_interface) { ni_client_ask_up_down_interface (ni_interface->priv->ni_client, ni_interface, TRUE); } -#if 0 -void ni_interface_consume_values (NIInterface *ni_interface, char *name, gint arp_type, guint master_index, guint mtu, guint flags) { - g_object_freeze_notify (G_OBJECT (ni_interface)); +void ni_interface_run_dhcp (NIInterface *ni_interface, int type) { + g_return_if_fail (NI_IS_INTERFACE (ni_interface)); - if (ni_interface->priv->name == NULL) { - ni_interface->priv->name = g_strdup (name); - g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_NAME]); - } else if (strcmp (ni_interface->priv->name, name) != 0) { - g_free (ni_interface->priv->name); - - ni_interface->priv->name = g_strdup (name); - g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_NAME]); - } - - - if (ni_interface->priv->arp_type != arp_type) { - ni_interface->priv->arp_type = arp_type; - g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_ARP_TYPE]); - } - - if (ni_interface->priv->master_index != master_index) { - ni_interface->priv->master_index = master_index; - g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_MASTER_INDEX]); - } - - if (ni_interface->priv->mtu != mtu) { - ni_interface->priv->master_index = master_index; - g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_MASTER_INDEX]); - } - - if (ni_interface->priv->flags != flags) { - ni_interface->priv->flags = flags; - g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_FLAGS]); - } - - g_object_thaw_notify (G_OBJECT (ni_interface)); + ni_client_ask_dhcp_run_interface (ni_interface->priv->ni_client, ni_interface, type); +} + +void ni_interface_stop_dhcp (NIInterface *ni_interface) { + g_return_if_fail (NI_IS_INTERFACE (ni_interface)); + + ni_client_ask_dhcp_stop_interface (ni_interface->priv->ni_client, ni_interface); +} + +guint ni_interface_get_dhcp_type (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0); + + return ni_interface->priv->dhcp_type; +} + +guint ni_interface_get_dhcp_status (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0); + + return ni_interface->priv->dhcp_status; +} + +guint ni_interface_get_dhcp_lease_time (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0); + + return ni_interface->priv->dhcp_lease_time; +} + +guint ni_interface_get_dhcp_prefix (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0); + + return ni_interface->priv->dhcp_prefix; +} + +const struct_addr * ni_interface_get_dhcp_addr (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), NULL); + + return &ni_interface->priv->dhcp_addr; +} + +gboolean ni_interface_has_dhcp_brd_addr (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), FALSE); + + return ni_interface->priv->has_dhcp_broadcast; +} + +gboolean ni_interface_has_dhcp_gw_addr (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), FALSE); + + return ni_interface->priv->has_dhcp_gw; +} + +gboolean ni_interface_has_dhcp_server_addr (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), FALSE); + + return ni_interface->priv->has_dhcp_server; +} + +const struct_addr * ni_interface_get_dhcp_brd_addr (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), NULL); + + return &ni_interface->priv->dhcp_broadcast; +} + +const struct_addr * ni_interface_get_dhcp_gw_addr (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), NULL); + + return &ni_interface->priv->dhcp_gateway; +} + +const struct_addr * ni_interface_get_dhcp_server_addr (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), NULL); + + return &ni_interface->priv->dhcp_server; } -#endif static void ni_interface_init (NIInterface *ni_interface) { NIInterfacePrivate *priv = ni_interface_get_instance_private (ni_interface); @@ -748,5 +914,19 @@ static void ni_interface_init (NIInterface *ni_interface) { priv->mtu = 0; priv->flags = 0; priv->ip_list = NULL; + + priv->dhcp_type_first_time = TRUE; + priv->dhcp_type = 0; + priv->dhcp_status = 0; + priv->dhcp_lease_time = 0; + priv->has_dhcp_broadcast = FALSE; + priv->has_dhcp_gw = FALSE; + priv->has_dhcp_server = FALSE; + + memset (&priv->dhcp_addr, 0, sizeof (priv->dhcp_addr)); + memset (&priv->dhcp_broadcast, 0, sizeof (priv->dhcp_broadcast)); + memset (&priv->dhcp_gateway, 0, sizeof (priv->dhcp_gateway)); + memset (&priv->dhcp_server, 0, sizeof (priv->dhcp_server)); + priv->dhcp_prefix = 0; } diff --git a/client-gtk/ni-interface.h b/client-gtk/ni-interface.h index e166351..cb2c0ff 100644 --- a/client-gtk/ni-interface.h +++ b/client-gtk/ni-interface.h @@ -30,6 +30,8 @@ #include #include +#include "ni-ip.h" + G_BEGIN_DECLS typedef struct _NIInterfaceClass NIInterfaceClass; @@ -77,6 +79,20 @@ 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_stop_dhcp (NIInterface *ni_interface); + +guint ni_interface_get_dhcp_type (NIInterface *ni_interface); +guint ni_interface_get_dhcp_status (NIInterface *ni_interface); +guint ni_interface_get_dhcp_lease_time (NIInterface *ni_interface); +guint ni_interface_get_dhcp_prefix (NIInterface *ni_interface); +const struct_addr * ni_interface_get_dhcp_addr (NIInterface *ni_interface); +gboolean ni_interface_has_dhcp_brd_addr (NIInterface *ni_interface); +gboolean ni_interface_has_dhcp_gw_addr (NIInterface *ni_interface); +gboolean ni_interface_has_dhcp_server_addr (NIInterface *ni_interface); +const struct_addr * ni_interface_get_dhcp_brd_addr (NIInterface *ni_interface); +const struct_addr * ni_interface_get_dhcp_gw_addr (NIInterface *ni_interface); +const struct_addr * ni_interface_get_dhcp_server_addr (NIInterface *ni_interface); G_END_DECLS diff --git a/client-gtk/ni-marshal.list b/client-gtk/ni-marshal.list index efd30bc..9432be0 100644 --- a/client-gtk/ni-marshal.list +++ b/client-gtk/ni-marshal.list @@ -1 +1,2 @@ BOOLEAN:POINTER,UINT +VOID:UINT,UINT diff --git a/client-gtk/ni-window-interface.c b/client-gtk/ni-window-interface.c index 63ab545..22c7acf 100644 --- a/client-gtk/ni-window-interface.c +++ b/client-gtk/ni-window-interface.c @@ -46,7 +46,7 @@ struct _NIWindowInterfacePrivate { NIInterface *ni_interface; GtkWidget *vbox, *notebook; - GtkWidget *vbox_ipv4, *vbox_ipv6, *vbox_info, *vbox_bridges; + GtkWidget *vbox_ipv4, *vbox_ipv6, *vbox_info, *vbox_bridges, *vbox_dhcpv4; GtkWidget *info_name, *info_updown, *info_mtu, *info_slave; GtkWidget *button_name_apply, *button_name_revert; GtkWidget *button_mtu_apply, *button_mtu_revert; @@ -56,8 +56,10 @@ struct _NIWindowInterfacePrivate { GtkWidget *del_ipv4_button, *del_ipv6_button, *del_bport_button; GtkWidget *tree_ipv4, *tree_ipv6, *tree_bridge_ports; - /* Cosas de los bridges */ - + GtkWidget *button_dhcp_run, *button_dhcp_stop; + GtkWidget *dhcpv4_info; + GtkWidget *menu_dhcpv4; + int dhcp_type; }; enum { @@ -575,6 +577,83 @@ static void ni_window_interface_changed_master_cb (GObject *object, GParamSpec * ni_window_interface_update_state_from_master (window_iface); } +static void ni_window_interface_update_dhcp_status (NIWindowInterface *window_iface, NIInterface *ni_interface) { + guint type, status, prefix, lease_time; + char buffer[1024]; + char buffer_ip[256]; + const struct_addr *addr; + gint pos = 0; + + 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"); + } else { + if (type == 1) { + pos = g_snprintf (buffer, sizeof (buffer), "Información cliente DHCP: Cliente ISC\n"); + } else if (type == 2) { + pos = g_snprintf (buffer, sizeof (buffer), "Información cliente DHCP: Cliente Busybox UDHCPC\n"); + } + + 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); + + if (ni_interface_has_dhcp_gw_addr (ni_interface)) { + addr = ni_interface_get_dhcp_gw_addr (ni_interface); + inet_ntop (AF_INET, addr, buffer_ip, sizeof (buffer_ip)); + + pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "Gateway: %s\n", buffer_ip); + } + + 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); + } + + 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); + } + + 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); + } + + gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_info), buffer); + } +} + +static void ni_window_interface_dhcp_type_changed_cb (NIInterface *ni_interface, guint old_type, guint new_type, gpointer data) { + NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data); + + /* Obtuvimos cambio en el estado del DHCP, actualizar los botones y ejecutar la información de estado */ + if (new_type == 0) { + /* El dhcp está muerto */ + gtk_widget_set_sensitive (window_iface->priv->button_dhcp_run, TRUE); + gtk_widget_set_sensitive (window_iface->priv->button_dhcp_stop, FALSE); + } else { + gtk_widget_set_sensitive (window_iface->priv->button_dhcp_run, FALSE); + gtk_widget_set_sensitive (window_iface->priv->button_dhcp_stop, TRUE); + } + + ni_window_interface_update_dhcp_status (window_iface, ni_interface); +} + +static void ni_window_interface_dhcp_status_updated_cb (NIInterface *ni_interface, gpointer data) { + NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data); + + ni_window_interface_update_dhcp_status (window_iface, ni_interface); +} + /* Eventos de bridges */ static gboolean ni_window_interface_check_bport_to_delete_foreach_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data); static void ni_window_interface_removed_from_bridge_cb (NIInterface *ni_interface, guint old_master, gpointer data); @@ -712,6 +791,37 @@ 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); + + // Ejecutar el DHCP aquí + ni_interface_run_dhcp (window_iface->priv->ni_interface, window_iface->priv->dhcp_type); +} + +static void ni_window_interface_dhcp_stop_cb (GtkWidget *button, gpointer data) { + NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data); + + // Ejecutar el DHCP aquí + ni_interface_stop_dhcp (window_iface->priv->ni_interface); +} + +static void ni_window_interface_dhcp_type_isc_cb (GtkWidget *button, gpointer data) { + NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data); + + if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (button))) { + window_iface->priv->dhcp_type = 1; + } +} + +static void ni_window_interface_dhcp_type_busybox_cb (GtkWidget *button, gpointer data) { + NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data); + + if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (button))) { + window_iface->priv->dhcp_type = 2; + } +} + /* Construcción del objeto */ static void ni_window_interface_constructed (GObject *obj) { GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_WINDOW)); @@ -737,6 +847,9 @@ static void ni_window_interface_constructed (GObject *obj) { g_signal_connect (window_iface->priv->ni_interface, "notify::flags", G_CALLBACK (ni_window_interface_changed_flags_cb), window_iface); g_signal_connect (window_iface->priv->ni_interface, "notify::master-index", G_CALLBACK (ni_window_interface_changed_master_cb), window_iface); + g_signal_connect (window_iface->priv->ni_interface, "dhcp-type-changed", G_CALLBACK (ni_window_interface_dhcp_type_changed_cb), window_iface); + g_signal_connect (window_iface->priv->ni_interface, "dhcp-status-updated", G_CALLBACK (ni_window_interface_dhcp_status_updated_cb), window_iface); + /* TODO: Recorrer las ips, y procesar la información */ ip_list = ni_interface_get_ip_list (window_iface->priv->ni_interface); @@ -754,6 +867,8 @@ static void ni_window_interface_constructed (GObject *obj) { if (ni_interface_get_iface_type (window_iface->priv->ni_interface) == NI_LINK_TYPE_BRIDGE) { ni_window_interface_aditional_setup_for_bridge (window_iface); } + + ni_window_interface_dhcp_type_changed_cb (window_iface->priv->ni_interface, 0, ni_interface_get_dhcp_type (window_iface->priv->ni_interface), window_iface); } static void ni_window_interface_dispose (GObject *obj) { @@ -1047,6 +1162,65 @@ static void prepare_bridge_tab (NIWindowInterface *window_iface) { gtk_widget_show (label_tab); } +static void prepare_dhcpv4_tab (NIWindowInterface *window_iface) { + GtkWidget *vbox, *hbox, *label, *button; + GtkSizeGroup *size_l; + GtkWindow *window = GTK_WINDOW (window_iface); + NIWindowInterfacePrivate *priv = window_iface->priv; + GtkWidget *item; + + priv->vbox_dhcpv4 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); + label = gtk_label_new ("DHCPv4"); + gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->vbox_dhcpv4, label); + gtk_container_set_border_width (GTK_CONTAINER (priv->vbox_dhcpv4), 5); + + size_l = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + + /* Poner las labels de información de la propia interfaz */ + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5); + gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4), hbox, FALSE, FALSE, 0); + + /* Preparar el menú para ejecutar el cliente de DHCP */ + priv->menu_dhcpv4 = gtk_menu_new (); + priv->dhcp_type = 1; + + item = gtk_radio_menu_item_new_with_label (NULL, "Correr ISC DHCP Client"); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE); + g_signal_connect (item, "activate", G_CALLBACK (ni_window_interface_dhcp_type_isc_cb), window_iface); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_dhcpv4), item); + gtk_widget_show (item); + + item = gtk_radio_menu_item_new_with_label_from_widget (GTK_RADIO_MENU_ITEM (item), "Correr Busybox UDHCPC"); + g_signal_connect (item, "activate", G_CALLBACK (ni_window_interface_dhcp_type_busybox_cb), window_iface); + gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_dhcpv4), item); + gtk_widget_show (item); + + label = gtk_label_new ("Cliente 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->button_dhcp_stop = gtk_button_new_from_icon_name ("process-stop", GTK_ICON_SIZE_BUTTON); + gtk_widget_set_sensitive (priv->button_dhcp_stop, FALSE); + g_signal_connect (priv->button_dhcp_stop, "clicked", G_CALLBACK (ni_window_interface_dhcp_stop_cb), window_iface); + gtk_box_pack_end (GTK_BOX (hbox), priv->button_dhcp_stop, FALSE, FALSE, 0); + + button = gtk_menu_button_new (); + gtk_menu_button_set_popup (GTK_MENU_BUTTON (button), priv->menu_dhcpv4); + gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0); + + priv->button_dhcp_run = gtk_button_new_from_icon_name ("system-run", GTK_ICON_SIZE_BUTTON); + gtk_widget_set_sensitive (priv->button_dhcp_run, FALSE); + 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); + + /* 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); +} + static void ni_window_interface_init (NIWindowInterface *window_iface) { NIWindowInterfacePrivate *priv = ni_window_interface_get_instance_private (window_iface); window_iface->priv = priv; @@ -1109,6 +1283,9 @@ static void ni_window_interface_init (NIWindowInterface *window_iface) { selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_ipv4)); g_signal_connect (selection, "changed", G_CALLBACK (has_ip_selected_v4_cb), window_iface); + /* Página del cliente de DHCP */ + prepare_dhcpv4_tab (window_iface); + /* Página de IPv6 */ priv->vbox_ipv6 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); label = gtk_label_new ("IPv6"); diff --git a/src/common.h b/src/common.h index e65342d..54f4105 100644 --- a/src/common.h +++ b/src/common.h @@ -135,7 +135,6 @@ enum { DHCP_CLIENT_FAILED, DHCP_CLIENT_KILLED, - DHCP_CLIENT_EXTERNAL_RUNNING }; #define DHCP_CLIENT_FLAG_AUTO_RESTART 0x0001 diff --git a/src/dhcp_client.c b/src/dhcp_client.c index 50ecb36..4e4a497 100644 --- a/src/dhcp_client.c +++ b/src/dhcp_client.c @@ -33,10 +33,13 @@ #include "interfaces.h" #include "common.h" +#include "manager.h" #include "dhcp_client.h" #include "network-inador-manager.h" +static void interfaces_dhcp_clear_info (InterfaceDHCPClientInfo *dhcpc); + void interfaces_dhcp_client_ignore_kill (GPid pid, gint status, gpointer data) { g_spawn_check_exit_status (status, NULL); } @@ -90,6 +93,11 @@ void interfaces_dhcp_client_killed_cb (GPid pid, gint status, gpointer data) { /* Revisar si necesito algo */ } + interfaces_dhcp_clear_info (&iface->dhcpc); + /* Enviar actualización de estado aquí */ + iface->dhcpc.dhcp_state = DHCP_CLIENT_KILLED; + manager_send_event_dhcp_change (iface->handle, &iface->dhcpc); + if (iface->dhcpc.type == IFACE_ISC_DHCLIENT || iface->dhcpc.type == IFACE_BUSYBOX_UDHCPC) { if (iface->dhcpc.flags & DHCP_CLIENT_FLAG_AUTO_RESTART) { /* Se cerró o mataron el proceso, reiniciar */ @@ -111,15 +119,15 @@ void interfaces_dhcp_client_killed_cb (GPid pid, gint status, gpointer data) { g_error_free (error); error = NULL; - iface->dhcpc.flags = DHCP_CLIENT_KILLED; + iface->dhcpc.dhcp_state = DHCP_CLIENT_KILLED; iface->dhcpc.process_watch = 0; } else { - iface->dhcpc.dhcp_state = DHCP_CLIENT_EXTERNAL_RUNNING; + iface->dhcpc.dhcp_state = DHCP_CLIENT_SELECTING; iface->dhcpc.process_watch = g_child_watch_add (iface->dhcpc.process_pid, interfaces_dhcp_client_killed_cb, iface); } } else { /* En caso contrario, solo dejar la muerte escrita */ - iface->dhcpc.flags = DHCP_CLIENT_KILLED; + iface->dhcpc.dhcp_state = DHCP_CLIENT_KILLED; iface->dhcpc.process_watch = 0; } } @@ -192,12 +200,14 @@ int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type return -1; } - iface->dhcpc.dhcp_state = DHCP_CLIENT_EXTERNAL_RUNNING; + iface->dhcpc.dhcp_state = DHCP_CLIENT_SELECTING; iface->dhcpc.type = type; iface->dhcpc.flags = flags; iface->dhcpc.process_watch = g_child_watch_add (iface->dhcpc.process_pid, interfaces_dhcp_client_killed_cb, iface); + manager_send_event_dhcp_change (handle, &iface->dhcpc); + return 0; } @@ -229,11 +239,12 @@ int interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index) { kill (iface->dhcpc.process_pid, SIGTERM); 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: Enviar actualización de estado aquí */ + /* Enviar actualización de estado aquí */ + manager_send_event_dhcp_change (handle, &iface->dhcpc); } return 0; @@ -302,5 +313,7 @@ void interfaces_dhcp_client_internal_feed_from_client (NetworkInadorHandle *hand inet_ntop (AF_INET, &iface->dhcpc.dhcp_server_ip, buf_d, sizeof (buf_d)); printf ("----> DHCP Server (%s), IP obtenida: %s/%i, GW: %s y bcast: %s, lease: %i\n", buf_d, buf_a, prefix, buf_b, buf_c, lease_time); } + + manager_send_event_dhcp_change (handle, &iface->dhcpc); } diff --git a/src/interfaces.c b/src/interfaces.c index fd0bedf..6015a4f 100644 --- a/src/interfaces.c +++ b/src/interfaces.c @@ -113,8 +113,8 @@ static int _interfaces_receive_message_interface (struct nl_msg *msg, void *arg, if (iface == NULL) { /* Crear esta interfaz */ iface = malloc (sizeof (Interface)); - iface->handle = handle; memset (iface, 0, sizeof (Interface)); + iface->handle = handle; handle->interfaces = g_list_append (handle->interfaces, iface); diff --git a/src/manager.c b/src/manager.c index e1f2404..919f5e6 100644 --- a/src/manager.c +++ b/src/manager.c @@ -948,13 +948,13 @@ void _manager_send_dhcp_status (ManagerClientInfo *manager_client, InterfaceDHCP /* Los campos de bits */ buffer[10] = 0; - if (memcmp (&dhcpc->gateway, &empty, 4) == 0) { + if (memcmp (&dhcpc->gateway, &empty, 4) != 0) { buffer[10] |= 0x01; } - if (memcmp (&dhcpc->broadcast, &empty, 4) == 0) { + if (memcmp (&dhcpc->broadcast, &empty, 4) != 0) { buffer[10] |= 0x02; } - if (memcmp (&dhcpc->dhcp_server_ip, &empty, 4) == 0) { + if (memcmp (&dhcpc->dhcp_server_ip, &empty, 4) != 0) { buffer[10] |= 0x04; } @@ -1209,6 +1209,25 @@ void manager_send_event_ip_del (NetworkInadorHandle *handle, IPAddr *ip_addr) { } } +void manager_send_event_dhcp_change (NetworkInadorHandle *handle, InterfaceDHCPClientInfo *dhcpc) { + Interface *iface = container_of (dhcpc, Interface, dhcpc); + GList *g; + ManagerClientInfo *manager_client; + + printf ("___ MANAGER ___ Informando cambio DHCP: %s (%i)\n", iface->name, iface->index); + + if (handle->manager == NULL) return; + + for (g = handle->manager->connected_client_list; g != NULL; g = g->next) { + manager_client = (ManagerClientInfo *) g->data; + + if (manager_client->wanted_events & NET_INADOR_EVENT_MASK_DHCP_STATUS) { + printf ("___ MANAGER ___ Informando a la conexión (%i)\n", manager_client->fd); + _manager_send_dhcp_status (manager_client, dhcpc, TRUE); + } + } +} + int manager_init (NetworkInadorHandle *handle) { NetworkInadorManager *manager; struct sockaddr_un socket_name; diff --git a/src/manager.h b/src/manager.h index b381aac..382e000 100644 --- a/src/manager.h +++ b/src/manager.h @@ -33,6 +33,7 @@ void manager_send_event_interface_del (NetworkInadorHandle *handle, uint32_t ind void manager_send_event_interface_update (NetworkInadorHandle *handle, Interface *iface); void manager_send_event_ip_add (NetworkInadorHandle *handle, IPAddr *ip_addr); void manager_send_event_ip_del (NetworkInadorHandle *handle, IPAddr *ip_addr); +void manager_send_event_dhcp_change (NetworkInadorHandle *handle, InterfaceDHCPClientInfo *dhcpc); #endif /* __MANAGER_H__ */