Reorganizo las estructuras de direcciones de IPv4 y IPv6.

master
Félix Arreola Rodríguez 2021-08-08 02:05:45 -05:00
parent 8a9690c502
commit 89570f4139
2 changed files with 191 additions and 100 deletions

View File

@ -41,15 +41,27 @@
#define TRUE !FALSE
#endif
typedef struct _NetworkInadorHandle NetworkInadorHandle;
typedef struct _NetworkInadorManager NetworkInadorManager;
typedef union {
struct in_addr v4;
struct in6_addr v6;
} struct_addr;
typedef struct _IPAddr {
sa_family_t family;
union {
struct in_addr sin_addr;
struct in6_addr sin6_addr;
};
uint32_t prefix;
unsigned char flags;
int prefix;
struct_addr local_addr;
struct_addr addr;
struct_addr brd_addr;
int is_p2p;
int has_brd;
int has_local;
uint32_t flags;
unsigned char scope;
} IPAddr;
@ -93,15 +105,15 @@ typedef struct _WirelessInfo {
} WirelessInfo;
typedef struct _Interface {
uint32_t index;
char name[IFNAMSIZ];
int ifi_type;
uint16_t ifi_type;
unsigned char real_hw[ETHER_ADDR_LEN * 2 + 1];
unsigned int index;
/* Para las interfaces dentro de un bridge */
unsigned int master_index;
uint32_t master_index;
unsigned int mtu;
uint32_t mtu;
/* Para las interfaces vlan */
unsigned int vlan_parent;

View File

@ -34,18 +34,29 @@
#include "ip-address.h"
#include "interfaces.h"
static IPAddr *_ip_address_search_addr (Interface *iface, sa_family_t family, void *addr_data, uint32_t prefix) {
static IPAddr *_ip_address_search_addr (Interface *iface, sa_family_t family, void *addr, uint32_t prefix, void *local_addr) {
GList *g;
IPAddr *addr;
IPAddr *ip_addr;
int family_size = 0;
if (family == AF_INET) {
family_size = sizeof (struct in_addr);
} else if (family == AF_INET6) {
family_size = sizeof (struct in6_addr);
}
for (g = iface->address; g != NULL; g = g->next) {
addr = (IPAddr *) g->data;
ip_addr = (IPAddr *) g->data;
if (addr->family == family) {
if (family == AF_INET && memcmp (&addr->sin_addr, addr_data, sizeof (struct in_addr)) == 0 && addr->prefix == prefix) {
return addr;
} else if (family == AF_INET6 && memcmp (&addr->sin6_addr, addr_data, sizeof (struct in6_addr)) == 0 && addr->prefix == prefix) {
return addr;
if (ip_addr->family != family) continue;
if (memcmp (&ip_addr->addr, addr, family_size) == 0 && ip_addr->prefix == prefix) {
if (local_addr != NULL) {
if (memcmp (&ip_addr->local_addr, local_addr, family_size) == 0) {
return ip_addr;
}
} else {
return ip_addr;
}
}
}
@ -54,16 +65,24 @@ static IPAddr *_ip_address_search_addr (Interface *iface, sa_family_t family, vo
}
int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg) {
NetworkInadorHandle *handle = (NetworkInadorHandle *) arg;
Interface *iface;
IPAddr *ip_addr;
struct nlmsghdr *reply;
struct ifaddrmsg *addr_msg;
int remaining;
struct nlattr *attr;
NetworkInadorHandle *handle = (NetworkInadorHandle *) arg;
Interface *iface;
int has_addr = 0;
struct in_addr sin_addr;
struct in6_addr sin6_addr;
IPAddr *addr;
struct_addr addr;
struct_addr local_addr;
struct_addr brd_addr;
/* TODO: Decidir si guardamos también la IP anycast */
uint32_t flags;
int family;
int has_brd = 0, has_local = 0;
int family_size = 0;
reply = nlmsg_hdr (msg);
@ -78,62 +97,100 @@ int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg) {
return NL_SKIP;
}
printf ("-> New addr\n");
flags = addr_msg->ifa_flags;
family = addr_msg->ifa_family;
if (family == AF_INET) {
family_size = sizeof (struct in_addr);
} else if (family == AF_INET6) {
family_size = sizeof (struct in6_addr);
}
nlmsg_for_each_attr(attr, reply, sizeof (struct ifaddrmsg), remaining) {
if (nla_type (attr) != IFA_ADDRESS) continue;
if (addr_msg->ifa_family == AF_INET && nla_len (attr) == 4) {
/* IP de ipv4 */
memcpy (&sin_addr, nla_data (attr), nla_len (attr));
has_addr = 1;
} else if (addr_msg->ifa_family == AF_INET6 && nla_len (attr) == 16) {
/* IP de ipv6 */
memcpy (&sin6_addr, nla_data (attr), nla_len (attr));
has_addr = 1;
printf ("-> new addr type attr: %i\n", nla_type (attr));
switch (nla_type (attr)) {
case IFA_FLAGS:
memcpy (&flags, nla_data (attr), nla_len (attr));
break;
case IFA_ADDRESS:
memcpy (&addr, nla_data (attr), nla_len (attr));
break;
case IFA_LOCAL:
memcpy (&local_addr, nla_data (attr), nla_len (attr));
has_local = 1;
break;
case IFA_BROADCAST:
memcpy (&brd_addr, nla_data (attr), nla_len (attr));
has_brd = 1;
break;
}
}
ip_addr = _ip_address_search_addr (iface, family, &addr, addr_msg->ifa_prefixlen, (has_local ? &local_addr : NULL));
if (addr_msg->ifa_family == AF_INET) {
addr = _ip_address_search_addr (iface, AF_INET, &sin_addr, addr_msg->ifa_prefixlen);
} else if (addr_msg->ifa_family == AF_INET6) {
addr = _ip_address_search_addr (iface, AF_INET6, &sin6_addr, addr_msg->ifa_prefixlen);
/* Agregar los datos al objeto */
if (ip_addr == NULL) {
ip_addr = g_new0 (IPAddr, 1);
iface->address = g_list_append (iface->address, ip_addr);
ip_addr->family = addr_msg->ifa_family;
memcpy (&ip_addr->addr, &addr, family_size);
ip_addr->prefix = addr_msg->ifa_prefixlen;
}
if (addr == NULL) {
addr = g_new0 (IPAddr, 1);
iface->address = g_list_append (iface->address, addr);
addr->family = addr_msg->ifa_family;
if (addr->family == AF_INET) {
memcpy (&addr->sin_addr, &sin_addr, sizeof (struct in_addr));
} else if (addr->family == AF_INET6) {
memcpy (&addr->sin6_addr, &sin6_addr, sizeof (struct in6_addr));
ip_addr->flags = flags;
ip_addr->scope = addr_msg->ifa_scope;
/* Actualizar la local o la broadcast */
ip_addr->is_p2p = 0;
if (has_local) {
ip_addr->has_local = 1;
memcpy (&ip_addr->local_addr, &local_addr, family_size);
/* Revisar si las direcciones son P2P */
if (memcmp (&local_addr, &addr, family_size) != 0) {
ip_addr->is_p2p = 1;
}
addr->prefix = addr_msg->ifa_prefixlen;
}
addr->flags = addr_msg->ifa_flags;
addr->scope = addr_msg->ifa_scope;
if (has_brd) {
ip_addr->has_brd = 1;
memcpy (&ip_addr->brd_addr, &brd_addr, family_size);
}
char buffer[2048];
inet_ntop (addr->family, &addr->sin_addr, buffer, sizeof (buffer));
printf ("Dirección IP + %s/%d sobre interfaz: %d, scope: %d, flags: %d\n", buffer, addr->prefix, iface->index, ((unsigned int) addr->scope), ((unsigned int) addr->flags));
char buffer_2[2048];
if (ip_addr->is_p2p) {
inet_ntop (ip_addr->family, &ip_addr->addr, buffer_2, sizeof (buffer_2));
inet_ntop (ip_addr->family, &ip_addr->local_addr, buffer, sizeof (buffer));
printf ("Dirección IP + %s/%d peer %s sobre interfaz: %d, scope: %d, flags: %u\n", buffer, ip_addr->prefix, buffer_2, iface->index, (unsigned int) ip_addr->scope, ip_addr->flags);
} else {
inet_ntop (ip_addr->family, &ip_addr->addr, buffer, sizeof (buffer));
printf ("Dirección IP + %s/%d sobre interfaz: %d, scope: %d, flags: %u\n", buffer, ip_addr->prefix, iface->index, (unsigned int) ip_addr->scope, ip_addr->flags);
}
return NL_SKIP;
}
int ip_address_receive_message_deladdr (struct nl_msg *msg, void *arg) {
NetworkInadorHandle *handle = (NetworkInadorHandle *) arg;
Interface *iface;
IPAddr *ip_addr = NULL;
struct nlmsghdr *reply;
struct ifaddrmsg *addr_msg;
int remaining;
struct nlattr *attr;
NetworkInadorHandle *handle = (NetworkInadorHandle *) arg;
Interface *iface;
struct in_addr sin_addr;
struct in6_addr sin6_addr;
IPAddr *addr = NULL;
struct_addr addr;
struct_addr local_addr;
int family, family_size = 0;
int has_local = 0;
reply = nlmsg_hdr (msg);
@ -148,34 +205,42 @@ int ip_address_receive_message_deladdr (struct nl_msg *msg, void *arg) {
return NL_SKIP;
}
family = addr_msg->ifa_family;
if (family == AF_INET) {
family_size = sizeof (struct in_addr);
} else if (family == AF_INET6) {
family_size = sizeof (struct in6_addr);
}
printf ("DEL MSG\n");
nlmsg_for_each_attr(attr, reply, sizeof (struct ifaddrmsg), remaining) {
if (nla_type (attr) != IFA_ADDRESS) continue;
if (addr_msg->ifa_family == AF_INET && nla_len (attr) == 4) {
/* IP de ipv4 */
memcpy (&sin_addr, nla_data (attr), nla_len (attr));
} else if (addr_msg->ifa_family == AF_INET6 && nla_len (attr) == 16) {
/* IP de ipv6 */
memcpy (&sin6_addr, nla_data (attr), nla_len (attr));
printf ("-> del addr type attr: %i\n", nla_type (attr));
switch (nla_type (attr)) {
case IFA_ADDRESS:
memcpy (&addr, nla_data (attr), nla_len (attr));
break;
case IFA_LOCAL:
memcpy (&local_addr, nla_data (attr), nla_len (attr));
has_local = 1;
break;
}
}
ip_addr = _ip_address_search_addr (iface, family, &addr, addr_msg->ifa_prefixlen, (has_local ? &local_addr : NULL));
if (addr_msg->ifa_family == AF_INET) {
addr = _ip_address_search_addr (iface, AF_INET, &sin_addr, addr_msg->ifa_prefixlen);
} else if (addr_msg->ifa_family == AF_INET6) {
addr = _ip_address_search_addr (iface, AF_INET6, &sin6_addr, addr_msg->ifa_prefixlen);
}
if (addr == NULL) {
if (ip_addr == NULL) {
printf ("IP no encontrada\n");
return NL_SKIP;
}
/* Eliminar de la lista ligada */
iface->address = g_list_remove (iface->address, addr);
char buffer[2048];
inet_ntop (ip_addr->family, &ip_addr->local_addr, buffer, sizeof (buffer));
printf ("Dirección IP - %s/%d sobre interfaz: %d, scope: %d, flags: %u\n", buffer, ip_addr->prefix, iface->index, (unsigned int) ip_addr->scope, ip_addr->flags);
g_free (addr);
/* Eliminar de la lista ligada */
iface->address = g_list_remove (iface->address, ip_addr);
g_free (ip_addr);
return NL_SKIP;
}
@ -204,11 +269,12 @@ static int _ip_address_wait_error (struct sockaddr_nl *nla, struct nlmsgerr *l_e
return NL_SKIP;
}
int ip_address_add_ip (NetworkInadorHandle *handle, int index, IPAddr *addr) {
int ip_address_add_ip (NetworkInadorHandle *handle, int index, IPAddr *ip_addr) {
struct nl_msg * msg;
struct ifaddrmsg addr_hdr;
int ret, error;
Interface *iface;
int family_size = 0;
iface = _interfaces_locate_by_index (handle->interfaces, index);
@ -218,10 +284,10 @@ int ip_address_add_ip (NetworkInadorHandle *handle, int index, IPAddr *addr) {
return -1;
}
addr_hdr.ifa_family = addr->family;
addr_hdr.ifa_prefixlen = addr->prefix;
addr_hdr.ifa_flags = addr->flags;
addr_hdr.ifa_scope = addr->scope;
addr_hdr.ifa_family = ip_addr->family;
addr_hdr.ifa_prefixlen = ip_addr->prefix;
addr_hdr.ifa_flags = ip_addr->flags;
addr_hdr.ifa_scope = ip_addr->scope;
addr_hdr.ifa_index = index;
msg = nlmsg_alloc_simple (RTM_NEWADDR, NLM_F_REQUEST);
@ -233,12 +299,18 @@ int ip_address_add_ip (NetworkInadorHandle *handle, int index, IPAddr *addr) {
return -1;
}
if (addr->family == AF_INET) {
ret = nla_put (msg, IFA_LOCAL, sizeof (addr->sin_addr), &addr->sin_addr);
ret = nla_put (msg, IFA_ADDRESS, sizeof (addr->sin_addr), &addr->sin_addr);
} else {
ret = nla_put (msg, IFA_LOCAL, sizeof (addr->sin6_addr), &addr->sin6_addr);
ret = nla_put (msg, IFA_ADDRESS, sizeof (addr->sin6_addr), &addr->sin6_addr);
if (ip_addr->family == AF_INET) {
family_size = sizeof (struct in_addr);
} else if (ip_addr->family == AF_INET6) {
family_size = sizeof (struct in6_addr);
}
ret = nla_put (msg, IFA_ADDRESS, family_size, &ip_addr->addr);
if (ip_addr->has_local) {
ret |= nla_put (msg, IFA_LOCAL, family_size, &ip_addr->local_addr);
}
if (ip_addr->has_brd) {
ret |= nla_put (msg, IFA_LOCAL, family_size, &ip_addr->brd_addr);
}
if (ret != 0) {
@ -271,12 +343,13 @@ int ip_address_add_ip (NetworkInadorHandle *handle, int index, IPAddr *addr) {
return 0;
}
int ip_address_del_ip (NetworkInadorHandle *handle, int index, IPAddr *addr) {
int ip_address_del_ip (NetworkInadorHandle *handle, int index, IPAddr *ip_addr) {
struct nl_msg * msg;
struct ifaddrmsg addr_hdr;
int ret, error;
Interface *iface;
GList *addr_pos;
int family_size = 0;
iface = _interfaces_locate_by_index (handle->interfaces, index);
@ -286,7 +359,7 @@ int ip_address_del_ip (NetworkInadorHandle *handle, int index, IPAddr *addr) {
return -1;
}
addr_pos = g_list_find (iface->address, addr);
addr_pos = g_list_find (iface->address, ip_addr);
if (addr_pos == NULL) {
printf ("Error, la dirección solicitada no pertenece a la interfaz\n");
@ -294,10 +367,10 @@ int ip_address_del_ip (NetworkInadorHandle *handle, int index, IPAddr *addr) {
return -1;
}
addr_hdr.ifa_family = addr->family;
addr_hdr.ifa_prefixlen = addr->prefix;
addr_hdr.ifa_flags = addr->flags;
addr_hdr.ifa_scope = addr->scope;
addr_hdr.ifa_family = ip_addr->family;
addr_hdr.ifa_prefixlen = ip_addr->prefix;
addr_hdr.ifa_flags = ip_addr->flags;
addr_hdr.ifa_scope = ip_addr->scope;
addr_hdr.ifa_index = index;
msg = nlmsg_alloc_simple (RTM_DELADDR, NLM_F_REQUEST);
@ -309,12 +382,18 @@ int ip_address_del_ip (NetworkInadorHandle *handle, int index, IPAddr *addr) {
return -1;
}
if (addr->family == AF_INET) {
ret = nla_put (msg, IFA_LOCAL, sizeof (addr->sin_addr), &addr->sin_addr);
ret = nla_put (msg, IFA_ADDRESS, sizeof (addr->sin_addr), &addr->sin_addr);
} else {
ret = nla_put (msg, IFA_LOCAL, sizeof (addr->sin6_addr), &addr->sin6_addr);
ret = nla_put (msg, IFA_ADDRESS, sizeof (addr->sin6_addr), &addr->sin6_addr);
if (ip_addr->family == AF_INET) {
family_size = sizeof (struct in_addr);
} else if (ip_addr->family == AF_INET6) {
family_size = sizeof (struct in6_addr);
}
ret = nla_put (msg, IFA_ADDRESS, family_size, &ip_addr->addr);
if (ip_addr->has_local) {
ret |= nla_put (msg, IFA_LOCAL, family_size, &ip_addr->local_addr);
}
if (ip_addr->has_brd) {
ret |= nla_put (msg, IFA_LOCAL, family_size, &ip_addr->brd_addr);
}
if (ret != 0) {