1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
$NetBSD: patch-aa,v 1.1.1.1 2011/07/26 06:05:00 agc Exp $
bridge is only compilable on Linux right now
--- src/util/bridge.c 2011/07/17 17:36:59 1.1
+++ src/util/bridge.c 2011/07/17 17:37:20
@@ -39,10 +39,21 @@
# include <paths.h>
# include <sys/wait.h>
+#if defined(__linux__)
# include <linux/param.h> /* HZ */
# include <linux/sockios.h> /* SIOCBRADDBR etc. */
# include <linux/if_bridge.h> /* SYSFS_BRIDGE_ATTR */
# include <linux/if_tun.h> /* IFF_TUN, IFF_NO_PI */
+#elif defined(__NetBSD__)
+# include <sys/param.h>
+# include <sys/sockio.h>
+# include <net/if.h>
+# include <net/if_tap.h>
+# include <net/if_ether.h>
+# include <net/if_bridgevar.h>
+# include <net/if_tun.h>
+#endif
+
# include <net/if_arp.h> /* ARPHRD_ETHER */
# include "internal.h"
@@ -309,6 +320,7 @@
if (virStrcpyStatic(ifr.ifr_name, ifname) == NULL)
return EINVAL;
+#ifdef __linux__
/* To fill ifr.ifr_hdaddr.sa_family field */
if (ioctl(ctl->fd, SIOCGIFHWADDR, &ifr) != 0)
return errno;
@@ -316,6 +328,15 @@
memcpy(ifr.ifr_hwaddr.sa_data, macaddr, VIR_MAC_BUFLEN);
return ioctl(ctl->fd, SIOCSIFHWADDR, &ifr) == 0 ? 0 : errno;
+#elif defined(__NetBSD__)
+ /* To fill ifr.ifr_hdaddr.sa_family field */
+ if (ioctl(ctl->fd, SIOCGIFADDR, &ifr) != 0)
+ return errno;
+
+ memcpy(ifr.ifr_addr.sa_data, macaddr, VIR_MAC_BUFLEN);
+
+ return ioctl(ctl->fd, SIOCSIFADDR, &ifr) == 0 ? 0 : errno;
+#endif
}
/**
@@ -459,6 +480,10 @@
}
# endif
+#ifndef USE_ARG
+#define USE_ARG(x) /*LINTED*/(void)&(x)
+#endif
+
/**
* brAddTap:
* @ctl: bridge control pointer
@@ -487,6 +512,7 @@
bool up,
int *tapfd)
{
+#if defined(__linux__)
int fd;
struct ifreq ifr;
@@ -549,11 +575,68 @@
VIR_FORCE_CLOSE(fd);
return errno;
+#elif defined(__NetBSD__)
+ int fd;
+ struct ifreq ifr;
+
+ USE_ARG(vnet_hdr);
+ if (!ctl || !ctl->fd || !bridge || !ifname)
+ return EINVAL;
+
+ if ((fd = open("/dev/tun", O_RDWR)) < 0)
+ return errno;
+
+ memset(&ifr, 0, sizeof(ifr));
+
+ if (ioctl(fd, TAPGIFNAME, &ifr) < 0)
+ goto error;
+
+ if (virStrcpyStatic(ifr.ifr_name, *ifname) == NULL) {
+ errno = EINVAL;
+ goto error;
+ }
+
+ if (ioctl(fd, TUNSIFHEAD, &ifr) < 0)
+ goto error;
+
+ /* We need to set the interface MAC before adding it
+ * to the bridge, because the bridge assumes the lowest
+ * MAC of all enslaved interfaces & we don't want it
+ * seeing the kernel allocate random MAC for the TAP
+ * device before we set our static MAC.
+ */
+ if ((errno = ifSetInterfaceMac(ctl, ifr.ifr_name, macaddr)))
+ goto error;
+ /* We need to set the interface MTU before adding it
+ * to the bridge, because the bridge will have its
+ * MTU adjusted automatically when we add the new interface.
+ */
+ if ((errno = brSetInterfaceMtu(ctl, bridge, ifr.ifr_name)))
+ goto error;
+ if ((errno = brAddInterface(ctl, bridge, ifr.ifr_name)))
+ goto error;
+ if (up && ((errno = brSetInterfaceUp(ctl, ifr.ifr_name, 1))))
+ goto error;
+ VIR_FREE(*ifname);
+ if (!(*ifname = strdup(ifr.ifr_name)))
+ goto error;
+ if (tapfd)
+ *tapfd = fd;
+ else
+ VIR_FORCE_CLOSE(fd);
+ return 0;
+
+ error:
+ VIR_FORCE_CLOSE(fd);
+
+ return errno;
+#endif
}
int brDeleteTap(brControl *ctl,
const char *ifname)
{
+#if defined(__linux__)
struct ifreq try;
int fd;
@@ -580,6 +663,34 @@
VIR_FORCE_CLOSE(fd);
return errno;
+#elif defined(__NetBSD__)
+ struct ifreq try;
+ int fd;
+
+ if (!ctl || !ctl->fd || !ifname)
+ return EINVAL;
+
+ if ((fd = open("/dev/tun", O_RDWR)) < 0)
+ return errno;
+
+ memset(&try, 0, sizeof(try));
+ if (ioctl(fd, TAPGIFNAME, &try) < 0)
+ goto error;
+
+
+ if (virStrcpyStatic(try.ifr_name, ifname) == NULL) {
+ errno = EINVAL;
+ goto error;
+ }
+
+ if (ioctl(fd, TUNSIFHEAD, &try) < 0)
+ goto error;
+
+ error:
+ VIR_FORCE_CLOSE(fd);
+
+ return errno;
+#endif
}
|