Primera fase del cliente de dhcp.
parent
fc9194365a
commit
476ab66ca8
|
@ -47,3 +47,5 @@ client-gtk/inador-gtk-client
|
|||
client-gtk/ni-marshal.c
|
||||
client-gtk/ni-marshal.h
|
||||
client-gtk/core
|
||||
|
||||
src/ni-iface-helper
|
||||
|
|
|
@ -8,9 +8,16 @@ network_inador_SOURCES = main.c \
|
|||
ip-address.c ip-address.h \
|
||||
bridge.c bridge.h \
|
||||
manager.c manager.h \
|
||||
dhcp_client.c dhcp_client.h \
|
||||
wireless_if.c wireless_if.h \
|
||||
wireless_bss.c wireless_bss.h
|
||||
|
||||
libexec_PROGRAMS = ni-iface-helper
|
||||
|
||||
ni_iface_helper_SOURCES = ni-iface-helper.c
|
||||
ni_iface_helper_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
ni_iface_helper_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
#network_inador_CPPFLAGS = -DGAMEDATA_DIR=\"$(gamedatadir)/\" -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS)
|
||||
network_inador_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS)
|
||||
network_inador_CFLAGS = $(GLIB_CFLAGS) $(LIBNL3_CFLAGS) $(LIBNLGEN3_CFLAGS) $(AM_CFLAGS)
|
||||
|
|
34
src/common.h
34
src/common.h
|
@ -107,7 +107,39 @@ typedef struct _WirelessInfo {
|
|||
GList *aps;
|
||||
} WirelessInfo;
|
||||
|
||||
/* Información del proceso de DHCP */
|
||||
enum {
|
||||
IFACE_NO_DHCP = 0,
|
||||
IFACE_ISC_DHCLIENT
|
||||
};
|
||||
|
||||
enum {
|
||||
DHCP_CLIENT_INITING,
|
||||
|
||||
DHCP_CLIENT_SELECTING,
|
||||
DHCP_CLIENT_REQUESTING,
|
||||
DHCP_CLIENT_BOUND,
|
||||
DHCP_CLIENT_RENEWING,
|
||||
|
||||
DHCP_CLIENT_KILLED,
|
||||
DHCP_CLIENT_EXTERNAL_RUNNING
|
||||
};
|
||||
|
||||
#define DHCP_CLIENT_FLAG_AUTO_RESTART 0x0001
|
||||
|
||||
typedef struct _InterfaceDHCPClientInfo {
|
||||
int type;
|
||||
|
||||
uint32_t flags;
|
||||
int dhcp_state;
|
||||
|
||||
/* Para vigilar el proceso */
|
||||
GPid process_pid;
|
||||
guint process_watch;
|
||||
} InterfaceDHCPClientInfo;
|
||||
|
||||
struct _Interface {
|
||||
NetworkInadorHandle *handle;
|
||||
uint32_t index;
|
||||
char name[IFNAMSIZ];
|
||||
uint32_t link_type;
|
||||
|
@ -134,7 +166,7 @@ struct _Interface {
|
|||
|
||||
GList *address;
|
||||
|
||||
//DHCPStateInfo dhcp_info;
|
||||
InterfaceDHCPClientInfo dhcpc;
|
||||
|
||||
/* Información wireless */
|
||||
WirelessInfo *wireless;
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
/*
|
||||
* dhcp_client.c
|
||||
* This file is part of Network Inador
|
||||
*
|
||||
* Copyright (C) 2021 - Félix Arreola Rodríguez
|
||||
*
|
||||
* Network Inador is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Network Inador is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Network Inador; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "interfaces.h"
|
||||
#include "common.h"
|
||||
|
||||
#include "dhcp_client.h"
|
||||
#include "network-inador-manager.h"
|
||||
|
||||
void interfaces_dhcp_client_ignore_kill (GPid pid, gint status, gpointer data) {
|
||||
g_spawn_check_exit_status (status, NULL);
|
||||
}
|
||||
|
||||
void interfaces_dhcp_prepare_args_for_dhclient (char **argv, int size, char *iface_name) {
|
||||
gchar pid_file[256];
|
||||
|
||||
snprintf (pid_file, sizeof (pid_file), "/run/dhclient-%s.pid", iface_name);
|
||||
/* Preparar los argumentos para el proceso */
|
||||
argv[0] = "/sbin/dhclient";
|
||||
argv[1] = "-d";
|
||||
argv[2] = "-q";
|
||||
argv[3] = "-pf";
|
||||
argv[4] = pid_file;
|
||||
argv[5] = "-sf";
|
||||
argv[6] = "/home/gatuno/Proyectos/NetworkInador/src/ni-iface-helper";
|
||||
argv[7] = iface_name;
|
||||
argv[8] = NULL;
|
||||
}
|
||||
|
||||
void interfaces_dhcp_client_killed_cb (GPid pid, gint status, gpointer data) {
|
||||
Interface *iface = (Interface *) data;
|
||||
gboolean ret;
|
||||
GError *error = NULL;
|
||||
char *argv[20];
|
||||
|
||||
/* Preparar los argumentos */
|
||||
interfaces_dhcp_prepare_args_for_dhclient (argv, 20, iface->name);
|
||||
|
||||
if (g_spawn_check_exit_status (status, NULL)) {
|
||||
/* Revisar si necesito algo */
|
||||
}
|
||||
|
||||
if (iface->dhcpc.type == IFACE_ISC_DHCLIENT) {
|
||||
if (iface->dhcpc.flags & DHCP_CLIENT_FLAG_AUTO_RESTART) {
|
||||
/* Se cerró o mataron el proceso, reiniciar */
|
||||
ret = g_spawn_async_with_pipes (
|
||||
"/",
|
||||
argv,
|
||||
NULL,
|
||||
G_SPAWN_DO_NOT_REAP_CHILD,
|
||||
NULL,
|
||||
NULL,
|
||||
&iface->dhcpc.process_pid,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&error);
|
||||
|
||||
if (ret == FALSE) {
|
||||
printf ("Error dhcp: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
error = NULL;
|
||||
|
||||
iface->dhcpc.flags = DHCP_CLIENT_KILLED;
|
||||
iface->dhcpc.process_watch = 0;
|
||||
} else {
|
||||
iface->dhcpc.dhcp_state = DHCP_CLIENT_EXTERNAL_RUNNING;
|
||||
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.process_watch = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type, uint32_t flags) {
|
||||
/* IFNAMSIZ */
|
||||
Interface *iface;
|
||||
gboolean ret;
|
||||
GError *error = NULL;
|
||||
char *argv[20];
|
||||
|
||||
iface = _interfaces_locate_by_index (handle->interfaces, index);
|
||||
|
||||
if (iface == NULL) {
|
||||
printf ("Error, solicitaron operación sobre interfaz que no existe\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Preparar los argumentos */
|
||||
interfaces_dhcp_prepare_args_for_dhclient (argv, 20, iface->name);
|
||||
|
||||
if (iface->dhcpc.type != IFACE_NO_DHCP) {
|
||||
/* No puedo correr otro tipo de DHCP */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iface->dhcpc.type == IFACE_ISC_DHCLIENT && iface->dhcpc.dhcp_state != DHCP_CLIENT_KILLED) {
|
||||
/* El cliente de dhcp ya está corriendo, no hacer nada */
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = g_spawn_async_with_pipes (
|
||||
"/",
|
||||
argv,
|
||||
NULL,
|
||||
G_SPAWN_DO_NOT_REAP_CHILD,
|
||||
NULL,
|
||||
NULL,
|
||||
&iface->dhcpc.process_pid,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&error);
|
||||
|
||||
if (ret == FALSE) {
|
||||
|
||||
printf ("Error dhcp: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
error = NULL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
iface->dhcpc.dhcp_state = DHCP_CLIENT_EXTERNAL_RUNNING;
|
||||
iface->dhcpc.type = IFACE_ISC_DHCLIENT;
|
||||
iface->dhcpc.flags = flags;
|
||||
|
||||
iface->dhcpc.process_watch = g_child_watch_add (iface->dhcpc.process_pid, interfaces_dhcp_client_killed_cb, iface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index) {
|
||||
Interface *iface;
|
||||
|
||||
iface = _interfaces_locate_by_index (handle->interfaces, index);
|
||||
|
||||
if (iface == NULL) {
|
||||
printf ("Error, solicitaron operación sobre interfaz que no existe\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (iface->dhcpc.type == IFACE_NO_DHCP) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (iface->dhcpc.type == IFACE_ISC_DHCLIENT) {
|
||||
if (iface->dhcpc.dhcp_state == DHCP_CLIENT_KILLED) return;
|
||||
|
||||
/* Proceso, matar y reiniciar estado */
|
||||
iface->dhcpc.type = IFACE_NO_DHCP;
|
||||
iface->dhcpc.flags &= (~DHCP_CLIENT_FLAG_AUTO_RESTART);
|
||||
|
||||
g_source_remove (iface->dhcpc.process_watch);
|
||||
iface->dhcpc.process_watch = 0;
|
||||
g_child_watch_add (iface->dhcpc.process_pid, interfaces_dhcp_client_ignore_kill, NULL);
|
||||
|
||||
kill (iface->dhcpc.process_pid, SIGTERM);
|
||||
}
|
||||
}
|
||||
|
||||
void interfaces_dhcp_client_internal_set_status (NetworkInadorHandle *handle, int index, int status) {
|
||||
Interface *iface;
|
||||
|
||||
iface = _interfaces_locate_by_index (handle->interfaces, index);
|
||||
|
||||
if (iface == NULL) {
|
||||
printf ("Error, solicitaron operación sobre interfaz que no existe\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (iface->dhcpc.type == IFACE_NO_DHCP) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (iface->dhcpc.type == IFACE_ISC_DHCLIENT) {
|
||||
/* Un proceso muerto no puede informar de cambios de estados */
|
||||
if (iface->dhcpc.dhcp_state == DHCP_CLIENT_KILLED) return;
|
||||
|
||||
switch (status) {
|
||||
case NET_INADOR_DHCP_STATUS_INITING:
|
||||
iface->dhcpc.dhcp_state = DHCP_CLIENT_INITING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* dhcp_client.h
|
||||
* This file is part of Network Inador
|
||||
*
|
||||
* Copyright (C) 2021 - Félix Arreola Rodríguez
|
||||
*
|
||||
* Network Inador is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Network Inador is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Network Inador; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __DHCP_CLIENT_H__
|
||||
#define __DHCP_CLIENT_H__
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type, uint32_t flags);
|
||||
void interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index);
|
||||
void interfaces_dhcp_client_internal_set_status (NetworkInadorHandle *handle, int index, int status);
|
||||
|
||||
#endif /* __DHCP_CLIENT_H__ */
|
||||
|
|
@ -256,6 +256,22 @@ Interface * _interfaces_locate_by_index (GList *list, int index) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
Interface * _interfaces_locate_by_name (GList *list, const char *name) {
|
||||
Interface *iface;
|
||||
|
||||
GList *g;
|
||||
|
||||
for (g = list; g != NULL; g = g->next) {
|
||||
iface = (Interface *) g->data;
|
||||
|
||||
if (strcmp (iface->name, name) == 0) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int _interfaces_wait_ack_or_error (struct nl_msg *msg, void *arg) {
|
||||
int *ret = (int *) arg;
|
||||
struct nlmsgerr *l_err;
|
||||
|
|
|
@ -36,6 +36,7 @@ int _interfaces_wait_ack_or_error (struct nl_msg *msg, void *arg);
|
|||
int _interfaces_wait_error (struct sockaddr_nl *nla, struct nlmsgerr *l_err, void *arg);
|
||||
|
||||
Interface * _interfaces_locate_by_index (GList *list, int index);
|
||||
Interface * _interfaces_locate_by_name (GList *list, const char *name);
|
||||
|
||||
int interfaces_change_mac_address (NetworkInadorHandle *handle, int index, void *new_mac);
|
||||
int interfaces_change_mtu (NetworkInadorHandle *handle, int index, uint32_t new_mtu);
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "netlink-events.h"
|
||||
#include "ip-address.h"
|
||||
#include "bridge.h"
|
||||
#include "dhcp_client.h"
|
||||
|
||||
/* Usados para salir en caso de una señal */
|
||||
static int sigterm_pipe_fds[2] = { -1, -1 };
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "ip-address.h"
|
||||
#include "bridge.h"
|
||||
#include "network-inador-manager.h"
|
||||
#include "dhcp_client.h"
|
||||
|
||||
#define COMMAND_SOCKET_PATH "/tmp/network-inador.socket"
|
||||
|
||||
|
@ -634,6 +635,57 @@ static void _manager_handle_set_event_mask (ManagerClientInfo *manager_client, u
|
|||
manager_client->wanted_events = events;
|
||||
}
|
||||
|
||||
static void _manager_execute_dhcp_set_status (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
|
||||
int name_len;
|
||||
unsigned char name[IFNAMSIZ];
|
||||
Interface *iface;
|
||||
|
||||
if (buffer_len < 4) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_DHCP_SET_STATUS);
|
||||
return;
|
||||
}
|
||||
|
||||
name_len = buffer[3];
|
||||
if (name_len == 0 || name_len >= IFNAMSIZ) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_BAD_STRING, NET_INADOR_COMMAND_DHCP_SET_STATUS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (name_len + 4 < buffer_len) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_DHCP_SET_STATUS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer[2] < NET_INADOR_DHCP_STATUS_INITING || buffer[2] > NET_INADOR_DHCP_STATUS_RENEWING) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_VALUE, NET_INADOR_COMMAND_DHCP_SET_STATUS);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy (name, &buffer[4], name_len);
|
||||
name[name_len] = 0;
|
||||
|
||||
iface = _interfaces_locate_by_name (manager_client->manager->handle->interfaces, name);
|
||||
if (iface == NULL) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_IFACE_INDEX, NET_INADOR_COMMAND_DHCP_SET_STATUS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (iface->dhcpc.type != IFACE_ISC_DHCLIENT) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_DHCP_SET_STATUS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (iface->dhcpc.dhcp_state == DHCP_CLIENT_KILLED) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_DHCP_SET_STATUS);
|
||||
return;
|
||||
}
|
||||
|
||||
interfaces_dhcp_client_internal_set_status (manager_client->manager->handle, iface->index, buffer[2]);
|
||||
|
||||
/* OK */
|
||||
_manager_send_executed (manager_client);
|
||||
}
|
||||
|
||||
static gboolean _manager_client_data (GIOChannel *source, GIOCondition condition, gpointer data) {
|
||||
ManagerClientInfo *manager_client = (ManagerClientInfo *) data;
|
||||
NetworkInadorManager *manager = manager_client->manager;
|
||||
|
@ -720,6 +772,9 @@ static gboolean _manager_client_data (GIOChannel *source, GIOCondition condition
|
|||
case NET_INADOR_COMMAND_SET_MASTER:
|
||||
_manager_execute_set_or_clear_master (manager_client, buffer, bytes, FALSE);
|
||||
break;
|
||||
case NET_INADOR_COMMAND_DHCP_SET_STATUS:
|
||||
_manager_execute_dhcp_set_status (manager_client, buffer, bytes);
|
||||
break;
|
||||
default:
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_WRONG_COMMAND, command);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,9 @@ enum {
|
|||
NET_INADOR_COMMAND_REMOVE_IP,
|
||||
|
||||
NET_INADOR_COMMAND_SET_EVENT_MASK = 192,
|
||||
|
||||
/* Los siguientes comandos son para uso interno */
|
||||
NET_INADOR_COMMAND_DHCP_SET_STATUS = 224,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -61,9 +64,15 @@ enum {
|
|||
|
||||
NET_INADOR_RESPONSE_IFACE = 2,
|
||||
NET_INADOR_RESPONSE_IPADDR,
|
||||
|
||||
};
|
||||
|
||||
enum {
|
||||
NET_INADOR_DHCP_STATUS_INITING = 1,
|
||||
NET_INADOR_DHCP_STATUS_SELECTING,
|
||||
NET_INADOR_DHCP_STATUS_REQUESTING,
|
||||
NET_INADOR_DHCP_STATUS_BOUND,
|
||||
NET_INADOR_DHCP_STATUS_RENEWING
|
||||
};
|
||||
|
||||
#endif /* __NETWOR_INADOR_MANAGER_H__ */
|
||||
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* ni-iface-helper.c
|
||||
* This file is part of Network Inador
|
||||
*
|
||||
* Copyright (C) 2021 - Félix Arreola Rodríguez
|
||||
*
|
||||
* Network Inador is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Network Inador is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Network Inador; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "network-inador-manager.h"
|
||||
|
||||
#define COMMAND_SOCKET_PATH "/tmp/network-inador.socket"
|
||||
|
||||
extern char** environ;
|
||||
|
||||
int debug (int argc, char *argv[]) {
|
||||
char **item;
|
||||
int fd;
|
||||
|
||||
fd = open ("/tmp/var_dhcp.env", O_CREAT | O_WRONLY | O_TRUNC, 0644);
|
||||
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (item = environ; *item; item++) {
|
||||
char *name, *val, **p;
|
||||
|
||||
/* Split on the = */
|
||||
name = strdup (*item);
|
||||
val = strchr (name, '=');
|
||||
if (!val || val == name) {
|
||||
free (name);
|
||||
continue;
|
||||
}
|
||||
*val++ = '\0';
|
||||
|
||||
/* Ignore non-DCHP-related environment variables
|
||||
for (p = (char **) ignore; *p; p++) {
|
||||
if (strncmp (name, *p, strlen (*p)) == 0)
|
||||
goto next;
|
||||
}*/
|
||||
|
||||
write (fd, "Name: <", 7);
|
||||
write (fd, name, strlen (name));
|
||||
write (fd, ">, Value: <", 11);
|
||||
write (fd, val, strlen (val));
|
||||
write (fd, ">\n", 2);
|
||||
}
|
||||
|
||||
close (fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *retrieve_env (const char *name) {
|
||||
char *bus, *dup, *get;
|
||||
|
||||
get = getenv (name);
|
||||
|
||||
if (get == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bus = strchr (get, '=');
|
||||
|
||||
if (!bus || bus == get) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dup = strdup (&get[1]);
|
||||
|
||||
if (dup == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dup;
|
||||
}
|
||||
|
||||
int wait_for_ack_or_error (int s) {
|
||||
unsigned char buffer[128];
|
||||
int ret;
|
||||
|
||||
ret = recv (s, buffer, sizeof (buffer), 0);
|
||||
|
||||
if (ret < 3) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer[0] == NET_INADOR_TYPE_RESPONSE_ERROR) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer[0] == NET_INADOR_TYPE_RESPONSE && buffer[1] == NET_INADOR_RESPONSE_EXECUTED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void send_preinit (int s, char *interface) {
|
||||
unsigned char buffer[128];
|
||||
|
||||
buffer[0] = NET_INADOR_TYPE_COMMAND;
|
||||
buffer[1] = NET_INADOR_COMMAND_DHCP_SET_STATUS;
|
||||
|
||||
buffer[2] = NET_INADOR_DHCP_STATUS_INITING;
|
||||
buffer[3] = strlen (interface);
|
||||
strncpy (&buffer[4], interface, buffer[3]);
|
||||
|
||||
send (s, buffer, 3 + buffer[3], 0);
|
||||
|
||||
if (wait_for_ack_or_error (s) < 0) {
|
||||
close (s);
|
||||
return;
|
||||
}
|
||||
|
||||
close (s);
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
char *reason, *interface;
|
||||
int s, ret;
|
||||
struct sockaddr_un path_dest;
|
||||
|
||||
debug (argc, argv);
|
||||
|
||||
reason = retrieve_env ("reason");
|
||||
|
||||
interface = retrieve_env ("interface");
|
||||
|
||||
if (reason == NULL || interface == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Intentar abrir el socket a la escucha */
|
||||
s = socket (AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
|
||||
|
||||
if (s < 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
path_dest.sun_family = AF_UNIX;
|
||||
strncpy (path_dest.sun_path, COMMAND_SOCKET_PATH, sizeof (path_dest.sun_path));
|
||||
ret = connect (s, (struct sockaddr *) &path_dest, sizeof (path_dest));
|
||||
|
||||
if (ret < 0) {
|
||||
perror ("Connect");
|
||||
close (s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp (reason, "PREINIT") == 0 || strcmp (reason, "FAIL") == 0) {
|
||||
send_preinit (s, interface);
|
||||
|
||||
return 0;
|
||||
} else if (strcmp (reason, "REBOOT") == 0 || strcmp (reason, "RENEW") == 0) {
|
||||
/*
|
||||
* Los valores más importantes recibidos:
|
||||
* new_domain_name_servers -> los DNS
|
||||
* new_expiry -> el timestamp de la hora
|
||||
* new_domain_name -> DNS search name
|
||||
* new_routers -> Lista de routers
|
||||
* new_subnet_mask -> Máscara de red en formato largo
|
||||
* new_broadcast_address -> Dirección broadcast
|
||||
* new_ip_address -> Dirección IP
|
||||
* new_dhcp_lease_time -> Tiempo en segundos
|
||||
*/
|
||||
} else if (strcmp (reason, "EXPIRE") == 0) {
|
||||
/* Los mismos valores, pero con old_ */
|
||||
} else {
|
||||
|
||||
|
||||
close (s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue