NetworkInador/src/dhcp_client.c

261 lines
7.5 KiB
C
Raw Normal View History

2021-12-28 23:21:31 -06:00
/*
* 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 <sys/socket.h>
#include <arpa/inet.h>
2021-12-28 23:21:31 -06:00
#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, char *pid_file, size_t pid_file_len) {
snprintf (pid_file, pid_file_len, "/run/dhclient-%s.pid", iface_name);
2021-12-28 23:21:31 -06:00
/* 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-dhcp-helper";
2021-12-28 23:21:31 -06:00
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];
gchar pid_file[256];
2021-12-28 23:21:31 -06:00
/* Preparar los argumentos */
interfaces_dhcp_prepare_args_for_dhclient (argv, 20, iface->name, pid_file, sizeof (pid_file));
2021-12-28 23:21:31 -06:00
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];
gchar pid_file[256];
2021-12-28 23:21:31 -06:00
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, pid_file, sizeof (pid_file));
2021-12-28 23:21:31 -06:00
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_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) {
2021-12-28 23:21:31 -06:00
Interface *iface;
struct in_addr empty_v4;
2021-12-28 23:21:31 -06:00
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_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;
2021-12-28 23:21:31 -06:00
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);
}
2021-12-28 23:21:31 -06:00
}