From 89570f4139611377bda7a384704b90328926c7a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Arreola=20Rodr=C3=ADguez?= Date: Sun, 8 Aug 2021 02:05:45 -0500 Subject: [PATCH] Reorganizo las estructuras de direcciones de IPv4 y IPv6. --- src/common.h | 32 ++++-- src/ip-address.c | 259 +++++++++++++++++++++++++++++++---------------- 2 files changed, 191 insertions(+), 100 deletions(-) diff --git a/src/common.h b/src/common.h index ed5a81c..225d777 100644 --- a/src/common.h +++ b/src/common.h @@ -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; diff --git a/src/ip-address.c b/src/ip-address.c index be3519d..a0f7be4 100644 --- a/src/ip-address.c +++ b/src/ip-address.c @@ -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) {