/*
File: ftpproxy/main.c
Copyright (C) 1999, 2000 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 <unistd.h>
#include <stdarg.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <syslog.h>
#include <sys/time.h>
#include "ftp.h"
#include "ip-lib.h"
#include "lib.h"
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
#define LOGFACILITY LOG_FTP
#else
#define LOGFACILITY LOG_DAEMON
#endif
char *program = "";
char progname[80] = "";
int debug = 0;
int extralog = 0;
int bindport = 0;
int daemonmode = 0;
int showconfig = 0;
extern int acceptloop(int sock);
void missing_arg(int c, char *string)
{
fprintf (stderr, "%s: missing arg: -%c, %s\n", program, c, string);
exit (-1);
}
int main(int argc, char *argv[], char *envp[])
{
int c, i, k;
char *p, option[80];
config_t *config;
if ((p = strrchr(argv[0], '/')) == NULL)
program = argv[0];
else {
copy_string(progname, &p[1], sizeof(progname));
program = progname;
}
config = allocate(sizeof(config_t));
config->timeout = 15 * 60;
config->allow_passwdblanks = 0;
config->allow_anyremote = 0;
strcpy(config->varname, "PROXY_");
openlog(program, LOG_PID, LOGFACILITY);
k = 1;
while (k < argc && argv[k][0] == '-' && argv[k][1] != 0) {
copy_string(option, argv[k++], sizeof(option));
for (i=1; (c = option[i]) != 0; i++) {
if (c == 'd') {
if (debug == 1)
debug = 2;
else
debug = 1;
}
else if (c == 'a') {
if (k >= argc)
missing_arg(c, "access control program");
copy_string(config->acp, argv[k++], sizeof(config->acp));
}
else if (c == 'B')
config->allow_passwdblanks = 1;
else if (c == 'b')
config->allow_blanks = 1;
else if (c == 'c') {
if (k >= argc)
missing_arg(c, "command control program");
copy_string(config->ccp, argv[k++], sizeof(config->ccp));
}
else if (c == 'e')
config->selectserver = 1;
else if (c == 'f' || c == 'F') {
if (k >= argc)
missing_arg(c, "configuration file");
if (c == 'F')
showconfig = 1;
copy_string(config->configfile, argv[k++], sizeof(config->configfile));
}
else if (c == 'l')
extralog = 1;
else if (c == 'm')
config->monitor = 1;
else if (c == 'n')
config->numeric_only = 1;
else if (c == 'p') {
if (k >= argc)
missing_arg(c, "data port");
config->dataport = strtoul(argv[k++], NULL, 10);
if (config->dataport == 0)
config->dataport = 20;
}
else if (c == 'q') {
/*
* Specify source interface for outgoing
* connections -- 26JAN04asg
*/
if (k >= argc)
missing_arg(c, "source interface");
copy_string(config->sourceip, argv[k++], sizeof(config->sourceip));
}
else if (c == 's') {
if (k >= argc)
missing_arg(c, "server list");
config->serverlist = argv[k++];
}
else if (c == 't') {
if (k >= argc)
missing_arg(c, "timeout");
config->timeout = atoi(argv[k++]);
if (config->timeout < 1)
config->timeout = 60;
}
else if (c == 'u')
config->use_last_at = 1;
else if (c == 'v') {
if (k >= argc)
missing_arg(c, "varname prefix");
copy_string(config->varname, argv[k++], sizeof(config->varname));
}
else if (c == 'x') {
if (k >= argc)
missing_arg(c, "dynamic configuration program");
copy_string(config->ctp, argv[k++], sizeof(config->ctp));
}
else if (c == 'X') {
if (k >= argc)
missing_arg(c, "xferlog file");
copy_string(config->xferlog, argv[k++], sizeof(config->xferlog));
}
else if (c == 'y') {
/*
* To make 'bad multihomed servers' happy and
* to allow server-server transfers through the
* proxy -- 31JAN02asg
*/
config->allow_anyremote = 1;
}
else if (c == 'z') {
if (k >= argc)
missing_arg(c, "buffer size");
config->bsize = atoi(argv[k++]);
}
else if (c == 'V') {
printf("ftp.proxy version: %s asg@ftpproxy.org\n", VERSION);
exit (0);
}
else if (c == 'D') {
if (k >= argc)
missing_arg(c, "port number");
bindport = strtoul(argv[k++], NULL, 10);
daemonmode = 1;
}
else {
fprintf (stderr, "%s: unknown option: -%c\n", program, c);
exit (-1);
}
}
}
/*
* Print configuration if requested and exit
*/
if (showconfig != 0) {
int havesection = 0;
char *interface = "";
readconfig(config, config->configfile, "");
if (k < argc) {
interface = argv[k++];
havesection = readconfig(config, config->configfile, interface);
}
if (*interface == 0)
printf ("interface: global\n");
else {
printf ("interface: %s\n", interface);
printf ("status: %s\n", (havesection != 0)? "configured": "unconfigured");
}
printconfig(config);
exit (0);
}
/*
* Normal processing starts here.
*/
if (config->selectserver == 0) {
/*
* Fixed proxy server together with CTP doesn't make
* much sense -- 040303asg
*/
if (*config->ctp != 0) {
p = argv[k++];
/* syslog(LOG_NOTICE, "configured to use ctp, ignoring server argument: %s", p); */
fprintf (stderr, "%s: configured to use ctp, ignoring server argument: %s", program, p);
}
else {
if (k >= argc) {
fprintf (stderr, "usage: %s [<options>] <server>\n", program);
exit (1);
}
copy_string(config->server, argv[k++], sizeof(config->server));
}
}
if (k < argc) {
fprintf (stderr, "%s: extra arguments on command line: %s ...\n", program, argv[k]);
exit (1);
}
if (*config->configfile != 0) {
syslog(LOG_NOTICE, "configured to use config file. %s", p);
readconfig(config, config->configfile, "");
}
if (daemonmode != 0) {
signal(SIGCHLD, SIG_IGN);
config->standalone = 1;
if (bindport > 0) {
int sock;
sock = bind_to_port("", bindport);
acceptloop(sock);
}
signal(SIGCHLD, SIG_DFL);
}
proxy_request(config);
exit (0);
}
syntax highlighted by Code2HTML, v. 0.9.1