From abe5cb027416771da3d01c9b55d12a8f70618ed8 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Thu, 27 Oct 2016 08:58:48 -0400 Subject: network code split --- src/fnet/veth.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 src/fnet/veth.c (limited to 'src/fnet/veth.c') diff --git a/src/fnet/veth.c b/src/fnet/veth.c new file mode 100644 index 000000000..d06bc9256 --- /dev/null +++ b/src/fnet/veth.c @@ -0,0 +1,230 @@ +/* code based on iproute2 ip/iplink.c, modified to be included in firejail project + * + * Original source code: + * + * Information: + * http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2 + * + * Download: + * http://www.kernel.org/pub/linux/utils/net/iproute2/ + * + * Repository: + * git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git + * + * License: GPL v2 + * + * Original copyright header + * + * iplink.c "ip link". + * + * This program 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. + * + * Authors: Alexey Kuznetsov, + * + */ + /* + * Copyright (C) 2014-2016 Firejail Authors + * + * This file is part of firejail project + * + * This program 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. + * + * This program 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "fnet.h" +#include "../include/libnetlink.h" +#include +#include + +struct iplink_req +{ + struct nlmsghdr n; + struct ifinfomsg i; + char buf[1024]; +}; + +static struct rtnl_handle rth = { .fd = -1 }; + +int net_create_veth(const char *dev, const char *nsdev, unsigned pid) { + int len; + struct iplink_req req; + + assert(dev); + assert(nsdev); + assert(pid); + + if (rtnl_open(&rth, 0) < 0) { + fprintf(stderr, "cannot open netlink\n"); + exit(1); + } + + memset(&req, 0, sizeof(req)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL; + req.n.nlmsg_type = RTM_NEWLINK; + req.i.ifi_family = 0; + + if (dev) { + len = strlen(dev) + 1; + addattr_l(&req.n, sizeof(req), IFLA_IFNAME, dev, len); + } + + struct rtattr *linkinfo = NLMSG_TAIL(&req.n); + addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); + addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "veth", strlen("veth")); + + struct rtattr * data = NLMSG_TAIL(&req.n); + addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0); + + struct rtattr * peerdata = NLMSG_TAIL(&req.n); + addattr_l (&req.n, sizeof(req), VETH_INFO_PEER, NULL, 0); + req.n.nlmsg_len += sizeof(struct ifinfomsg); + + // place the link in the child namespace + addattr_l (&req.n, sizeof(req), IFLA_NET_NS_PID, &pid, 4); + + if (nsdev) { + int len = strlen(nsdev) + 1; + addattr_l(&req.n, sizeof(req), IFLA_IFNAME, nsdev, len); + } + peerdata->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)peerdata; + + data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data; + linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; + + // send message + if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) + exit(2); + + return 0; +} + + +int net_create_macvlan(const char *dev, const char *parent, unsigned pid) { + int len; + struct iplink_req req; + assert(dev); + assert(parent); + + if (rtnl_open(&rth, 0) < 0) { + fprintf(stderr, "cannot open netlink\n"); + exit(1); + } + + memset(&req, 0, sizeof(req)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL; + req.n.nlmsg_type = RTM_NEWLINK; + req.i.ifi_family = 0; + + // find parent ifindex + int parent_ifindex = if_nametoindex(parent); + if (parent_ifindex <= 0) { + fprintf(stderr, "Error: cannot find network device %s\n", parent); + exit(1); + } + + // add parent + addattr_l(&req.n, sizeof(req), IFLA_LINK, &parent_ifindex, 4); + + // add new interface name + len = strlen(dev) + 1; + addattr_l(&req.n, sizeof(req), IFLA_IFNAME, dev, len); + + // place the interface in child namespace + addattr_l (&req.n, sizeof(req), IFLA_NET_NS_PID, &pid, 4); + + + // add link info for the new interface + struct rtattr *linkinfo = NLMSG_TAIL(&req.n); + addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); + addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "macvlan", strlen("macvlan")); + + // set macvlan bridge mode + struct rtattr * data = NLMSG_TAIL(&req.n); + addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0); + int macvlan_type = MACVLAN_MODE_BRIDGE; + addattr_l (&req.n, sizeof(req), IFLA_INFO_KIND, &macvlan_type, 4); + + data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data; +// req.n.nlmsg_len += sizeof(struct ifinfomsg); + + + data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data; + linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; + + // send message + if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) + exit(2); + + return 0; +} + +// move the interface dev in namespace of program pid +// when the interface is moved, netlink does not preserve interface configuration +int net_move_interface(const char *dev, unsigned pid) { + struct iplink_req req; + assert(dev); + + if (rtnl_open(&rth, 0) < 0) { + fprintf(stderr, "cannot open netlink\n"); + exit(1); + } + + memset(&req, 0, sizeof(req)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_NEWLINK; + req.i.ifi_family = 0; + + // find ifindex + int ifindex = if_nametoindex(dev); + if (ifindex <= 0) { + fprintf(stderr, "Error: cannot find interface %s\n", dev); + exit(1); + } + req.i.ifi_index = ifindex; + + // place the interface in child namespace + addattr_l (&req.n, sizeof(req), IFLA_NET_NS_PID, &pid, 4); + + // send message + if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) + exit(2); + + return 0; +} + +/* +int main(int argc, char **argv) { + printf("Hello\n"); + + + char *dev = argv[3]; + char *nsdev = argv[8]; + unsigned pid; + sscanf(argv[10], "%u", &pid); + + + net_create_veth(dev, nsdev, pid); + + return 0; +} +*/ \ No newline at end of file -- cgit v1.2.3-54-g00ecf