Agrego cliente busybox udhcpc y comandos del manager.

master
Félix Arreola Rodríguez 2022-01-02 13:54:25 -06:00
parent f048dde998
commit 072b89bd62
6 changed files with 351 additions and 28 deletions

View File

@ -45,6 +45,10 @@
#define INFINITY_LIFE_TIME 0xFFFFFFFFU #define INFINITY_LIFE_TIME 0xFFFFFFFFU
#endif #endif
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
typedef struct _NetworkInadorHandle NetworkInadorHandle; typedef struct _NetworkInadorHandle NetworkInadorHandle;
typedef struct _NetworkInadorManager NetworkInadorManager; typedef struct _NetworkInadorManager NetworkInadorManager;
typedef struct _Interface Interface; typedef struct _Interface Interface;
@ -117,7 +121,8 @@ typedef struct _WirelessInfo {
/* Información del proceso de DHCP */ /* Información del proceso de DHCP */
enum { enum {
IFACE_NO_DHCP = 0, IFACE_NO_DHCP = 0,
IFACE_ISC_DHCLIENT IFACE_ISC_DHCLIENT,
IFACE_BUSYBOX_UDHCPC
}; };
/* FIXME: Revisar estos estados */ /* FIXME: Revisar estos estados */
@ -150,6 +155,7 @@ typedef struct _InterfaceDHCPClientInfo {
int prefix; int prefix;
struct_addr dhcp_server_ip; struct_addr dhcp_server_ip;
uint32_t lease_time;
/* TODO: Falta almacenar la información de DNS */ /* TODO: Falta almacenar la información de DNS */
} InterfaceDHCPClientInfo; } InterfaceDHCPClientInfo;

View File

