From dfc2abecd1a11fb2e6422cd25df4cb7fa5466399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Arreola=20Rodr=C3=ADguez?= Date: Tue, 4 Jan 2022 00:08:47 -0600 Subject: [PATCH] =?UTF-8?q?Agrego=20m=C3=BAltiples=20gateways=20y=20la=20i?= =?UTF-8?q?nformaci=C3=B3n=20de=20DNS=20en=20los=20eventos=20DHCP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client-gtk/ni-interface.c | 71 ++++++++++++------ client-gtk/ni-interface.h | 5 +- client-gtk/ni-window-interface.c | 41 ++++++++-- src/common.h | 5 +- src/dhcp_client.c | 38 ++++++++-- src/dhcp_client.h | 2 +- src/manager.c | 64 ++++++++++------ src/ni-dhcp-iface-helper.c | 125 +++++++++++++++++++++++++------ 8 files changed, 270 insertions(+), 81 deletions(-) diff --git a/client-gtk/ni-interface.c b/client-gtk/ni-interface.c index f32eaf3..87b2474 100644 --- a/client-gtk/ni-interface.c +++ b/client-gtk/ni-interface.c @@ -49,11 +49,12 @@ struct _NIInterfacePrivate { 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; + gboolean has_dhcp_broadcast, has_dhcp_server; + int dhcp_gw_c, dhcp_dns_c; + struct_addr dhcp_addr, dhcp_broadcast, dhcp_gateways[7], dhcp_server, dhcp_dns[7]; guint dhcp_prefix; - /* TODO: Falta procesar la información del DNS */ + char dhcp_domain_name[256]; }; enum { @@ -575,7 +576,7 @@ 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; + gint family_size = 0, c, g; guint bits, pos; int old_type; @@ -591,33 +592,28 @@ static void ni_interface_process_dhcp_status (NIInterface *ni_interface, gpointe 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) { + if (buffer[10] & 0x01) { /* Hay una IP broadcast de DHCP */ ni_interface->priv->has_dhcp_broadcast = TRUE; } ni_interface->priv->has_dhcp_server = FALSE; - if (buffer[10] & 0x04) { + if (buffer[10] & 0x02) { /* Hay un servidor DHCP */ ni_interface->priv->has_dhcp_server = TRUE; } - /* TODO: Procesar aquí la información de DNS */ + ni_interface->priv->dhcp_gw_c = (buffer[10] & 0x1C) >> 2; + ni_interface->priv->dhcp_dns_c = (buffer[10] & 0xE0) >> 5; 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); + for (g = 0; g < ni_interface->priv->dhcp_gw_c; g++) { + memcpy (&ni_interface->priv->dhcp_gateways[g], &buffer[pos], family_size); pos += family_size; } @@ -631,7 +627,18 @@ static void ni_interface_process_dhcp_status (NIInterface *ni_interface, gpointe pos += family_size; } - /* TODO: Procesar la información de los DNS */ + for (g = 0; g < ni_interface->priv->dhcp_dns_c; g++) { + memcpy (&ni_interface->priv->dhcp_dns[g], &buffer[pos], family_size); + pos += family_size; + } + + /* Copiar el domain name */ + ni_interface->priv->dhcp_domain_name[0] = 0; + if (buffer[11] > 0) { + memcpy (ni_interface->priv->dhcp_domain_name, &buffer[pos], buffer[11]); + pos += buffer[11]; + } + 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); @@ -869,10 +876,10 @@ gboolean ni_interface_has_dhcp_brd_addr (NIInterface *ni_interface) { 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); +gint ni_interface_get_dhcp_gw_count (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0); - return ni_interface->priv->has_dhcp_gw; + return ni_interface->priv->dhcp_gw_c; } gboolean ni_interface_has_dhcp_server_addr (NIInterface *ni_interface) { @@ -881,6 +888,12 @@ gboolean ni_interface_has_dhcp_server_addr (NIInterface *ni_interface) { return ni_interface->priv->has_dhcp_server; } +gint ni_interface_get_dhcp_dns_count (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0); + + return ni_interface->priv->dhcp_dns_c; +} + const struct_addr * ni_interface_get_dhcp_brd_addr (NIInterface *ni_interface) { g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), NULL); @@ -890,7 +903,7 @@ const struct_addr * ni_interface_get_dhcp_brd_addr (NIInterface *ni_interface) { 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; + return ni_interface->priv->dhcp_gateways; } const struct_addr * ni_interface_get_dhcp_server_addr (NIInterface *ni_interface) { @@ -899,6 +912,20 @@ const struct_addr * ni_interface_get_dhcp_server_addr (NIInterface *ni_interface return &ni_interface->priv->dhcp_server; } +const struct_addr * ni_interface_get_dhcp_dns_addr (NIInterface *ni_interface) { + g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), NULL); + + return ni_interface->priv->dhcp_dns; +} + +const char *ni_interface_get_dhcp_domain_name (NIInterface *ni_interface) { + + if (ni_interface->priv->dhcp_domain_name[0] == 0) { + return NULL; + } + return ni_interface->priv->dhcp_domain_name; +} + static void ni_interface_init (NIInterface *ni_interface) { NIInterfacePrivate *priv = ni_interface_get_instance_private (ni_interface); ni_interface->priv = priv; @@ -920,12 +947,12 @@ static void ni_interface_init (NIInterface *ni_interface) { priv->dhcp_status = 0; priv->dhcp_lease_time = 0; priv->has_dhcp_broadcast = FALSE; - priv->has_dhcp_gw = FALSE; + priv->dhcp_gw_c = 0; + priv->dhcp_dns_c = 0; 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 cb2c0ff..3de415b 100644 --- a/client-gtk/ni-interface.h +++ b/client-gtk/ni-interface.h @@ -88,11 +88,14 @@ 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); +gint ni_interface_get_dhcp_gw_count (NIInterface *ni_interface); gboolean ni_interface_has_dhcp_server_addr (NIInterface *ni_interface); +gint ni_interface_get_dhcp_dns_count (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); +const struct_addr * ni_interface_get_dhcp_dns_addr (NIInterface *ni_interface); +const char *ni_interface_get_dhcp_domain_name (NIInterface *ni_interface); G_END_DECLS diff --git a/client-gtk/ni-window-interface.c b/client-gtk/ni-window-interface.c index 22c7acf..9a07e2d 100644 --- a/client-gtk/ni-window-interface.c +++ b/client-gtk/ni-window-interface.c @@ -579,10 +579,11 @@ static void ni_window_interface_changed_master_cb (GObject *object, GParamSpec * 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[2048]; char buffer_ip[256]; const struct_addr *addr; - gint pos = 0; + gint pos = 0, c, g; + const char *domain_name; type = ni_interface_get_dhcp_type (ni_interface); @@ -601,11 +602,19 @@ static void ni_window_interface_update_dhcp_status (NIWindowInterface *window_if 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)); + 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, "Gateway: %s\n", 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 (ni_interface_has_dhcp_brd_addr (ni_interface)) { @@ -615,6 +624,21 @@ static void ni_window_interface_update_dhcp_status (NIWindowInterface *window_if pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "Broadcast: %s\n", buffer_ip); } + 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 (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)); @@ -628,6 +652,11 @@ static void ni_window_interface_update_dhcp_status (NIWindowInterface *window_if pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "Tiempo de concesión: %i seg(s)\n", lease_time); } + 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_info), buffer); } } diff --git a/src/common.h b/src/common.h index 54f4105..2fee78f 100644 --- a/src/common.h +++ b/src/common.h @@ -150,7 +150,10 @@ typedef struct _InterfaceDHCPClientInfo { guint process_watch; /* La información obtenida desde el cliente */ - struct_addr ip, gateway, broadcast; + 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; diff --git a/src/dhcp_client.c b/src/dhcp_client.c index 4e4a497..bdfd32b 100644 --- a/src/dhcp_client.c +++ b/src/dhcp_client.c @@ -24,6 +24,8 @@ #include #include +#include + #include #include #include @@ -135,13 +137,14 @@ void interfaces_dhcp_client_killed_cb (GPid pid, gint status, gpointer data) { static void interfaces_dhcp_clear_info (InterfaceDHCPClientInfo *dhcpc) { memset (&dhcpc->ip, 0, sizeof (dhcpc->ip)); - memset (&dhcpc->gateway, 0, sizeof (dhcpc->gateway)); + dhcpc->gw_c = 0; + dhcpc->dns_c = 0; memset (&dhcpc->broadcast, 0, sizeof (dhcpc->broadcast)); memset (&dhcpc->dhcp_server_ip, 0, sizeof (dhcpc->dhcp_server_ip)); dhcpc->lease_time = 0; dhcpc->prefix = 0; - /* TODO: Borrar la información de DNS */ + dhcpc->domain_name[0] = 0; } int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type, uint32_t flags) { @@ -250,9 +253,10 @@ int interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index) { return 0; } -void interfaces_dhcp_client_internal_feed_from_client (NetworkInadorHandle *handle, int index, int status, struct_addr *ip, int prefix, struct_addr *gateway, struct_addr *broadcast, struct_addr *dhcp_server, uint32_t lease_time, struct_addr *dns_list, int dns_count, char *domain_name) { +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; iface = _interfaces_locate_by_index (handle->interfaces, index); @@ -300,18 +304,40 @@ void interfaces_dhcp_client_internal_feed_from_client (NetworkInadorHandle *hand memcpy (&iface->dhcpc.ip, ip, sizeof (iface->dhcpc.ip)); iface->dhcpc.prefix = prefix; - memcpy (&iface->dhcpc.gateway, gateway, sizeof (iface->dhcpc.gateway)); + iface->dhcpc.gw_c = gw_c; + for (g = 0; g < gw_c && g < 7; g++) { + memcpy (&iface->dhcpc.gateways[g], &gateways[g], 4); + } memcpy (&iface->dhcpc.broadcast, broadcast, sizeof (iface->dhcpc.broadcast)); memcpy (&iface->dhcpc.dhcp_server_ip, dhcp_server, sizeof (iface->dhcpc.dhcp_server_ip)); iface->dhcpc.lease_time = lease_time; + + iface->dhcpc.dns_c = dns_count; + for (g = 0; g < dns_count && g < 7; g++) { + memcpy (&iface->dhcpc.dns[g], &dns_list[g], 4); + } + + strncpy (iface->dhcpc.domain_name, domain_name, sizeof (iface->dhcpc.domain_name)); + char buf_a[256], buf_b[256], buf_c[256], buf_d[256]; inet_ntop (AF_INET, &iface->dhcpc.ip, buf_a, sizeof (buf_a)); - inet_ntop (AF_INET, &iface->dhcpc.gateway, buf_b, sizeof (buf_b)); inet_ntop (AF_INET, &iface->dhcpc.broadcast, buf_c, sizeof (buf_c)); 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); + printf ("----> (%i) DHCP Server (%s), IP obtenida: %s/%i, GW: ", (unsigned int) time (NULL), buf_d, buf_a, prefix); + + for (g = 0; g < gw_c; g++) { + inet_ntop (AF_INET, &iface->dhcpc.gateways[g], buf_b, sizeof (buf_b)); + printf ("%s, ", buf_b); + } + printf ("bcast: %s, lease: %i, DNS: ", buf_c, lease_time); + for (g = 0; g < dns_count; g++) { + inet_ntop (AF_INET, &iface->dhcpc.dns[g], buf_b, sizeof (buf_b)); + printf ("%s, ", buf_b); + } + + printf (" y domain name <%s>\n", domain_name); } manager_send_event_dhcp_change (handle, &iface->dhcpc); diff --git a/src/dhcp_client.h b/src/dhcp_client.h index c624a45..cd82aaa 100644 --- a/src/dhcp_client.h +++ b/src/dhcp_client.h @@ -27,7 +27,7 @@ int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type, uint32_t flags); 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 *gateway, struct_addr *broadcast, struct_addr *dhcp_server, uint32_t lease_time, struct_addr *dns_list, int dns_count, char *domain_name); +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); #endif /* __DHCP_CLIENT_H__ */ diff --git a/src/manager.c b/src/manager.c index 919f5e6..9eeb25c 100644 --- a/src/manager.c +++ b/src/manager.c @@ -677,8 +677,9 @@ static void _manager_execute_dhcp_client_feed (ManagerClientInfo *manager_client int family; int pos, prefix, g; uint32_t lease_time; - struct_addr ip, gateway, broadcast, dhcp_server; - struct_addr dns[8]; + struct_addr ip, broadcast, dhcp_server; + struct_addr dns[8], gateways[8]; + int gw_c, dns_c; if (buffer_len < 16) { _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_DHCP_CLIENT_FEED); @@ -695,7 +696,7 @@ static void _manager_execute_dhcp_client_feed (ManagerClientInfo *manager_client } /* Revisar el estado */ - if (buffer[3] < DHCP_CLIENT_SELECTING || buffer[3] > DHCP_CLIENT_EXPIRED) { + if (buffer[3] < DHCP_CLIENT_SELECTING || buffer[3] > DHCP_CLIENT_FAILED) { _manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_VALUE, NET_INADOR_COMMAND_DHCP_CLIENT_FEED); return; } @@ -708,10 +709,15 @@ static void _manager_execute_dhcp_client_feed (ManagerClientInfo *manager_client } _MANAGER_CHECK_BYTE_OR_OUT(family, buffer, 5); // Dirección IP - _MANAGER_CHECK_BYTE_OR_OUT(family, buffer, 7); // Ruta por defecto _MANAGER_CHECK_BYTE_OR_OUT(family, buffer, 8); // Dirección Broadcast _MANAGER_CHECK_BYTE_OR_OUT(family, buffer, 9); // Dirección del servidor + /* Revisar la posible ruta de gateways */ + if (family == AF_INET && buffer[7] % 4 != 0) { + _manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_VALUE, NET_INADOR_COMMAND_DHCP_CLIENT_FEED); + return; + } + /* La lista de servidores DNS */ if (family == AF_INET && buffer[10] % 4 != 0) { _manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_VALUE, NET_INADOR_COMMAND_DHCP_CLIENT_FEED); @@ -753,11 +759,11 @@ static void _manager_execute_dhcp_client_feed (ManagerClientInfo *manager_client } /* Recuperar la ruta por defecto */ - if (buffer[7] != 0) { - pos = 16 + name_len + buffer[5]; - memcpy (&gateway, &buffer[pos], buffer[7]); - } else { - memset (&gateway, 0, sizeof (gateway)); + gw_c = buffer[7] / 4; + pos = 16 + name_len + buffer[5]; + for (g = 0; g < gw_c && g < 8; g++) { + memcpy (&gateways[g].v4, &buffer[pos], 4); + pos += 4; } /* Recuperar el broadcast */ @@ -777,11 +783,11 @@ static void _manager_execute_dhcp_client_feed (ManagerClientInfo *manager_client } /* Recuperar todos los servidores DNS */ - g = 0; - while (g < 8 && g < (buffer[10] / 4)) { + dns_c = buffer[10] / 4; + pos = 16 + name_len + buffer[5] + buffer[7] + buffer[8] + buffer[9]; + for (g = 0; g < 8 && g < dns_c; g++) { memcpy (&dns[g].v4, &buffer[pos], 4); pos += 4; - g++; } /* Recuperar el domain name */ @@ -803,7 +809,7 @@ static void _manager_execute_dhcp_client_feed (ManagerClientInfo *manager_client return; } } - interfaces_dhcp_client_internal_feed_from_client (manager_client->manager->handle, iface->index, buffer[3], &ip, buffer[6], &gateway, &broadcast, &dhcp_server, lease_time, dns, (buffer[10] / 4), domain_name); + interfaces_dhcp_client_internal_feed_from_client (manager_client->manager->handle, iface->index, buffer[3], &ip, buffer[6], gateways, gw_c, &broadcast, &dhcp_server, lease_time, dns, dns_c, domain_name); /* OK */ _manager_send_executed (manager_client); @@ -920,6 +926,7 @@ void _manager_send_dhcp_status (ManagerClientInfo *manager_client, InterfaceDHCP int pos; int family = AF_INET; struct in_addr empty; + int g; memset (&empty, 0, sizeof (empty)); @@ -948,26 +955,31 @@ 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->broadcast, &empty, 4) != 0) { buffer[10] |= 0x01; } - if (memcmp (&dhcpc->broadcast, &empty, 4) != 0) { + if (memcmp (&dhcpc->dhcp_server_ip, &empty, 4) != 0) { buffer[10] |= 0x02; } - if (memcmp (&dhcpc->dhcp_server_ip, &empty, 4) != 0) { - buffer[10] |= 0x04; - } - /* TODO: Falta enviar la información de cantidad de servidores DNS */ - buffer[11] = 0; + /* Cantidad de GWs */ + g = dhcpc->gw_c & 0x07; + buffer[10] |= (g << 2); + + /* Cantidad de DNS */ + g = dhcpc->dns_c & 0x07; + buffer[10] |= (g << 5); + + buffer[11] = strlen (dhcpc->domain_name); memcpy (&buffer[12], &dhcpc->lease_time, 4); /* La dirección principal */ memcpy (&buffer[16], &dhcpc->ip, family_size); pos = 16 + family_size; - if (memcmp (&dhcpc->gateway, &empty, 4) != 0) { - memcpy (&buffer[pos], &dhcpc->gateway, family_size); + + for (g = 0; g < dhcpc->gw_c; g++) { + memcpy (&buffer[pos], &dhcpc->gateways[g], family_size); pos += family_size; } @@ -981,7 +993,13 @@ void _manager_send_dhcp_status (ManagerClientInfo *manager_client, InterfaceDHCP pos += family_size; } - /* TODO: Falta aquí enviar la lista de servidores DNS y el domain name */ + for (g = 0; g < dhcpc->dns_c; g++) { + memcpy (&buffer[pos], &dhcpc->dns[g], family_size); + pos += family_size; + } + + memcpy (&buffer[pos], dhcpc->domain_name, buffer[11]); + pos += buffer[11]; send (manager_client->fd, buffer, pos, 0); } diff --git a/src/ni-dhcp-iface-helper.c b/src/ni-dhcp-iface-helper.c index a4a5052..49f92eb 100644 --- a/src/ni-dhcp-iface-helper.c +++ b/src/ni-dhcp-iface-helper.c @@ -79,6 +79,17 @@ int debug (int argc, char *argv[]) { return 0; } +enum { + DHCP_CLIENT_SELECTING, + DHCP_CLIENT_BOUND, + DHCP_CLIENT_RENEWED, + + DHCP_CLIENT_EXPIRED, + DHCP_CLIENT_FAILED, + + DHCP_CLIENT_KILLED, +}; + uint32_t utils_ip4_netmask_to_prefix (uint32_t netmask) { uint32_t prefix; uint8_t v; @@ -151,14 +162,20 @@ int wait_for_ack_or_error (int s) { return -1; } -void send_preinit (int s, char *interface) { +void send_basic (int s, char *interface, int tipo) { unsigned char buffer[128]; buffer[0] = NET_INADOR_TYPE_COMMAND; buffer[1] = NET_INADOR_COMMAND_DHCP_CLIENT_FEED; buffer[2] = AF_INET; - buffer[3] = NET_INADOR_DHCP_STATUS_SELECTING; + if (tipo == DHCP_CLIENT_SELECTING) { + buffer[3] = NET_INADOR_DHCP_STATUS_SELECTING; + } else if (tipo == DHCP_CLIENT_EXPIRED) { + buffer[3] = NET_INADOR_DHCP_STATUS_EXPIRED; + } else if (tipo == DHCP_CLIENT_FAILED) { + buffer[3] = NET_INADOR_DHCP_STATUS_FAILED; + } buffer[4] = strlen (interface); memset (&buffer[5], 0, 11); @@ -171,10 +188,10 @@ void send_preinit (int s, char *interface) { } } -void send_bound_renew (int s, int is_bound, char *interface, struct in_addr *ip, int prefix, struct in_addr *gateway, struct in_addr *broadcast, struct in_addr *dhcp_server, uint32_t lease_time) { +void send_bound_renew (int s, int is_bound, char *interface, struct in_addr *ip, int prefix, struct in_addr *gateways, int gw_c, struct in_addr *broadcast, struct in_addr *dhcp_server, uint32_t lease_time, struct in_addr *dns, int dns_c, char *domain_name) { unsigned char buffer[128]; struct in_addr empty; - int pos; + int pos, g; memset (&empty, 0, sizeof (empty)); @@ -192,6 +209,10 @@ void send_bound_renew (int s, int is_bound, char *interface, struct in_addr *ip, buffer[6] = prefix; + if (lease_time != 0) { + memcpy (&buffer[12], &lease_time, 4); + } + pos = 16; /* Copiar el nombre de la interfaz */ @@ -205,10 +226,10 @@ void send_bound_renew (int s, int is_bound, char *interface, struct in_addr *ip, pos += 4; } - if (memcmp (&empty, gateway, sizeof (empty)) != 0) { - /* Tenemos una ruta */ - buffer[7] = 4; - memcpy (&buffer[pos], gateway, 4); + /* Procesar las múltiples rutas posibles */ + buffer[7] = 4 * gw_c; + for (g = 0; g < gw_c; g++) { + memcpy (&buffer[pos], &gateways[g], 4); pos += 4; } @@ -226,11 +247,19 @@ void send_bound_renew (int s, int is_bound, char *interface, struct in_addr *ip, pos += 4; } - if (lease_time != 0) { - memcpy (&buffer[12], &lease_time, 4); + /* Procesar los múltiples dns */ + buffer[10] = 4 * dns_c; + for (g = 0; g < dns_c; g++) { + memcpy (&buffer[pos], &dns[g], 4); + pos += 4; } - /* TODO: Faltan los DNS */ + /* Procesar el nombre de dominio */ + if (domain_name != NULL && domain_name[0] != 0) { + buffer[11] = strlen (domain_name); + memcpy (&buffer[pos], domain_name, buffer[11]); + pos += buffer[11]; + } send (s, buffer, pos, 0); if (wait_for_ack_or_error (s) < 0) { @@ -256,6 +285,51 @@ int parse_ip (char *var, struct in_addr *addr) { return 0; } +int parse_multiple_ip (char *var, struct in_addr *addr, int max) { + int res; + char buffer[512]; + char *inicio, *bus; + int c = 0; + size_t offset; + + if (var == NULL) return 0; + + inicio = var; + while (inicio[0] != 0) { + bus = strchr (inicio, ' '); + + if (bus == NULL) break; + + /* Desboardamiento */ + offset = bus - inicio; + + if (offset + 1 > sizeof (buffer)) { + return 0; + } + strncpy (buffer, inicio, offset); + buffer[offset] = 0; + inicio = &var[offset + 1]; + + res = parse_ip (buffer, &addr[c]); + if (res < 0) continue; + + c++; + if (c == max) return c; + } + + /* Parsear lo último, si es que queda algo */ + if (inicio[0] != 0) { + res = parse_ip (inicio, &addr[c]); + if (res < 0) { + return c; + } + + c++; + } + + return c; +} + int parse_int (char *var, int *entero) { int res; @@ -306,11 +380,14 @@ int main (int argc, char *argv[]) { char *reason, *interface; int s, ret, tipo; struct sockaddr_un path_dest; - struct in_addr ip, netmask, gateway, broadcast, dhcp_server; + struct in_addr ip, netmask, broadcast, dhcp_server; + struct in_addr gateways[7]; + struct in_addr dns[7]; + int gw_c, dns_c; + int prefix, lease_time; debug (argc, argv); - tipo = 0; /* Tratar de determinar si estamos siendo corridos por un el DHCP del ISC o por el udhcpc busybox */ @@ -371,9 +448,9 @@ int main (int argc, char *argv[]) { if (strcmp (reason, "PREINIT") == 0 || // ISC DHCP strcmp (reason, "deconfig") == 0 // Busybox udhcpc ) { - send_preinit (s, interface); + send_basic (s, interface, DHCP_CLIENT_SELECTING); } if (strcmp (reason, "FAIL") == 0) { - + send_basic (s, interface, DHCP_CLIENT_FAILED); } else if (strcmp (reason, "BOUND") == 0 || strcmp (reason, "REBOOT") == 0 || strcmp (reason, "RENEW") == 0 || strcmp (reason, "REBIND") == 0 || // 4 de ISC DHCP strcmp (reason, "bound") == 0 || strcmp (reason, "renew") == 0 // 2 de Busybox udhcpc @@ -390,7 +467,7 @@ int main (int argc, char *argv[]) { * new_dhcp_lease_time -> Tiempo en segundos */ /* Parsear y revisar las direcciones IP recibidas */ - char *s_ip, *s_mask, *s_gateway, *s_broadcast, *s_lease_time, *s_dhcp_server; + char *s_ip, *s_mask, *s_gateway, *s_broadcast, *s_lease_time, *s_dhcp_server, *s_dns, *s_domain_name; if (tipo == IFACE_ISC_DHCLIENT) { s_ip = getenv ("new_ip_address"); s_mask = getenv ("new_subnet_mask"); @@ -398,6 +475,8 @@ int main (int argc, char *argv[]) { s_broadcast = getenv ("new_broadcast_address"); s_lease_time = getenv ("new_dhcp_lease_time"); s_dhcp_server = getenv ("new_dhcp_server_identifier"); + s_dns = getenv ("new_domain_name_servers"); + s_domain_name = getenv ("new_domain_name"); } else if (tipo == IFACE_BUSYBOX_UDHCPC) { s_ip = getenv ("ip"); s_mask = getenv ("subnet"); @@ -405,6 +484,8 @@ int main (int argc, char *argv[]) { s_broadcast = getenv ("broadcast"); s_lease_time = getenv ("lease"); s_dhcp_server = getenv ("serverid"); + s_dns = getenv ("dns"); + s_domain_name = getenv ("domain"); } /* TODO: Faltan los DNS */ @@ -419,9 +500,7 @@ int main (int argc, char *argv[]) { } prefix = utils_ip4_netmask_to_prefix (netmask.s_addr); - if (parse_ip (s_gateway, &gateway) < 0) { - memset (&gateway, 0, sizeof (gateway)); - } + gw_c = parse_multiple_ip (s_gateway, gateways, 7); if (parse_ip (s_broadcast, &broadcast) < 0) { memset (&broadcast, 0, sizeof (broadcast)); @@ -435,18 +514,22 @@ int main (int argc, char *argv[]) { lease_time = 0; } + dns_c = parse_multiple_ip (s_dns, dns, 7); int is_bound = 0; if (strcmp (reason, "BOUND") == 0 || strcmp (reason, "REBOOT") == 0 || // Del ISC dhcp strcmp (reason, "bound") == 0 // del busybox ) { is_bound = 1; } - send_bound_renew (s, is_bound, interface, &ip, prefix, &gateway, &broadcast, &dhcp_server, lease_time); + send_bound_renew (s, is_bound, interface, &ip, prefix, gateways, gw_c, &broadcast, &dhcp_server, lease_time, dns, dns_c, s_domain_name); } else if (strcmp (reason, "EXPIRE") == 0 || strcmp (reason, "STOP") == 0 || strcmp (reason, "RELEASE") == 0) { /* Los mismos valores, pero con old_ */ + send_basic (s, interface, DHCP_CLIENT_EXPIRED); } else { + send_basic (s, interface, DHCP_CLIENT_FAILED); + close (s); - + return -1; } close (s);