Agrego eventos del estado del DHCP

master
Félix Arreola Rodríguez 2022-01-02 23:07:39 -06:00
parent 072b89bd62
commit 0ff00a8b9c
11 changed files with 550 additions and 54 deletions

View File

@ -230,6 +230,19 @@ static gboolean ni_client_data_read (NIClient *ni_client, gpointer data, guint s
} }
return TRUE; return TRUE;
break; break;
case NET_INADOR_EVENT_DHCP_STATUS:
memcpy (&index, &buffer[2], 4);
/* Si la interfaz no existe, proccesarla yo, para que se cree el objeto, si la interfaz ya existe, dejar pasar el mensaje */
ni_interface = (NIInterface *) g_hash_table_lookup (ni_client->priv->interfaces, GINT_TO_POINTER(index));
if (ni_interface == NULL) {
/* Esta es una condición de error interesante. No debería ocurrir. Absorber el evento */
return TRUE;
}
/* Dejar pasar el evento para que la propia interfaz lo procese */
return FALSE;
break;
} }
} else if (buffer[0] == NET_INADOR_TYPE_RESPONSE) { } else if (buffer[0] == NET_INADOR_TYPE_RESPONSE) {
switch (buffer[1]) { switch (buffer[1]) {
@ -246,6 +259,19 @@ static gboolean ni_client_data_read (NIClient *ni_client, gpointer data, guint s
return FALSE; return FALSE;
} }
break; break;
case NET_INADOR_RESPONSE_DHCP_STATUS:
memcpy (&index, &buffer[2], 4);
/* Si la interfaz no existe, proccesarla yo, para que se cree el objeto, si la interfaz ya existe, dejar pasar el mensaje */
ni_interface = (NIInterface *) g_hash_table_lookup (ni_client->priv->interfaces, GINT_TO_POINTER(index));
if (ni_interface == NULL) {
/* Esta es una condición de error interesante. No debería ocurrir. Absorber el evento */
return TRUE;
}
/* Dejar pasar el evento para que la propia interfaz lo procese */
return FALSE;
break;
} }
} }
@ -349,7 +375,7 @@ static void ni_client_init (NIClient *ni_client) {
priv->client_socket = -1; priv->client_socket = -1;
priv->socket_path = NULL; priv->socket_path = NULL;
priv->source = 0; priv->source = 0;
priv->events = NET_INADOR_EVENT_MASK_INTERFACES | NET_INADOR_EVENT_MASK_IP; priv->events = NET_INADOR_EVENT_MASK_INTERFACES | NET_INADOR_EVENT_MASK_IP | NET_INADOR_EVENT_MASK_DHCP_STATUS;
priv->interfaces = g_hash_table_new (g_direct_hash, g_direct_equal); priv->interfaces = g_hash_table_new (g_direct_hash, g_direct_equal);
} }
@ -554,6 +580,49 @@ void ni_client_ask_up_down_interface (NIClient *ni_client, NIInterface *ni_inter
send (ni_client->priv->client_socket, buffer, 6, 0); send (ni_client->priv->client_socket, buffer, 6, 0);
} }
void ni_client_ask_dhcp_run_interface (NIClient *ni_client, NIInterface *ni_interface, int type) {
unsigned char buffer[16];
uint32_t index;
uint32_t flags = 0x1;
if (ni_client->priv->client_socket < 0) {
return;
}
if (type < 1 || type > 2) {
/* Solo se permite tipo 1 o tipo 2 */
return;
}
index = ni_interface_get_index (ni_interface);
buffer[0] = NET_INADOR_TYPE_COMMAND;
buffer[1] = NET_INADOR_COMMAND_RUN_DHCP;
memcpy (&buffer[2], &index, 4);
buffer[6] = AF_INET;
buffer[7] = type;
memcpy (&buffer[8], &flags, 4);
send (ni_client->priv->client_socket, buffer, 12, 0);
}
void ni_client_ask_dhcp_stop_interface (NIClient *ni_client, NIInterface *ni_interface) {
unsigned char buffer[8];
uint32_t index;
if (ni_client->priv->client_socket < 0) {
return;
}
index = ni_interface_get_index (ni_interface);
buffer[0] = NET_INADOR_TYPE_COMMAND;
buffer[1] = NET_INADOR_COMMAND_STOP_DHCP;
memcpy (&buffer[2], &index, 4);
buffer[6] = AF_INET;
send (ni_client->priv->client_socket, buffer, 7, 0);
}
void ni_client_ask_create_bridge (NIClient *ni_client, const gchar *name) { void ni_client_ask_create_bridge (NIClient *ni_client, const gchar *name) {
unsigned char buffer[128]; unsigned char buffer[128];
int n_len; int n_len;
@ -607,6 +676,23 @@ void ni_client_ask_interface_set_master (NIClient *ni_client, NIInterface *ni_in
send (ni_client->priv->client_socket, buffer, 10, 0); send (ni_client->priv->client_socket, buffer, 10, 0);
} }
void ni_client_ask_interface_dhcp_status (NIClient *ni_client, NIInterface *ni_interface) {
unsigned char buffer[8];
uint32_t index;
if (ni_client->priv->client_socket < 0) {
return;
}
index = ni_interface_get_index (ni_interface);
buffer[0] = NET_INADOR_TYPE_COMMAND;
buffer[1] = NET_INADOR_COMMAND_GET_DHCP_STATUS;
memcpy (&buffer[2], &index, 4);
buffer[6] = AF_INET;
send (ni_client->priv->client_socket, buffer, 7, 0);
}
static void ni_client_foreach_has_table (gpointer key, gpointer value, gpointer data) { static void ni_client_foreach_has_table (gpointer key, gpointer value, gpointer data) {
GList **lista = (GList **) data; GList **lista = (GList **) data;

View File

@ -77,7 +77,6 @@ NIClient *ni_client_new (void);
NIClient *ni_client_new_with_path (const char *path); NIClient *ni_client_new_with_path (const char *path);
gboolean ni_client_connect (NIClient *ni_client); gboolean ni_client_connect (NIClient *ni_client);
void ni_client_ask_ip_interface (NIClient *ni_client, NIInterface *ni_interface, int family); void ni_client_ask_ip_interface (NIClient *ni_client, NIInterface *ni_interface, int family);
void ni_client_ask_ips (NIClient *ni_client, NIInterface *ni_interface);
void ni_client_ask_ip_new (NIClient *ni_client, NIInterface *ni_interface, int family, int prefix, struct_addr *addr, uint32_t flags, unsigned char scope, int has_local, struct_addr *local_addr, int has_brd, struct_addr *brd_addr, uint32_t *cacheinfo); void ni_client_ask_ip_new (NIClient *ni_client, NIInterface *ni_interface, int family, int prefix, struct_addr *addr, uint32_t flags, unsigned char scope, int has_local, struct_addr *local_addr, int has_brd, struct_addr *brd_addr, uint32_t *cacheinfo);
void ni_client_ask_ip_delete (NIClient *ni_client, NIInterface *ni_interface, NIIP *ni_ip); void ni_client_ask_ip_delete (NIClient *ni_client, NIInterface *ni_interface, NIIP *ni_ip);
void ni_client_ask_change_iface_name (NIClient *ni_client, NIInterface *ni_interface, const gchar *new_name); void ni_client_ask_change_iface_name (NIClient *ni_client, NIInterface *ni_interface, const gchar *new_name);
@ -90,6 +89,11 @@ NIInterface *ni_client_get_interface_by_index (NIClient *ni_client, guint index)
void ni_client_ask_interface_clear_master (NIClient *ni_client, NIInterface *ni_interface); void ni_client_ask_interface_clear_master (NIClient *ni_client, NIInterface *ni_interface);
void ni_client_ask_interface_set_master (NIClient *ni_client, NIInterface *ni_interface, NIInterface *master); void ni_client_ask_interface_set_master (NIClient *ni_client, NIInterface *ni_interface, NIInterface *master);
void ni_client_ask_dhcp_stop_interface (NIClient *ni_client, NIInterface *ni_interface);
void ni_client_ask_dhcp_run_interface (NIClient *ni_client, NIInterface *ni_interface, int type);
void ni_client_ask_interface_dhcp_status (NIClient *ni_client, NIInterface *ni_interface);
G_END_DECLS G_END_DECLS
#endif /* __NI_CLIENT_H__ */ #endif /* __NI_CLIENT_H__ */

View File

@ -27,6 +27,7 @@
#include "ni-client.h" #include "ni-client.h"
#include "ni-interface.h" #include "ni-interface.h"
#include "ni-ip.h" #include "ni-ip.h"
#include "ni-marshal.h"
#include "../src/network-inador-manager.h" #include "../src/network-inador-manager.h"
@ -43,6 +44,16 @@ struct _NIInterfacePrivate {
gboolean is_wireless; gboolean is_wireless;
GList *ip_list; 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 { enum {
@ -73,6 +84,9 @@ enum {
ADDED_TO_BRIDGE, ADDED_TO_BRIDGE,
REMOVED_FROM_BRIDGE, REMOVED_FROM_BRIDGE,
DHCP_TYPE_CHANGED,
DHCP_STATUS_UPDATED,
LAST_SIGNAL LAST_SIGNAL
}; };
@ -138,6 +152,9 @@ static void ni_interface_constructed (GObject *obj) {
/* Solicitar listado de IP's */ /* Solicitar listado de IP's */
ni_client_ask_ip_interface (ni_interface->priv->ni_client, ni_interface, AF_UNSPEC); 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);
} }
} }
@ -344,6 +361,28 @@ static void ni_interface_class_init (NIInterfaceClass *klass) {
G_TYPE_NONE, G_TYPE_NONE,
1, 1,
G_TYPE_UINT); 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) { static gint ni_interface_locate_ip (gconstpointer *a, gconstpointer *b) {
@ -487,7 +526,6 @@ static void ni_interface_process_ip_added (NIInterface *ni_interface, gpointer d
ni_interface->priv->ip_list = g_list_append (ni_interface->priv->ip_list, ni_ip); ni_interface->priv->ip_list = g_list_append (ni_interface->priv->ip_list, ni_ip);
printf ("Emitiendo signal de IP-addr\n");
g_signal_emit (ni_interface, signals[NEW_IP], 0, ni_ip); g_signal_emit (ni_interface, signals[NEW_IP], 0, ni_ip);
} }
@ -535,6 +573,74 @@ static void ni_interface_process_ip_removed (NIInterface *ni_interface, gpointer
} }
} }
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) { static gboolean ni_interface_process_interface_response (NIClient *ni_client, unsigned char *buffer, guint size, gpointer user_data) {
NIInterface *ni_interface = (NIInterface *) user_data; NIInterface *ni_interface = (NIInterface *) user_data;
uint32_t index; uint32_t index;
@ -575,6 +681,17 @@ static gboolean ni_interface_process_interface_response (NIClient *ni_client, un
ni_interface_process_ip_removed (ni_interface, buffer, size); ni_interface_process_ip_removed (ni_interface, buffer, size);
return TRUE; return TRUE;
break; 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) { } else if (buffer[0] == NET_INADOR_TYPE_RESPONSE) {
switch (buffer[1]) { switch (buffer[1]) {
@ -585,7 +702,6 @@ static gboolean ni_interface_process_interface_response (NIClient *ni_client, un
/* Mensaje de IP, pero no para mí, dejar pasar */ /* Mensaje de IP, pero no para mí, dejar pasar */
return FALSE; return FALSE;
} }
printf ("Response IP addr sobre interfaz\n");
ni_interface_process_ip_added (ni_interface, buffer, size); ni_interface_process_ip_added (ni_interface, buffer, size);
return TRUE; return TRUE;
@ -601,6 +717,17 @@ static gboolean ni_interface_process_interface_response (NIClient *ni_client, un
ni_interface_process_interface_update (ni_interface, buffer, size); ni_interface_process_interface_update (ni_interface, buffer, size);
return TRUE; return TRUE;
break; 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;
} }
} }
@ -694,44 +821,83 @@ void ni_interface_set_up (NIInterface *ni_interface) {
ni_client_ask_up_down_interface (ni_interface->priv->ni_client, ni_interface, TRUE); ni_client_ask_up_down_interface (ni_interface->priv->ni_client, ni_interface, TRUE);
} }
#if 0 void ni_interface_run_dhcp (NIInterface *ni_interface, int type) {
void ni_interface_consume_values (NIInterface *ni_interface, char *name, gint arp_type, guint master_index, guint mtu, guint flags) { g_return_if_fail (NI_IS_INTERFACE (ni_interface));
g_object_freeze_notify (G_OBJECT (ni_interface));
if (ni_interface->priv->name == NULL) { ni_client_ask_dhcp_run_interface (ni_interface->priv->ni_client, ni_interface, type);
ni_interface->priv->name = g_strdup (name); }
g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_NAME]);
} else if (strcmp (ni_interface->priv->name, name) != 0) { void ni_interface_stop_dhcp (NIInterface *ni_interface) {
g_free (ni_interface->priv->name); g_return_if_fail (NI_IS_INTERFACE (ni_interface));
ni_interface->priv->name = g_strdup (name); ni_client_ask_dhcp_stop_interface (ni_interface->priv->ni_client, ni_interface);
g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_NAME]); }
}
guint ni_interface_get_dhcp_type (NIInterface *ni_interface) {
g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0);
if (ni_interface->priv->arp_type != arp_type) {
ni_interface->priv->arp_type = arp_type; return ni_interface->priv->dhcp_type;
g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_ARP_TYPE]); }
}
guint ni_interface_get_dhcp_status (NIInterface *ni_interface) {
if (ni_interface->priv->master_index != master_index) { g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0);
ni_interface->priv->master_index = master_index;
g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_MASTER_INDEX]); return ni_interface->priv->dhcp_status;
} }
if (ni_interface->priv->mtu != mtu) { guint ni_interface_get_dhcp_lease_time (NIInterface *ni_interface) {
ni_interface->priv->master_index = master_index; g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0);
g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_MASTER_INDEX]);
} return ni_interface->priv->dhcp_lease_time;
}
if (ni_interface->priv->flags != flags) {
ni_interface->priv->flags = flags; guint ni_interface_get_dhcp_prefix (NIInterface *ni_interface) {
g_object_notify_by_pspec (G_OBJECT (ni_interface), obj_properties[PROP_FLAGS]); g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), 0);
}
return ni_interface->priv->dhcp_prefix;
g_object_thaw_notify (G_OBJECT (ni_interface)); }
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;
} }
#endif
static void ni_interface_init (NIInterface *ni_interface) { static void ni_interface_init (NIInterface *ni_interface) {
NIInterfacePrivate *priv = ni_interface_get_instance_private (ni_interface); NIInterfacePrivate *priv = ni_interface_get_instance_private (ni_interface);
@ -748,5 +914,19 @@ static void ni_interface_init (NIInterface *ni_interface) {
priv->mtu = 0; priv->mtu = 0;
priv->flags = 0; priv->flags = 0;
priv->ip_list = NULL; 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;
} }

View File

@ -30,6 +30,8 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include "ni-ip.h"
G_BEGIN_DECLS G_BEGIN_DECLS
typedef struct _NIInterfaceClass NIInterfaceClass; typedef struct _NIInterfaceClass NIInterfaceClass;
@ -77,6 +79,20 @@ const GList *ni_interface_get_ip_list (NIInterface *ni_interface);
guint ni_interface_get_flags (NIInterface *ni_interface); guint ni_interface_get_flags (NIInterface *ni_interface);
void ni_interface_set_down (NIInterface *ni_interface); void ni_interface_set_down (NIInterface *ni_interface);
void ni_interface_set_up (NIInterface *ni_interface); void ni_interface_set_up (NIInterface *ni_interface);
void ni_interface_run_dhcp (NIInterface *ni_interface, int type);
void ni_interface_stop_dhcp (NIInterface *ni_interface);
guint ni_interface_get_dhcp_type (NIInterface *ni_interface);
guint ni_interface_get_dhcp_status (NIInterface *ni_interface);
guint ni_interface_get_dhcp_lease_time (NIInterface *ni_interface);
guint ni_interface_get_dhcp_prefix (NIInterface *ni_interface);
const struct_addr * ni_interface_get_dhcp_addr (NIInterface *ni_interface);
gboolean ni_interface_has_dhcp_brd_addr (NIInterface *ni_interface);
gboolean ni_interface_has_dhcp_gw_addr (NIInterface *ni_interface);
gboolean ni_interface_has_dhcp_server_addr (NIInterface *ni_interface);
const struct_addr * ni_interface_get_dhcp_brd_addr (NIInterface *ni_interface);
const struct_addr * ni_interface_get_dhcp_gw_addr (NIInterface *ni_interface);
const struct_addr * ni_interface_get_dhcp_server_addr (NIInterface *ni_interface);
G_END_DECLS G_END_DECLS

View File

@ -1 +1,2 @@
BOOLEAN:POINTER,UINT BOOLEAN:POINTER,UINT
VOID:UINT,UINT

View File

@ -46,7 +46,7 @@ struct _NIWindowInterfacePrivate {
NIInterface *ni_interface; NIInterface *ni_interface;
GtkWidget *vbox, *notebook; GtkWidget *vbox, *notebook;
GtkWidget *vbox_ipv4, *vbox_ipv6, *vbox_info, *vbox_bridges; GtkWidget *vbox_ipv4, *vbox_ipv6, *vbox_info, *vbox_bridges, *vbox_dhcpv4;
GtkWidget *info_name, *info_updown, *info_mtu, *info_slave; GtkWidget *info_name, *info_updown, *info_mtu, *info_slave;
GtkWidget *button_name_apply, *button_name_revert; GtkWidget *button_name_apply, *button_name_revert;
GtkWidget *button_mtu_apply, *button_mtu_revert; GtkWidget *button_mtu_apply, *button_mtu_revert;
@ -56,8 +56,10 @@ struct _NIWindowInterfacePrivate {
GtkWidget *del_ipv4_button, *del_ipv6_button, *del_bport_button; GtkWidget *del_ipv4_button, *del_ipv6_button, *del_bport_button;
GtkWidget *tree_ipv4, *tree_ipv6, *tree_bridge_ports; GtkWidget *tree_ipv4, *tree_ipv6, *tree_bridge_ports;
/* Cosas de los bridges */ GtkWidget *button_dhcp_run, *button_dhcp_stop;
GtkWidget *dhcpv4_info;
GtkWidget *menu_dhcpv4;
int dhcp_type;
}; };
enum { enum {
@ -575,6 +577,83 @@ static void ni_window_interface_changed_master_cb (GObject *object, GParamSpec *
ni_window_interface_update_state_from_master (window_iface); ni_window_interface_update_state_from_master (window_iface);
} }
static void ni_window_interface_update_dhcp_status (NIWindowInterface *window_iface, NIInterface *ni_interface) {
guint type, status, prefix, lease_time;
char buffer[1024];
char buffer_ip[256];
const struct_addr *addr;
gint pos = 0;
type = ni_interface_get_dhcp_type (ni_interface);
if (type == 0) {
gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_info), "Información cliente DHCP:\nNo hay proceso corriendo");
} else {
if (type == 1) {
pos = g_snprintf (buffer, sizeof (buffer), "Información cliente DHCP: Cliente ISC\n");
} else if (type == 2) {
pos = g_snprintf (buffer, sizeof (buffer), "Información cliente DHCP: Cliente Busybox UDHCPC\n");
}
addr = ni_interface_get_dhcp_addr (ni_interface);
prefix = ni_interface_get_dhcp_prefix (ni_interface);
inet_ntop (AF_INET, addr, buffer_ip, sizeof (buffer_ip));
pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "Dirección IP: %s/%i\n", buffer_ip, prefix);
if (ni_interface_has_dhcp_gw_addr (ni_interface)) {
addr = ni_interface_get_dhcp_gw_addr (ni_interface);
inet_ntop (AF_INET, addr, buffer_ip, sizeof (buffer_ip));
pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "Gateway: %s\n", buffer_ip);
}
if (ni_interface_has_dhcp_brd_addr (ni_interface)) {
addr = ni_interface_get_dhcp_brd_addr (ni_interface);
inet_ntop (AF_INET, addr, buffer_ip, sizeof (buffer_ip));
pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "Broadcast: %s\n", buffer_ip);
}
if (ni_interface_has_dhcp_server_addr (ni_interface)) {
addr = ni_interface_get_dhcp_server_addr (ni_interface);
inet_ntop (AF_INET, addr, buffer_ip, sizeof (buffer_ip));
pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "DHCP Server: %s\n", buffer_ip);
}
lease_time = ni_interface_get_dhcp_lease_time (ni_interface);
if (lease_time != 0) {
pos += g_snprintf (&buffer[pos], sizeof (buffer) - pos, "Tiempo de concesión: %i seg(s)\n", lease_time);
}
gtk_label_set_text (GTK_LABEL (window_iface->priv->dhcpv4_info), buffer);
}
}
static void ni_window_interface_dhcp_type_changed_cb (NIInterface *ni_interface, guint old_type, guint new_type, gpointer data) {
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
/* Obtuvimos cambio en el estado del DHCP, actualizar los botones y ejecutar la información de estado */
if (new_type == 0) {
/* El dhcp está muerto */
gtk_widget_set_sensitive (window_iface->priv->button_dhcp_run, TRUE);
gtk_widget_set_sensitive (window_iface->priv->button_dhcp_stop, FALSE);
} else {
gtk_widget_set_sensitive (window_iface->priv->button_dhcp_run, FALSE);
gtk_widget_set_sensitive (window_iface->priv->button_dhcp_stop, TRUE);
}
ni_window_interface_update_dhcp_status (window_iface, ni_interface);
}
static void ni_window_interface_dhcp_status_updated_cb (NIInterface *ni_interface, gpointer data) {
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
ni_window_interface_update_dhcp_status (window_iface, ni_interface);
}
/* Eventos de bridges */ /* Eventos de bridges */
static gboolean ni_window_interface_check_bport_to_delete_foreach_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data); static gboolean ni_window_interface_check_bport_to_delete_foreach_cb (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data);
static void ni_window_interface_removed_from_bridge_cb (NIInterface *ni_interface, guint old_master, gpointer data); static void ni_window_interface_removed_from_bridge_cb (NIInterface *ni_interface, guint old_master, gpointer data);
@ -712,6 +791,37 @@ static void ni_window_interface_aditional_setup_for_bridge (NIWindowInterface *w
} }
} }
/* Eventos de los botones de DHCP */
static void ni_window_interface_dhcp_run_cb (GtkWidget *button, gpointer data) {
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
// Ejecutar el DHCP aquí
ni_interface_run_dhcp (window_iface->priv->ni_interface, window_iface->priv->dhcp_type);
}
static void ni_window_interface_dhcp_stop_cb (GtkWidget *button, gpointer data) {
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
// Ejecutar el DHCP aquí
ni_interface_stop_dhcp (window_iface->priv->ni_interface);
}
static void ni_window_interface_dhcp_type_isc_cb (GtkWidget *button, gpointer data) {
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (button))) {
window_iface->priv->dhcp_type = 1;
}
}
static void ni_window_interface_dhcp_type_busybox_cb (GtkWidget *button, gpointer data) {
NIWindowInterface *window_iface = NI_WINDOW_INTERFACE (data);
if (gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (button))) {
window_iface->priv->dhcp_type = 2;
}
}
/* Construcción del objeto */ /* Construcción del objeto */
static void ni_window_interface_constructed (GObject *obj) { static void ni_window_interface_constructed (GObject *obj) {
GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_WINDOW)); GObjectClass *parent_class = G_OBJECT_CLASS (g_type_class_peek (GTK_TYPE_WINDOW));
@ -737,6 +847,9 @@ static void ni_window_interface_constructed (GObject *obj) {
g_signal_connect (window_iface->priv->ni_interface, "notify::flags", G_CALLBACK (ni_window_interface_changed_flags_cb), window_iface); g_signal_connect (window_iface->priv->ni_interface, "notify::flags", G_CALLBACK (ni_window_interface_changed_flags_cb), window_iface);
g_signal_connect (window_iface->priv->ni_interface, "notify::master-index", G_CALLBACK (ni_window_interface_changed_master_cb), window_iface); g_signal_connect (window_iface->priv->ni_interface, "notify::master-index", G_CALLBACK (ni_window_interface_changed_master_cb), window_iface);
g_signal_connect (window_iface->priv->ni_interface, "dhcp-type-changed", G_CALLBACK (ni_window_interface_dhcp_type_changed_cb), window_iface);
g_signal_connect (window_iface->priv->ni_interface, "dhcp-status-updated", G_CALLBACK (ni_window_interface_dhcp_status_updated_cb), window_iface);
/* TODO: Recorrer las ips, y procesar la información */ /* TODO: Recorrer las ips, y procesar la información */
ip_list = ni_interface_get_ip_list (window_iface->priv->ni_interface); ip_list = ni_interface_get_ip_list (window_iface->priv->ni_interface);
@ -754,6 +867,8 @@ static void ni_window_interface_constructed (GObject *obj) {
if (ni_interface_get_iface_type (window_iface->priv->ni_interface) == NI_LINK_TYPE_BRIDGE) { if (ni_interface_get_iface_type (window_iface->priv->ni_interface) == NI_LINK_TYPE_BRIDGE) {
ni_window_interface_aditional_setup_for_bridge (window_iface); ni_window_interface_aditional_setup_for_bridge (window_iface);
} }
ni_window_interface_dhcp_type_changed_cb (window_iface->priv->ni_interface, 0, ni_interface_get_dhcp_type (window_iface->priv->ni_interface), window_iface);
} }
static void ni_window_interface_dispose (GObject *obj) { static void ni_window_interface_dispose (GObject *obj) {
@ -1047,6 +1162,65 @@ static void prepare_bridge_tab (NIWindowInterface *window_iface) {
gtk_widget_show (label_tab); gtk_widget_show (label_tab);
} }
static void prepare_dhcpv4_tab (NIWindowInterface *window_iface) {
GtkWidget *vbox, *hbox, *label, *button;
GtkSizeGroup *size_l;
GtkWindow *window = GTK_WINDOW (window_iface);
NIWindowInterfacePrivate *priv = window_iface->priv;
GtkWidget *item;
priv->vbox_dhcpv4 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
label = gtk_label_new ("DHCPv4");
gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), priv->vbox_dhcpv4, label);
gtk_container_set_border_width (GTK_CONTAINER (priv->vbox_dhcpv4), 5);
size_l = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
/* Poner las labels de información de la propia interfaz */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4), hbox, FALSE, FALSE, 0);
/* Preparar el menú para ejecutar el cliente de DHCP */
priv->menu_dhcpv4 = gtk_menu_new ();
priv->dhcp_type = 1;
item = gtk_radio_menu_item_new_with_label (NULL, "Correr ISC DHCP Client");
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE);
g_signal_connect (item, "activate", G_CALLBACK (ni_window_interface_dhcp_type_isc_cb), window_iface);
gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_dhcpv4), item);
gtk_widget_show (item);
item = gtk_radio_menu_item_new_with_label_from_widget (GTK_RADIO_MENU_ITEM (item), "Correr Busybox UDHCPC");
g_signal_connect (item, "activate", G_CALLBACK (ni_window_interface_dhcp_type_busybox_cb), window_iface);
gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu_dhcpv4), item);
gtk_widget_show (item);
label = gtk_label_new ("Cliente DHCP:");
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_size_group_add_widget (size_l, label);
priv->button_dhcp_stop = gtk_button_new_from_icon_name ("process-stop", GTK_ICON_SIZE_BUTTON);
gtk_widget_set_sensitive (priv->button_dhcp_stop, FALSE);
g_signal_connect (priv->button_dhcp_stop, "clicked", G_CALLBACK (ni_window_interface_dhcp_stop_cb), window_iface);
gtk_box_pack_end (GTK_BOX (hbox), priv->button_dhcp_stop, FALSE, FALSE, 0);
button = gtk_menu_button_new ();
gtk_menu_button_set_popup (GTK_MENU_BUTTON (button), priv->menu_dhcpv4);
gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
priv->button_dhcp_run = gtk_button_new_from_icon_name ("system-run", GTK_ICON_SIZE_BUTTON);
gtk_widget_set_sensitive (priv->button_dhcp_run, FALSE);
g_signal_connect (priv->button_dhcp_run, "clicked", G_CALLBACK (ni_window_interface_dhcp_run_cb), window_iface);
gtk_box_pack_end (GTK_BOX (hbox), priv->button_dhcp_run, FALSE, FALSE, 0);
/* Las labels del estado */
priv->dhcpv4_info = gtk_label_new ("Información cliente DHCP: ");
gtk_label_set_selectable (GTK_LABEL (priv->dhcpv4_info), TRUE);
gtk_label_set_xalign (GTK_LABEL (priv->dhcpv4_info), 0.0);
gtk_box_pack_start (GTK_BOX (priv->vbox_dhcpv4), priv->dhcpv4_info, FALSE, FALSE, 0);
}
static void ni_window_interface_init (NIWindowInterface *window_iface) { static void ni_window_interface_init (NIWindowInterface *window_iface) {
NIWindowInterfacePrivate *priv = ni_window_interface_get_instance_private (window_iface); NIWindowInterfacePrivate *priv = ni_window_interface_get_instance_private (window_iface);
window_iface->priv = priv; window_iface->priv = priv;
@ -1109,6 +1283,9 @@ static void ni_window_interface_init (NIWindowInterface *window_iface) {
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_ipv4)); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_ipv4));
g_signal_connect (selection, "changed", G_CALLBACK (has_ip_selected_v4_cb), window_iface); g_signal_connect (selection, "changed", G_CALLBACK (has_ip_selected_v4_cb), window_iface);
/* Página del cliente de DHCP */
prepare_dhcpv4_tab (window_iface);
/* Página de IPv6 */ /* Página de IPv6 */
priv->vbox_ipv6 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5); priv->vbox_ipv6 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
label = gtk_label_new ("IPv6"); label = gtk_label_new ("IPv6");

