aboutsummaryrefslogtreecommitdiffstats
path: root/src/fnet/veth.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fnet/veth.c')
-rw-r--r--src/fnet/veth.c236
1 files changed, 236 insertions, 0 deletions
diff --git a/src/fnet/veth.c b/src/fnet/veth.c
new file mode 100644
index 000000000..546fafcec
--- /dev/null
+++ b/src/fnet/veth.c
@@ -0,0 +1,236 @@
1/* code based on iproute2 ip/iplink.c, modified to be included in firejail project
2 *
3 * Original source code:
4 *
5 * Information:
6 * http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2
7 *
8 * Download:
9 * http://www.kernel.org/pub/linux/utils/net/iproute2/
10 *
11 * Repository:
12 * git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
13 *
14 * License: GPL v2
15 *
16 * Original copyright header
17 *
18 * iplink.c "ip link".
19 *
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version
23 * 2 of the License, or (at your option) any later version.
24 *
25 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
26 *
27 */
28 /*
29 * Copyright (C) 2014-2016 Firejail Authors
30 *
31 * This file is part of firejail project
32 *
33 * This program is free software; you can redistribute it and/or modify
34 * it under the terms of the GNU General Public License as published by
35 * the Free Software Foundation; either version 2 of the License, or
36 * (at your option) any later version.
37 *
38 * This program is distributed in the hope that it will be useful,
39 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41 * GNU General Public License for more details.
42 *
43 * You should have received a copy of the GNU General Public License along
44 * with this program; if not, write to the Free Software Foundation, Inc.,
45 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
46*/
47
48#include "fnet.h"
49#include "../include/libnetlink.h"
50#include <linux/veth.h>
51#include <net/if.h>
52
53struct iplink_req
54{
55 struct nlmsghdr n;
56 struct ifinfomsg i;
57 char buf[1024];
58};
59
60static struct rtnl_handle rth = { .fd = -1 };
61
62int net_create_veth(const char *dev, const char *nsdev, unsigned pid) {
63 int len;
64 struct iplink_req req;
65
66 assert(dev);
67 assert(nsdev);
68 assert(pid);
69
70 if (rtnl_open(&rth, 0) < 0) {
71 fprintf(stderr, "cannot open netlink\n");
72 exit(1);
73 }
74
75 memset(&req, 0, sizeof(req));
76
77 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
78 req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
79 req.n.nlmsg_type = RTM_NEWLINK;
80 req.i.ifi_family = 0;
81
82 if (dev) {
83 len = strlen(dev) + 1;
84 addattr_l(&req.n, sizeof(req), IFLA_IFNAME, dev, len);
85 }
86
87 struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
88 addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
89 addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "veth", strlen("veth"));
90
91 struct rtattr * data = NLMSG_TAIL(&req.n);
92 addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
93
94 struct rtattr * peerdata = NLMSG_TAIL(&req.n);
95 addattr_l (&req.n, sizeof(req), VETH_INFO_PEER, NULL, 0);
96 req.n.nlmsg_len += sizeof(struct ifinfomsg);
97
98 // place the link in the child namespace
99 addattr_l (&req.n, sizeof(req), IFLA_NET_NS_PID, &pid, 4);
100
101 if (nsdev) {
102 int len = strlen(nsdev) + 1;
103 addattr_l(&req.n, sizeof(req), IFLA_IFNAME, nsdev, len);
104 }
105 peerdata->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)peerdata;
106
107 data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
108 linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
109
110 // send message
111 if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
112 exit(2);
113
114 rtnl_close(&rth);
115
116 return 0;
117}
118
119
120int net_create_macvlan(const char *dev, const char *parent, unsigned pid) {
121 int len;
122 struct iplink_req req;
123 assert(dev);
124 assert(parent);
125
126 if (rtnl_open(&rth, 0) < 0) {
127 fprintf(stderr, "cannot open netlink\n");
128 exit(1);
129 }
130
131 memset(&req, 0, sizeof(req));
132
133 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
134 req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL;
135 req.n.nlmsg_type = RTM_NEWLINK;
136 req.i.ifi_family = 0;
137
138 // find parent ifindex
139 int parent_ifindex = if_nametoindex(parent);
140 if (parent_ifindex <= 0) {
141 fprintf(stderr, "Error: cannot find network device %s\n", parent);
142 exit(1);
143 }
144
145 // add parent
146 addattr_l(&req.n, sizeof(req), IFLA_LINK, &parent_ifindex, 4);
147
148 // add new interface name
149 len = strlen(dev) + 1;
150 addattr_l(&req.n, sizeof(req), IFLA_IFNAME, dev, len);
151
152 // place the interface in child namespace
153 addattr_l (&req.n, sizeof(req), IFLA_NET_NS_PID, &pid, 4);
154
155
156 // add link info for the new interface
157 struct rtattr *linkinfo = NLMSG_TAIL(&req.n);
158 addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
159 addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "macvlan", strlen("macvlan"));
160
161 // set macvlan bridge mode
162 struct rtattr * data = NLMSG_TAIL(&req.n);
163 addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0);
164 int macvlan_type = MACVLAN_MODE_BRIDGE;
165 addattr_l (&req.n, sizeof(req), IFLA_INFO_KIND, &macvlan_type, 4);
166
167 data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
168// req.n.nlmsg_len += sizeof(struct ifinfomsg);
169
170
171 data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data;
172 linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo;
173
174 // send message
175 if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
176 exit(2);
177
178 rtnl_close(&rth);
179
180 return 0;
181}
182
183// move the interface dev in namespace of program pid
184// when the interface is moved, netlink does not preserve interface configuration
185int net_move_interface(const char *dev, unsigned pid) {
186 struct iplink_req req;
187 assert(dev);
188
189 if (rtnl_open(&rth, 0) < 0) {
190 fprintf(stderr, "cannot open netlink\n");
191 exit(1);
192 }
193
194 memset(&req, 0, sizeof(req));
195
196 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
197 req.n.nlmsg_flags = NLM_F_REQUEST;
198 req.n.nlmsg_type = RTM_NEWLINK;
199 req.i.ifi_family = 0;
200
201 // find ifindex
202 int ifindex = if_nametoindex(dev);
203 if (ifindex <= 0) {
204 fprintf(stderr, "Error: cannot find interface %s\n", dev);
205 exit(1);
206 }
207 req.i.ifi_index = ifindex;
208
209 // place the interface in child namespace
210 addattr_l (&req.n, sizeof(req), IFLA_NET_NS_PID, &pid, 4);
211
212 // send message
213 if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0)
214 exit(2);
215
216 rtnl_close(&rth);
217
218 return 0;
219}
220
221/*
222int main(int argc, char **argv) {
223 printf("Hello\n");
224
225
226 char *dev = argv[3];
227 char *nsdev = argv[8];
228 unsigned pid;
229 sscanf(argv[10], "%u", &pid);
230
231
232 net_create_veth(dev, nsdev, pid);
233
234 return 0;
235}
236*/ \ No newline at end of file