/*

    File: ftpproxy/ip-lib.c

    Copyright (C) 1999  Wolfgang Zekoll  <wzk@quietsche-entchen.de>
    Copyright (C) 2000, 2003  Andreas Schoenberg  <asg@ftpproxy.org>
  
    This software is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
  
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
  
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 */
 
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include <signal.h>
#include <syslog.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>

#include "lib.h"
#include "ip-lib.h"


static void alarm_handler()
{
	return;
}


int openip(char *host, unsigned int port, char *srcip, unsigned int srcport)
{
	int	socketd;
	struct sockaddr_in server;
	struct hostent *hostp, *gethostbyname();

	socketd = socket(AF_INET, SOCK_STREAM, 0);
	if (socketd < 0)
		return (-1);
  
  	/*
	 * Enhancement to use a particular local interface and source port,
	 * mentioned by Juergen Ilse, <ilse@asys-h.de>.
	 */

  	if (srcip != NULL  &&  *srcip != 0) {
		struct sockaddr_in laddr;

		if (srcport != 0) {
			int	one;

			one = 1;
	 		setsockopt (socketd, SOL_SOCKET, SO_REUSEADDR, (int *) &one, sizeof(one));
			}
 
 		/*
         	 * Bind local socket to srcport and srcip
         	 */

 		memset(&laddr, 0, sizeof(laddr));
 		laddr.sin_family = AF_INET;
 		laddr.sin_port   = htons(srcport);

 		if (srcip == NULL  ||  *srcip == 0)
 			srcip = "0.0.0.0";	/* Can't happen but who cares. */
 		else {
 			struct hostent *ifp;
 
 			ifp = gethostbyname(srcip);
 			if (ifp == NULL) {
 				syslog(LOG_NOTICE, "-ERR: can't lookup %s", srcip);
 				exit (1);
 				}
 
 			memcpy(&laddr.sin_addr, ifp->h_addr, ifp->h_length);
 	 	 	}
 
 		if (bind(socketd, (struct sockaddr *) &laddr, sizeof(laddr))) {
 			syslog(LOG_NOTICE, "-ERR: can't bind to %s:%u", srcip, ntohs(laddr.sin_port));
 	    		exit (1);
 	  		}
		}


	server.sin_family = AF_INET;
	hostp = gethostbyname(host);
	if (hostp == NULL)
		return (-1);
  
	memcpy(&server.sin_addr, hostp->h_addr, hostp->h_length);
	server.sin_port = htons(port);

	signal(SIGALRM, alarm_handler);
	alarm(10);
	if (connect(socketd, (struct sockaddr *) &server, sizeof(server)) < 0)
		return (-1);

	alarm(0);
	signal(SIGALRM, SIG_DFL);
	
 	return (socketd);
}	

unsigned int getportnum(char *name)
{
	unsigned int port;
	struct servent *portdesc;
	
	if (isdigit(*name) != 0)
		port = atol(name);
	else {
		portdesc = getservbyname(name, "tcp");
		if (portdesc == NULL) {
			syslog(LOG_NOTICE, "-ERR: service not found: %s", name);
			exit (-1);
			}

		port = ntohs(portdesc->s_port);
		if (port == 0) {
			syslog(LOG_NOTICE, "-ERR: port error: %s\n", name);
			exit (-1);
			}
		}
	
	return (port);
}

unsigned int get_port(char *server, unsigned int def_port)
{
	unsigned int port;
	char	*p;

	if ((p = strchr(server, ':')) == NULL)
		return (def_port);

	*p++ = 0;
	port = getportnum(p);

	return (port);
}

int bind_to_port(char *interface, unsigned int port)
{
	struct sockaddr_in saddr;
	int	sock;

	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		syslog(LOG_NOTICE, "-ERR: can't create socket: %s", strerror(errno));
		exit (-1);
		}
	else {
		int	opt;

		opt = 1;
		setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
		}


	memset(&saddr, 0, sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_port   = htons(port);
	
	if (interface == NULL  ||  *interface == 0)
		interface = "0.0.0.0";
	else {
		struct hostent *ifp;

		ifp = gethostbyname(interface);
		if (ifp == NULL) {
			syslog(LOG_NOTICE, "-ERR: can't lookup %s", interface);
			exit (-1);
			}

		memcpy(&saddr.sin_addr, ifp->h_addr, ifp->h_length);
		}
		
		
	if (bind(sock, (struct sockaddr *) &saddr, sizeof(saddr))) {
		syslog(LOG_NOTICE, "-ERR: can't bind to %s:%u", interface, port);
		exit (-1);
		}
		
		
	if (listen(sock, 5) < 0) {
		syslog(LOG_NOTICE, "-ERR: listen error:  %s", strerror(errno));
		exit (-1);
		}

	return (sock);
}



syntax highlighted by Code2HTML, v. 0.9.1