View File

@ -135,7 +135,6 @@ enum {
DHCP_CLIENT_FAILED, DHCP_CLIENT_FAILED,
DHCP_CLIENT_KILLED, DHCP_CLIENT_KILLED,
DHCP_CLIENT_EXTERNAL_RUNNING
}; };
#define DHCP_CLIENT_FLAG_AUTO_RESTART 0x0001 #define DHCP_CLIENT_FLAG_AUTO_RESTART 0x0001

View File

@ -33,10 +33,13 @@
#include "interfaces.h" #include "interfaces.h"
#include "common.h" #include "common.h"
#include "manager.h"
#include "dhcp_client.h" #include "dhcp_client.h"
#include "network-inador-manager.h" #include "network-inador-manager.h"
static void interfaces_dhcp_clear_info (InterfaceDHCPClientInfo *dhcpc);
void interfaces_dhcp_client_ignore_kill (GPid pid, gint status, gpointer data) { 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);
} }
@ -90,6 +93,11 @@ void interfaces_dhcp_client_killed_cb (GPid pid, gint status, gpointer data) {
/* Revisar si necesito algo */ /* Revisar si necesito algo */
} }
interfaces_dhcp_clear_info (&iface->dhcpc);
/* Enviar actualización de estado aquí */
iface->dhcpc.dhcp_state = DHCP_CLIENT_KILLED;
manager_send_event_dhcp_change (iface->handle, &iface->dhcpc);
if (iface->dhcpc.type == IFACE_ISC_DHCLIENT || iface->dhcpc.type == IFACE_BUSYBOX_UDHCPC) { 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 */
@ -111,15 +119,15 @@ void interfaces_dhcp_client_killed_cb (GPid pid, gint status, gpointer data) {
g_error_free (error); g_error_free (error);
error = NULL; error = NULL;
iface->dhcpc.flags = DHCP_CLIENT_KILLED; iface->dhcpc.dhcp_state = DHCP_CLIENT_KILLED;
iface->dhcpc.process_watch = 0; iface->dhcpc.process_watch = 0;
} else { } else {
iface->dhcpc.dhcp_state = DHCP_CLIENT_EXTERNAL_RUNNING; iface->dhcpc.dhcp_state = DHCP_CLIENT_SELECTING;
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);
} }
} else { } else {
/* En caso contrario, solo dejar la muerte escrita */ /* En caso contrario, solo dejar la muerte escrita */
iface->dhcpc.flags = DHCP_CLIENT_KILLED; iface->dhcpc.dhcp_state = DHCP_CLIENT_KILLED;
iface->dhcpc.process_watch = 0; iface->dhcpc.process_watch = 0;
} }
} }
@ -192,12 +200,14 @@ int interfaces_dhcp_client_run (NetworkInadorHandle *handle, int index, int type
return -1; return -1;
} }
iface->dhcpc.dhcp_state = DHCP_CLIENT_EXTERNAL_RUNNING; iface->dhcpc.dhcp_state = DHCP_CLIENT_SELECTING;
iface->dhcpc.type = type; 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);
manager_send_event_dhcp_change (handle, &iface->dhcpc);
return 0; return 0;
} }
@ -229,11 +239,12 @@ int interfaces_dhcp_client_stop (NetworkInadorHandle *handle, int index) {
kill (iface->dhcpc.process_pid, SIGTERM); kill (iface->dhcpc.process_pid, SIGTERM);
iface->dhcpc.type = IFACE_NO_DHCP; iface->dhcpc.type = IFACE_NO_DHCP;
iface->dhcpc.dhcp_state = DHCP_CLIENT_KILLED;
/* TODO: Revisar aquí si es pertinente desconfigurar la interfaz y borrar la información obtenida */ /* TODO: Revisar aquí si es pertinente desconfigurar la interfaz y borrar la información obtenida */
interfaces_dhcp_clear_info (&iface->dhcpc); interfaces_dhcp_clear_info (&iface->dhcpc);
/* TODO: Enviar actualización de estado aquí */ /* Enviar actualización de estado aquí */
manager_send_event_dhcp_change (handle, &iface->dhcpc);
} }
return 0; return 0;
@ -302,5 +313,7 @@ void interfaces_dhcp_client_internal_feed_from_client (NetworkInadorHandle *hand
inet_ntop (AF_INET, &iface->dhcpc.dhcp_server_ip, buf_d, sizeof (buf_d)); 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); 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);
} }
manager_send_event_dhcp_change (handle, &iface->dhcpc);
} }

