diff --git a/src/Makefile.am b/src/Makefile.am index fe85544..948bd2b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,6 +5,7 @@ network_inador_SOURCES = main.c common.h \ netlink-events.c netlink-events.h \ interfaces.c interfaces.h \ ip-address.c ip-address.h \ + bridge.c bridge.h \ wireless_if.c wireless_if.h \ wireless_bss.c wireless_bss.h diff --git a/src/bridge.c b/src/bridge.c new file mode 100644 index 0000000..f770f26 --- /dev/null +++ b/src/bridge.c @@ -0,0 +1,288 @@ +/* + * bridge.c + * This file is part of Network-inador + * + * Copyright (C) 2018 - 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 + */ + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "common.h" +#include "interfaces.h" + +int interfaces_bridge_create (NetworkInadorHandle *handle, const char *name) { + struct nl_msg * msg; + struct ifinfomsg iface_hdr; + struct nlattr *info; + int ret, error, len; + const char *type = "bridge"; + + if (name != NULL) { + /* Validar la longitud del nombre, por seguridad */ + len = strlen (name) + 1; + if (len == 1) { + /* Nombre muy corto */ + return -1; + } + if (len > IFNAMSIZ) { + /* Nombre muy largo */ + return -1; + } + } + + memset (&iface_hdr, 0, sizeof (iface_hdr)); + iface_hdr.ifi_family = AF_UNSPEC; + iface_hdr.ifi_index = 0; + + msg = nlmsg_alloc_simple (RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL); + ret = nlmsg_append (msg, &iface_hdr, sizeof (iface_hdr), NLMSG_ALIGNTO); + + if (ret != 0) { + nlmsg_free (msg); + + return -1; + } + + info = nla_nest_start (msg, IFLA_LINKINFO); + + if (info == NULL) { + nlmsg_free (msg); + + return -1; + } + + ret = nla_put_string (msg, IFLA_INFO_KIND, type); + + if (ret != 0) { + nla_nest_end (msg, info); + nlmsg_free (msg); + + return -1; + } + nla_nest_end (msg, info); + + nl_complete_msg (handle->nl_sock_route, msg); + + ret = nl_send (handle->nl_sock_route, msg); + + nlmsg_free (msg); + if (ret <= 0) { + return -1; + } + + error = 0; + nl_socket_modify_cb (handle->nl_sock_route, NL_CB_VALID, NL_CB_CUSTOM, _interfaces_wait_ack_or_error, &error); + nl_socket_modify_cb (handle->nl_sock_route, NL_CB_INVALID, NL_CB_CUSTOM, _interfaces_wait_ack_or_error, &error); + nl_socket_modify_cb (handle->nl_sock_route, NL_CB_ACK, NL_CB_CUSTOM, _interfaces_wait_ack_or_error, &error); + nl_socket_modify_err_cb (handle->nl_sock_route, NL_CB_CUSTOM, _interfaces_wait_error, &error); + + nl_recvmsgs_default (handle->nl_sock_route); + + if (ret <= 0 || error < 0) { + return -1; + } + + return 0; +} + +int interfaces_bridge_set_master_interface (NetworkInadorHandle *handle, int master_index, int index) { + struct nl_msg * msg; + struct ifinfomsg iface_hdr; + struct nlattr *info; + int ret, error; + Interface *master_iface, *iface; + + master_iface = _interfaces_locate_by_index (handle->interfaces, master_index); + iface = _interfaces_locate_by_index (handle->interfaces, index); + + if (master_iface == NULL || iface == NULL) { + printf ("Error, solicitaron operación sobre interfaz que no existe\n"); + + return -1; + } + + memset (&iface_hdr, 0, sizeof (iface_hdr)); + iface_hdr.ifi_family = AF_UNSPEC; + iface_hdr.ifi_index = iface->index; + + msg = nlmsg_alloc_simple (RTM_NEWLINK, NLM_F_REQUEST); + ret = nlmsg_append (msg, &iface_hdr, sizeof (iface_hdr), NLMSG_ALIGNTO); + + if (ret != 0) { + nlmsg_free (msg); + + return -1; + } + + ret = nla_put_u32 (msg, IFLA_MASTER, master_iface->index); + + if (ret != 0) { + nlmsg_free (msg); + + return -1; + } + + nl_complete_msg (handle->nl_sock_route, msg); + + ret = nl_send (handle->nl_sock_route, msg); + + nlmsg_free (msg); + if (ret <= 0) { + return -1; + } + + error = 0; + nl_socket_modify_cb (handle->nl_sock_route, NL_CB_VALID, NL_CB_CUSTOM, _interfaces_wait_ack_or_error, &error); + nl_socket_modify_cb (handle->nl_sock_route, NL_CB_INVALID, NL_CB_CUSTOM, _interfaces_wait_ack_or_error, &error); + nl_socket_modify_cb (handle->nl_sock_route, NL_CB_ACK, NL_CB_CUSTOM, _interfaces_wait_ack_or_error, &error); + nl_socket_modify_err_cb (handle->nl_sock_route, NL_CB_CUSTOM, _interfaces_wait_error, &error); + + nl_recvmsgs_default (handle->nl_sock_route); + + if (ret <= 0 || error < 0) { + return -1; + } + + return 0; +} + +int interfaces_bridge_remove_master_interface (NetworkInadorHandle *handle, int index) { + struct nl_msg * msg; + struct ifinfomsg iface_hdr; + struct nlattr *info; + int ret, error; + Interface *iface; + + iface = _interfaces_locate_by_index (handle->interfaces, index); + + if (iface == NULL) { + printf ("Error, solicitaron operación sobre interfaz que no existe\n"); + + return -1; + } + + memset (&iface_hdr, 0, sizeof (iface_hdr)); + iface_hdr.ifi_family = AF_UNSPEC; + iface_hdr.ifi_index = iface->index; + + msg = nlmsg_alloc_simple (RTM_NEWLINK, NLM_F_REQUEST); + ret = nlmsg_append (msg, &iface_hdr, sizeof (iface_hdr), NLMSG_ALIGNTO); + + if (ret != 0) { + nlmsg_free (msg); + + return -1; + } + + ret = nla_put_u32 (msg, IFLA_MASTER, 0); + + if (ret != 0) { + nlmsg_free (msg); + + return -1; + } + + nl_complete_msg (handle->nl_sock_route, msg); + + ret = nl_send (handle->nl_sock_route, msg); + + nlmsg_free (msg); + if (ret <= 0) { + return -1; + } + + error = 0; + nl_socket_modify_cb (handle->nl_sock_route, NL_CB_VALID, NL_CB_CUSTOM, _interfaces_wait_ack_or_error, &error); + nl_socket_modify_cb (handle->nl_sock_route, NL_CB_INVALID, NL_CB_CUSTOM, _interfaces_wait_ack_or_error, &error); + nl_socket_modify_cb (handle->nl_sock_route, NL_CB_ACK, NL_CB_CUSTOM, _interfaces_wait_ack_or_error, &error); + nl_socket_modify_err_cb (handle->nl_sock_route, NL_CB_CUSTOM, _interfaces_wait_error, &error); + + nl_recvmsgs_default (handle->nl_sock_route); + + if (ret <= 0 || error < 0) { + return -1; + } + + return 0; +} + +int interfaces_bridge_delete (NetworkInadorHandle *handle, int index) { + struct nl_msg * msg; + struct ifinfomsg iface_hdr; + struct nlattr *info; + int ret, error, len; + Interface *iface; + + iface = _interfaces_locate_by_index (handle->interfaces, index); + + if (iface == NULL) { + printf ("Error, solicitaron operación sobre interfaz que no existe\n"); + + return -1; + } + + memset (&iface_hdr, 0, sizeof (iface_hdr)); + iface_hdr.ifi_family = AF_UNSPEC; + iface_hdr.ifi_index = iface->index; + + msg = nlmsg_alloc_simple (RTM_DELLINK, NLM_F_REQUEST | NLM_F_EXCL); + ret = nlmsg_append (msg, &iface_hdr, sizeof (iface_hdr), NLMSG_ALIGNTO); + + if (ret != 0) { + nlmsg_free (msg); + + return -1; + } + + nl_complete_msg (handle->nl_sock_route, msg); + + ret = nl_send (handle->nl_sock_route, msg); + + nlmsg_free (msg); + if (ret <= 0) { + return -1; + } + + error = 0; + nl_socket_modify_cb (handle->nl_sock_route, NL_CB_VALID, NL_CB_CUSTOM, _interfaces_wait_ack_or_error, &error); + nl_socket_modify_cb (handle->nl_sock_route, NL_CB_INVALID, NL_CB_CUSTOM, _interfaces_wait_ack_or_error, &error); + nl_socket_modify_cb (handle->nl_sock_route, NL_CB_ACK, NL_CB_CUSTOM, _interfaces_wait_ack_or_error, &error); + nl_socket_modify_err_cb (handle->nl_sock_route, NL_CB_CUSTOM, _interfaces_wait_error, &error); + + nl_recvmsgs_default (handle->nl_sock_route); + + if (ret <= 0 || error < 0) { + return -1; + } + + return 0; +} + diff --git a/src/bridge.h b/src/bridge.h new file mode 100644 index 0000000..a0b2f83 --- /dev/null +++ b/src/bridge.h @@ -0,0 +1,34 @@ +/* + * bridge.h + * This file is part of Network-inador + * + * Copyright (C) 2018 - 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 __BRIDGE_H__ +#define __BRIDGE_H__ + +#include "common.h" + +int interfaces_bridge_create (NetworkInadorHandle *handle, const char *name); +int interfaces_bridge_set_master_interface (NetworkInadorHandle *handle, int master_index, int index); +int interfaces_bridge_remove_master_interface (NetworkInadorHandle *handle, int index); +int interfaces_bridge_delete (NetworkInadorHandle *handle, int index); + +#endif + diff --git a/src/common.h b/src/common.h index 36c6c85..ed5a81c 100644 --- a/src/common.h +++ b/src/common.h @@ -109,15 +109,12 @@ typedef struct _Interface { /* Banderas estilo ioctl */ short flags; + int is_wireless; + char wireless_protocol[IFNAMSIZ]; /* Tipo */ - int is_loopback; - int is_wireless; - int is_bridge; - int is_vlan; - int is_nlmon; - int is_dummy; + char tipo_string[IFNAMSIZ]; GList *address; diff --git a/src/interfaces.c b/src/interfaces.c index 008d4b5..a0b9f8b 100644 --- a/src/interfaces.c +++ b/src/interfaces.c @@ -96,11 +96,6 @@ static int _interfaces_receive_message_interface (struct nl_msg *msg, void *arg, iface->flags = iface_msg->ifi_flags; iface->index = iface_msg->ifi_index; - if (iface_msg->ifi_type == ARPHRD_LOOPBACK) { - /* Es loopback */ - iface->is_loopback = 1; - } - nlmsg_for_each_attr(attr, reply, sizeof (struct ifinfomsg), remaining) { switch (nla_type (attr)) { //nla_len (Attr); @@ -149,16 +144,8 @@ static int _interfaces_receive_message_interface (struct nl_msg *msg, void *arg, switch (nla_type (sub_attr)) { case IFLA_INFO_KIND: printf ("IFLA_INFO_KIND: %s\n", nla_data (sub_attr)); - if (strcmp (nla_data (sub_attr), "vlan") == 0) { - iface->is_vlan = 1; - - } else if (strcmp (nla_data (sub_attr), "nlmon") == 0) { - iface->is_nlmon = 1; - } else if (strcmp (nla_data (sub_attr), "bridge") == 0) { - iface->is_bridge = 1; - } else if (strcmp (nla_data (sub_attr), "dummy") == 0) { - iface->is_dummy = 1; - } + strncpy (iface->tipo_string, nla_data (sub_attr), sizeof (iface->tipo_string) - 1); + iface->tipo_string[sizeof (iface->tipo_string) - 1] = 0; break; } } @@ -202,7 +189,7 @@ Interface * _interfaces_locate_by_index (GList *list, int index) { return NULL; } -static int _interfaces_wait_ack_or_error (struct nl_msg *msg, void *arg) { +int _interfaces_wait_ack_or_error (struct nl_msg *msg, void *arg) { int *ret = (int *) arg; struct nlmsgerr *l_err; struct nlmsghdr *reply; @@ -218,7 +205,7 @@ static int _interfaces_wait_ack_or_error (struct nl_msg *msg, void *arg) { return NL_SKIP; } -static int _interfaces_wait_error (struct sockaddr_nl *nla, struct nlmsgerr *l_err, void *arg) { +int _interfaces_wait_error (struct sockaddr_nl *nla, struct nlmsgerr *l_err, void *arg) { int *ret = (int *) arg; *ret = l_err->error; diff --git a/src/interfaces.h b/src/interfaces.h index 084da53..90f6a74 100644 --- a/src/interfaces.h +++ b/src/interfaces.h @@ -32,6 +32,9 @@ void interfaces_init (NetworkInadorHandle *handle); int interface_receive_message_newlink (struct nl_msg *msg, void *arg); int interface_receive_message_dellink (struct nl_msg *msg, void *arg); +int _interfaces_wait_ack_or_error (struct nl_msg *msg, void *arg); +int _interfaces_wait_error (struct sockaddr_nl *nla, struct nlmsgerr *l_err, void *arg); + Interface * _interfaces_locate_by_index (GList *list, int index); int interfaces_change_mac_address (NetworkInadorHandle *handle, int index, void *new_mac); diff --git a/src/ip-address.c b/src/ip-address.c index 39f1e0d..be3519d 100644 --- a/src/ip-address.c +++ b/src/ip-address.c @@ -114,13 +114,13 @@ int ip_address_receive_message_newaddr (struct nl_msg *msg, void *arg) { addr->prefix = addr_msg->ifa_prefixlen; } - char buffer[2048]; - inet_ntop (addr->family, &addr->sin_addr, buffer, sizeof (buffer)); - printf ("Dirección IP %s/%d sobre interfaz: %d\n", buffer, addr->prefix, iface->index); - addr->flags = addr_msg->ifa_flags; addr->scope = addr_msg->ifa_scope; + 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)); + return NL_SKIP; } diff --git a/src/main.c b/src/main.c index eaeb1c8..1469b85 100644 --- a/src/main.c +++ b/src/main.c @@ -39,6 +39,8 @@ #include "common.h" #include "interfaces.h" #include "netlink-events.h" +#include "ip-address.h" +#include "bridge.h" /* Usados para salir en caso de una señal */ static int sigterm_pipe_fds[2] = { -1, -1 };