Agrego múltiples gateways y la información de DNS en los eventos DHCP

master
Félix Arreola Rodríguez 2022-01-04 00:08:47 -06:00
parent 0ff00a8b9c
commit dfc2abecd1
8 changed files with 270 additions and 81 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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);
pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "Gateway: %s\n", buffer_ip);
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 (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);
}
}

View File

@ -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;

View File

@ -24,6 +24,8 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
@ -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);

View File

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

View File

@ -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);
}

View File

@ -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);