@ -41,7 +41,7 @@ void interfaces_dhcp_client_ignore_kill (GPid pid, gint status, gpointer data) {
g_spawn_check_exit_status (status, NULL); g_spawn_check_exit_status (status, NULL);
} }
void interfaces_dhcp_prepare_args_for_dhclient (char **argv, int size, char *iface_name, char *pid_file, size_t pid_file_len) { void interfaces_dhcp_prepare_args_for_isc_dhclient (char **argv, int size, char *iface_name, char *pid_file, size_t pid_file_len) {
snprintf (pid_file, pid_file_len, "/run/dhclient-%s.pid", iface_name); snprintf (pid_file, pid_file_len, "/run/dhclient-%s.pid", iface_name);
/* Preparar los argumentos para el proceso */ /* Preparar los argumentos para el proceso */
@ -56,6 +56,22 @@ void interfaces_dhcp_prepare_args_for_dhclient (char **argv, int size, char *ifa
argv[8] = NULL; argv[8] = NULL;
} }
void interfaces_dhcp_prepare_args_for_busybox_udhcpc (char **argv, int size, char *iface_name, char *pid_file, size_t pid_file_len) {
snprintf (pid_file, pid_file_len, "/run/dhclient-%s.pid", iface_name);
/* Preparar los argumentos para el proceso */
argv[0] = "/bin/busybox";
argv[1] = "udhcpc";
argv[2] = "-i";
argv[3] = iface_name;
argv[4] = "-p";
argv[5] = pid_file;
argv[6] = "-s";
argv[7] = "/home/gatuno/Proyectos/NetworkInador/src/ni-dhcp-helper";
argv[8] = "-f";
argv[9] = NULL;
}
void interfaces_dhcp_client_killed_cb (GPid pid, gint status, gpointer data) { void interfaces_dhcp_client_killed_cb (GPid pid, gint status, gpointer data) {
Interface *iface = (Interface *) data; Interface *iface = (Interface *) data;
gboolean ret; gboolean ret;
@ -64,13 +80,17 @@ void interfaces_dhcp_client_killed_cb (GPid pid, gint status, gpointer data) {
gchar pid_file[256]; gchar pid_file[256];
/* Preparar los argumentos */ /* Preparar los argumentos */
interfaces_dhcp_prepare_args_for_dhclient (argv, 20, iface->name, pid_file, sizeof (pid_file)); if (iface->dhcpc.type == IFACE_ISC_DHCLIENT) {
interfaces_dhcp_prepare_args_for_isc_dhclient (argv, 20, iface->name, pid_file, sizeof (pid_file));
} else if (iface->dhcpc.type == IFACE_BUSYBOX_UDHCPC) {
interfaces_dhcp_prepare_args_for_busybox_udhcpc (argv, 20, iface->name, pid_file, sizeof (pid_file));
}
if (g_spawn_check_exit_status (status, NULL)) { if (g_spawn_check_exit_status (status, NULL)) {
/* Revisar si necesito algo */ /* Revisar si necesito algo */
} }
if (iface->dhcpc.type == IFACE_ISC_DHCLIENT) { if (iface->dhcpc.type == IFACE_ISC_DHCLIENT || iface->dhcpc.type == IFACE_BUSYBOX_UDHCPC) {
if (iface->dhcpc.flags & DHCP_CLIENT_FLAG_AUTO_RESTART) { if (iface->dhcpc.flags & DHCP_CLIENT_FLAG_AUTO_RESTART) {
/* Se cerró o mataron el proceso, reiniciar */ /* Se cerró o mataron el proceso, reiniciar */
ret = g_spawn_async_with_pipes ( ret = g_spawn_async_with_pipes (
@ -105,6 +125,17 @@ 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));
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 */
}
int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type, uint32_t flags) { int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type, uint32_t flags) {
/* IFNAMSIZ */ /* IFNAMSIZ */
Interface *iface; Interface *iface;
@ -122,18 +153,23 @@ int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type
} }
/* Preparar los argumentos */ /* Preparar los argumentos */
interfaces_dhcp_prepare_args_for_dhclient (argv, 20, iface->name, pid_file, sizeof (pid_file)); if (type == IFACE_ISC_DHCLIENT) {
interfaces_dhcp_prepare_args_for_isc_dhclient (argv, 20, iface->name, pid_file, sizeof (pid_file));
} else if (type == IFACE_BUSYBOX_UDHCPC) {
interfaces_dhcp_prepare_args_for_busybox_udhcpc (argv, 20, iface->name, pid_file, sizeof (pid_file));
}
if (iface->dhcpc.type != IFACE_NO_DHCP) { if (iface->dhcpc.type != IFACE_NO_DHCP) {
/* No puedo correr otro tipo de DHCP */ /* No puedo correr otro tipo de DHCP */
return -1; return -1;
} }
if (iface->dhcpc.type == IFACE_ISC_DHCLIENT && iface->dhcpc.dhcp_state != DHCP_CLIENT_KILLED) { if ((iface->dhcpc.type == IFACE_ISC_DHCLIENT || iface->dhcpc.type == IFACE_BUSYBOX_UDHCPC) && iface->dhcpc.dhcp_state != DHCP_CLIENT_KILLED) {
/* El cliente de dhcp ya está corriendo, no hacer nada */ /* El cliente de dhcp ya está corriendo, no hacer nada */
return -1; return -1;
} }
interfaces_dhcp_clear_info (&iface->dhcpc);
ret = g_spawn_async_with_pipes ( ret = g_spawn_async_with_pipes (
"/", "/",
argv, argv,
@ -157,7 +193,7 @@ int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type
} }
iface->dhcpc.dhcp_state = DHCP_CLIENT_EXTERNAL_RUNNING; iface->dhcpc.dhcp_state = DHCP_CLIENT_EXTERNAL_RUNNING;
iface->dhcpc.type = IFACE_ISC_DHCLIENT; iface->dhcpc.type = type;
iface->dhcpc.flags = flags; iface->dhcpc.flags = flags;
iface->dhcpc.process_watch = g_child_watch_add (iface->dhcpc.process_pid, interfaces_dhcp_client_killed_cb, iface); iface->dhcpc.process_watch = g_child_watch_add (iface->dhcpc.process_pid, interfaces_dhcp_client_killed_cb, iface);
@ -165,7 +201,7 @@ int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type
return 0; return 0;
} }
void interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index) { int interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index) {
Interface *iface; Interface *iface;
iface = _interfaces_locate_by_index (handle->interfaces, index); iface = _interfaces_locate_by_index (handle->interfaces, index);
@ -173,18 +209,18 @@ void interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index) {
if (iface == NULL) { if (iface == NULL) {
printf ("Error, solicitaron operación sobre interfaz que no existe\n"); printf ("Error, solicitaron operación sobre interfaz que no existe\n");
return; return -1;
} }
if (iface->dhcpc.type == IFACE_NO_DHCP) { if (iface->dhcpc.type == IFACE_NO_DHCP) {
return; return -1;
} }
if (iface->dhcpc.type == IFACE_ISC_DHCLIENT) { if (iface->dhcpc.type == IFACE_ISC_DHCLIENT || iface->dhcpc.type == IFACE_BUSYBOX_UDHCPC) {
if (iface->dhcpc.dhcp_state == DHCP_CLIENT_KILLED) return; if (iface->dhcpc.dhcp_state == DHCP_CLIENT_KILLED) return -1;
/* Proceso, matar y reiniciar estado */ /* Proceso, matar y reiniciar estado */
iface->dhcpc.type = IFACE_NO_DHCP;
iface->dhcpc.flags &= (~DHCP_CLIENT_FLAG_AUTO_RESTART); iface->dhcpc.flags &= (~DHCP_CLIENT_FLAG_AUTO_RESTART);
g_source_remove (iface->dhcpc.process_watch); g_source_remove (iface->dhcpc.process_watch);
@ -192,7 +228,15 @@ void interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index) {
g_child_watch_add (iface->dhcpc.process_pid, interfaces_dhcp_client_ignore_kill, NULL); g_child_watch_add (iface->dhcpc.process_pid, interfaces_dhcp_client_ignore_kill, NULL);
kill (iface->dhcpc.process_pid, SIGTERM); kill (iface->dhcpc.process_pid, SIGTERM);
iface->dhcpc.type = IFACE_NO_DHCP;
/* 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í */
} }
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 *gateway, struct_addr *broadcast, struct_addr *dhcp_server, uint32_t lease_time, struct_addr *dns_list, int dns_count, char *domain_name) {
@ -211,7 +255,8 @@ void interfaces_dhcp_client_internal_feed_from_client (NetworkInadorHandle *hand
return; return;
} }
if (iface->dhcpc.type == IFACE_ISC_DHCLIENT) { // TODO: Cuando entre a estado Selecting, previo otro estado diferente, borrar la IP, si es que tenemos
if (iface->dhcpc.type == IFACE_ISC_DHCLIENT || iface->dhcpc.type == IFACE_BUSYBOX_UDHCPC) {
/* Un proceso muerto no puede informar de cambios de estados */ /* Un proceso muerto no puede informar de cambios de estados */
if (iface->dhcpc.dhcp_state == DHCP_CLIENT_KILLED) return; if (iface->dhcpc.dhcp_state == DHCP_CLIENT_KILLED) return;
@ -248,6 +293,7 @@ void interfaces_dhcp_client_internal_feed_from_client (NetworkInadorHandle *hand
memcpy (&iface->dhcpc.broadcast, broadcast, sizeof (iface->dhcpc.broadcast)); memcpy (&iface->dhcpc.broadcast, broadcast, sizeof (iface->dhcpc.broadcast));
memcpy (&iface->dhcpc.dhcp_server_ip, dhcp_server, sizeof (iface->dhcpc.dhcp_server_ip)); memcpy (&iface->dhcpc.dhcp_server_ip, dhcp_server, sizeof (iface->dhcpc.dhcp_server_ip));
iface->dhcpc.lease_time = lease_time;
char buf_a[256], buf_b[256], buf_c[256], buf_d[256]; 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.ip, buf_a, sizeof (buf_a));

View File

@ -26,7 +26,7 @@
#include "common.h" #include "common.h"
int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type, uint32_t flags); int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type, uint32_t flags);
void interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index); 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 *gateway, 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__ */ #endif /* __DHCP_CLIENT_H__ */

View File

@ -46,6 +46,8 @@
#define COMMAND_SOCKET_PATH "/tmp/network-inador.socket" #define COMMAND_SOCKET_PATH "/tmp/network-inador.socket"
void _manager_send_dhcp_status (ManagerClientInfo *manager_client, InterfaceDHCPClientInfo *dhcpc, gboolean is_event);
static void _manager_send_error (ManagerClientInfo *manager_client, int error, int orig_cmd) { static void _manager_send_error (ManagerClientInfo *manager_client, int error, int orig_cmd) {
unsigned char buffer[8]; unsigned char buffer[8];
@ -732,7 +734,7 @@ static void _manager_execute_dhcp_client_feed (ManagerClientInfo *manager_client
return; return;
} }
if (iface->dhcpc.type != IFACE_ISC_DHCLIENT) { if (iface->dhcpc.type != IFACE_ISC_DHCLIENT && iface->dhcpc.type != IFACE_BUSYBOX_UDHCPC) {
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_DHCP_CLIENT_FEED); _manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_DHCP_CLIENT_FEED);
return; return;
} }
@ -807,6 +809,183 @@ static void _manager_execute_dhcp_client_feed (ManagerClientInfo *manager_client
_manager_send_executed (manager_client); _manager_send_executed (manager_client);
} }
static void _manager_execute_dhcp_run (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
Interface *iface;
int ret;
int family, tipo;
uint32_t flags;
if (buffer_len < 12) {
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_RUN_DHCP);
return;
}
family = buffer[6];
//if (family != AF_INET && family != AF_INET6) {
if (family != AF_INET) {
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_FAMILY, NET_INADOR_COMMAND_RUN_DHCP);
return;
}
iface = _manager_fetch_interface (manager_client, &buffer[2], NET_INADOR_COMMAND_RUN_DHCP);
if (iface == NULL) return;
tipo = buffer[7];
if (tipo == 1) {
tipo = IFACE_ISC_DHCLIENT;
} else if (tipo == 2) {
tipo = IFACE_BUSYBOX_UDHCPC;
} else {
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_VALUE, NET_INADOR_COMMAND_RUN_DHCP);
return;
}
/* TODO: Revisar las banderas */
memcpy (&flags, &buffer[8], 4);
ret = interfaces_dhcp_client_run (manager_client->manager->handle, iface->index, tipo, flags);
if (ret == 0) {
/* OK */
_manager_send_executed (manager_client);
} else {
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_RUN_DHCP);
}
}
static void _manager_execute_dhcp_stop (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
Interface *iface;
int ret;
int family;
if (buffer_len < 7) {
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_STOP_DHCP);
return;
}
family = buffer[6];
//if (family != AF_INET && family != AF_INET6) {
if (family != AF_INET) {
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_FAMILY, NET_INADOR_COMMAND_STOP_DHCP);
return;
}
iface = _manager_fetch_interface (manager_client, &buffer[2], NET_INADOR_COMMAND_STOP_DHCP);
if (iface == NULL) return;
ret = interfaces_dhcp_client_stop (manager_client->manager->handle, iface->index);
if (ret == 0) {
/* OK */
_manager_send_executed (manager_client);
} else {
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_STOP_DHCP);
}
}
static void _manager_execute_dhcp_get_status (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
Interface *iface;
int family;
if (buffer_len < 7) {
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_GET_DHCP_STATUS);
return;
}
family = buffer[6];
//if (family != AF_INET && family != AF_INET6) {
if (family != AF_INET) {
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_FAMILY, NET_INADOR_COMMAND_GET_DHCP_STATUS);
return;
}
iface = _manager_fetch_interface (manager_client, &buffer[2], NET_INADOR_COMMAND_GET_DHCP_STATUS);
if (iface == NULL) return;
_manager_send_dhcp_status (manager_client, &iface->dhcpc, FALSE);
}
void _manager_send_dhcp_status (ManagerClientInfo *manager_client, InterfaceDHCPClientInfo *dhcpc, gboolean is_event) {
Interface *iface;
unsigned char buffer[80];
int family_size = 0;
int label_len;
int pos;
int family = AF_INET;
struct in_addr empty;
memset (&empty, 0, sizeof (empty));
iface = container_of (dhcpc, Interface, dhcpc);
if (is_event) {
buffer[0] = NET_INADOR_TYPE_EVENT;
buffer[1] = NET_INADOR_EVENT_DHCP_STATUS;
} else {
buffer[0] = NET_INADOR_TYPE_RESPONSE;
buffer[1] = NET_INADOR_RESPONSE_DHCP_STATUS;
}
/* Familia */
if (family == AF_INET) {
family_size = sizeof (struct in_addr);
}
memcpy (&buffer[2], &iface->index, 4);
buffer[6] = family;
buffer[7] = dhcpc->type;
buffer[8] = dhcpc->dhcp_state;
/* Prefijo */
buffer[9] = dhcpc->prefix;
/* Los campos de bits */
buffer[10] = 0;
if (memcmp (&dhcpc->gateway, &empty, 4) == 0) {
buffer[10] |= 0x01;
}
if (memcmp (&dhcpc->broadcast, &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;
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);
pos += family_size;
}
if (memcmp (&dhcpc->broadcast, &empty, 4) != 0) {
memcpy (&buffer[pos], &dhcpc->broadcast, family_size);
pos += family_size;
}
if (memcmp (&dhcpc->dhcp_server_ip, &empty, 4) != 0) {
memcpy (&buffer[pos], &dhcpc->dhcp_server_ip, family_size);
pos += family_size;
}
/* TODO: Falta aquí enviar la lista de servidores DNS y el domain name */
send (manager_client->fd, buffer, pos, 0);
}
static gboolean _manager_client_data (GIOChannel *source, GIOCondition condition, gpointer data) { static gboolean _manager_client_data (GIOChannel *source, GIOCondition condition, gpointer data) {
ManagerClientInfo *manager_client = (ManagerClientInfo *) data; ManagerClientInfo *manager_client = (ManagerClientInfo *) data;
NetworkInadorManager *manager = manager_client->manager; NetworkInadorManager *manager = manager_client->manager;
@ -896,6 +1075,15 @@ static gboolean _manager_client_data (GIOChannel *source, GIOCondition condition
case NET_INADOR_COMMAND_DHCP_CLIENT_FEED: case NET_INADOR_COMMAND_DHCP_CLIENT_FEED:
_manager_execute_dhcp_client_feed (manager_client, buffer, bytes); _manager_execute_dhcp_client_feed (manager_client, buffer, bytes);
break; break;
case NET_INADOR_COMMAND_RUN_DHCP:
_manager_execute_dhcp_run (manager_client, buffer, bytes);
break;
case NET_INADOR_COMMAND_STOP_DHCP:
_manager_execute_dhcp_stop (manager_client, buffer, bytes);
break;
case NET_INADOR_COMMAND_GET_DHCP_STATUS:
_manager_execute_dhcp_get_status (manager_client, buffer, bytes);
break;
default: default:
_manager_send_error (manager_client, NET_INADOR_ERROR_WRONG_COMMAND, command); _manager_send_error (manager_client, NET_INADOR_ERROR_WRONG_COMMAND, command);
} }

View File

@ -12,6 +12,7 @@ enum {
/* Lista de eventos */ /* Lista de eventos */
#define NET_INADOR_EVENT_MASK_INTERFACES 0x01 #define NET_INADOR_EVENT_MASK_INTERFACES 0x01
#define NET_INADOR_EVENT_MASK_IP 0x02 #define NET_INADOR_EVENT_MASK_IP 0x02
#define NET_INADOR_EVENT_MASK_DHCP_STATUS 0x04
enum { enum {
NET_INADOR_COMMAND_LIST_IFACES = 1, NET_INADOR_COMMAND_LIST_IFACES = 1,
@ -34,6 +35,10 @@ enum {
NET_INADOR_COMMAND_ADD_IP, NET_INADOR_COMMAND_ADD_IP,
NET_INADOR_COMMAND_REMOVE_IP, NET_INADOR_COMMAND_REMOVE_IP,
NET_INADOR_COMMAND_RUN_DHCP = 48,
NET_INADOR_COMMAND_STOP_DHCP,
NET_INADOR_COMMAND_GET_DHCP_STATUS,
NET_INADOR_COMMAND_SET_EVENT_MASK = 192, NET_INADOR_COMMAND_SET_EVENT_MASK = 192,
/* Los siguientes comandos son para uso interno */ /* Los siguientes comandos son para uso interno */
@ -56,7 +61,9 @@ enum {
NET_INADOR_EVENT_IFACE_ADDED = 2, NET_INADOR_EVENT_IFACE_ADDED = 2,
NET_INADOR_EVENT_IPADDR_ADDED, NET_INADOR_EVENT_IPADDR_ADDED,
NET_INADOR_EVENT_IFACE_REMOVED, NET_INADOR_EVENT_IFACE_REMOVED,
NET_INADOR_EVENT_IPADDR_REMOVED NET_INADOR_EVENT_IPADDR_REMOVED,
NET_INADOR_EVENT_DHCP_STATUS = 6
}; };
enum { enum {
@ -64,6 +71,8 @@ enum {
NET_INADOR_RESPONSE_IFACE = 2, NET_INADOR_RESPONSE_IFACE = 2,
NET_INADOR_RESPONSE_IPADDR, NET_INADOR_RESPONSE_IPADDR,
NET_INADOR_RESPONSE_DHCP_STATUS = 6
}; };
enum { enum {

View File

@ -274,17 +274,77 @@ int parse_int (char *var, int *entero) {
return 0; return 0;
} }
enum {
IFACE_ISC_DHCLIENT = 1,
IFACE_BUSYBOX_UDHCPC
};
const char *isc_dhcp_reasons[] = {
"MEDIUM",
"PREINIT",
"BOUND",
"RENEW",
"REBIND",
"REBOOT",
"EXPIRE",
"FAIL",
"STOP",
"RELEASE",
"NBI",
"TIMEOUT",
NULL
};
const char *busybox_dhcp_argv[] = {
"deconfig",
"bound",
"renew",
"nak"
};
int main (int argc, char *argv[]) { int main (int argc, char *argv[]) {
char *reason, *interface; char *reason, *interface;
int s, ret; int s, ret, tipo;
struct sockaddr_un path_dest; struct sockaddr_un path_dest;
struct in_addr ip, netmask, gateway, broadcast, dhcp_server; struct in_addr ip, netmask, gateway, broadcast, dhcp_server;
int prefix, lease_time; int prefix, lease_time;
debug (argc, argv); debug (argc, argv);
tipo = 0;
/* Tratar de determinar si estamos siendo corridos por un el DHCP del ISC o por el udhcpc busybox */
reason = getenv ("reason"); reason = getenv ("reason");
if (reason != NULL) {
s = 0;
while (isc_dhcp_reasons[s] != NULL) {
if (strcmp (reason, isc_dhcp_reasons[s]) == 0) {
/* Es un ISC DHCP Client */
tipo = IFACE_ISC_DHCLIENT;
break;
}
s++;
}
}
if (tipo == 0 && argc > 1) {
/* Intentar revisar si es un busybox udhcpc */
s = 0;
while (busybox_dhcp_argv[s] != NULL) {
if (strcmp (argv[1], busybox_dhcp_argv[s]) == 0) {
tipo = IFACE_BUSYBOX_UDHCPC;
reason = argv[1];
break;
}
s++;
}
}
if (tipo == 0) {
return 1;
}
interface = getenv ("interface"); interface = getenv ("interface");
if (reason == NULL || interface == NULL) { if (reason == NULL || interface == NULL) {
@ -308,12 +368,15 @@ int main (int argc, char *argv[]) {
return 1; return 1;
} }
if (strcmp (reason, "PREINIT") == 0) { if (strcmp (reason, "PREINIT") == 0 || // ISC DHCP
strcmp (reason, "deconfig") == 0 // Busybox udhcpc
) {
send_preinit (s, interface); send_preinit (s, interface);
} if (strcmp (reason, "FAIL") == 0) { } if (strcmp (reason, "FAIL") == 0) {
} else if (strcmp (reason, "BOUND") == 0 || strcmp (reason, "REBOOT") == 0 || } else if (strcmp (reason, "BOUND") == 0 || strcmp (reason, "REBOOT") == 0 ||
strcmp (reason, "RENEW") == 0 || strcmp (reason, "REBIND") == 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
) { ) {
/* /*
* Los valores más importantes recibidos: * Los valores más importantes recibidos:
@ -328,12 +391,21 @@ int main (int argc, char *argv[]) {
*/ */
/* Parsear y revisar las direcciones IP recibidas */ /* 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;
if (tipo == IFACE_ISC_DHCLIENT) {
s_ip = getenv ("new_ip_address"); s_ip = getenv ("new_ip_address");
s_mask = getenv ("new_subnet_mask"); s_mask = getenv ("new_subnet_mask");
s_gateway = getenv ("new_routers"); s_gateway = getenv ("new_routers");
s_broadcast = getenv ("new_broadcast_address"); s_broadcast = getenv ("new_broadcast_address");
s_lease_time = getenv ("new_dhcp_lease_time"); s_lease_time = getenv ("new_dhcp_lease_time");
s_dhcp_server = getenv ("new_dhcp_server_identifier"); s_dhcp_server = getenv ("new_dhcp_server_identifier");
} else if (tipo == IFACE_BUSYBOX_UDHCPC) {
s_ip = getenv ("ip");
s_mask = getenv ("subnet");
s_gateway = getenv ("router");
s_broadcast = getenv ("broadcast");
s_lease_time = getenv ("lease");
s_dhcp_server = getenv ("serverid");
}
/* TODO: Faltan los DNS */ /* TODO: Faltan los DNS */
if (parse_ip (s_ip, &ip) < 0) { if (parse_ip (s_ip, &ip) < 0) {
@ -364,7 +436,9 @@ int main (int argc, char *argv[]) {
} }
int is_bound = 0; int is_bound = 0;
if (strcmp (reason, "BOUND") == 0 || strcmp (reason, "REBOOT") == 0) { if (strcmp (reason, "BOUND") == 0 || strcmp (reason, "REBOOT") == 0 || // Del ISC dhcp
strcmp (reason, "bound") == 0 // del busybox
) {
is_bound = 1; 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, &gateway, &broadcast, &dhcp_server, lease_time);