View File

@ -113,8 +113,8 @@ static int _interfaces_receive_message_interface (struct nl_msg *msg, void *arg,
if (iface == NULL) { if (iface == NULL) {
/* Crear esta interfaz */ /* Crear esta interfaz */
iface = malloc (sizeof (Interface)); iface = malloc (sizeof (Interface));
iface->handle = handle;
memset (iface, 0, sizeof (Interface)); memset (iface, 0, sizeof (Interface));
iface->handle = handle;
handle->interfaces = g_list_append (handle->interfaces, iface); handle->interfaces = g_list_append (handle->interfaces, iface);

View File

@ -948,13 +948,13 @@ void _manager_send_dhcp_status (ManagerClientInfo *manager_client, InterfaceDHCP
/* Los campos de bits */ /* Los campos de bits */
buffer[10] = 0; buffer[10] = 0;
if (memcmp (&dhcpc->gateway, &empty, 4) == 0) { if (memcmp (&dhcpc->gateway, &empty, 4) != 0) {
buffer[10] |= 0x01; buffer[10] |= 0x01;
} }
if (memcmp (&dhcpc->broadcast, &empty, 4) == 0) { if (memcmp (&dhcpc->broadcast, &empty, 4) != 0) {
buffer[10] |= 0x02; buffer[10] |= 0x02;
} }
if (memcmp (&dhcpc->dhcp_server_ip, &empty, 4) == 0) { if (memcmp (&dhcpc->dhcp_server_ip, &empty, 4) != 0) {
buffer[10] |= 0x04; buffer[10] |= 0x04;
} }
@ -1209,6 +1209,25 @@ void manager_send_event_ip_del (NetworkInadorHandle *handle, IPAddr *ip_addr) {
} }
} }
void manager_send_event_dhcp_change (NetworkInadorHandle *handle, InterfaceDHCPClientInfo *dhcpc) {
Interface *iface = container_of (dhcpc, Interface, dhcpc);
GList *g;
ManagerClientInfo *manager_client;
printf ("___ MANAGER ___ Informando cambio DHCP: %s (%i)\n", iface->name, iface->index);
if (handle->manager == NULL) return;
for (g = handle->manager->connected_client_list; g != NULL; g = g->next) {
manager_client = (ManagerClientInfo *) g->data;
if (manager_client->wanted_events & NET_INADOR_EVENT_MASK_DHCP_STATUS) {
printf ("___ MANAGER ___ Informando a la conexión (%i)\n", manager_client->fd);
_manager_send_dhcp_status (manager_client, dhcpc, TRUE);
}
}
}
int manager_init (NetworkInadorHandle *handle) { int manager_init (NetworkInadorHandle *handle) {
NetworkInadorManager *manager; NetworkInadorManager *manager;
struct sockaddr_un socket_name; struct sockaddr_un socket_name;

View File

@ -33,6 +33,7 @@ void manager_send_event_interface_del (NetworkInadorHandle *handle, uint32_t ind
void manager_send_event_interface_update (NetworkInadorHandle *handle, Interface *iface); void manager_send_event_interface_update (NetworkInadorHandle *handle, Interface *iface);
void manager_send_event_ip_add (NetworkInadorHandle *handle, IPAddr *ip_addr); void manager_send_event_ip_add (NetworkInadorHandle *handle, IPAddr *ip_addr);
void manager_send_event_ip_del (NetworkInadorHandle *handle, IPAddr *ip_addr); void manager_send_event_ip_del (NetworkInadorHandle *handle, IPAddr *ip_addr);
void manager_send_event_dhcp_change (NetworkInadorHandle *handle, InterfaceDHCPClientInfo *dhcpc);
#endif /* __MANAGER_H__ */ #endif /* __MANAGER_H__ */