Agrego comandos que alimentan la información del cliente DHCP
parent
bf315b5b03
commit
f048dde998
|
@ -48,4 +48,4 @@ client-gtk/ni-marshal.c
|
|||
client-gtk/ni-marshal.h
|
||||
client-gtk/core
|
||||
|
||||
src/ni-iface-helper
|
||||
src/ni-dhcp-helper
|
||||
|
|
|
@ -12,11 +12,11 @@ network_inador_SOURCES = main.c \
|
|||
wireless_if.c wireless_if.h \
|
||||
wireless_bss.c wireless_bss.h
|
||||
|
||||
libexec_PROGRAMS = ni-iface-helper
|
||||
libexec_PROGRAMS = ni-dhcp-helper
|
||||
|
||||
ni_iface_helper_SOURCES = ni-iface-helper.c
|
||||
ni_iface_helper_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
ni_iface_helper_CFLAGS = $(AM_CFLAGS)
|
||||
ni_dhcp_helper_SOURCES = ni-dhcp-iface-helper.c
|
||||
ni_dhcp_helper_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
ni_dhcp_helper_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
#network_inador_CPPFLAGS = -DGAMEDATA_DIR=\"$(gamedatadir)/\" -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS)
|
||||
network_inador_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS)
|
||||
|
|
17
src/common.h
17
src/common.h
|
@ -120,13 +120,14 @@ enum {
|
|||
IFACE_ISC_DHCLIENT
|
||||
};
|
||||
|
||||
/* FIXME: Revisar estos estados */
|
||||
enum {
|
||||
DHCP_CLIENT_INITING,
|
||||
|
||||
DHCP_CLIENT_SELECTING,
|
||||
DHCP_CLIENT_REQUESTING,
|
||||
DHCP_CLIENT_BOUND,
|
||||
DHCP_CLIENT_RENEWING,
|
||||
DHCP_CLIENT_RENEWED,
|
||||
|
||||
DHCP_CLIENT_EXPIRED,
|
||||
DHCP_CLIENT_FAILED,
|
||||
|
||||
DHCP_CLIENT_KILLED,
|
||||
DHCP_CLIENT_EXTERNAL_RUNNING
|
||||
|
@ -143,6 +144,14 @@ typedef struct _InterfaceDHCPClientInfo {
|
|||
/* Para vigilar el proceso */
|
||||
GPid process_pid;
|
||||
guint process_watch;
|
||||
|
||||
/* La información obtenida desde el cliente */
|
||||
struct_addr ip, gateway, broadcast;
|
||||
int prefix;
|
||||
|
||||
struct_addr dhcp_server_ip;
|
||||
|
||||
/* TODO: Falta almacenar la información de DNS */
|
||||
} InterfaceDHCPClientInfo;
|
||||
|
||||
struct _Interface {
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "interfaces.h"
|
||||
|
@ -38,10 +41,9 @@ 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];
|
||||
void interfaces_dhcp_prepare_args_for_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, sizeof (pid_file), "/run/dhclient-%s.pid", iface_name);
|
||||
/* Preparar los argumentos para el proceso */
|
||||
argv[0] = "/sbin/dhclient";
|
||||
argv[1] = "-d";
|
||||
|
@ -49,7 +51,7 @@ void interfaces_dhcp_prepare_args_for_dhclient (char **argv, int size, char *ifa
|
|||
argv[3] = "-pf";
|
||||
argv[4] = pid_file;
|
||||
argv[5] = "-sf";
|
||||
argv[6] = "/home/gatuno/Proyectos/NetworkInador/src/ni-iface-helper";
|
||||
argv[6] = "/home/gatuno/Proyectos/NetworkInador/src/ni-dhcp-helper";
|
||||
argv[7] = iface_name;
|
||||
argv[8] = NULL;
|
||||
}
|
||||
|
@ -59,9 +61,10 @@ void interfaces_dhcp_client_killed_cb (GPid pid, gint status, gpointer data) {
|
|||
gboolean ret;
|
||||
GError *error = NULL;
|
||||
char *argv[20];
|
||||
gchar pid_file[256];
|
||||
|
||||
/* Preparar los argumentos */
|
||||
interfaces_dhcp_prepare_args_for_dhclient (argv, 20, iface->name);
|
||||
interfaces_dhcp_prepare_args_for_dhclient (argv, 20, iface->name, pid_file, sizeof (pid_file));
|
||||
|
||||
if (g_spawn_check_exit_status (status, NULL)) {
|
||||
/* Revisar si necesito algo */
|
||||
|
@ -108,6 +111,7 @@ int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type
|
|||
gboolean ret;
|
||||
GError *error = NULL;
|
||||
char *argv[20];
|
||||
gchar pid_file[256];
|
||||
|
||||
iface = _interfaces_locate_by_index (handle->interfaces, index);
|
||||
|
||||
|
@ -118,7 +122,7 @@ int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type
|
|||
}
|
||||
|
||||
/* Preparar los argumentos */
|
||||
interfaces_dhcp_prepare_args_for_dhclient (argv, 20, iface->name);
|
||||
interfaces_dhcp_prepare_args_for_dhclient (argv, 20, iface->name, pid_file, sizeof (pid_file));
|
||||
|
||||
if (iface->dhcpc.type != IFACE_NO_DHCP) {
|
||||
/* No puedo correr otro tipo de DHCP */
|
||||
|
@ -191,8 +195,9 @@ void interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index) {
|
|||
}
|
||||
}
|
||||
|
||||
void interfaces_dhcp_client_internal_set_status (NetworkInadorHandle *handle, int index, int status) {
|
||||
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) {
|
||||
Interface *iface;
|
||||
struct in_addr empty_v4;
|
||||
|
||||
iface = _interfaces_locate_by_index (handle->interfaces, index);
|
||||
|
||||
|
@ -211,10 +216,45 @@ void interfaces_dhcp_client_internal_set_status (NetworkInadorHandle *handle, in
|
|||
if (iface->dhcpc.dhcp_state == DHCP_CLIENT_KILLED) return;
|
||||
|
||||
switch (status) {
|
||||
case NET_INADOR_DHCP_STATUS_INITING:
|
||||
iface->dhcpc.dhcp_state = DHCP_CLIENT_INITING;
|
||||
case NET_INADOR_DHCP_STATUS_SELECTING:
|
||||
iface->dhcpc.dhcp_state = DHCP_CLIENT_SELECTING;
|
||||
break;
|
||||
case NET_INADOR_DHCP_STATUS_BOUND:
|
||||
iface->dhcpc.dhcp_state = DHCP_CLIENT_BOUND;
|
||||
break;
|
||||
case NET_INADOR_DHCP_STATUS_RENEWED:
|
||||
iface->dhcpc.dhcp_state = DHCP_CLIENT_RENEWED;
|
||||
break;
|
||||
case NET_INADOR_DHCP_STATUS_EXPIRED:
|
||||
iface->dhcpc.dhcp_state = DHCP_CLIENT_EXPIRED;
|
||||
/* Borrar la IP anterior, si es que está puesta */
|
||||
break;
|
||||
case NET_INADOR_DHCP_STATUS_FAILED:
|
||||
iface->dhcpc.dhcp_state = DHCP_CLIENT_FAILED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf ("----> DHCP status: %i\n", iface->dhcpc.dhcp_state);
|
||||
|
||||
if (status == NET_INADOR_DHCP_STATUS_BOUND || status == NET_INADOR_DHCP_STATUS_RENEWED) {
|
||||
/* Copiar las variables de estado */
|
||||
memset (&empty_v4, 0, sizeof (empty_v4));
|
||||
|
||||
memcpy (&iface->dhcpc.ip, ip, sizeof (iface->dhcpc.ip));
|
||||
iface->dhcpc.prefix = prefix;
|
||||
|
||||
memcpy (&iface->dhcpc.gateway, gateway, sizeof (iface->dhcpc.gateway));
|
||||
|
||||
memcpy (&iface->dhcpc.broadcast, broadcast, sizeof (iface->dhcpc.broadcast));
|
||||
memcpy (&iface->dhcpc.dhcp_server_ip, dhcp_server, sizeof (iface->dhcpc.dhcp_server_ip));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
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);
|
||||
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__ */
|
||||
|
||||
|
|
131
src/manager.c
131
src/manager.c
|
@ -659,52 +659,149 @@ 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;
|
||||
#define _MANAGER_CHECK_BYTE_OR_OUT(FAMILY,BUF,POS) \
|
||||
if (BUF[POS] != 0) { \
|
||||
if (FAMILY == AF_INET && BUF[POS] != 4) { \
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_VALUE, NET_INADOR_COMMAND_DHCP_CLIENT_FEED); \
|
||||
return; \
|
||||
} \
|
||||
}
|
||||
|
||||
static void _manager_execute_dhcp_client_feed (ManagerClientInfo *manager_client, unsigned char *buffer, int buffer_len) {
|
||||
int name_len, wanted;
|
||||
unsigned char name[IFNAMSIZ];
|
||||
unsigned char domain_name[256];
|
||||
Interface *iface;
|
||||
int family;
|
||||
int pos, prefix, g;
|
||||
uint32_t lease_time;
|
||||
struct_addr ip, gateway, broadcast, dhcp_server;
|
||||
struct_addr dns[8];
|
||||
|
||||
if (buffer_len < 4) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_DHCP_SET_STATUS);
|
||||
if (buffer_len < 16) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_DHCP_CLIENT_FEED);
|
||||
return;
|
||||
}
|
||||
|
||||
name_len = buffer[3];
|
||||
/* Revisar la familia */
|
||||
family = buffer[2];
|
||||
|
||||
if (family != AF_INET && family != AF_INET6) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_FAMILY, NET_INADOR_COMMAND_DHCP_CLIENT_FEED);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Revisar el estado */
|
||||
if (buffer[3] < DHCP_CLIENT_SELECTING || buffer[3] > DHCP_CLIENT_EXPIRED) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_VALUE, NET_INADOR_COMMAND_DHCP_CLIENT_FEED);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Revisar la longitud del nombre de la interfaz */
|
||||
name_len = buffer[4];
|
||||
if (name_len == 0 || name_len >= IFNAMSIZ) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_BAD_STRING, NET_INADOR_COMMAND_DHCP_SET_STATUS);
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_BAD_STRING, NET_INADOR_COMMAND_DHCP_CLIENT_FEED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (name_len + 4 < buffer_len) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_DHCP_SET_STATUS);
|
||||
_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
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
wanted = 16 + name_len + buffer[5] + buffer[7] + buffer[8] + buffer[9] + buffer[10] + buffer[11];
|
||||
if (wanted < buffer_len) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_DHCP_CLIENT_FEED);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy (name, &buffer[4], name_len);
|
||||
/* Recuperar el nombre de la interfaz */
|
||||
memcpy (name, &buffer[16], 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);
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_IFACE_INDEX, NET_INADOR_COMMAND_DHCP_CLIENT_FEED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (iface->dhcpc.type != IFACE_ISC_DHCLIENT) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_DHCP_SET_STATUS);
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_DHCP_CLIENT_FEED);
|
||||
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);
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_NOT_EXECUTED, NET_INADOR_COMMAND_DHCP_CLIENT_FEED);
|
||||
return;
|
||||
}
|
||||
|
||||
interfaces_dhcp_client_internal_set_status (manager_client->manager->handle, iface->index, buffer[2]);
|
||||
/* Recuperar el resto de valores, empezando por la IP */
|
||||
if (buffer[5] != 0) {
|
||||
pos = 16 + name_len;
|
||||
memcpy (&ip, &buffer[pos], buffer[5]);
|
||||
} else {
|
||||
memset (&ip, 0, sizeof (ip));
|
||||
}
|
||||
|
||||
/* 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));
|
||||
}
|
||||
|
||||
/* Recuperar el broadcast */
|
||||
if (buffer[8] != 0) {
|
||||
pos = 16 + name_len + buffer[5] + buffer[7];
|
||||
memcpy (&broadcast, &buffer[pos], buffer[8]);
|
||||
} else {
|
||||
memset (&broadcast, 0, sizeof (broadcast));
|
||||
}
|
||||
|
||||
/* Recuperar el servidor DHCP */
|
||||
if (buffer[9] != 0) {
|
||||
pos = 16 + name_len + buffer[5] + buffer[7] + buffer[8];
|
||||
memcpy (&dhcp_server, &buffer[pos], buffer[9]);
|
||||
} else {
|
||||
memset (&dhcp_server, 0, sizeof (dhcp_server));
|
||||
}
|
||||
|
||||
/* Recuperar todos los servidores DNS */
|
||||
g = 0;
|
||||
while (g < 8 && g < (buffer[10] / 4)) {
|
||||
memcpy (&dns[g].v4, &buffer[pos], 4);
|
||||
pos += 4;
|
||||
g++;
|
||||
}
|
||||
|
||||
/* Recuperar el domain name */
|
||||
domain_name[0] = 0;
|
||||
if (buffer[11] != 0) {
|
||||
pos = 16 + name_len + buffer[5] + buffer[7] + buffer[8] + buffer[9] + buffer[10];
|
||||
memcpy (domain_name, &buffer[pos], buffer[11]);
|
||||
domain_name[buffer[11]] = 0;
|
||||
}
|
||||
|
||||
/* Copiar el lease_time */
|
||||
memcpy (&lease_time, &buffer[12], 4);
|
||||
|
||||
/* TODO: Ejecutar aquí validaciones de estado, revisar que la IP existe, que el prefix sea válido, bla, bla, bla */
|
||||
if (family == AF_INET) {
|
||||
prefix = buffer[6];
|
||||
if (prefix > 32) {
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_INVALID_VALUE, NET_INADOR_COMMAND_DHCP_CLIENT_FEED);
|
||||
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);
|
||||
|
||||
/* OK */
|
||||
_manager_send_executed (manager_client);
|
||||
|
@ -796,8 +893,8 @@ 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);
|
||||
case NET_INADOR_COMMAND_DHCP_CLIENT_FEED:
|
||||
_manager_execute_dhcp_client_feed (manager_client, buffer, bytes);
|
||||
break;
|
||||
default:
|
||||
_manager_send_error (manager_client, NET_INADOR_ERROR_WRONG_COMMAND, command);
|
||||
|
|
|
@ -37,7 +37,7 @@ enum {
|
|||
NET_INADOR_COMMAND_SET_EVENT_MASK = 192,
|
||||
|
||||
/* Los siguientes comandos son para uso interno */
|
||||
NET_INADOR_COMMAND_DHCP_SET_STATUS = 224,
|
||||
NET_INADOR_COMMAND_DHCP_CLIENT_FEED = 224,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -67,11 +67,13 @@ enum {
|
|||
};
|
||||
|
||||
enum {
|
||||
NET_INADOR_DHCP_STATUS_INITING = 1,
|
||||
NET_INADOR_DHCP_STATUS_SELECTING,
|
||||
NET_INADOR_DHCP_STATUS_REQUESTING,
|
||||
NET_INADOR_DHCP_STATUS_SELECTING = 1,
|
||||
NET_INADOR_DHCP_STATUS_BOUND,
|
||||
NET_INADOR_DHCP_STATUS_RENEWING
|
||||
NET_INADOR_DHCP_STATUS_RENEWED,
|
||||
|
||||
NET_INADOR_DHCP_STATUS_EXPIRED,
|
||||
NET_INADOR_DHCP_STATUS_FAILED,
|
||||
|
||||
};
|
||||
|
||||
#endif /* __NETWOR_INADOR_MANAGER_H__ */
|
||||
|
|
|
@ -0,0 +1,380 @@
|
|||
/*
|
||||
* 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 <arpa/inet.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;
|
||||
}
|
||||
|
||||
uint32_t utils_ip4_netmask_to_prefix (uint32_t netmask) {
|
||||
uint32_t prefix;
|
||||
uint8_t v;
|
||||
const uint8_t *p = (uint8_t *) &netmask;
|
||||
|
||||
if (p[3]) {
|
||||
prefix = 24;
|
||||
v = p[3];
|
||||
} else if (p[2]) {
|
||||
prefix = 16;
|
||||
v = p[2];
|
||||
} else if (p[1]) {
|
||||
prefix = 8;
|
||||
v = p[1];
|
||||
} else {
|
||||
prefix = 0;
|
||||
v = p[0];
|
||||
}
|
||||
|
||||
while (v) {
|
||||
prefix++;
|
||||
v <<= 1;
|
||||
}
|
||||
|
||||
return prefix;
|
||||
}
|
||||
|
||||
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_CLIENT_FEED;
|
||||
|
||||
buffer[2] = AF_INET;
|
||||
buffer[3] = NET_INADOR_DHCP_STATUS_SELECTING;
|
||||
buffer[4] = strlen (interface);
|
||||
memset (&buffer[5], 0, 11);
|
||||
|
||||
strncpy (&buffer[16], interface, buffer[4]);
|
||||
|
||||
send (s, buffer, 16 + buffer[4], 0);
|
||||
|
||||
if (wait_for_ack_or_error (s) < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
unsigned char buffer[128];
|
||||
struct in_addr empty;
|
||||
int pos;
|
||||
|
||||
memset (&empty, 0, sizeof (empty));
|
||||
|
||||
buffer[0] = NET_INADOR_TYPE_COMMAND;
|
||||
buffer[1] = NET_INADOR_COMMAND_DHCP_CLIENT_FEED;
|
||||
|
||||
buffer[2] = AF_INET;
|
||||
if (is_bound) {
|
||||
buffer[3] = NET_INADOR_DHCP_STATUS_BOUND;
|
||||
} else {
|
||||
buffer[3] = NET_INADOR_DHCP_STATUS_RENEWED;
|
||||
}
|
||||
buffer[4] = strlen (interface);
|
||||
memset (&buffer[5], 0, 11);
|
||||
|
||||
buffer[6] = prefix;
|
||||
|
||||
pos = 16;
|
||||
|
||||
/* Copiar el nombre de la interfaz */
|
||||
strncpy (&buffer[16], interface, buffer[4]);
|
||||
pos = 16 + buffer[4];
|
||||
|
||||
if (memcmp (&empty, ip, sizeof (empty)) != 0) {
|
||||
/* Tenemos una IP */
|
||||
buffer[5] = 4;
|
||||
memcpy (&buffer[pos], ip, 4);
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
if (memcmp (&empty, gateway, sizeof (empty)) != 0) {
|
||||
/* Tenemos una ruta */
|
||||
buffer[7] = 4;
|
||||
memcpy (&buffer[pos], gateway, 4);
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
if (memcmp (&empty, broadcast, sizeof (empty)) != 0) {
|
||||
/* Tenemos broadcast */
|
||||
buffer[8] = 4;
|
||||
memcpy (&buffer[pos], broadcast, 4);
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
if (memcmp (&empty, dhcp_server, sizeof (empty)) != 0) {
|
||||
/* Tenemos IP del servidor DHCP */
|
||||
buffer[9] = 4;
|
||||
memcpy (&buffer[pos], dhcp_server, 4);
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
if (lease_time != 0) {
|
||||
memcpy (&buffer[12], &lease_time, 4);
|
||||
}
|
||||
|
||||
/* TODO: Faltan los DNS */
|
||||
send (s, buffer, pos, 0);
|
||||
|
||||
if (wait_for_ack_or_error (s) < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int parse_ip (char *var, struct in_addr *addr) {
|
||||
int res;
|
||||
|
||||
if (var == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = inet_pton (AF_INET, var, addr);
|
||||
|
||||
if (res <= 0) {
|
||||
memset (addr, 0, sizeof (*addr));
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_int (char *var, int *entero) {
|
||||
int res;
|
||||
|
||||
if (var == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = sscanf (var, "%i", entero);
|
||||
|
||||
if (res <= 0) {
|
||||
*entero = 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
char *reason, *interface;
|
||||
int s, ret;
|
||||
struct sockaddr_un path_dest;
|
||||
struct in_addr ip, netmask, gateway, broadcast, dhcp_server;
|
||||
int prefix, lease_time;
|
||||
|
||||
debug (argc, argv);
|
||||
|
||||
reason = getenv ("reason");
|
||||
|
||||
interface = getenv ("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) {
|
||||
send_preinit (s, interface);
|
||||
} if (strcmp (reason, "FAIL") == 0) {
|
||||
|
||||
} else if (strcmp (reason, "BOUND") == 0 || strcmp (reason, "REBOOT") == 0 ||
|
||||
strcmp (reason, "RENEW") == 0 || strcmp (reason, "REBIND") == 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
|
||||
*/
|
||||
/* Parsear y revisar las direcciones IP recibidas */
|
||||
char *s_ip, *s_mask, *s_gateway, *s_broadcast, *s_lease_time, *s_dhcp_server;
|
||||
s_ip = getenv ("new_ip_address");
|
||||
s_mask = getenv ("new_subnet_mask");
|
||||
s_gateway = getenv ("new_routers");
|
||||
s_broadcast = getenv ("new_broadcast_address");
|
||||
s_lease_time = getenv ("new_dhcp_lease_time");
|
||||
s_dhcp_server = getenv ("new_dhcp_server_identifier");
|
||||
/* TODO: Faltan los DNS */
|
||||
|
||||
if (parse_ip (s_ip, &ip) < 0) {
|
||||
close (s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (parse_ip (s_mask, &netmask) < 0) {
|
||||
close (s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
prefix = utils_ip4_netmask_to_prefix (netmask.s_addr);
|
||||
if (parse_ip (s_gateway, &gateway) < 0) {
|
||||
memset (&gateway, 0, sizeof (gateway));
|
||||
}
|
||||
|
||||
if (parse_ip (s_broadcast, &broadcast) < 0) {
|
||||
memset (&broadcast, 0, sizeof (broadcast));
|
||||
}
|
||||
|
||||
if (parse_ip (s_dhcp_server, &dhcp_server) < 0) {
|
||||
memset (&dhcp_server, 0, sizeof (dhcp_server));
|
||||
}
|
||||
|
||||
if (parse_int (s_lease_time, &lease_time) < 0) {
|
||||
lease_time = 0;
|
||||
}
|
||||
|
||||
int is_bound = 0;
|
||||
if (strcmp (reason, "BOUND") == 0 || strcmp (reason, "REBOOT") == 0) {
|
||||
is_bound = 1;
|
||||
}
|
||||
send_bound_renew (s, is_bound, interface, &ip, prefix, &gateway, &broadcast, &dhcp_server, lease_time);
|
||||
} else if (strcmp (reason, "EXPIRE") == 0 || strcmp (reason, "STOP") == 0 || strcmp (reason, "RELEASE") == 0) {
|
||||
/* Los mismos valores, pero con old_ */
|
||||
} else {
|
||||
|
||||
|
||||
}
|
||||
close (s);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,203 +0,0 @@
|
|||
/*
|
||||
* 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