Line | Source | Count |
1 | | - |
2 | | - |
3 | | - |
4 | | - |
5 | | - |
6 | | - |
7 | | - |
8 | | - |
9 | | - |
10 | | - |
11 | | - |
12 | | - |
13 | | - |
14 | | - |
15 | | - |
16 | | - |
17 | #include "includes.h" | - |
18 | | - |
19 | #include <sys/types.h> | - |
20 | #include <sys/ioctl.h> | - |
21 | | - |
22 | #include <netinet/in.h> | - |
23 | #include <arpa/inet.h> | - |
24 | #include <netinet/ip.h> | - |
25 | | - |
26 | #include <errno.h> | - |
27 | #include <fcntl.h> | - |
28 | #include <stdarg.h> | - |
29 | #include <string.h> | - |
30 | #include <unistd.h> | - |
31 | | - |
32 | #include "openbsd-compat/sys-queue.h" | - |
33 | #include "log.h" | - |
34 | #include "misc.h" | - |
35 | #include "sshbuf.h" | - |
36 | #include "channels.h" | - |
37 | #include "ssherr.h" | - |
38 | | - |
39 | | - |
40 | | - |
41 | | - |
42 | | - |
43 | | - |
44 | #if defined(SYS_RDOMAIN_LINUX) || defined(SSH_TUN_LINUX) | - |
45 | #include <linux/if.h> | - |
46 | #endif | - |
47 | | - |
48 | #if defined(SYS_RDOMAIN_LINUX) | - |
49 | char * | - |
50 | sys_get_rdomain(int fd) | - |
51 | { | - |
52 | char dev[IFNAMSIZ + 1]; | - |
53 | socklen_t len = sizeof(dev) - 1; | - |
54 | | - |
55 | if (getsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, dev, &len) == -1) { | - |
56 | error("%s: cannot determine VRF for fd=%d : %s", | - |
57 | __func__, fd, strerror(errno)); | - |
58 | return NULL; | - |
59 | } | - |
60 | dev[len] = '\0'; | - |
61 | return strdup(dev); | - |
62 | } | - |
63 | | - |
64 | int | - |
65 | sys_set_rdomain(int fd, const char *name) | - |
66 | { | - |
67 | if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, | - |
68 | name, strlen(name)) == -1) { | - |
69 | error("%s: setsockopt(%d, SO_BINDTODEVICE, %s): %s", | - |
70 | __func__, fd, name, strerror(errno)); | - |
71 | return -1; | - |
72 | } | - |
73 | return 0; | - |
74 | } | - |
75 | | - |
76 | int | - |
77 | sys_valid_rdomain(const char *name) | - |
78 | { | - |
79 | int fd; | - |
80 | | - |
81 | | - |
82 | | - |
83 | | - |
84 | | - |
85 | | - |
86 | if ((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) | - |
87 | return 0; | - |
88 | if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, | - |
89 | name, strlen(name)) == -1) { | - |
90 | close(fd); | - |
91 | return 0; | - |
92 | } | - |
93 | close(fd); | - |
94 | return 1; | - |
95 | } | - |
96 | #elif defined(SYS_RDOMAIN_XXX) | - |
97 | | - |
98 | char * | - |
99 | sys_get_rdomain(int fd) | - |
100 | { | - |
101 | return NULL; | - |
102 | } | - |
103 | | - |
104 | int | - |
105 | sys_set_rdomain(int fd, const char *name) | - |
106 | { | - |
107 | return -1; | - |
108 | } | - |
109 | | - |
110 | int | - |
111 | valid_rdomain(const char *name) | - |
112 | { | - |
113 | return 0; | - |
114 | } | - |
115 | | - |
116 | void | - |
117 | sys_set_process_rdomain(const char *name) | - |
118 | { | - |
119 | fatal("%s: not supported", __func__); | - |
120 | } | - |
121 | #endif /* defined(SYS_RDOMAIN_XXX) */ | - |
122 | | - |
123 | | - |
124 | | - |
125 | | - |
126 | | - |
127 | | - |
128 | | - |
129 | | - |
130 | | - |
131 | | - |
132 | | - |
133 | | - |
134 | | - |
135 | | - |
136 | | - |
137 | | - |
138 | #if defined(SSH_TUN_LINUX) | - |
139 | #include <linux/if_tun.h> | - |
140 | | - |
141 | int | - |
142 | sys_tun_open(int tun, int mode, char **ifname) | - |
143 | { | - |
144 | struct ifreq ifr; | - |
145 | int fd = -1; | - |
146 | const char *name = NULL; | - |
147 | | - |
148 | if (ifname != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
149 | *ifname = NULL; never executed: *ifname = ((void *)0) ; | 0 |
150 | | - |
151 | if ((fd = open("/dev/net/tun", O_RDWR)) == -1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
152 | debug("%s: failed to open tunnel control interface: %s", | - |
153 | __func__, strerror(errno)); | - |
154 | return (-1); never executed: return (-1); | 0 |
155 | } | - |
156 | | - |
157 | bzero(&ifr, sizeof(ifr)); | - |
158 | | - |
159 | if (mode == SSH_TUNMODE_ETHERNET) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
160 | ifr.ifr_flags = IFF_TAP; | - |
161 | name = "tap%d"; | - |
162 | } else { never executed: end of block | 0 |
163 | ifr.ifr_flags = IFF_TUN; | - |
164 | name = "tun%d"; | - |
165 | } never executed: end of block | 0 |
166 | ifr.ifr_flags |= IFF_NO_PI; | - |
167 | | - |
168 | if (tun != SSH_TUNID_ANY) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
169 | if (tun > SSH_TUNID_MAX) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
170 | debug("%s: invalid tunnel id %x: %s", __func__, | - |
171 | tun, strerror(errno)); | - |
172 | goto failed; never executed: goto failed; | 0 |
173 | } | - |
174 | snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), name, tun); | - |
175 | } never executed: end of block | 0 |
176 | | - |
177 | if (ioctl(fd, TUNSETIFF, &ifr) == -1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
178 | debug("%s: failed to configure tunnel (mode %d): %s", __func__, | - |
179 | mode, strerror(errno)); | - |
180 | goto failed; never executed: goto failed; | 0 |
181 | } | - |
182 | | - |
183 | if (tun == SSH_TUNID_ANY)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
184 | debug("%s: tunnel mode %d fd %d", __func__, mode, fd); never executed: debug("%s: tunnel mode %d fd %d", __func__, mode, fd); | 0 |
185 | else | - |
186 | debug("%s: %s mode %d fd %d", __func__, ifr.ifr_name, mode, fd); never executed: debug("%s: %s mode %d fd %d", __func__, ifr. ifr_ifrn.ifrn_name , mode, fd); | 0 |
187 | | - |
188 | if (ifname != NULL && (*ifname = strdup(ifr.ifr_name)) == NULL) never executed: __retval = (char *) memcpy (__retval, ifr. ifr_ifrn.ifrn_name, __len); TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
189 | goto failed; never executed: goto failed; | 0 |
190 | | - |
191 | return (fd); never executed: return (fd); | 0 |
192 | | - |
193 | failed: | - |
194 | close(fd); | - |
195 | return (-1); never executed: return (-1); | 0 |
196 | } | - |
197 | #endif /* SSH_TUN_LINUX */ | - |
198 | | - |
199 | #ifdef SSH_TUN_FREEBSD | - |
200 | #include <sys/socket.h> | - |
201 | #include <net/if.h> | - |
202 | | - |
203 | #ifdef HAVE_NET_IF_TUN_H | - |
204 | #include <net/if_tun.h> | - |
205 | #endif | - |
206 | | - |
207 | int | - |
208 | sys_tun_open(int tun, int mode, char **ifname) | - |
209 | { | - |
210 | struct ifreq ifr; | - |
211 | char name[100]; | - |
212 | int fd = -1, sock, flag; | - |
213 | const char *tunbase = "tun"; | - |
214 | | - |
215 | if (ifname != NULL) | - |
216 | *ifname = NULL; | - |
217 | | - |
218 | if (mode == SSH_TUNMODE_ETHERNET) { | - |
219 | #ifdef SSH_TUN_NO_L2 | - |
220 | debug("%s: no layer 2 tunnelling support", __func__); | - |
221 | return (-1); | - |
222 | #else | - |
223 | tunbase = "tap"; | - |
224 | #endif | - |
225 | } | - |
226 | | - |
227 | | - |
228 | if (tun <= SSH_TUNID_MAX) { | - |
229 | snprintf(name, sizeof(name), "/dev/%s%d", tunbase, tun); | - |
230 | fd = open(name, O_RDWR); | - |
231 | } else if (tun == SSH_TUNID_ANY) { | - |
232 | for (tun = 100; tun >= 0; tun--) { | - |
233 | snprintf(name, sizeof(name), "/dev/%s%d", | - |
234 | tunbase, tun); | - |
235 | if ((fd = open(name, O_RDWR)) >= 0) | - |
236 | break; | - |
237 | } | - |
238 | } else { | - |
239 | debug("%s: invalid tunnel %u\n", __func__, tun); | - |
240 | return (-1); | - |
241 | } | - |
242 | | - |
243 | if (fd < 0) { | - |
244 | debug("%s: %s open failed: %s", __func__, name, | - |
245 | strerror(errno)); | - |
246 | return (-1); | - |
247 | } | - |
248 | | - |
249 | | - |
250 | flag = 1; | - |
251 | #if defined(TUNSIFHEAD) && !defined(SSH_TUN_PREPEND_AF) | - |
252 | if (mode != SSH_TUNMODE_ETHERNET && | - |
253 | ioctl(fd, TUNSIFHEAD, &flag) == -1) { | - |
254 | debug("%s: ioctl(%d, TUNSIFHEAD, 1): %s", __func__, fd, | - |
255 | strerror(errno)); | - |
256 | close(fd); | - |
257 | } | - |
258 | #endif | - |
259 | | - |
260 | debug("%s: %s mode %d fd %d", __func__, name, mode, fd); | - |
261 | | - |
262 | | - |
263 | snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun); | - |
264 | if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) | - |
265 | goto failed; | - |
266 | | - |
267 | if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) | - |
268 | goto failed; | - |
269 | if ((ifr.ifr_flags & IFF_UP) == 0) { | - |
270 | ifr.ifr_flags |= IFF_UP; | - |
271 | if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) | - |
272 | goto failed; | - |
273 | } | - |
274 | | - |
275 | if (ifname != NULL && (*ifname = strdup(ifr.ifr_name)) == NULL) | - |
276 | goto failed; | - |
277 | | - |
278 | close(sock); | - |
279 | return (fd); | - |
280 | | - |
281 | failed: | - |
282 | if (fd >= 0) | - |
283 | close(fd); | - |
284 | if (sock >= 0) | - |
285 | close(sock); | - |
286 | debug("%s: failed to set %s mode %d: %s", __func__, name, | - |
287 | mode, strerror(errno)); | - |
288 | return (-1); | - |
289 | } | - |
290 | #endif /* SSH_TUN_FREEBSD */ | - |
291 | | - |
292 | | - |
293 | | - |
294 | | - |
295 | | - |
296 | #if defined(SSH_TUN_FILTER) | - |
297 | | - |
298 | | - |
299 | | - |
300 | | - |
301 | #define OPENBSD_AF_INET 2 | - |
302 | #define OPENBSD_AF_INET6 24 | - |
303 | | - |
304 | int | - |
305 | sys_tun_infilter(struct ssh *ssh, struct Channel *c, char *buf, int _len) | - |
306 | { | - |
307 | int r; | - |
308 | size_t len; | - |
309 | char *ptr = buf; | - |
310 | #if defined(SSH_TUN_PREPEND_AF) | - |
311 | char rbuf[CHAN_RBUF]; | - |
312 | struct ip iph; | - |
313 | #endif | - |
314 | #if defined(SSH_TUN_PREPEND_AF) || defined(SSH_TUN_COMPAT_AF) | - |
315 | u_int32_t af; | - |
316 | #endif | - |
317 | | - |
318 | | - |
319 | if (_len < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
320 | return -1; never executed: return -1; | 0 |
321 | len = _len; | - |
322 | | - |
323 | #if defined(SSH_TUN_PREPEND_AF) | - |
324 | if (len <= sizeof(iph) || len > sizeof(rbuf) - 4)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
325 | return -1; never executed: return -1; | 0 |
326 | | - |
327 | memcpy(&iph, buf, sizeof(iph)); | - |
328 | af = iph.ip_v == 6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET;TRUE | never evaluated | FALSE | never evaluated |
| 0 |
329 | | - |
330 | memcpy(rbuf + 4, buf, len); | - |
331 | len += 4; | - |
332 | POKE_U32(rbuf, af); | - |
333 | ptr = rbuf; | - |
334 | #elif defined(SSH_TUN_COMPAT_AF) | - |
335 | | - |
336 | if (len <= 4) | - |
337 | return -1; | - |
338 | af = PEEK_U32(buf); | - |
339 | | - |
340 | POKE_U32(buf, af == AF_INET6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET); | - |
341 | #endif | - |
342 | | - |
343 | if ((r = sshbuf_put_string(c->input, ptr, len)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
344 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); never executed: fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 0 |
345 | return (0); never executed: return (0); | 0 |
346 | } | - |
347 | | - |
348 | u_char * | - |
349 | sys_tun_outfilter(struct ssh *ssh, struct Channel *c, | - |
350 | u_char **data, size_t *dlen) | - |
351 | { | - |
352 | u_char *buf; | - |
353 | u_int32_t af; | - |
354 | int r; | - |
355 | | - |
356 | | - |
357 | if ((r = sshbuf_get_string(c->output, data, dlen)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
358 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); never executed: fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 0 |
359 | if (*dlen < sizeof(af))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
360 | return (NULL); never executed: return ( ((void *)0) ); | 0 |
361 | buf = *data; | - |
362 | | - |
363 | #if defined(SSH_TUN_PREPEND_AF) | - |
364 | | - |
365 | *dlen -= sizeof(af); | - |
366 | buf = *data + sizeof(af); | - |
367 | #elif defined(SSH_TUN_COMPAT_AF) | - |
368 | | - |
369 | af = (PEEK_U32(buf) == OPENBSD_AF_INET6) ? AF_INET6 : AF_INET; | - |
370 | POKE_U32(buf, af); | - |
371 | #endif | - |
372 | return (buf); never executed: return (buf); | 0 |
373 | } | - |
374 | #endif /* SSH_TUN_FILTER */ | - |
| | |