--- configure.in +++ configure.in 2002/05/16 10:00:33 @@ -204,10 +204,11 @@ AC_HEADER_TIME AC_CHECK_HEADERS(sys/time.h sys/select.h fcntl.h sys/fcntl.h) - AC_CHECK_HEADERS(sys/filio.h sys/conf.h paths.h stropts.h) -AC_CHECK_HEADERS(sys/sockio.h net/if.h netinet/in_systm.h) +AC_CHECK_HEADERS(sys/sockio.h) +AC_CHECK_HEADERS(net/if.h net/pfvar.h) +AC_CHECK_HEADERS(netinet/in_systm.h) AC_CHECK_HEADERS(netinet/ip.h netinet/ip_fil.h netinet/ip_nat.h) AC_CHECK_HEADERS(netinet/ip_compat.h netinet/ip_fil_compat.h) --- common/com-socket.c +++ common/com-socket.c 2002/05/16 10:00:33 @@ -97,6 +97,9 @@ #if defined(HAVE_NET_IF_H) # include #endif +#if defined(HAVE_NET_PFVAR_H) +# include +#endif #if defined(HAVE_NETINET_IP_H) # include @@ -1970,15 +1973,21 @@ int socket_orgdst(HLS *phls, u_int32_t *addr, u_int16_t *port) { - struct sockaddr_in name; + struct sockaddr_in name; #if defined(HAVE_LINUX_NETFILTER_IPV4_H) && defined(SO_ORIGINAL_DST) - struct sockaddr_in dest; + struct sockaddr_in dest; #endif #if defined(HAVE_NETINET_IP_NAT_H) && defined(SIOCGNATL) - natlookup_t natlook, *nlptr = &natlook; - int rc, nat_fd = -1; + natlookup_t natlook, *nlptr = &natlook; + int rc, nat_fd = -1; +#endif +#if defined(HAVE_NET_PFVAR_H) + int rc, nat_fd = -1; + struct protoent *proto; + struct sockaddr_in peer; + struct pfioc_natlook natlook; #endif - socklen_t len; + socklen_t len; /* ** sanity args checks @@ -2042,6 +2051,73 @@ return 0; } +#endif + +#if defined(HAVE_NET_PFVAR_H) + + /* + ** OpenBSD PF table lookup + */ + len = sizeof(peer); + memset(&peer, 0, len); + if(getpeername(phls->sock, (struct sockaddr *)&peer, &len) < 0) { + syslog_error("can't get peername for socket %d", phls->sock); + return -1; + } + + if(!(proto = getprotobyname("tcp"))) + { + syslog_error("can't get protocol number for tcp"); + return -1; + } + + if((nat_fd = open("/dev/pf", O_RDWR, 0)) < 0) { + endprotoent(); + syslog_error("can't open pf device '/dev/pf'"); + return -1; + } + + memset(&natlook, 0, sizeof(natlook)); + natlook.af = AF_INET; + natlook.proto = proto->p_proto; + natlook.direction = PF_OUT; + natlook.saddr.v4.s_addr = peer.sin_addr.s_addr; /* peer */ + natlook.sport = peer.sin_port; + natlook.daddr.v4.s_addr = name.sin_addr.s_addr; /* sock */ + natlook.dport = name.sin_port; + + endprotoent(); + + rc = ioctl(nat_fd, DIOCNATLOOK, &natlook); + close(nat_fd); + + if(rc < 0) { + if(errno != ENOENT) { + syslog_error("can't get nat transparent proxy " + "destination"); + } + return -1; + } + +#if defined(COMPILE_DEBUG) + debug(2, "nat transparent proxy destination: %s:%d", + socket_addr2str(ntohl(natlook.rdaddr.v4.s_addr)), + ntohs(natlook.rdport)); +#endif + + if((natlook.rdport == name.sin_port) && + (natlook.rdaddr.v4.s_addr == name.sin_addr.s_addr)) + { + syslog_write(T_DBG, + "nat proxy destination %s:%d is local", + socket_addr2str(ntohl(natlook.rdaddr.v4.s_addr)), + ntohs(natlook.rdport)); + return -1; + } + + *addr = natlook.rdaddr.v4.s_addr; + *port = natlook.rdport; + return 0; #endif #if defined(HAVE_NETINET_IP_NAT_H) && defined(SIOCGNATL)