Messages in this thread | | | From | Patrick Schaaf <> | Subject | Re: [PATCH] getsockopt() on netfilter-redirected socket | Date | Sun, 3 Oct 1999 11:49:16 +0200 (MEST) |
| |
> (Rusty screams `NO!!!' as he reads the patch to put NAT back into the > IP stack...)
(Patrick nods and agrees - that's why I called the patch "dirty")
> Please use the NAT code's SO_ORIGINAL_DST. Yes, this means recoding > squid, and yes I've been bad for not fixing that, but please send me > the squid patch instead...
Well, first of all I simply did not see SO_ORIGINAL_DST exists. While that means recoding applications, it is certainly the nicer way - and most applications like squid (or my patched ssh) need to do something special in that place anyway. The approach does pose some problems, though:
- what should I #include to get at the SO_ORIGINAL_DST #define? The include/ directory from the netfilter distribution is not installed anywhere. The includes crossreference each other. so something like 'ln -s /some/where/netfilter-0.1.9/include /usr/include/netfilter' (and then #include <netfilter/NAT/ip_nat.h>) does not work. I don't see an elegant way out of this.
- after finding testsuite/get_address (well, not really, I first grepped through the kernel for some time :), it was clear that I should use SOL_IP in the getsockopt() call.
- the call works for root, but not for an ordinary user. The same getsockopt() call (e.g. using get_address) that succeeds for root, returns EPERM for my own processes. The cause, if I don't misread, is these lines in net/core/netfilter.c:nf_sockopt
if (!capable(CAP_NET_ADMIN)) return -EPERM;
I am not using the capability mechanism, but I'll assume I don't have that as a normal user (and squid, apache and consorts also won't have it, hopefully). So, I vote for removing that check, at least for the GET part of the equation, or better: move it into the individual handlers instead of that central place.
Find appended the source for an 'nf_getsockname()' function, with the SO_ORIGINAL_DST #defined locally to work around the #include stuff. My ssh is happily using that (when run as root :), and for squid and other applications it should simply be a matter of linking that function in, and replacing all calls to 'getsockname' with 'nf_getsockname'.
Rusty, as an alternative to this approach, how would you like the kernel side getsockname() implementation to try SO_ORIGINAL_DST in-kernel? That way user level need not care, sk_buff and struct sock is left alone, and there's only that one place learning a small bit about NAT. Still a bit ugly and inconsequential, but I would prefer that.
best regards Patrick
/* nf_getsockname() - netfilter SO_ORIGINAL_DST variant of getsockname() * * Within the new Linux netfilter framework, NAT functionality is cleanly * separated from the TCP/IP core processing. In old days, you could easily * retrieve the original destination (IP address and port) of a transparently * proxied connection by calling the normal getsockname() syscall. * With netfilter, getsockname() returns the real local IP address and port. * However, the netfilter code gives all TCP sockets a new socket option, * SO_ORIGINAL_DST, for retrieval of the original IP/port combination. * * This file implements a function nf_getsockname(), with the same calling * convention as getsockname() itself; it uses SO_ORIGINAL_DST, and if that * fails, falls back to using getsockname() itself. */
#include <errno.h> #include <netinet/in.h> #include <sys/socket.h> #if 0 #include "NAT/ip_nat.h" #endif #ifndef SO_ORIGINAL_DST #define SO_ORIGINAL_DST 80 #endif
int nf_getsockname(int fd, struct sockaddr *sa, int *salen) { if (*salen != sizeof(struct sockaddr_in)) { errno = EINVAL; return -1; } if (0 == getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, sa, salen)) { return 0; } return getsockname(fd, sa, salen); }
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |