933 lines
26 KiB
C
933 lines
26 KiB
C
/*
|
|
* ni-interface.c
|
|
* This file is part of NetworkInador
|
|
*
|
|
* Copyright (C) 2021 - Gatuno
|
|
*
|
|
* NetworkInador 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.
|
|
*
|
|
* NetworkInador 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 NetworkInador; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "ni-client.h"
|
|
#include "ni-interface.h"
|
|
#include "ni-ip.h"
|
|
#include "ni-marshal.h"
|
|
|
|
#include "../src/network-inador-manager.h"
|
|
|
|
struct _NIInterfacePrivate {
|
|
NIClient *ni_client;
|
|
|
|
guint index;
|
|
gchar *name;
|
|
guint type;
|
|
|
|
guint master_index;
|
|
guint mtu;
|
|
guint flags;
|
|
|
|
gboolean is_wireless;
|
|
GList *ip_list;
|
|
|
|
/* Información del DHCP */
|
|
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;
|
|
guint dhcp_prefix;
|
|
|
|
/* TODO: Falta procesar la información del DNS */
|
|
};
|
|
|
|
enum {
|
|
PROP_NI_CLIENT = 1,
|
|
|
|
PROP_INDEX,
|
|
PROP_NAME,
|
|
PROP_TYPE,
|
|
|
|
PROP_MASTER_INDEX,
|
|
|
|
PROP_MTU,
|
|
|
|
PROP_FLAGS,
|
|
|
|
PROP_WIRELESS,
|
|
|
|
N_PROPERTIES
|
|
};
|
|
|
|
static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
|
|
|
|
enum {
|
|
NEW_IP,
|
|
|
|
DELETE_IP,
|
|
|
|
ADDED_TO_BRIDGE,
|
|
REMOVED_FROM_BRIDGE,
|
|
|
|
DHCP_TYPE_CHANGED,
|
|
DHCP_STATUS_UPDATED,
|
|
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
static guint signals[LAST_SIGNAL];
|
|
|
|
struct _SearchIP {
|
|
guint family;
|
|
guint prefix;
|
|
|
|
struct_addr local_addr;
|
|
struct_addr addr;
|
|
|
|
gboolean has_local_addr;
|
|
};
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (NIInterface, ni_interface, G_TYPE_OBJECT)
|
|
|
|
static gboolean ni_interface_process_interface_response (NIClient *ni_client, unsigned char *buffer, guint size, gpointer data);
|
|
|
|
#if 0
|
|
static GObject *ni_interface_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) {
|
|
GObject *obj;
|
|
GObjectClass *parent_class = g_type_class_peek (G_TYPE_OBJECT);
|
|
NIInterface *ni_interface;
|
|
|
|
obj = parent_class->constructor (type, n_construct_properties, construct_properties);
|
|
|
|
ni_interface = NI_INTERFACE (obj);
|
|
{
|
|
int g;
|
|
for (g = 0; g < n_construct_properties; g++) {
|
|
GParamSpec *pspec = construct_properties[g].pspec;
|
|
GValue *value = construct_properties[g].value;
|
|
|
|
/* Manejar el valor */
|
|
if (strcmp (g_param_spec_get_name (pspec), "index") == 0) {
|
|
printf ("Estableciendo sobre el constructor, el index\n");
|
|
ni_interface->priv->index = g_value_get_uint (value);
|
|
|
|
ni_interface_check_and_connect_signal (ni_interface);
|
|
} else if (strcmp (g_param_spec_get_name (pspec), "ni-client") == 0) {
|
|
ni_interface->priv->ni_client = NI_CLIENT (g_value_get_object (value));
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
#endif
|
|
|
|
static void ni_interface_constructed (GObject *obj) {
|
|
NIInterface *ni_interface;
|
|
GObjectClass *parent_class = g_type_class_peek (G_TYPE_OBJECT);
|
|
|
|
parent_class->constructed (obj);
|
|
|
|
ni_interface = NI_INTERFACE (obj);
|
|
|
|
if (ni_interface->priv->ni_client != NULL && ni_interface->priv->index != 0) {
|
|
/* Conectar la señal de datos */
|
|
g_signal_connect (ni_interface->priv->ni_client, "packet-read", G_CALLBACK (ni_interface_process_interface_response), ni_interface);
|
|
|
|
/* Solicitar listado de IP's */
|
|
ni_client_ask_ip_interface (ni_interface->priv->ni_client, ni_interface, AF_UNSPEC);
|
|
|
|
/* Solicitar la información del estado del DHCP */
|
|
ni_client_ask_interface_dhcp_status (ni_interface->priv->ni_client, ni_interface);
|
|
}
|
|
}
|
|
|
|
static void ni_interface_dispose (GObject *obj) {
|
|
NIInterface *ni_interface;
|
|
GObjectClass *parent_class = g_type_class_peek (G_TYPE_OBJECT);
|
|
|
|
ni_interface = NI_INTERFACE (obj);
|
|
|
|
g_signal_handlers_disconnect_by_func (ni_interface->priv->ni_client, G_CALLBACK (ni_interface_process_interface_response), ni_interface);
|
|
|
|
parent_class->dispose (obj);
|
|
}
|
|
|
|
static void ni_interface_finalize (GObject *obj) {
|
|
NIInterface *ni_interface;
|
|
GObjectClass *parent_class = g_type_class_peek (G_TYPE_OBJECT);
|
|
|
|
ni_interface = NI_INTERFACE (obj);
|
|
|
|
/* Nada que hacer, por el momento */
|
|
|
|
parent_class->finalize (obj);
|
|
}
|
|
|
|
static void ni_interface_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) {
|
|
NIInterface *ni_interface = NI_INTERFACE (object);
|
|
g_return_if_fail (NI_IS_INTERFACE (object));
|
|
|
|
switch (prop_id) {
|
|
case PROP_NI_CLIENT:
|
|
ni_interface->priv->ni_client = NI_CLIENT (g_value_get_object (value));
|
|
break;
|
|
case PROP_INDEX:
|
|
ni_interface->priv->index = g_value_get_uint (value);
|
|
break;
|
|
case PROP_NAME:
|
|
if (ni_interface->priv->name != NULL) {
|
|
g_free (ni_interface->priv->name);
|
|
}
|
|
ni_interface->priv->name = g_value_dup_string (value);
|
|
break;
|
|
case PROP_TYPE:
|
|
ni_interface->priv->type = g_value_get_uint (value);
|
|
break;
|
|
case PROP_WIRELESS:
|
|
ni_interface->priv->is_wireless = g_value_get_boolean (value);
|
|
break;
|
|
case PROP_MTU:
|
|
ni_interface->priv->mtu = g_value_get_uint (value);
|
|
break;
|
|
case PROP_MASTER_INDEX:
|
|
ni_interface->priv->master_index = g_value_get_uint (value);
|
|
break;
|
|
case PROP_FLAGS:
|
|
ni_interface->priv->flags = g_value_get_uint (value);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
}
|
|
}
|
|
|
|
static void ni_interface_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
|
|
NIInterface *ni_interface = NI_INTERFACE (object);
|
|
g_return_if_fail (NI_IS_INTERFACE (object));
|
|
|
|
switch (prop_id) {
|
|
case PROP_NI_CLIENT:
|
|
g_value_set_object (value, ni_interface->priv->ni_client);
|
|
break;
|
|
case PROP_INDEX:
|
|
g_value_set_uint (value, ni_interface->priv->index);
|
|
break;
|
|
case PROP_NAME:
|
|
g_value_set_string (value, ni_interface->priv->name);
|
|
break;
|
|
case PROP_TYPE:
|
|
g_value_set_uint (value, ni_interface->priv->type);
|
|
break;
|
|
case PROP_WIRELESS:
|
|
g_value_set_boolean (value, ni_interface->priv->is_wireless);
|
|
break;
|
|
case PROP_MTU:
|
|
g_value_set_uint (value, ni_interface->priv->mtu);
|
|
break;
|
|
case PROP_MASTER_INDEX:
|
|
g_value_set_uint (value, ni_interface->priv->master_index);
|
|
break;
|
|
case PROP_FLAGS:
|
|
g_value_set_uint (value, ni_interface->priv->flags);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
}
|
|
}
|
|
|
|
static void ni_interface_class_init (NIInterfaceClass *klass) {
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->set_property = ni_interface_set_property;
|
|
object_class->get_property = ni_interface_get_property;
|
|
object_class->constructed = ni_interface_constructed;
|
|
object_class->dispose = ni_interface_dispose;
|
|
object_class->finalize = ni_interface_finalize;
|
|
|
|
obj_properties[PROP_NI_CLIENT] = g_param_spec_object (
|
|
"ni-client",
|
|
"Network Inador Client",
|
|
"The client object",
|
|
NI_TYPE_CLIENT,
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
|
|
|
obj_properties[PROP_INDEX] = g_param_spec_uint (
|
|
"index",
|
|
"Index",
|
|
"The index of the interface.",
|
|
1, G_MAXUINT, 1,
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
|
|
|
obj_properties[PROP_NAME] = g_param_spec_string (
|
|
"name",
|
|
"Name",
|
|
"Name of the interface",
|
|
NULL,
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
|
|
|
obj_properties[PROP_TYPE] = g_param_spec_uint (
|
|
"type",
|
|
"Interface Type",
|
|
"Type of the interface.",
|
|
0, G_MAXUINT, 1,
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
|
|
|
obj_properties[PROP_MASTER_INDEX] = g_param_spec_uint (
|
|
"master-index",
|
|
"Master index",
|
|
"The index of the master interface",
|
|
0, G_MAXUINT, 0,
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
|
|
|
obj_properties[PROP_MTU] = g_param_spec_uint (
|
|
"mtu",
|
|
"MTU",
|
|
"The mtu of the interface.",
|
|
0, G_MAXUINT, 1500,
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
|
|
|
obj_properties[PROP_FLAGS] = g_param_spec_uint (
|
|
"flags",
|
|
"Flags",
|
|
"The flags of the interface.",
|
|
0, G_MAXUINT, 0,
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
|
|
|
obj_properties[PROP_WIRELESS] = g_param_spec_boolean (
|
|
"wireless",
|
|
"Wireless",
|
|
"Indicates if this interface is wireless",
|
|
FALSE,
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
|
|
|
|
g_object_class_install_properties (object_class, N_PROPERTIES, obj_properties);
|
|
|
|
signals[NEW_IP] = g_signal_new ("new-ip",
|
|
G_TYPE_FROM_CLASS (klass),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
g_cclosure_marshal_VOID__OBJECT,
|
|
G_TYPE_NONE,
|
|
1,
|
|
NI_TYPE_IP);
|
|
|
|
signals[DELETE_IP] = g_signal_new ("delete-ip",
|
|
G_TYPE_FROM_CLASS (klass),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
g_cclosure_marshal_VOID__OBJECT,
|
|
G_TYPE_NONE,
|
|
1,
|
|
NI_TYPE_IP);
|
|
|
|
signals[ADDED_TO_BRIDGE] = g_signal_new ("added-to-bridge",
|
|
G_TYPE_FROM_CLASS (klass),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
g_cclosure_marshal_VOID__UINT,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_UINT);
|
|
|
|
signals[REMOVED_FROM_BRIDGE] = g_signal_new ("removed-from-bridge",
|
|
G_TYPE_FROM_CLASS (klass),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
g_cclosure_marshal_VOID__UINT,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_UINT);
|
|
|
|
signals[DHCP_TYPE_CHANGED] = g_signal_new ("dhcp-type-changed",
|
|
G_TYPE_FROM_CLASS (klass),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
_ni_marshal_VOID__UINT_UINT,
|
|
G_TYPE_NONE,
|
|
2,
|
|
G_TYPE_UINT,
|
|
G_TYPE_UINT);
|
|
|
|
signals[DHCP_STATUS_UPDATED] = g_signal_new ("dhcp-status-updated",
|
|
G_TYPE_FROM_CLASS (klass),
|
|
G_SIGNAL_RUN_LAST,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
g_cclosure_marshal_VOID__VOID,
|
|
G_TYPE_NONE,
|
|
0);
|
|
}
|
|
|
|
static gint ni_interface_locate_ip (gconstpointer *a, gconstpointer *b) {
|
|
NIIP *ni_ip = (NIIP *) a;
|
|
struct _SearchIP *search_ip = (struct _SearchIP *) b;
|
|
int family_size = 0;
|
|
|
|
if (ni_ip_get_family (ni_ip) != search_ip->family) return -1;
|
|
|
|
if (search_ip->family == AF_INET) {
|
|
family_size = sizeof (struct in_addr);
|
|
} else if (search_ip->family == AF_INET6) {
|
|
family_size = sizeof (struct in6_addr);
|
|
}
|
|
|
|
if (ni_ip_get_prefix (ni_ip) != search_ip->prefix) return -1;
|
|
|
|
if (memcmp (ni_ip_get_addr (ni_ip), &search_ip->addr, family_size) != 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (ni_ip_has_local (ni_ip) != search_ip->has_local_addr) {
|
|
return -1;
|
|
}
|
|
|
|
if (search_ip->has_local_addr) {
|
|
if (memcmp (ni_ip_get_local_addr (ni_ip), &search_ip->local_addr, family_size) != 0) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void ni_interface_process_interface_update (NIInterface *ni_interface, gpointer data, guint size) {
|
|
unsigned char *buffer = (unsigned char *) data;
|
|
|
|
uint32_t master_index, mtu, previous_m_index;
|
|
uint16_t flags;
|
|
guint name_size;
|
|
char iface_name[128];
|
|
|
|
memcpy (&master_index, &buffer[10], 4);
|
|
memcpy (&mtu, &buffer[14], 4);
|
|
memcpy (&flags, &buffer[18], 2);
|
|
|
|
name_size = buffer[21];
|
|
memcpy (iface_name, &buffer[22], name_size);
|
|
iface_name[name_size] = 0;
|
|
|
|
g_object_freeze_notify (G_OBJECT (ni_interface));
|
|
if (ni_interface->priv->name == NULL) {
|
|
ni_interface->priv->name = g_strdup (iface_name);
|
|
g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_NAME]);
|
|
} else if (strcmp (ni_interface->priv->name, iface_name) != 0) {
|
|
g_free (ni_interface->priv->name);
|
|
|
|
ni_interface->priv->name = g_strdup (iface_name);
|
|
g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_NAME]);
|
|
}
|
|
|
|
if (ni_interface->priv->master_index != master_index) {
|
|
previous_m_index = ni_interface->priv->master_index;
|
|
ni_interface->priv->master_index = master_index;
|
|
g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_MASTER_INDEX]);
|
|
if (previous_m_index == 0) {
|
|
g_signal_emit (ni_interface, signals[ADDED_TO_BRIDGE], 0, master_index);
|
|
} else {
|
|
g_signal_emit (ni_interface, signals[REMOVED_FROM_BRIDGE], 0, previous_m_index);
|
|
}
|
|
}
|
|
|
|
if (ni_interface->priv->mtu != mtu) {
|
|
ni_interface->priv->mtu = mtu;
|
|
g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_MASTER_INDEX]);
|
|
}
|
|
|
|
if (ni_interface->priv->flags != flags) {
|
|
ni_interface->priv->flags = flags;
|
|
g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_FLAGS]);
|
|
}
|
|
|
|
g_object_thaw_notify (G_OBJECT (ni_interface));
|
|
}
|
|
|
|
static void ni_interface_process_ip_added (NIInterface *ni_interface, gpointer data, guint size) {
|
|
unsigned char *buffer = (unsigned char *) data;
|
|
uint32_t index, flags;
|
|
guint family, prefix, bits, scope, pos;
|
|
guint32 cacheinfo[4];
|
|
char label[256];
|
|
gint family_size = 0;
|
|
gint label_len;
|
|
gboolean has_local_addr = FALSE, has_brd_addr = FALSE;
|
|
NIIP *ni_ip;
|
|
struct_addr addr, local_addr, brd_addr;
|
|
GList *g;
|
|
|
|
family = buffer[6];
|
|
prefix = buffer[7];
|
|
bits = buffer[8];
|
|
scope = buffer[9];
|
|
|
|
if (bits & 0x01) has_local_addr = TRUE;
|
|
if (bits & 0x02) has_brd_addr = TRUE;
|
|
memcpy (&flags, &buffer[10], 4);
|
|
|
|
if (family == AF_INET) {
|
|
family_size = sizeof (struct in_addr);
|
|
} else if (family == AF_INET6) {
|
|
family_size = sizeof (struct in6_addr);
|
|
}
|
|
|
|
/* Copiar los timestamp */
|
|
memcpy (cacheinfo, &buffer[14], 16);
|
|
|
|
memcpy (&addr, &buffer[30], family_size);
|
|
|
|
pos = 30 + family_size;
|
|
if (has_local_addr) {
|
|
memcpy (&local_addr, &buffer[pos], family_size);
|
|
pos += family_size;
|
|
}
|
|
|
|
if (has_brd_addr) {
|
|
memcpy (&brd_addr, &buffer[pos], family_size);
|
|
pos += family_size;
|
|
}
|
|
|
|
/* Leer la label, si es que existe */
|
|
label[0] = 0;
|
|
label_len = buffer[pos];
|
|
pos++;
|
|
|
|
if (label_len > 0) {
|
|
memcpy (label, &buffer[pos], label_len);
|
|
label[label_len] = 0;
|
|
}
|
|
|
|
ni_ip = ni_ip_new (ni_interface, family, prefix, &addr, flags, scope, has_local_addr, (has_local_addr ? &local_addr : NULL), has_brd_addr, (has_brd_addr ? &brd_addr : NULL), cacheinfo, (label_len != 0) ? label : NULL);
|
|
|
|
ni_interface->priv->ip_list = g_list_append (ni_interface->priv->ip_list, ni_ip);
|
|
|
|
g_signal_emit (ni_interface, signals[NEW_IP], 0, ni_ip);
|
|
}
|
|
|
|
static void ni_interface_process_ip_removed (NIInterface *ni_interface, gpointer data, guint size) {
|
|
unsigned char *buffer = (unsigned char *) data;
|
|
struct _SearchIP search_ip;
|
|
gint family_size = 0;
|
|
guint bits, pos;
|
|
GList *g;
|
|
NIIP *ni_ip;
|
|
|
|
search_ip.family = buffer[6];
|
|
search_ip.prefix = buffer[7];
|
|
bits = buffer[8];
|
|
|
|
if (bits & 0x01) search_ip.has_local_addr = TRUE;
|
|
|
|
if (search_ip.family == AF_INET) {
|
|
family_size = sizeof (struct in_addr);
|
|
} else if (search_ip.family == AF_INET6) {
|
|
family_size = sizeof (struct in6_addr);
|
|
}
|
|
|
|
memcpy (&search_ip.addr, &buffer[10], family_size);
|
|
|
|
pos = 10 + family_size;
|
|
if (search_ip.has_local_addr) {
|
|
memcpy (&search_ip.local_addr, &buffer[pos], family_size);
|
|
pos += family_size;
|
|
}
|
|
|
|
/* Localizar la IP y eliminarla */
|
|
g = g_list_find_custom (ni_interface->priv->ip_list, &search_ip, (GCompareFunc) ni_interface_locate_ip);
|
|
|
|
if (g == NULL) {
|
|
/* ¿IP eliminada sin que exista? Super error */
|
|
} else {
|
|
ni_ip = (NIIP *) g->data;
|
|
ni_interface->priv->ip_list = g_list_remove (ni_interface->priv->ip_list, g->data);
|
|
|
|
/* Ahora, ya desligado, emitir la señal */
|
|
g_signal_emit (ni_interface, signals[DELETE_IP], 0, ni_ip);
|
|
|
|
g_object_unref (ni_ip);
|
|
}
|
|
}
|
|
|
|
static void ni_interface_process_dhcp_status (NIInterface *ni_interface, gpointer data, guint size) {
|
|
unsigned char *buffer = (unsigned char *) data;
|
|
gint family_size = 0;
|
|
guint bits, pos;
|
|
int old_type;
|
|
|
|
if (buffer[6] != AF_INET) {
|
|
return;
|
|
}
|
|
|
|
old_type = ni_interface->priv->dhcp_type;
|
|
|
|
family_size = sizeof (struct in_addr);
|
|
|
|
ni_interface->priv->dhcp_type = buffer[7];
|
|
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) {
|
|
/* Hay una IP broadcast de DHCP */
|
|
ni_interface->priv->has_dhcp_broadcast = TRUE;
|
|
}
|
|
|
|
ni_interface->priv->has_dhcp_server = FALSE;
|
|
if (buffer[10] & 0x04) {
|
|
/* Hay un servidor DHCP */
|
|
ni_interface->priv->has_dhcp_server = TRUE;
|
|
}
|
|
|
|
/* TODO: Procesar aquí la información de DNS */
|
|
|
|
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);
|
|
pos += family_size;
|
|
}
|
|
|
|
if (ni_interface->priv->has_dhcp_broadcast) {
|
|
memcpy (&ni_interface->priv->dhcp_broadcast, &buffer[pos], family_size);
|
|
pos += family_size;
|
|
}
|
|
|
|
if (ni_interface->priv->has_dhcp_server) {
|
|
memcpy (&ni_interface->priv->dhcp_server, &buffer[pos], family_size);
|
|
pos += family_size;
|
|
}
|
|
|
|
/* TODO: Procesar la información de los DNS */
|
|
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);
|
|
ni_interface->priv->dhcp_type_first_time = FALSE;
|
|
} else {
|
|
g_signal_emit (ni_interface, signals[DHCP_STATUS_UPDATED], 0);
|
|
}
|
|
}
|
|
|
|
static gboolean ni_interface_process_interface_response (NIClient *ni_client, unsigned char *buffer, guint size, gpointer user_data) {
|
|
NIInterface *ni_interface = (NIInterface *) user_data;
|
|
uint32_t index;
|
|
|
|
if (buffer[0] == NET_INADOR_TYPE_EVENT) {
|
|
switch (buffer[1]) {
|
|
case NET_INADOR_EVENT_IPADDR_ADDED:
|
|
memcpy (&index, &buffer[2], 4);
|
|
|
|
if (index != ni_interface->priv->index) {
|
|
/* Mensaje de IP, pero no para mí, dejar pasar */
|
|
return FALSE;
|
|
}
|
|
|
|
ni_interface_process_ip_added (ni_interface, buffer, size);
|
|
|
|
return TRUE;
|
|
break;
|
|
case NET_INADOR_EVENT_IFACE_ADDED:
|
|
/* Mensaje de actualización de mi estado */
|
|
memcpy (&index, &buffer[2], 4);
|
|
|
|
if (index != ni_interface->priv->index) {
|
|
/* Mensaje de la interfaz, pero no para mí, dejar pasar */
|
|
return FALSE;
|
|
}
|
|
|
|
ni_interface_process_interface_update (ni_interface, buffer, size);
|
|
return TRUE;
|
|
break;
|
|
case NET_INADOR_EVENT_IPADDR_REMOVED:
|
|
memcpy (&index, &buffer[2], 4);
|
|
|
|
if (index != ni_interface->priv->index) {
|
|
/* Mensaje de la interfaz, pero no para mí, dejar pasar */
|
|
return FALSE;
|
|
}
|
|
ni_interface_process_ip_removed (ni_interface, buffer, size);
|
|
return TRUE;
|
|
break;
|
|
case NET_INADOR_EVENT_DHCP_STATUS:
|
|
memcpy (&index, &buffer[2], 4);
|
|
|
|
if (index != ni_interface->priv->index) {
|
|
/* Mensaje de la interfaz, pero no para mí, dejar pasar */
|
|
return FALSE;
|
|
}
|
|
|
|
ni_interface_process_dhcp_status (ni_interface, buffer, size);
|
|
return TRUE;
|
|
break;
|
|
}
|
|
} else if (buffer[0] == NET_INADOR_TYPE_RESPONSE) {
|
|
switch (buffer[1]) {
|
|
case NET_INADOR_RESPONSE_IPADDR:
|
|
memcpy (&index, &buffer[2], 4);
|
|
|
|
if (index != ni_interface->priv->index) {
|
|
/* Mensaje de IP, pero no para mí, dejar pasar */
|
|
return FALSE;
|
|
}
|
|
ni_interface_process_ip_added (ni_interface, buffer, size);
|
|
|
|
return TRUE;
|
|
break;
|
|
case NET_INADOR_RESPONSE_IFACE:
|
|
memcpy (&index, &buffer[2], 4);
|
|
|
|
if (index != ni_interface->priv->index) {
|
|
/* Mensaje de la interfaz, pero no para mí, dejar pasar */
|
|
return FALSE;
|
|
}
|
|
|
|
ni_interface_process_interface_update (ni_interface, buffer, size);
|
|
return TRUE;
|
|
break;
|
|
case NET_INADOR_RESPONSE_DHCP_STATUS:
|
|
memcpy (&index, &buffer[2], 4);
|
|
|
|
if (index != ni_interface->priv->index) {
|
|
/* Mensaje de la interfaz, pero no para mí, dejar pasar */
|
|
return FALSE;
|
|
}
|
|
|
|
ni_interface_process_dhcp_status (ni_interface, buffer, size);
|
|
return TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE; /* Que se siga procesando */
|
|
}
|
|
|
|
guint ni_interface_get_index (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0);
|
|
return ni_interface->priv->index;
|
|
}
|
|
|
|
void ni_interface_set_name (NIInterface *ni_interface, const gchar *name) {
|
|
g_return_if_fail (NI_IS_INTERFACE (ni_interface));
|
|
|
|
/* Enviar la petición al ni_client */
|
|
ni_client_ask_change_iface_name (ni_interface->priv->ni_client, ni_interface, name);
|
|
}
|
|
|
|
const gchar *ni_interface_get_name (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), NULL);
|
|
return ni_interface->priv->name;
|
|
}
|
|
|
|
guint ni_interface_get_iface_type (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0);
|
|
return ni_interface->priv->type;
|
|
}
|
|
|
|
gboolean ni_interface_is_wireless (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), FALSE);
|
|
return ni_interface->priv->is_wireless;
|
|
}
|
|
|
|
NIClient *ni_interface_get_client (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), NULL);
|
|
return ni_interface->priv->ni_client;
|
|
}
|
|
|
|
const GList *ni_interface_get_ip_list (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), NULL);
|
|
return ni_interface->priv->ip_list;
|
|
}
|
|
|
|
guint ni_interface_get_flags (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0);
|
|
|
|
return ni_interface->priv->flags;
|
|
}
|
|
|
|
void ni_interface_set_mtu (NIInterface *ni_interface, guint mtu) {
|
|
g_return_if_fail (NI_IS_INTERFACE (ni_interface));
|
|
|
|
/* Enviar la petición al ni_client */
|
|
ni_client_ask_change_iface_mtu (ni_interface->priv->ni_client, ni_interface, mtu);
|
|
}
|
|
|
|
guint ni_interface_get_mtu (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0);
|
|
return ni_interface->priv->mtu;
|
|
}
|
|
|
|
guint ni_interface_get_master (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0);
|
|
return ni_interface->priv->master_index;
|
|
}
|
|
|
|
void ni_interface_clear_master (NIInterface *ni_interface) {
|
|
g_return_if_fail (NI_IS_INTERFACE (ni_interface));
|
|
|
|
if (ni_interface->priv->master_index == 0) return;
|
|
ni_client_ask_interface_clear_master (ni_interface->priv->ni_client, ni_interface);
|
|
}
|
|
|
|
void ni_interface_set_master (NIInterface *ni_interface, NIInterface *master) {
|
|
g_return_if_fail (NI_IS_INTERFACE (ni_interface));
|
|
g_return_if_fail (NI_IS_INTERFACE (master));
|
|
|
|
if (ni_interface->priv->master_index != 0) return;
|
|
ni_client_ask_interface_set_master (ni_interface->priv->ni_client, ni_interface, master);
|
|
}
|
|
|
|
void ni_interface_set_down (NIInterface *ni_interface) {
|
|
g_return_if_fail (NI_IS_INTERFACE (ni_interface));
|
|
|
|
ni_client_ask_up_down_interface (ni_interface->priv->ni_client, ni_interface, FALSE);
|
|
}
|
|
|
|
void ni_interface_set_up (NIInterface *ni_interface) {
|
|
g_return_if_fail (NI_IS_INTERFACE (ni_interface));
|
|
|
|
ni_client_ask_up_down_interface (ni_interface->priv->ni_client, ni_interface, TRUE);
|
|
}
|
|
|
|
void ni_interface_run_dhcp (NIInterface *ni_interface, int type) {
|
|
g_return_if_fail (NI_IS_INTERFACE (ni_interface));
|
|
|
|
ni_client_ask_dhcp_run_interface (ni_interface->priv->ni_client, ni_interface, type);
|
|
}
|
|
|
|
void ni_interface_stop_dhcp (NIInterface *ni_interface) {
|
|
g_return_if_fail (NI_IS_INTERFACE (ni_interface));
|
|
|
|
ni_client_ask_dhcp_stop_interface (ni_interface->priv->ni_client, ni_interface);
|
|
}
|
|
|
|
guint ni_interface_get_dhcp_type (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0);
|
|
|
|
return ni_interface->priv->dhcp_type;
|
|
}
|
|
|
|
guint ni_interface_get_dhcp_status (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0);
|
|
|
|
return ni_interface->priv->dhcp_status;
|
|
}
|
|
|
|
guint ni_interface_get_dhcp_lease_time (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0);
|
|
|
|
return ni_interface->priv->dhcp_lease_time;
|
|
}
|
|
|
|
guint ni_interface_get_dhcp_prefix (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0);
|
|
|
|
return ni_interface->priv->dhcp_prefix;
|
|
}
|
|
|
|
const struct_addr * ni_interface_get_dhcp_addr (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), NULL);
|
|
|
|
return &ni_interface->priv->dhcp_addr;
|
|
}
|
|
|
|
gboolean ni_interface_has_dhcp_brd_addr (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), FALSE);
|
|
|
|
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);
|
|
|
|
return ni_interface->priv->has_dhcp_gw;
|
|
}
|
|
|
|
gboolean ni_interface_has_dhcp_server_addr (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), FALSE);
|
|
|
|
return ni_interface->priv->has_dhcp_server;
|
|
}
|
|
|
|
const struct_addr * ni_interface_get_dhcp_brd_addr (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), NULL);
|
|
|
|
return &ni_interface->priv->dhcp_broadcast;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
const struct_addr * ni_interface_get_dhcp_server_addr (NIInterface *ni_interface) {
|
|
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), NULL);
|
|
|
|
return &ni_interface->priv->dhcp_server;
|
|
}
|
|
|
|
static void ni_interface_init (NIInterface *ni_interface) {
|
|
NIInterfacePrivate *priv = ni_interface_get_instance_private (ni_interface);
|
|
ni_interface->priv = priv;
|
|
|
|
/* initialize all public and private members to reasonable default values.
|
|
* They are all automatically initialized to 0 to begin with. */
|
|
priv->ni_client = NULL;
|
|
priv->index = 0;
|
|
priv->name = NULL;
|
|
priv->type = 0;
|
|
priv->is_wireless = FALSE;
|
|
priv->master_index = 0;
|
|
priv->mtu = 0;
|
|
priv->flags = 0;
|
|
priv->ip_list = NULL;
|
|
|
|
priv->dhcp_type_first_time = TRUE;
|
|
priv->dhcp_type = 0;
|
|
priv->dhcp_status = 0;
|
|
priv->dhcp_lease_time = 0;
|
|
priv->has_dhcp_broadcast = FALSE;
|
|
priv->has_dhcp_gw = FALSE;
|
|
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;
|
|
}
|
|
|