From 6fcb8d4e17a4fd6eb5c287c96088c0bb76e8cdcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Arreola=20Rodr=C3=ADguez?= Date: Fri, 10 Aug 2018 01:15:38 -0500 Subject: [PATCH] =?UTF-8?q?Agrego=20comandos=20b=C3=A1sicos=20para=20crear?= =?UTF-8?q?=20bridges,=20agregar=20interfaces=20y=20eliminarlas.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Makefile.am | 4 +- src/bridge.c | 300 +++++++++++++++++++++++++++++++++++++++++++ src/bridge.h | 33 +++++ src/network-inador.c | 1 + src/rta_aux.c | 71 ++++++++++ src/rta_aux.h | 31 +++++ 6 files changed, 439 insertions(+), 1 deletion(-) create mode 100644 src/bridge.c create mode 100644 src/bridge.h create mode 100644 src/rta_aux.c create mode 100644 src/rta_aux.h diff --git a/src/Makefile.am b/src/Makefile.am index 5feed3e..c1cf8f4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,7 +5,9 @@ network_inador_SOURCES = network-inador.c network-inador.h \ events.c events.h \ interfaces.c interfaces.h \ manager.c manager.h \ - utils.c utils.h + utils.c utils.h \ + bridge.c bridge.h \ + rta_aux.c rta_aux.h #network_inador_CPPFLAGS = -DGAMEDATA_DIR=\"$(gamedatadir)/\" -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS) network_inador_CPPFLAGS = -DLOCALEDIR=\"$(localedir)\" $(AM_CPPFLAGS) diff --git a/src/bridge.c b/src/bridge.c new file mode 100644 index 0000000..583e7c7 --- /dev/null +++ b/src/bridge.c @@ -0,0 +1,300 @@ +/* + * bridge.c + * This file is part of Network-inador + * + * Copyright (C) 2011 - 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 +#include + +#include "interfaces.h" +#include "rta_aux.h" + +void bridge_create (int sock, const char *name) { + struct msghdr rtnl_msg; + struct iovec io; + struct sockaddr_nl kernel; + char buffer[8192]; + int len; + struct nlmsghdr *nl; + struct ifinfomsg *ifi; + struct rtattr *linkinfo; + struct nlmsgerr *l_err; + struct sockaddr_nl local_nl; + socklen_t local_size; + + if (name != NULL) { + /* Validar la longitud del nombre, por seguridad */ + len = strlen (name) + 1; + if (len == 1) { + /* Nombre muy corto */ + return; + } + if (len > IFNAMSIZ) { + /* Nombre muy largo */ + return; + } + } + + /* Recuperar el puerto local del netlink */ + local_size = sizeof (local_nl); + getsockname (sock, (struct sockaddr *) &local_nl, &local_size); + + memset (&kernel, 0, sizeof (kernel)); + memset (buffer, 0, sizeof (buffer)); + memset (&io, 0, sizeof (io)); + memset (&rtnl_msg, 0, sizeof (rtnl_msg)); + + kernel.nl_family = AF_NETLINK; /* fill-in kernel address (destination of our message) */ + kernel.nl_groups = 0; + + nl = (struct nlmsghdr *) buffer; + nl->nlmsg_len = NLMSG_LENGTH (sizeof(struct ifinfomsg)); + nl->nlmsg_type = RTM_NEWLINK; + nl->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL; + nl->nlmsg_seq = global_nl_seq++; + nl->nlmsg_pid = local_nl.nl_pid; + + ifi = (struct ifinfomsg*) NLMSG_DATA (nl); + ifi->ifi_family = AF_UNSPEC; + ifi->ifi_index = 0; + + /* Si existe un nombre, anexar como atributo */ + if (name != NULL) { + rta_addattr_l (nl, sizeof (buffer), IFLA_IFNAME, name, strlen (name)); + } + + linkinfo = rta_addattr_nest (nl, sizeof (buffer), IFLA_LINKINFO); + rta_addattr_l (nl, sizeof (buffer), IFLA_INFO_KIND, "bridge", strlen ("bridge")); + rta_addattr_nest_end (nl, linkinfo); + + io.iov_base = buffer; + io.iov_len = nl->nlmsg_len; + + rtnl_msg.msg_iov = &io; + rtnl_msg.msg_iovlen = 1; + rtnl_msg.msg_name = &kernel; + rtnl_msg.msg_namelen = sizeof(kernel); + + len = sendmsg (sock, (struct msghdr *) &rtnl_msg, 0); + + /* Esperar la respuesta */ + memset (&io, 0, sizeof (io)); + memset (&rtnl_msg, 0, sizeof (rtnl_msg)); + memset (buffer, 0, sizeof (buffer)); + + io.iov_base = buffer; + io.iov_len = sizeof (buffer); + rtnl_msg.msg_iov = &io; + rtnl_msg.msg_iovlen = 1; + rtnl_msg.msg_name = &kernel; + rtnl_msg.msg_namelen = sizeof(kernel); + + len = recvmsg(sock, &rtnl_msg, 0); + nl = (struct nlmsghdr *) buffer; + for (; NLMSG_OK(nl, len); nl = NLMSG_NEXT(nl, len)) { + if (nl->nlmsg_type == NLMSG_DONE) { + printf ("Bridge ADD Msg type: DONE!\n"); + break; + } + if (nl->nlmsg_type == NLMSG_ERROR) { + l_err = (struct nlmsgerr*) NLMSG_DATA (nl); + if (nl->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr))) { + printf ("Bridge ADD Error tamaño truncado\n"); + } else if (l_err->error != 0) { + // Error: + printf ("Bridge ADD Error: %i\n", l_err->error); + } + break; + } + } +} + +void bridge_add_interface (int sock, Interface *bridge, Interface *slave) { + struct msghdr rtnl_msg; + struct iovec io; + struct sockaddr_nl kernel; + char buffer[8192]; + int len; + struct nlmsghdr *nl; + struct ifinfomsg *ifi; + struct nlmsgerr *l_err; + struct sockaddr_nl local_nl; + socklen_t local_size; + + /* Recuperar el puerto local del netlink */ + local_size = sizeof (local_nl); + getsockname (sock, (struct sockaddr *) &local_nl, &local_size); + + memset (&kernel, 0, sizeof (kernel)); + memset (buffer, 0, sizeof (buffer)); + memset (&io, 0, sizeof (io)); + memset (&rtnl_msg, 0, sizeof (rtnl_msg)); + + kernel.nl_family = AF_NETLINK; /* fill-in kernel address (destination of our message) */ + kernel.nl_groups = 0; + + nl = (struct nlmsghdr *) buffer; + nl->nlmsg_len = NLMSG_LENGTH (sizeof(struct ifinfomsg)); + nl->nlmsg_type = RTM_NEWLINK; + nl->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + nl->nlmsg_seq = global_nl_seq++; + nl->nlmsg_pid = local_nl.nl_pid; + + ifi = (struct ifinfomsg*) NLMSG_DATA (nl); + ifi->ifi_family = AF_UNSPEC; + ifi->ifi_index = slave->index; + + rta_addattr_l (nl, sizeof (buffer), IFLA_MASTER, &bridge->index, 4); + + io.iov_base = buffer; + io.iov_len = nl->nlmsg_len; + + rtnl_msg.msg_iov = &io; + rtnl_msg.msg_iovlen = 1; + rtnl_msg.msg_name = &kernel; + rtnl_msg.msg_namelen = sizeof(kernel); + + len = sendmsg (sock, (struct msghdr *) &rtnl_msg, 0); + + /* Esperar la respuesta */ + memset (&io, 0, sizeof (io)); + memset (&rtnl_msg, 0, sizeof (rtnl_msg)); + memset (buffer, 0, sizeof (buffer)); + + io.iov_base = buffer; + io.iov_len = sizeof (buffer); + rtnl_msg.msg_iov = &io; + rtnl_msg.msg_iovlen = 1; + rtnl_msg.msg_name = &kernel; + rtnl_msg.msg_namelen = sizeof(kernel); + + len = recvmsg(sock, &rtnl_msg, 0); + nl = (struct nlmsghdr *) buffer; + for (; NLMSG_OK(nl, len); nl = NLMSG_NEXT(nl, len)) { + if (nl->nlmsg_type == NLMSG_DONE) { + printf ("Bridge ADD Slave Msg type: DONE!\n"); + break; + } + if (nl->nlmsg_type == NLMSG_ERROR) { + l_err = (struct nlmsgerr*) NLMSG_DATA (nl); + if (nl->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr))) { + printf ("Bridge ADD Slave Error tamaño truncado\n"); + } else if (l_err->error != 0) { + // Error: + printf ("Bridge ADD Slave Error: %i\n", l_err->error); + } + break; + } + } +} + +void bridge_remove_slave_from_bridge (int sock, Interface *slave) { + struct msghdr rtnl_msg; + struct iovec io; + struct sockaddr_nl kernel; + char buffer[8192]; + int len; + struct nlmsghdr *nl; + struct ifinfomsg *ifi; + struct nlmsgerr *l_err; + struct sockaddr_nl local_nl; + socklen_t local_size; + + /* Recuperar el puerto local del netlink */ + local_size = sizeof (local_nl); + getsockname (sock, (struct sockaddr *) &local_nl, &local_size); + + memset (&kernel, 0, sizeof (kernel)); + memset (buffer, 0, sizeof (buffer)); + memset (&io, 0, sizeof (io)); + memset (&rtnl_msg, 0, sizeof (rtnl_msg)); + + kernel.nl_family = AF_NETLINK; /* fill-in kernel address (destination of our message) */ + kernel.nl_groups = 0; + + nl = (struct nlmsghdr *) buffer; + nl->nlmsg_len = NLMSG_LENGTH (sizeof(struct ifinfomsg)); + nl->nlmsg_type = RTM_NEWLINK; + nl->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + nl->nlmsg_seq = global_nl_seq++; + nl->nlmsg_pid = local_nl.nl_pid; + + ifi = (struct ifinfomsg*) NLMSG_DATA (nl); + ifi->ifi_family = AF_UNSPEC; + ifi->ifi_index = slave->index; + + int ifindex = 0; + rta_addattr_l (nl, sizeof (buffer), IFLA_MASTER, &ifindex, 4); + + io.iov_base = buffer; + io.iov_len = nl->nlmsg_len; + + rtnl_msg.msg_iov = &io; + rtnl_msg.msg_iovlen = 1; + rtnl_msg.msg_name = &kernel; + rtnl_msg.msg_namelen = sizeof(kernel); + + len = sendmsg (sock, (struct msghdr *) &rtnl_msg, 0); + + /* Esperar la respuesta */ + memset (&io, 0, sizeof (io)); + memset (&rtnl_msg, 0, sizeof (rtnl_msg)); + memset (buffer, 0, sizeof (buffer)); + + io.iov_base = buffer; + io.iov_len = sizeof (buffer); + rtnl_msg.msg_iov = &io; + rtnl_msg.msg_iovlen = 1; + rtnl_msg.msg_name = &kernel; + rtnl_msg.msg_namelen = sizeof(kernel); + + len = recvmsg(sock, &rtnl_msg, 0); + nl = (struct nlmsghdr *) buffer; + for (; NLMSG_OK(nl, len); nl = NLMSG_NEXT(nl, len)) { + if (nl->nlmsg_type == NLMSG_DONE) { + printf ("Bridge NOMaster Msg type: DONE!\n"); + break; + } + if (nl->nlmsg_type == NLMSG_ERROR) { + l_err = (struct nlmsgerr*) NLMSG_DATA (nl); + if (nl->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr))) { + printf ("Bridge NOMaster Error tamaño truncado\n"); + } else if (l_err->error != 0) { + // Error: + printf ("Bridge NOMaster Error: %i\n", l_err->error); + } + break; + } + } +} diff --git a/src/bridge.h b/src/bridge.h new file mode 100644 index 0000000..587840e --- /dev/null +++ b/src/bridge.h @@ -0,0 +1,33 @@ +/* + * bridge.h + * This file is part of Network-inador + * + * Copyright (C) 2011 - 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 "network-inador.h" + +void bridge_create (int sock, const char *name); +void bridge_add_interface (int sock, Interface *bridge, Interface *slave); +void bridge_remove_slave_from_bridge (int sock, Interface *slave); + +#endif + diff --git a/src/network-inador.c b/src/network-inador.c index bd51d80..8fef09d 100644 --- a/src/network-inador.c +++ b/src/network-inador.c @@ -44,6 +44,7 @@ #include "interfaces.h" #include "events.h" #include "manager.h" +#include "bridge.h" static GMainLoop *loop = NULL; diff --git a/src/rta_aux.c b/src/rta_aux.c new file mode 100644 index 0000000..248aa42 --- /dev/null +++ b/src/rta_aux.c @@ -0,0 +1,71 @@ +/* + * rta_aux.c + * This file is part of Network-inador + * + * Copyright (C) 2011 - 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 +#include + +#define NLMSG_TAIL(nmsg) \ + ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) + +int rta_addattr_l (struct nlmsghdr *n, int maxlen, int type, const void *data, int alen) { + int len = RTA_LENGTH (alen); + struct rtattr *rta; + + if (NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len) > maxlen) { + return -1; + } + + rta = NLMSG_TAIL (n); + rta->rta_type = type; + rta->rta_len = len; + memcpy (RTA_DATA (rta), data, alen); + n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len); + + return 0; +} + +struct rtattr * rta_addattr_nest (struct nlmsghdr *n, int maxlen, int type) { + struct rtattr *nest = NLMSG_TAIL (n); + + rta_addattr_l (n, maxlen, type, NULL, 0); + + return nest; +} + +int rta_addattr_nest_end (struct nlmsghdr *n, struct rtattr *nest) { + nest->rta_len = (void *) NLMSG_TAIL (n) - (void *) nest; + return n->nlmsg_len; +} + diff --git a/src/rta_aux.h b/src/rta_aux.h new file mode 100644 index 0000000..d9ba3b7 --- /dev/null +++ b/src/rta_aux.h @@ -0,0 +1,31 @@ +/* + * rta_aux.h + * This file is part of Network-inador + * + * Copyright (C) 2011 - 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 __RTA_AUX_H__ +#define __RTA_AUX_H__ + +int rta_addattr_l (struct nlmsghdr *n, int maxlen, int type, const void *data, int alen); +struct rtattr * rta_addattr_nest (struct nlmsghdr *n, int maxlen, int type); +int rta_addattr_nest_end (struct nlmsghdr *n, struct rtattr *nest); + +#endif +