/*-
 * Copyright (c) 1993, 1996, Trusted Information Systems, Incorporated
 * All rights reserved.
 *
 * Redistribution and use are governed by the terms detailed in the
 * license document ("LICENSE") included with the toolkit.
 */

/*
 *	Author: Marcus J. Ranum, Trusted Information Systems, Inc.
 *              Patched by mat@hacksware.com
 */
static	char	RcsId[] = "$Header: /usr/home/rick/fwtk2.0/fwtk/lib/RCS/hnam.c,v 1.2 1996/12/10 18:08:42 rick Exp $";

#include	<sys/types.h>
#include	<sys/socket.h>
#include	<netinet/in.h>
#include	<netdb.h>
#include	<syslog.h>
#include	<ctype.h>

extern	char	*inet_ntoa();


#include	"firewall.h"

#ifdef __FreeBSD__ /* or OpenBSD, NetBSD, BSDI, etc. Fix this for your system. */
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/errno.h>  
#include <sys/syslog.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <net/if.h>

#include	"ip_compat.h"
#include	"ip_fil.h"
#include	"ip_nat.h"
#include <errno.h>		
extern int errno;
#endif /* __FreeBSD__ */


char	*
maphostname(name)
char	*name;
{
	struct	hostent		*hp;
	struct	sockaddr_in	sin;
	char			*p;

	p = name;
	while(*p != '\0' && (*p == '.' || *p == '*' || isdigit(*p)))
		p++;

	if(*p == '\0')
		return(name);

	if((hp = gethostbyname(name)) == (struct hostent *)0)
		return(name);

	if (hp->h_length > sizeof(sin.sin_addr.s_addr)) {
		syslog(LLEV,"securityalert: invalid host address length (%d) hostname %.128s", hp->h_length, name);
		name = "invalid";
		return (name);
	}
	bcopy(hp->h_addr,&sin.sin_addr,hp->h_length);
	return(inet_ntoa(sin.sin_addr));
}

char *getdsthost(fd, ptr)
int fd;
int *ptr;
{
	struct sockaddr_in sin;
	struct hostent	   * hp;
	int		   sl = sizeof(struct sockaddr_in), err = 0, local_h = 0, i = 0;
	static char buf[255];
        char  hostbuf[255];
#ifdef __FreeBSD__
	int natfd;
	struct sockaddr_in rsin;
        natlookup_t nlp;
        natlookup_t *nlp_p=&nlp;
#endif

#ifdef linux
	if (!(err = getsockname(0, &sin, &sl))) {
		if(ptr)	
			* ptr = ntohs(sin.sin_port);

		sprintf(buf, "%s", inet_ntoa(sin.sin_addr));
		gethostname(hostbuf, 254);
		hp = gethostbyname(hostbuf);
		while (hp->h_addr_list[i]) {
			bzero(&sin, &sl);
			memcpy(&sin.sin_addr, hp->h_addr_list[i++],
				sizeof(hp->h_addr_list[i++]));

			if (!strcmp(buf, inet_ntoa(sin.sin_addr)))
				local_h++;
		}

		if(local_h)
			return(NULL);
		else
			return(buf);
 }
#endif

#ifdef __FreeBSD__
/*  The basis for this block of code is Darren Reed's
 *  patches to the TIS ftwk's ftp-gw.
 */

	bzero((char*)&sin, sizeof(sin));
	bzero((char*)&rsin, sizeof(rsin));

        nlp.nl_flags = IPN_TCP;

        sin.sin_family=AF_INET;
	sl = sizeof(sin);
	if (getsockname(fd, (struct sockaddr*)&sin, &sl) < 0)
		return NULL;
	nlp.nl_inip.s_addr=sin.sin_addr.s_addr;
	nlp.nl_inport=sin.sin_port;

        rsin.sin_family=AF_INET;
	sl = sizeof(rsin);
	if(getpeername(fd, (struct sockaddr*)&rsin, &sl) < 0)
		return NULL;

	nlp.nl_outip.s_addr=rsin.sin_addr.s_addr;
	nlp.nl_outport=rsin.sin_port;

	if ((natfd = open("/dev/ipnat",O_RDONLY)) < 0)
		return NULL;
	if (ioctl(natfd, SIOCGNATL,&nlp_p) == (-1))
        {
	        syslog(LLEV,"SIOCGNATL error: %d",errno);
		return NULL;
        }

	close(natfd);

	if (ptr)
		*ptr = ntohs(nlp.nl_inport);

	sprintf(buf, "%s", inet_ntoa(nlp.nl_realip));
	syslog(LLEV,"connecting: %s",buf);
        return buf;
#endif

	/* No transparent proxy support */
	return(NULL);
}
