|
Lines 199-247
sys_tun_open(int tun, int mode)
Link Here
|
| 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 Channel *c, char *buf, int _len) |
| 207 |
{ |
211 |
{ |
| 208 |
#if defined(SSH_TUN_PREPEND_AF) |
212 |
int r; |
| 209 |
char rbuf[CHAN_RBUF]; |
213 |
size_t len; |
| 210 |
struct ip *iph; |
|
|
| 211 |
#endif |
| 212 |
u_int32_t *af; |
| 213 |
char *ptr = buf; |
214 |
char *ptr = buf; |
| 214 |
int r; |
|
|
| 215 |
|
| 216 |
#if defined(SSH_TUN_PREPEND_AF) |
215 |
#if defined(SSH_TUN_PREPEND_AF) |
| 217 |
if (len <= 0 || len > (int)(sizeof(rbuf) - sizeof(*af))) |
216 |
char rbuf[CHAN_RBUF]; |
| 218 |
return (-1); |
217 |
struct ip iph; |
| 219 |
ptr = (char *)&rbuf[0]; |
218 |
#endif |
| 220 |
bcopy(buf, ptr + sizeof(u_int32_t), len); |
219 |
#if defined(SSH_TUN_PREPEND_AF) || defined(SSH_TUN_COMPAT_AF) |
| 221 |
len += sizeof(u_int32_t); |
220 |
u_int32_t af; |
| 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) |
|
Lines 253-259
u_char *
Link Here
|
| 253 |
sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen) |
254 |
sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen) |
| 254 |
{ |
255 |
{ |
| 255 |
u_char *buf; |
256 |
u_char *buf; |
| 256 |
u_int32_t *af; |
257 |
u_int32_t af; |
| 257 |
int r; |
258 |
int r; |
| 258 |
size_t xxx_dlen; |
259 |
size_t xxx_dlen; |
| 259 |
|
260 |
|
|
Lines 262-282
sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen)
Link Here
|
| 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 != NULL) |
| 264 |
*dlen = xxx_dlen; |
265 |
*dlen = xxx_dlen; |
| 265 |
if (*dlen < sizeof(*af)) |
266 |
if (*dlen < sizeof(af)) |
| 266 |
return (NULL); |
267 |
return (NULL); |
| 267 |
buf = *data; |
268 |
buf = *data; |
| 268 |
|
269 |
|
| 269 |
#if defined(SSH_TUN_PREPEND_AF) |
270 |
#if defined(SSH_TUN_PREPEND_AF) |
| 270 |
*dlen -= sizeof(u_int32_t); |
271 |
/* skip address family */ |
| 271 |
buf = *data + sizeof(u_int32_t); |
272 |
*dlen -= sizeof(af); |
|
|
273 |
buf = *data + sizeof(af); |
| 272 |
#elif defined(SSH_TUN_COMPAT_AF) |
274 |
#elif defined(SSH_TUN_COMPAT_AF) |
| 273 |
af = ntohl(*(u_int32_t *)buf); |
275 |
/* translate address family */ |
| 274 |
if (*af == OPENBSD_AF_INET6) |
276 |
af = (PEEK_U32(buf) == OPENBSD_AF_INET6) ? AF_INET6 : AF_INET; |
| 275 |
*af = htonl(AF_INET6); |
277 |
POKE_U32(buf, af); |
| 276 |
else |
|
|
| 277 |
*af = htonl(AF_INET); |
| 278 |
#endif |
278 |
#endif |
| 279 |
|
|
|
| 280 |
return (buf); |
279 |
return (buf); |
| 281 |
} |
280 |
} |
| 282 |
#endif /* SSH_TUN_FILTER */ |
281 |
#endif /* SSH_TUN_FILTER */ |