diff --git a/src/Makefile.am b/src/Makefile.am index 948bd2b..11eb827 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,11 +1,13 @@ # Automake file for NetworkInador bin_PROGRAMS = network-inador -network_inador_SOURCES = main.c common.h \ +network_inador_SOURCES = main.c \ + common.h link-types.h \ netlink-events.c netlink-events.h \ interfaces.c interfaces.h \ ip-address.c ip-address.h \ bridge.c bridge.h \ + manager.c manager.h \ wireless_if.c wireless_if.h \ wireless_bss.c wireless_bss.h diff --git a/src/common.h b/src/common.h index 225d777..b836937 100644 --- a/src/common.h +++ b/src/common.h @@ -43,6 +43,7 @@ typedef struct _NetworkInadorHandle NetworkInadorHandle; typedef struct _NetworkInadorManager NetworkInadorManager; +typedef struct _Interface Interface; typedef union { struct in_addr v4; @@ -63,6 +64,8 @@ typedef struct _IPAddr { uint32_t flags; unsigned char scope; + + Interface *iface; } IPAddr; #define SSID_MAX_LEN 32 @@ -104,10 +107,11 @@ typedef struct _WirelessInfo { GList *aps; } WirelessInfo; -typedef struct _Interface { +struct _Interface { uint32_t index; char name[IFNAMSIZ]; - uint16_t ifi_type; + uint32_t link_type; + uint16_t arp_type; unsigned char real_hw[ETHER_ADDR_LEN * 2 + 1]; /* Para las interfaces dentro de un bridge */ @@ -126,7 +130,7 @@ typedef struct _Interface { char wireless_protocol[IFNAMSIZ]; /* Tipo */ - char tipo_string[IFNAMSIZ]; + char rtnl_type[IFNAMSIZ]; GList *address; @@ -134,7 +138,25 @@ typedef struct _Interface { /* Información wireless */ WirelessInfo *wireless; -} Interface; +}; + +/* Para los clientes y sus respectivos eventos */ +typedef struct { + int fd; + + /* Los eventos que quieren ser recibidos en este cliente */ + uint32_t wanted_events; + guint source; + NetworkInadorManager *manager; +} ManagerClientInfo; + +struct _NetworkInadorManager { + int socket; + + guint source; + GList *connected_client_list; + NetworkInadorHandle *handle; +}; /* Para vigilar eventos */ typedef struct _netlink_event_pair { @@ -142,10 +164,12 @@ typedef struct _netlink_event_pair { guint source; } NetlinkEventPair; -typedef struct { +struct _NetworkInadorHandle { GList *interfaces; //Routev4 *rtable_v4; + NetworkInadorManager *manager; + struct nl_sock * nl_sock_route; struct nl_sock * nl_sock_nl80211; @@ -153,7 +177,7 @@ typedef struct { NetlinkEventPair nl80211_scan; NetlinkEventPair nl80211_scan_results; -} NetworkInadorHandle; +}; #endif /* __COMMON_H__ */ diff --git a/src/interfaces.c b/src/interfaces.c index a0b9f8b..94b89c0 100644 --- a/src/interfaces.c +++ b/src/interfaces.c @@ -25,7 +25,7 @@ #include #include -#include +#include #include @@ -33,6 +33,9 @@ #include "interfaces.h" #include "ip-address.h" #include "wireless_if.h" +#include "manager.h" + +#include "link-types.h" static int _interfaces_receive_message_interface (struct nl_msg *msg, void *arg, int first_time); @@ -44,15 +47,60 @@ int interface_receive_message_newlink (struct nl_msg *msg, void *arg) { return _interfaces_receive_message_interface (msg, arg, FALSE); } +static uint32_t interfaces_check_link_type (Interface *iface) { + int g; + + /* Revisar primero el INFO_KIND */ + for (g = 0; g < (sizeof (linktypes) / sizeof (linktypes[0])); g++) { + if (linktypes[g].rtnl_type == NULL) continue; + if (strcmp (iface->rtnl_type, linktypes[g].rtnl_type) == 0) { + return linktypes->link_type; + } + } + + if (iface->arp_type == ARPHRD_LOOPBACK) + return NI_LINK_TYPE_LOOPBACK; + else if (iface->arp_type == ARPHRD_INFINIBAND) + return NI_LINK_TYPE_INFINIBAND; + else if (iface->arp_type == ARPHRD_SIT) + return NI_LINK_TYPE_SIT; + else if (iface->arp_type == ARPHRD_TUNNEL6) + return NI_LINK_TYPE_IP6TNL; + else if (iface->arp_type == ARPHRD_PPP) + return NI_LINK_TYPE_PPP; + else if (iface->arp_type == ARPHRD_IEEE802154) + return NI_LINK_TYPE_WPAN; + else if (iface->arp_type == ARPHRD_6LOWPAN) + return NI_LINK_TYPE_6LOWPAN; + + if (iface->is_wireless) { + return NI_LINK_TYPE_WIFI; + } + + if (iface->arp_type == ARPHRD_ETHER) { + if (strncmp (iface->name, "rmnet", 5) == 0 || + strncmp (iface->name, "rev_rmnet", 9) == 0 || + strncmp (iface->name, "ccmni", 5) == 0) + return NI_LINK_TYPE_WWAN_NET; + + return NI_LINK_TYPE_ETHERNET; + } + + return NI_LINK_TYPE_UNKNOWN; +} + static int _interfaces_receive_message_interface (struct nl_msg *msg, void *arg, int first_time) { struct nlmsghdr *reply; struct ifinfomsg *iface_msg; int remaining; struct nlattr *attr; NetworkInadorHandle *handle = (NetworkInadorHandle *) arg; - int was_new = 0; + int was_new = 0, was_update = 0; + uint32_t new_flags; + Interface *iface; uint32_t u32data; + char temp_name[128]; reply = nlmsg_hdr (msg); @@ -64,7 +112,8 @@ static int _interfaces_receive_message_interface (struct nl_msg *msg, void *arg, if (iface == NULL) { /* Crear esta interfaz */ - iface = g_new0 (Interface, 1); + iface = malloc (sizeof (Interface)); + memset (iface, 0, sizeof (Interface)); handle->interfaces = g_list_append (handle->interfaces, iface); @@ -85,25 +134,24 @@ static int _interfaces_receive_message_interface (struct nl_msg *msg, void *arg, } printf ("Interface %d agregada a la interfaz %d (bridge)\n", iface->index, iface->master_index); - /* Generar EVENTO AQUI */ + /* TODO: Generar EVENTO AQUI */ return NL_SKIP; } - printf ("Interface %d ifi_type: %d\n", iface_msg->ifi_index, iface_msg->ifi_type); - iface->ifi_type = iface_msg->ifi_type; - /* TODO: Checar aquí cambio de flags */ - printf ("Interface %d ifi_flags: %d\n", iface_msg->ifi_index, iface_msg->ifi_flags); - iface->flags = iface_msg->ifi_flags; + iface->arp_type = iface_msg->ifi_type; + new_flags = iface_msg->ifi_flags; iface->index = iface_msg->ifi_index; nlmsg_for_each_attr(attr, reply, sizeof (struct ifinfomsg), remaining) { switch (nla_type (attr)) { //nla_len (Attr); case IFLA_IFNAME: - printf ("Interface %d : %s\n", iface_msg->ifi_index, (char *) nla_data (attr)); // Actualizar el nombre de la interfaz */ - /* TODO Revisar cambio de nombre aquí y generar evento */ - strncpy (iface->name, nla_data (attr), IFNAMSIZ); + strncpy (temp_name, nla_data (attr), IFNAMSIZ); + if (strcmp (temp_name, iface->name) != 0) { + was_update = 1; + strncpy (iface->name, nla_data (attr), IFNAMSIZ); + } break; case IFLA_ADDRESS: if (nla_len (attr) > ETHER_ADDR_LEN) { @@ -121,7 +169,7 @@ static int _interfaces_receive_message_interface (struct nl_msg *msg, void *arg, if (first_time == FALSE) continue; u32data = nla_get_u32 (attr); iface->master_index = u32data; - printf ("Interface %d has master: %d\n", iface->index, iface->master_index); + //printf ("Interface %d has master: %d\n", iface->index, iface->master_index); break; case IFLA_MTU: if (nla_len (attr) != 4) { @@ -130,22 +178,26 @@ static int _interfaces_receive_message_interface (struct nl_msg *msg, void *arg, } u32data = nla_get_u32 (attr); - /* TODO: Revisar cambio de mtu y generar EVENTO aqui */ - iface->mtu = u32data; + if (iface->mtu != u32data) { + iface->mtu = u32data; + was_update = 1; + } //printf ("Interface %d has mtu: %u\n", iface->ifi_index, new->mtu); break; case IFLA_LINKINFO: { + printf ("La interfaz tiene linkinfo"); struct nlattr *sub_attr; int sub_remaining; nla_for_each_nested(sub_attr, attr, sub_remaining) { + printf ("\tLINK_INFO attr: %i\n", nla_type (sub_attr)); switch (nla_type (sub_attr)) { case IFLA_INFO_KIND: printf ("IFLA_INFO_KIND: %s\n", nla_data (sub_attr)); - strncpy (iface->tipo_string, nla_data (sub_attr), sizeof (iface->tipo_string) - 1); - iface->tipo_string[sizeof (iface->tipo_string) - 1] = 0; + strncpy (iface->rtnl_type, nla_data (sub_attr), sizeof (iface->rtnl_type) - 1); + iface->rtnl_type[sizeof (iface->rtnl_type) - 1] = 0; break; } } @@ -161,13 +213,28 @@ static int _interfaces_receive_message_interface (struct nl_msg *msg, void *arg, u32data = nla_get_u32 (attr); iface->vlan_parent = u32data; printf ("Interface %d: tiene como padre a %d\n", iface->index, iface->vlan_parent); - //default: - //printf ("RTA Attribute \"%hu\" no procesado\n", nla_type (attr)); + case IFA_FLAGS: + printf ("IFA_FLAGS: size %i\n", nla_len (attr)); + new_flags = nla_get_u32 (attr); + break; + default: + printf ("RTA Attribute \"%hu\" no procesado\n", nla_type (attr)); } } + if (iface->flags != new_flags) { + was_update = 1; + } + if (was_new) { + printf ("+++++ Interfaz nueva creada: %s\n", iface->name); wireless_interface_check (handle, iface); + + iface->link_type = interfaces_check_link_type (iface); + + manager_send_event_interface_add (handle, iface); + } else if (was_update) { + manager_send_event_interface_update (handle, iface); } return NL_SKIP; @@ -224,7 +291,7 @@ int interface_receive_message_dellink (struct nl_msg *msg, void *arg) { reply = nlmsg_hdr (msg); - if (reply->nlmsg_type != RTM_NEWLINK) return NL_SKIP; + if (reply->nlmsg_type != RTM_DELLINK) return NL_SKIP; iface_msg = nlmsg_data (reply); @@ -254,12 +321,16 @@ int interface_receive_message_dellink (struct nl_msg *msg, void *arg) { return NL_SKIP; } + printf ("----- Interfaz eliminada: %s\n", iface->name); + handle->interfaces = g_list_remove (handle->interfaces, iface); /* Antes de eliminar la interfaz, eliminar la lista ligada de todas las direcciones IP */ - g_list_free_full (iface->address, g_free); + g_list_free_full (iface->address, free); - g_free (iface); + manager_send_event_interface_del (handle, iface->index); + + free (iface); } int interfaces_change_mac_address (NetworkInadorHandle *handle, int index, void *new_mac) { @@ -278,7 +349,7 @@ int interfaces_change_mac_address (NetworkInadorHandle *handle, int index, void } iface_hdr.ifi_family = AF_UNSPEC; - iface_hdr.ifi_type = iface->ifi_type; + iface_hdr.ifi_type = iface->arp_type; iface_hdr.ifi_index = iface->index; iface_hdr.ifi_flags = iface->flags; iface_hdr.ifi_change = 0xFFFFFFFF; @@ -340,7 +411,7 @@ int interfaces_change_mtu (NetworkInadorHandle *handle, int index, uint32_t new_ } iface_hdr.ifi_family = AF_UNSPEC; - iface_hdr.ifi_type = iface->ifi_type; + iface_hdr.ifi_type = iface->arp_type; iface_hdr.ifi_index = iface->index; iface_hdr.ifi_flags = iface->flags; iface_hdr.ifi_change = 0xFFFFFFFF; @@ -409,7 +480,7 @@ static int _interfaces_change_admin_up (NetworkInadorHandle *handle, int index, } iface_hdr.ifi_family = AF_UNSPEC; - iface_hdr.ifi_type = iface->ifi_type; + iface_hdr.ifi_type = iface->arp_type; iface_hdr.ifi_index = iface->index; if (up) { iface_hdr.ifi_flags = iface->flags | IFF_UP; @@ -479,7 +550,7 @@ int interfaces_change_name (NetworkInadorHandle *handle, int index, char * new_n } iface_hdr.ifi_family = AF_UNSPEC; - iface_hdr.ifi_type = iface->ifi_type; + iface_hdr.ifi_type = iface->arp_type; iface_hdr.ifi_index = iface->index; iface_hdr.ifi_flags = iface->flags; iface_hdr.ifi_change = 0xFFFFFFFF; diff --git a/src/ip-address.c b/src/ip-address.c index a0f7be4..c0ce5e9 100644 --- a/src/ip-address.c +++ b/src/ip-address.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -33,6 +34,8 @@ #include "common.h" #include "ip-address.h" #include "interfaces.h" +#include "manager.h" + static IPAddr *_ip_address_search_addr (Interface *iface, sa_family_t family, void *addr, uint32_t prefix, void *local_addr) { GList *g; @@ -83,6 +86,7 @@ int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg) { int family; int has_brd = 0, has_local = 0; int family_size = 0; + int was_new = 0; reply = nlmsg_hdr (msg); @@ -132,7 +136,8 @@ int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg) { /* Agregar los datos al objeto */ if (ip_addr == NULL) { - ip_addr = g_new0 (IPAddr, 1); + ip_addr = malloc (sizeof (IPAddr)); + memset (ip_addr, 0, sizeof (*ip_addr)); iface->address = g_list_append (iface->address, ip_addr); @@ -140,6 +145,9 @@ int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg) { memcpy (&ip_addr->addr, &addr, family_size); ip_addr->prefix = addr_msg->ifa_prefixlen; + ip_addr->iface = iface; + + was_new = 1; } ip_addr->flags = flags; @@ -162,6 +170,12 @@ int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg) { memcpy (&ip_addr->brd_addr, &brd_addr, family_size); } + if (was_new) { + manager_send_event_ip_add (handle, ip_addr); + } else { + /* En caso contrario, enviar una actualización de IP */ + } + char buffer[2048]; char buffer_2[2048]; if (ip_addr->is_p2p) { @@ -240,7 +254,10 @@ int ip_address_receive_message_deladdr (struct nl_msg *msg, void *arg) { /* Eliminar de la lista ligada */ iface->address = g_list_remove (iface->address, ip_addr); - g_free (ip_addr); + /* Notificar del evento */ + manager_send_event_ip_del (handle, ip_addr); + + free (ip_addr); return NL_SKIP; } diff --git a/src/link-types.h b/src/link-types.h new file mode 100644 index 0000000..1b11ae8 --- /dev/null +++ b/src/link-types.h @@ -0,0 +1,138 @@ +/* + * link-types.h + * This file is part of Network Inador + * + * Copyright (C) 2021 - Félix Arreola Rodríguez + * + * Network Inador 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. + * + * Network Inador 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 Network Inador; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef __LINK_TYPES_H__ +#define __LINK_TYPES_H__ + +typedef enum { + /* Please don't interpret type numbers outside nm-platform and use functions + * like nm_platform_link_is_software() and nm_platform_supports_slaves(). + * + * type & 0x10000 -> Software device type + * type & 0x20000 -> Type supports slaves + */ + + /* No type, used as error value */ + NI_LINK_TYPE_NONE, + + /* Unknown type */ + NI_LINK_TYPE_UNKNOWN, + + /* Hardware types */ + NI_LINK_TYPE_ETHERNET, + NI_LINK_TYPE_INFINIBAND, + NI_LINK_TYPE_OLPC_MESH, + NI_LINK_TYPE_WIFI, + NI_LINK_TYPE_WWAN_NET, /* WWAN kernel netdevice */ + NI_LINK_TYPE_WIMAX, + NI_LINK_TYPE_WPAN, + NI_LINK_TYPE_6LOWPAN, + + /* Software types */ + NI_LINK_TYPE_BNEP = 0x10000, /* Bluetooth Ethernet emulation */ + NI_LINK_TYPE_DUMMY, + NI_LINK_TYPE_GRE, + NI_LINK_TYPE_GRETAP, + NI_LINK_TYPE_IFB, + NI_LINK_TYPE_IP6TNL, + NI_LINK_TYPE_IP6GRE, + NI_LINK_TYPE_IP6GRETAP, + NI_LINK_TYPE_IPIP, + NI_LINK_TYPE_LOOPBACK, + NI_LINK_TYPE_MACSEC, + NI_LINK_TYPE_MACVLAN, + NI_LINK_TYPE_MACVTAP, + NI_LINK_TYPE_OPENVSWITCH, + NI_LINK_TYPE_PPP, + NI_LINK_TYPE_SIT, + NI_LINK_TYPE_TUN, + NI_LINK_TYPE_VETH, + NI_LINK_TYPE_VLAN, + NI_LINK_TYPE_VXLAN, + NI_LINK_TYPE_WIREGUARD, + + /* Software types with slaves */ + NI_LINK_TYPE_BRIDGE = 0x10000 | 0x20000, + NI_LINK_TYPE_BOND, + NI_LINK_TYPE_TEAM, + + NI_LINK_TYPE_ANY = 0xffffffff, + +} NILinkType; + +typedef struct { + const NILinkType link_type; + const char *type_string; + + /* IFLA_INFO_KIND / rtnl_link_get_type() where applicable; the rtnl type + * should only be specified if the device type can be created without + * additional parameters, and if the device type can be determined from + * the rtnl_type. eg, tun/tap should not be specified since both + * tun and tap devices use "tun", and InfiniBand should not be + * specified because a PKey is required at creation. Drivers set this + * value from their 'struct rtnl_link_ops' structure. + */ + const char *rtnl_type; +} LinkDesc; + +static const LinkDesc linktypes[] = { + { NI_LINK_TYPE_NONE, "none", NULL }, + { NI_LINK_TYPE_UNKNOWN, "unknown", NULL }, + + { NI_LINK_TYPE_ETHERNET, "ethernet", NULL }, + { NI_LINK_TYPE_INFINIBAND, "infiniband", NULL }, + { NI_LINK_TYPE_OLPC_MESH, "olpc-mesh", NULL }, + { NI_LINK_TYPE_WIFI, "wifi", NULL }, + { NI_LINK_TYPE_WWAN_NET, "wwan", NULL }, + { NI_LINK_TYPE_WIMAX, "wimax", "wimax" }, + { NI_LINK_TYPE_WPAN, "wpan", NULL }, + { NI_LINK_TYPE_6LOWPAN, "6lowpan", NULL }, + + { NI_LINK_TYPE_BNEP, "bluetooth", NULL }, + { NI_LINK_TYPE_DUMMY, "dummy", "dummy" }, + { NI_LINK_TYPE_GRE, "gre", "gre" }, + { NI_LINK_TYPE_GRETAP, "gretap", "gretap" }, + { NI_LINK_TYPE_IFB, "ifb", "ifb" }, + { NI_LINK_TYPE_IP6TNL, "ip6tnl", "ip6tnl" }, + { NI_LINK_TYPE_IP6GRE, "ip6gre", "ip6gre" }, + { NI_LINK_TYPE_IP6GRETAP, "ip6gretap", "ip6gretap" }, + { NI_LINK_TYPE_IPIP, "ipip", "ipip" }, + { NI_LINK_TYPE_LOOPBACK, "loopback", NULL }, + { NI_LINK_TYPE_MACSEC, "macsec", "macsec" }, + { NI_LINK_TYPE_MACVLAN, "macvlan", "macvlan" }, + { NI_LINK_TYPE_MACVTAP, "macvtap", "macvtap" }, + { NI_LINK_TYPE_OPENVSWITCH, "openvswitch", "openvswitch" }, + { NI_LINK_TYPE_PPP, "ppp", NULL }, + { NI_LINK_TYPE_SIT, "sit", "sit" }, + { NI_LINK_TYPE_TUN, "tun", "tun" }, + { NI_LINK_TYPE_VETH, "veth", "veth" }, + { NI_LINK_TYPE_VLAN, "vlan", "vlan" }, + { NI_LINK_TYPE_VXLAN, "vxlan", "vxlan" }, + { NI_LINK_TYPE_WIREGUARD, "wireguard", "wireguard" }, + + { NI_LINK_TYPE_BRIDGE, "bridge", "bridge" }, + { NI_LINK_TYPE_BOND, "bond", "bond" }, + { NI_LINK_TYPE_TEAM, "team", "team" }, +}; + +#endif /* __LINK_TYPES_H__ */ + diff --git a/src/main.c b/src/main.c index 1469b85..8db3b16 100644 --- a/src/main.c +++ b/src/main.c @@ -37,6 +37,7 @@ #include #include "common.h" +#include "manager.h" #include "interfaces.h" #include "netlink-events.h" #include "ip-address.h" @@ -132,6 +133,8 @@ int main (int argc, char *argv[]) { interfaces_init (&handle); + manager_init (&handle); + g_main_loop_run (loop); /* Detener la llegada de eventos */ diff --git a/src/wireless_if.c b/src/wireless_if.c index 18aca24..cd7e77b 100644 --- a/src/wireless_if.c +++ b/src/wireless_if.c @@ -110,8 +110,6 @@ static void _wireless_if_process_bands (struct nlattr *list_bands, WirelessInfo static int _wireless_if_cb_valid_is_wifi (struct nl_msg *msg, void *arg) { struct _wireless_iface_is_wifi *is_wifi = (struct _wireless_iface_is_wifi *) arg; - printf ("%s: Argumento extra: %p\n", __func__, arg); - struct nlmsgerr *l_err; struct nlmsghdr *reply; struct genlmsghdr *gnlh;