diff options
author | Colin Watson <cjwatson@debian.org> | 2017-10-04 11:23:58 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2017-10-05 23:58:12 +0100 |
commit | 0556ea972b15607b7e13ff31bc05840881c91dd3 (patch) | |
tree | d6b8d48062d0278b5ae0eeff42d0e9afa9f26860 /openbsd-compat/port-tun.c | |
parent | db2122d97eb1ecdd8d99b7bf79b0dd2b5addfd92 (diff) | |
parent | 801a62eedaaf47b20dbf4b426dc3e084bf0c8d49 (diff) |
New upstream release (7.6p1)
Diffstat (limited to 'openbsd-compat/port-tun.c')
-rw-r--r-- | openbsd-compat/port-tun.c | 93 |
1 files changed, 45 insertions, 48 deletions
diff --git a/openbsd-compat/port-tun.c b/openbsd-compat/port-tun.c index a444adf1d..7579c6084 100644 --- a/openbsd-compat/port-tun.c +++ b/openbsd-compat/port-tun.c | |||
@@ -199,84 +199,81 @@ sys_tun_open(int tun, int mode) | |||
199 | */ | 199 | */ |
200 | 200 | ||
201 | #if defined(SSH_TUN_FILTER) | 201 | #if defined(SSH_TUN_FILTER) |
202 | /* | ||
203 | * The tunnel forwarding protocol prepends the address family of forwarded | ||
204 | * IP packets using OpenBSD's numbers. | ||
205 | */ | ||
202 | #define OPENBSD_AF_INET 2 | 206 | #define OPENBSD_AF_INET 2 |
203 | #define OPENBSD_AF_INET6 24 | 207 | #define OPENBSD_AF_INET6 24 |
204 | 208 | ||
205 | int | 209 | int |
206 | sys_tun_infilter(struct Channel *c, char *buf, int len) | 210 | sys_tun_infilter(struct ssh *ssh, struct Channel *c, char *buf, int _len) |
207 | { | 211 | { |
212 | int r; | ||
213 | size_t len; | ||
214 | char *ptr = buf; | ||
208 | #if defined(SSH_TUN_PREPEND_AF) | 215 | #if defined(SSH_TUN_PREPEND_AF) |
209 | char rbuf[CHAN_RBUF]; | 216 | char rbuf[CHAN_RBUF]; |
210 | struct ip *iph; | 217 | struct ip iph; |
211 | #endif | 218 | #endif |
212 | u_int32_t *af; | 219 | #if defined(SSH_TUN_PREPEND_AF) || defined(SSH_TUN_COMPAT_AF) |
213 | char *ptr = buf; | 220 | u_int32_t af; |
214 | int r; | ||
215 | |||
216 | #if defined(SSH_TUN_PREPEND_AF) | ||
217 | if (len <= 0 || len > (int)(sizeof(rbuf) - sizeof(*af))) | ||
218 | return (-1); | ||
219 | ptr = (char *)&rbuf[0]; | ||
220 | bcopy(buf, ptr + sizeof(u_int32_t), len); | ||
221 | len += sizeof(u_int32_t); | ||
222 | af = (u_int32_t *)ptr; | ||
223 | |||
224 | iph = (struct ip *)(ptr + sizeof(u_int32_t)); | ||
225 | switch (iph->ip_v) { | ||
226 | case 6: | ||
227 | *af = AF_INET6; | ||
228 | break; | ||
229 | case 4: | ||
230 | default: | ||
231 | *af = AF_INET; | ||
232 | break; | ||
233 | } | ||
234 | #endif | 221 | #endif |
235 | 222 | ||
236 | #if defined(SSH_TUN_COMPAT_AF) | 223 | /* XXX update channel input filter API to use unsigned length */ |
237 | if (len < (int)sizeof(u_int32_t)) | 224 | if (_len < 0) |
238 | return (-1); | 225 | return -1; |
226 | len = _len; | ||
239 | 227 | ||
240 | af = (u_int32_t *)ptr; | 228 | #if defined(SSH_TUN_PREPEND_AF) |
241 | if (*af == htonl(AF_INET6)) | 229 | if (len <= sizeof(iph) || len > sizeof(rbuf) - 4) |
242 | *af = htonl(OPENBSD_AF_INET6); | 230 | return -1; |
243 | else | 231 | /* Determine address family from packet IP header. */ |
244 | *af = htonl(OPENBSD_AF_INET); | 232 | memcpy(&iph, buf, sizeof(iph)); |
233 | af = iph.ip_v == 6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET; | ||
234 | /* Prepend address family to packet using OpenBSD constants */ | ||
235 | memcpy(rbuf + 4, buf, len); | ||
236 | len += 4; | ||
237 | POKE_U32(rbuf, af); | ||
238 | ptr = rbuf; | ||
239 | #elif defined(SSH_TUN_COMPAT_AF) | ||
240 | /* Convert existing address family header to OpenBSD value */ | ||
241 | if (len <= 4) | ||
242 | return -1; | ||
243 | af = PEEK_U32(buf); | ||
244 | /* Put it back */ | ||
245 | POKE_U32(buf, af == AF_INET6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET); | ||
245 | #endif | 246 | #endif |
246 | 247 | ||
247 | if ((r = sshbuf_put_string(&c->input, ptr, len)) != 0) | 248 | if ((r = sshbuf_put_string(c->input, ptr, len)) != 0) |
248 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 249 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
249 | return (0); | 250 | return (0); |
250 | } | 251 | } |
251 | 252 | ||
252 | u_char * | 253 | u_char * |
253 | sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen) | 254 | sys_tun_outfilter(struct ssh *ssh, struct Channel *c, |
255 | u_char **data, size_t *dlen) | ||
254 | { | 256 | { |
255 | u_char *buf; | 257 | u_char *buf; |
256 | u_int32_t *af; | 258 | u_int32_t af; |
257 | int r; | 259 | int r; |
258 | size_t xxx_dlen; | ||
259 | 260 | ||
260 | /* XXX new API is incompatible with this signature. */ | 261 | /* XXX new API is incompatible with this signature. */ |
261 | if ((r = sshbuf_get_string(&c->output, data, &xxx_dlen)) != 0) | 262 | if ((r = sshbuf_get_string(c->output, data, dlen)) != 0) |
262 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | 263 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
263 | if (dlen != NULL) | 264 | if (*dlen < sizeof(af)) |
264 | *dlen = xxx_dlen; | ||
265 | if (*dlen < sizeof(*af)) | ||
266 | return (NULL); | 265 | return (NULL); |
267 | buf = *data; | 266 | buf = *data; |
268 | 267 | ||
269 | #if defined(SSH_TUN_PREPEND_AF) | 268 | #if defined(SSH_TUN_PREPEND_AF) |
270 | *dlen -= sizeof(u_int32_t); | 269 | /* skip address family */ |
271 | buf = *data + sizeof(u_int32_t); | 270 | *dlen -= sizeof(af); |
271 | buf = *data + sizeof(af); | ||
272 | #elif defined(SSH_TUN_COMPAT_AF) | 272 | #elif defined(SSH_TUN_COMPAT_AF) |
273 | af = ntohl(*(u_int32_t *)buf); | 273 | /* translate address family */ |
274 | if (*af == OPENBSD_AF_INET6) | 274 | af = (PEEK_U32(buf) == OPENBSD_AF_INET6) ? AF_INET6 : AF_INET; |
275 | *af = htonl(AF_INET6); | 275 | POKE_U32(buf, af); |
276 | else | ||
277 | *af = htonl(AF_INET); | ||
278 | #endif | 276 | #endif |
279 | |||
280 | return (buf); | 277 | return (buf); |
281 | } | 278 | } |
282 | #endif /* SSH_TUN_FILTER */ | 279 | #endif /* SSH_TUN_FILTER */ |