diff --git a/client-gtk/ni-client.c b/client-gtk/ni-client.c index f11f4f4..9956eac 100644 --- a/client-gtk/ni-client.c +++ b/client-gtk/ni-client.c @@ -381,7 +381,7 @@ void ni_client_ask_interfaces (NIClient *ni_client) { send (ni_client->priv->client_socket, buffer, 2, 0); } -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) { +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) { unsigned char buffer[80]; uint32_t index; int family_size; @@ -416,9 +416,12 @@ void ni_client_ask_ip_new (NIClient *ni_client, NIInterface *ni_interface, int f buffer[9] = scope; memcpy (&buffer[10], &flags, 4); - memcpy (&buffer[14], addr, family_size); + /* Copiar los timestamp solicitados */ + memcpy (&buffer[14], cacheinfo, 8); - pos = 14 + family_size; + memcpy (&buffer[22], addr, family_size); + + pos = 22 + family_size; if (has_local) { memcpy (&buffer[pos], local_addr, family_size); diff --git a/client-gtk/ni-client.h b/client-gtk/ni-client.h index 37981d1..84f4f90 100644 --- a/client-gtk/ni-client.h +++ b/client-gtk/ni-client.h @@ -78,7 +78,7 @@ NIClient *ni_client_new_with_path (const char *path); 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_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); +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_change_iface_name (NIClient *ni_client, NIInterface *ni_interface, const gchar *new_name); void ni_client_ask_change_iface_mtu (NIClient *ni_client, NIInterface *ni_interface, guint new_mtu); diff --git a/client-gtk/ni-interface.c b/client-gtk/ni-interface.c index fe3c080..cef4909 100644 --- a/client-gtk/ni-interface.c +++ b/client-gtk/ni-interface.c @@ -433,7 +433,10 @@ static void ni_interface_process_ip_added (NIInterface *ni_interface, gpointer d 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; @@ -454,9 +457,12 @@ static void ni_interface_process_ip_added (NIInterface *ni_interface, gpointer d family_size = sizeof (struct in6_addr); } - memcpy (&addr, &buffer[14], family_size); + /* Copiar los timestamp */ + memcpy (cacheinfo, &buffer[14], 16); - pos = 14 + family_size; + memcpy (&addr, &buffer[30], family_size); + + pos = 30 + family_size; if (has_local_addr) { memcpy (&local_addr, &buffer[pos], family_size); pos += family_size; @@ -464,9 +470,20 @@ static void ni_interface_process_ip_added (NIInterface *ni_interface, gpointer d if (has_brd_addr) { memcpy (&brd_addr, &buffer[pos], family_size); + pos += family_size; } - 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)); + /* 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); diff --git a/client-gtk/ni-ip.c b/client-gtk/ni-ip.c index 4da8177..1b089a4 100644 --- a/client-gtk/ni-ip.c +++ b/client-gtk/ni-ip.c @@ -40,11 +40,19 @@ struct _NIIPPrivate { struct_addr addr; struct_addr brd_addr; + /* Timestamps */ + guint32 ifa_prefered; + guint32 ifa_valid; + guint32 cstamp; + guint32 tstamp; + gboolean has_brd; gboolean has_local; uint32_t flags; unsigned char scope; + + char label[256]; }; enum { @@ -174,11 +182,35 @@ const struct_addr *ni_ip_get_brd_addr (NIIP *ni_ip) { return &ni_ip->priv->brd_addr; } +uint32_t ni_ip_get_ifa_prefered (NIIP *ni_ip) { + g_return_val_if_fail (NI_IS_IP (ni_ip), 0); + + return ni_ip->priv->ifa_prefered; +} -NIIP *ni_ip_new (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 ni_ip_get_ifa_valid (NIIP *ni_ip) { + g_return_val_if_fail (NI_IS_IP (ni_ip), 0); + + return ni_ip->priv->ifa_valid; +} + +uint32_t ni_ip_get_cstamp (NIIP *ni_ip) { + g_return_val_if_fail (NI_IS_IP (ni_ip), 0); + + return ni_ip->priv->cstamp; +} + +uint32_t ni_ip_get_tstamp (NIIP *ni_ip) { + g_return_val_if_fail (NI_IS_IP (ni_ip), 0); + + return ni_ip->priv->tstamp; +} + +NIIP *ni_ip_new (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, guint32 *cacheinfo, char *label) { NIIP *ni_ip; g_return_val_if_fail (NI_IS_INTERFACE (ni_interface), NULL); + g_return_val_if_fail (cacheinfo != NULL, NULL); ni_ip = g_object_new (NI_TYPE_IP, "ni-interface", ni_interface, NULL); @@ -190,6 +222,16 @@ NIIP *ni_ip_new (NIInterface *ni_interface, int family, int prefix, struct_addr ni_ip->priv->flags = flags; ni_ip->priv->scope = scope; + /* Copiar los valores del arreglo */ + ni_ip->priv->ifa_prefered = cacheinfo[0]; + ni_ip->priv->ifa_valid = cacheinfo[1]; + ni_ip->priv->cstamp = cacheinfo[2]; + ni_ip->priv->tstamp = cacheinfo[3]; + + ni_ip->priv->label[0] = 0; + if (label != NULL && label[0] != 0) { + strncpy (ni_ip->priv->label, label, sizeof (ni_ip->priv->label)); + } if (family == AF_INET) { ni_ip->priv->family_size = sizeof (struct in_addr); } else if (family == AF_INET6) { diff --git a/client-gtk/ni-ip.h b/client-gtk/ni-ip.h index f9eaba5..4371a9d 100644 --- a/client-gtk/ni-ip.h +++ b/client-gtk/ni-ip.h @@ -80,8 +80,12 @@ unsigned char ni_ip_get_scope (NIIP *ni_ip); const struct_addr *ni_ip_get_addr (NIIP *ni_ip); const struct_addr *ni_ip_get_local_addr (NIIP *ni_ip); const struct_addr *ni_ip_get_brd_addr (NIIP *ni_ip); +uint32_t ni_ip_get_ifa_prefered (NIIP *ni_ip); +uint32_t ni_ip_get_ifa_valid (NIIP *ni_ip); +uint32_t ni_ip_get_cstamp (NIIP *ni_ip); +uint32_t ni_ip_get_tstamp (NIIP *ni_ip); -NIIP *ni_ip_new (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); +NIIP *ni_ip_new (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, guint32 *cacheinfo, char *label); G_END_DECLS diff --git a/client-gtk/ni-window-interface.c b/client-gtk/ni-window-interface.c index 026d68a..63ab545 100644 --- a/client-gtk/ni-window-interface.c +++ b/client-gtk/ni-window-interface.c @@ -187,7 +187,11 @@ static void ni_window_interface_addr_button_add_cb (GtkWidget *widget, int famil } //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) { - ni_client_ask_ip_new (ni_client, window_iface->priv->ni_interface, family, prefix, &addr, flags, 0, has_p2p, (has_p2p ? &p2p_addr : NULL), FALSE, NULL); + /* TODO: Pedir los tiempos de validez de la interfaz */ + guint32 cacheinfo[2]; + cacheinfo[0] = 0xFFFFFFFFU; + cacheinfo[1] = 0xFFFFFFFFU; + ni_client_ask_ip_new (ni_client, window_iface->priv->ni_interface, family, prefix, &addr, flags, 0, has_p2p, (has_p2p ? &p2p_addr : NULL), FALSE, NULL, cacheinfo); } gtk_widget_destroy (dialog); @@ -293,6 +297,45 @@ static void ni_window_interface_addr_v6_button_del_cb (GtkWidget *widget, gpoint ni_window_interface_addr_button_del_cb (widget, AF_INET6, data); } +/* Función para renderizar el tiempo de la IP en el arbol */ +void ni_window_interface_cell_renderer_timestamp (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell, GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data) { + NIIP *ni_ip; + char buffer[256]; + guint32 valid, prefered; + gint horas, minutos, segundos; + + gtk_tree_model_get (tree_model, iter, IP_STORE_COL_OBJECT, &ni_ip, -1); + + valid = ni_ip_get_ifa_valid (ni_ip); + prefered = ni_ip_get_ifa_prefered (ni_ip); + + if (valid == 0xFFFFFFFFU) { + g_object_set (cell, "text", "Indefinida", NULL); + } else { + horas = valid / 3600; + segundos = valid - (horas * 3600); + minutos = segundos / 60; + segundos = segundos - (minutos * 60); + + if (horas > 0) { + if (minutos > 0) { + snprintf (buffer, sizeof (buffer), "%i hora(s), %i minuto(s)", horas, minutos); + } else { + snprintf (buffer, sizeof (buffer), "%i hora(s)", horas); + } + } else if (minutos > 0) { + if (segundos > 0) { + snprintf (buffer, sizeof (buffer), "%i minuto(s), %i segundo(s)", minutos, segundos); + } else { + snprintf (buffer, sizeof (buffer), "%i minuto(s)", minutos); + } + } else { + snprintf (buffer, sizeof (buffer), "%i segundo(s)", segundos); + } + g_object_set (cell, "text", buffer, NULL); + } +} + /* Evento cuando cambian el nombre de la interfaz en el entry */ static void ni_window_interface_name_edit_cb (GtkEditable *editable, gpointer data) { NIWindowInterface *window_iface = (NIWindowInterface *) data; @@ -795,6 +838,7 @@ GtkWidget *ni_window_interface_create_tree_for_ip (GtkListStore *store, GtkWidge *tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store)); + gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (*tree), GTK_TREE_VIEW_GRID_LINES_HORIZONTAL); h = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (*tree)); v = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (*tree)); @@ -803,6 +847,15 @@ GtkWidget *ni_window_interface_create_tree_for_ip (GtkListStore *store, GtkWidge renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes ("Dirección", renderer, "text", IP_STORE_COL_MAIN_IP, NULL); + gtk_tree_view_column_set_resizable (GTK_TREE_VIEW_COLUMN (column), TRUE); + gtk_tree_view_append_column (GTK_TREE_VIEW (*tree), column); + + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_resizable (GTK_TREE_VIEW_COLUMN (column), TRUE); + gtk_tree_view_column_set_title (GTK_TREE_VIEW_COLUMN (column), "Vigencia"); + gtk_tree_view_column_pack_start (GTK_TREE_VIEW_COLUMN (column), renderer, TRUE); + gtk_tree_view_column_set_cell_data_func (GTK_TREE_VIEW_COLUMN (column), renderer, ni_window_interface_cell_renderer_timestamp, NULL, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (*tree), column); gtk_container_add (GTK_CONTAINER (scrolled), *tree); diff --git a/src/common.h b/src/common.h index d5359ff..fcd1ed3 100644 --- a/src/common.h +++ b/src/common.h @@ -41,6 +41,10 @@ #define TRUE !FALSE #endif +#ifndef INFINITY_LIFE_TIME +#define INFINITY_LIFE_TIME 0xFFFFFFFFU +#endif + typedef struct _NetworkInadorHandle NetworkInadorHandle; typedef struct _NetworkInadorManager NetworkInadorManager; typedef struct _Interface Interface; @@ -58,6 +62,9 @@ typedef struct _IPAddr { struct_addr addr; struct_addr brd_addr; + char label[256]; + struct ifa_cacheinfo cacheinfo; + int is_p2p; int has_brd; int has_local; diff --git a/src/ip-address.c b/src/ip-address.c index 14aac4a..b11e421 100644 --- a/src/ip-address.c +++ b/src/ip-address.c @@ -77,6 +77,8 @@ int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg) { int remaining; struct nlattr *attr; struct ifa_cacheinfo cacheinfo; + char label[256]; + int label_len; struct_addr addr; struct_addr local_addr; @@ -86,7 +88,7 @@ int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg) { /* TODO: Decidir si guardamos también la IP anycast */ int family; - int has_brd = 0, has_local = 0; + int has_brd = 0, has_local = 0, has_cacheinfo = 0; int family_size = 0; int was_new = 0; @@ -114,6 +116,15 @@ int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg) { family_size = sizeof (struct in6_addr); } + label[0] = 0; + label_len = 0; + + /* Prevaciar el cacheinfo */ + cacheinfo.ifa_prefered = INFINITY_LIFE_TIME; + cacheinfo.ifa_valid = INFINITY_LIFE_TIME; + cacheinfo.cstamp = 0; + cacheinfo.tstamp = 0; + nlmsg_for_each_attr(attr, reply, sizeof (struct ifaddrmsg), remaining) { printf ("-> new addr type attr: %i\n", nla_type (attr)); switch (nla_type (attr)) { @@ -134,6 +145,13 @@ int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg) { case IFA_CACHEINFO: memcpy (&cacheinfo, nla_data (attr), nla_len (attr)); printf ("Cache info timestamp: preferred: %u, valid: %u, created: %u, updated: %u\n", cacheinfo.ifa_prefered, cacheinfo.ifa_valid, cacheinfo.cstamp, cacheinfo.tstamp); + has_cacheinfo = 1; + break; + case IFA_LABEL: + label_len = nla_len (attr); + memcpy (label, nla_data(attr), label_len); + label[label_len] = 0; + printf ("-> La IP tiene label: %s\n", label); break; } } @@ -171,11 +189,21 @@ int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg) { } } + ip_addr->label[0] = 0; + if (label[0] != 0) { + memcpy (ip_addr->label, label, label_len); + ip_addr->label[label_len] = 0; + } + if (has_brd) { ip_addr->has_brd = 1; memcpy (&ip_addr->brd_addr, &brd_addr, family_size); } + if (has_cacheinfo) { + memcpy (&ip_addr->cacheinfo, &cacheinfo, sizeof (cacheinfo)); + } + if (was_new) { manager_send_event_ip_add (handle, ip_addr); } else { @@ -338,6 +366,13 @@ int ip_address_add_ip (NetworkInadorHandle *handle, int index, IPAddr *ip_addr) ret |= nla_put (msg, IFA_BROADCAST, family_size, &ip_addr->brd_addr); } + /* El tiempo preferido no puede ser mayor que el tiempo válido */ + if (ip_addr->cacheinfo.ifa_prefered > ip_addr->cacheinfo.ifa_valid) { + ip_addr->cacheinfo.ifa_prefered = ip_addr->cacheinfo.ifa_valid; + } + + ret |= nla_put (msg, IFA_CACHEINFO, 16, &ip_addr->cacheinfo); + if (ret != 0) { nlmsg_free (msg); diff --git a/src/manager.c b/src/manager.c index 3951c84..aa19436 100644 --- a/src/manager.c +++ b/src/manager.c @@ -130,6 +130,7 @@ void _manager_send_interface_del (ManagerClientInfo *manager_client, uint32_t in void _manager_send_ip (ManagerClientInfo *manager_client, IPAddr *ip_addr, gboolean is_event) { unsigned char buffer[80]; int family_size = 0; + int label_len; int pos; if (is_event) { @@ -140,6 +141,7 @@ void _manager_send_ip (ManagerClientInfo *manager_client, IPAddr *ip_addr, gbool buffer[1] = NET_INADOR_RESPONSE_IPADDR; } + /* Familia y máscara */ if (ip_addr->family == AF_INET) { family_size = sizeof (struct in_addr); } else if (ip_addr->family == AF_INET6) { @@ -149,6 +151,7 @@ void _manager_send_ip (ManagerClientInfo *manager_client, IPAddr *ip_addr, gbool buffer[6] = ip_addr->family; buffer[7] = ip_addr->prefix; + /* Los campos de bits */ buffer[8] = 0; if (ip_addr->has_local) { buffer[8] |= 0x01; @@ -157,11 +160,16 @@ void _manager_send_ip (ManagerClientInfo *manager_client, IPAddr *ip_addr, gbool buffer[8] |= 0x02; } + /* Byte scope y las flags */ buffer[9] = ip_addr->scope; memcpy (&buffer[10], &ip_addr->flags, 4); - memcpy (&buffer[14], &ip_addr->addr, family_size); - pos = 14 + family_size; + /* La información de marcas de tiempo de las IPs */ + memcpy (&buffer[14], &ip_addr->cacheinfo, 16); + + /* La dirección principal */ + memcpy (&buffer[30], &ip_addr->addr, family_size); + pos = 30 + family_size; if (ip_addr->has_local) { memcpy (&buffer[pos], &ip_addr->local_addr, family_size); pos += family_size; @@ -172,6 +180,17 @@ void _manager_send_ip (ManagerClientInfo *manager_client, IPAddr *ip_addr, gbool pos += family_size; } + if (ip_addr->label[0] != 0) { + label_len = strlen (ip_addr->label); + buffer[pos] = label_len; + pos++; + + memcpy (&buffer[pos], &ip_addr->label, label_len); + pos += label_len; + } else { + buffer[pos] = 0; + pos++; + } send (manager_client->fd, buffer, pos, 0); } @@ -446,7 +465,7 @@ void _manager_execute_add_ip (ManagerClientInfo *manager_client, unsigned char * family_size = sizeof (struct in6_addr); } /* Ya puedo revisar el resto de la longitud */ - wanted_size = 14 + family_size + (family_size * ip_addr.has_local) + (family_size * ip_addr.has_brd); + wanted_size = 22 + family_size + (family_size * ip_addr.has_local) + (family_size * ip_addr.has_brd); if (buffer_len < wanted_size) { _manager_send_error (manager_client, NET_INADOR_ERROR_INCOMPLETE_REQUEST, NET_INADOR_COMMAND_ADD_IP); return; @@ -455,8 +474,13 @@ void _manager_execute_add_ip (ManagerClientInfo *manager_client, unsigned char * ip_addr.scope = buffer[9]; memcpy (&ip_addr.flags, &buffer[10], 4); - memcpy (&ip_addr.addr, &buffer[14], family_size); - wanted_size = 14 + family_size; + /* Copiar los timestamp de tiempo válido y preferido */ + memset (&ip_addr.cacheinfo, 0, sizeof (ip_addr.cacheinfo)); + memcpy (&ip_addr.cacheinfo, &buffer[14], 8); + + /* Copiar las direcciones */ + memcpy (&ip_addr.addr, &buffer[22], family_size); + wanted_size = 22 + family_size; if (ip_addr.has_local) { memcpy (&ip_addr.local_addr, &buffer[wanted_size], family_size);