/* 
 * OpenGGSN - Gateway GPRS Support Node
 * Copyright (C) 2002, 2003, 2004 Mondru AB.
 * 
 * The contents of this file may be used under the terms of the GNU
 * General Public License Version 2, provided that the above copyright
 * notice and this permission notice is included in all copies or
 * substantial portions of the software.
 * 
 */

/* ggsn.c
 *
 */

#ifdef __linux__
#define _GNU_SOURCE 1		/* strdup() prototype, broken arpa/inet.h */
#endif

#include "../config.h"

#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif

#include <syslog.h>
#include <ctype.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>

#include <errno.h>

#include <time.h>

#include "../lib/tun.h"
#include "../lib/ippool.h"
#include "../lib/syserr.h"
#include "../gtp/pdp.h"
#include "../gtp/gtp.h"
#include "cmdline.h"

int end = 0;
int maxfd = 0;			/* For select()            */

struct in_addr listen_;
struct in_addr netaddr, destaddr, net, mask;	/* Network interface       */
struct in_addr dns1, dns2;	/* PCO DNS address         */
char *ipup, *ipdown;		/* Filename of scripts     */
int debug;			/* Print debug output      */
struct ul255_t pco;
struct ul255_t qos;
struct ul255_t apn;

struct gsn_t *gsn;		/* GSN instance            */
struct tun_t *tun;		/* TUN instance            */
struct ippool_t *ippool;	/* Pool of IP addresses    */

/* To exit gracefully. Used with GCC compilation flag -pg and gprof */
void signal_handler(int s)
{
	if (debug)
		printf("Received signal %d, exiting.\n", s);
	end = 1;
}

/* Used to write process ID to file. Assume someone else will delete */
void log_pid(char *pidfile)
{
	FILE *file;
	mode_t oldmask;

	oldmask = umask(022);
	file = fopen(pidfile, "w");
	umask(oldmask);
	if (!file) {
		sys_err(LOG_ERR, __FILE__, __LINE__, 0,
			"Failed to create process ID file: %s!", pidfile);
		return;
	}
	fprintf(file, "%d\n", (int)getpid());
	fclose(file);
}

#if defined(__sun__)
int daemon(int nochdir, int noclose)
{
	int fd;

	switch (fork()) {
	case -1:
		return (-1);
	case 0:
		break;
	default:
		_exit(0);
	}

	if (setsid() == -1)
		return (-1);

	if (!nochdir)
		chdir("/");

	if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
		dup2(fd, STDIN_FILENO);
		dup2(fd, STDOUT_FILENO);
		dup2(fd, STDERR_FILENO);
		if (fd > 2)
			close(fd);
	}
	return (0);
}
#endif

int encaps_printf(void *p, void *packet, unsigned len)
{
	unsigned int i;
	if (debug) {
		printf("The packet looks like this:\n");
		for (i = 0; i < len; i++) {
			printf("%02x ", (unsigned char)*(char *)(packet + i));
			if (!((i + 1) % 16))
				printf("\n");
		};
		printf("\n");
	}
	return 0;
}

int delete_context(struct pdp_t *pdp)
{
	if (debug)
		printf("Deleting PDP context\n");
	if (pdp->peer)
		ippool_freeip(ippool, (struct ippoolm_t *)pdp->peer);
	else
		sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Peer not defined!");
	return 0;
}

int create_context_ind(struct pdp_t *pdp)
{
	struct in_addr addr;
	struct ippoolm_t *member;

	if (debug)
		printf("Received create PDP context request\n");

	pdp->eua.l = 0;		/* TODO: Indicates dynamic IP */

	/* ulcpy(&pdp->qos_neg, &pdp->qos_req, sizeof(pdp->qos_req.v)); */
	memcpy(pdp->qos_neg0, pdp->qos_req0, sizeof(pdp->qos_req0));
	memcpy(&pdp->pco_neg, &pco, sizeof(pdp->pco_neg));

	memcpy(pdp->qos_neg.v, pdp->qos_req.v, pdp->qos_req.l);	/* TODO */
	pdp->qos_neg.l = pdp->qos_req.l;

	if (pdp_euaton(&pdp->eua, &addr)) {
		addr.s_addr = 0;	/* Request dynamic */
	}

	if (ippool_newip(ippool, &member, &addr, 0)) {
		gtp_create_context_resp(gsn, pdp, GTPCAUSE_NO_RESOURCES);
		return 0;	/* Allready in use, or no more available */
	}

	pdp_ntoeua(&member->addr, &pdp->eua);
	pdp->peer = member;
	pdp->ipif = tun;	/* TODO */
	member->peer = pdp;

	gtp_create_context_resp(gsn, pdp, GTPCAUSE_ACC_REQ);
	return 0;		/* Success */
}

/* Callback for receiving messages from tun */
int cb_tun_ind(struct tun_t *tun, void *pack, unsigned len)
{
	struct ippoolm_t *ipm;
	struct in_addr dst;
	struct tun_packet_t *iph = (struct tun_packet_t *)pack;

	dst.s_addr = iph->dst;

	if (debug)
		printf("Received packet from tun!\n");

	if (ippool_getip(ippool, &ipm, &dst)) {
		if (debug)
			printf("Received packet with no destination!!!\n");
		return 0;
	}

	if (ipm->peer)		/* Check if a peer protocol is defined */
		gtp_data_req(gsn, (struct pdp_t *)ipm->peer, pack, len);
	return 0;
}

int encaps_tun(struct pdp_t *pdp, void *pack, unsigned len)
{
	if (debug)
		printf("encaps_tun. Packet received: forwarding to tun\n");
	return tun_encaps((struct tun_t *)pdp->ipif, pack, len);
}

int main(int argc, char **argv)
{
	/* gengeopt declarations */
	struct gengetopt_args_info args_info;

	struct hostent *host;

	/* Handle keyboard interrupt SIGINT */
	struct sigaction s;
	s.sa_handler = (void *)signal_handler;
	if ((0 != sigemptyset(&s.sa_mask)) && debug)
		printf("sigemptyset failed.\n");
	s.sa_flags = SA_RESETHAND;
	if ((sigaction(SIGINT, &s, NULL) != 0) && debug)
		printf("Could not register SIGINT signal handler.\n");

	fd_set fds;		/* For select() */
	struct timeval idleTime;	/* How long to select() */

	int timelimit;		/* Number of seconds to be connected */
	int starttime;		/* Time program was started */

	/* open a connection to the syslog daemon */
	/*openlog(PACKAGE, LOG_PID, LOG_DAEMON); */

	/* TODO: Only use LOG__PERROR for linux */
#ifdef __linux__
	openlog(PACKAGE, (LOG_PID | LOG_PERROR), LOG_DAEMON);
#else
	openlog(PACKAGE, (LOG_PID), LOG_DAEMON);
#endif

	if (cmdline_parser(argc, argv, &args_info) != 0)
		exit(1);
	if (args_info.debug_flag) {
		printf("listen: %s\n", args_info.listen_arg);
		if (args_info.conf_arg)
			printf("conf: %s\n", args_info.conf_arg);
		printf("fg: %d\n", args_info.fg_flag);
		printf("debug: %d\n", args_info.debug_flag);
		printf("qos: %#08x\n", args_info.qos_arg);
		if (args_info.apn_arg)
			printf("apn: %s\n", args_info.apn_arg);
		if (args_info.net_arg)
			printf("net: %s\n", args_info.net_arg);
		if (args_info.dynip_arg)
			printf("dynip: %s\n", args_info.dynip_arg);
		if (args_info.statip_arg)
			printf("statip: %s\n", args_info.statip_arg);
		if (args_info.ipup_arg)
			printf("ipup: %s\n", args_info.ipup_arg);
		if (args_info.ipdown_arg)
			printf("ipdown: %s\n", args_info.ipdown_arg);
		if (args_info.pidfile_arg)
			printf("pidfile: %s\n", args_info.pidfile_arg);
		if (args_info.statedir_arg)
			printf("statedir: %s\n", args_info.statedir_arg);
		printf("timelimit: %d\n", args_info.timelimit_arg);
	}

	/* Try out our new parser */

	if (cmdline_parser_configfile(args_info.conf_arg, &args_info, 0, 0, 0)
	    != 0)
		exit(1);
	if (args_info.debug_flag) {
		printf("cmdline_parser_configfile\n");
		printf("listen: %s\n", args_info.listen_arg);
		printf("conf: %s\n", args_info.conf_arg);
		printf("fg: %d\n", args_info.fg_flag);
		printf("debug: %d\n", args_info.debug_flag);
		printf("qos: %#08x\n", args_info.qos_arg);
		if (args_info.apn_arg)
			printf("apn: %s\n", args_info.apn_arg);
		if (args_info.net_arg)
			printf("net: %s\n", args_info.net_arg);
		if (args_info.dynip_arg)
			printf("dynip: %s\n", args_info.dynip_arg);
		if (args_info.statip_arg)
			printf("statip: %s\n", args_info.statip_arg);
		if (args_info.ipup_arg)
			printf("ipup: %s\n", args_info.ipup_arg);
		if (args_info.ipdown_arg)
			printf("ipdown: %s\n", args_info.ipdown_arg);
		if (args_info.pidfile_arg)
			printf("pidfile: %s\n", args_info.pidfile_arg);
		if (args_info.statedir_arg)
			printf("statedir: %s\n", args_info.statedir_arg);
		printf("timelimit: %d\n", args_info.timelimit_arg);
	}

	/* Handle each option */

	/* debug                                                        */
	debug = args_info.debug_flag;

	/* listen                                                       */
	/* Do hostname lookup to translate hostname to IP address       */
	/* Any port listening is not possible as a valid address is     */
	/* required for create_pdp_context_response messages            */
	if (args_info.listen_arg) {
		if (!(host = gethostbyname(args_info.listen_arg))) {
			sys_err(LOG_ERR, __FILE__, __LINE__, 0,
				"Invalid listening address: %s!",
				args_info.listen_arg);
			exit(1);
		} else {
			memcpy(&listen_.s_addr, host->h_addr, host->h_length);
		}
	} else {
		sys_err(LOG_ERR, __FILE__, __LINE__, 0,
			"Listening address must be specified! "
			"Please use command line option --listen or "
			"edit %s configuration file\n", args_info.conf_arg);
		exit(1);
	}

	/* net                                                          */
	/* Store net as in_addr net and mask                            */
	if (args_info.net_arg) {
		if (ippool_aton(&net, &mask, args_info.net_arg, 0)) {
			sys_err(LOG_ERR, __FILE__, __LINE__, 0,
				"Invalid network address: %s!",
				args_info.net_arg);
			exit(1);
		}
		netaddr.s_addr = htonl(ntohl(net.s_addr) + 1);
		destaddr.s_addr = htonl(ntohl(net.s_addr) + 1);
	} else {
		sys_err(LOG_ERR, __FILE__, __LINE__, 0,
			"Network address must be specified: %s!",
			args_info.net_arg);
		exit(1);
	}

	/* dynip                                                        */
	if (!args_info.dynip_arg) {
		if (ippool_new(&ippool, args_info.net_arg, NULL, 1, 0,
			       IPPOOL_NONETWORK | IPPOOL_NOGATEWAY |
			       IPPOOL_NOBROADCAST)) {
			sys_err(LOG_ERR, __FILE__, __LINE__, 0,
				"Failed to allocate IP pool!");
			exit(1);
		}
	} else {
		if (ippool_new(&ippool, args_info.dynip_arg, NULL, 1, 0,
			       IPPOOL_NONETWORK | IPPOOL_NOGATEWAY |
			       IPPOOL_NOBROADCAST)) {
			sys_err(LOG_ERR, __FILE__, __LINE__, 0,
				"Failed to allocate IP pool!");
			exit(1);
		}
	}

	/* DNS1 and DNS2 */
#ifdef HAVE_INET_ATON
	dns1.s_addr = 0;
	if (args_info.pcodns1_arg) {
		if (0 == inet_aton(args_info.pcodns1_arg, &dns1)) {
			sys_err(LOG_ERR, __FILE__, __LINE__, 0,
				"Failed to convert pcodns1!");
			exit(1);
		}
	}
	dns2.s_addr = 0;
	if (args_info.pcodns2_arg) {
		if (0 == inet_aton(args_info.pcodns2_arg, &dns2)) {
			sys_err(LOG_ERR, __FILE__, __LINE__, 0,
				"Failed to convert pcodns2!");
			exit(1);
		}
	}
#else
	dns1.s_addr = 0;
	if (args_info.pcodns1_arg) {
		dns1.s_addr = inet_addr(args_info.pcodns1_arg);
		if (dns1.s_addr == -1) {
			sys_err(LOG_ERR, __FILE__, __LINE__, 0,
				"Failed to convert pcodns1!");
			exit(1);
		}
	}
	dns2.s_addr = 0;
	if (args_info.pcodns2_arg) {
		dns2.s_addr = inet_addr(args_info.pcodns2_arg);
		if (dns2.s_addr == -1) {
			sys_err(LOG_ERR, __FILE__, __LINE__, 0,
				"Failed to convert pcodns2!");
			exit(1);
		}
	}
#endif

	pco.l = 20;
	pco.v[0] = 0x80;	/* x0000yyy x=1, yyy=000: PPP */
	pco.v[1] = 0x80;	/* IPCP */
	pco.v[2] = 0x21;
	pco.v[3] = 0x10;	/* Length of contents */
	pco.v[4] = 0x02;	/* ACK */
	pco.v[5] = 0x00;	/* ID: Need to match request */
	pco.v[6] = 0x00;	/* Length */
	pco.v[7] = 0x10;
	pco.v[8] = 0x81;	/* DNS 1 */
	pco.v[9] = 0x06;
	memcpy(&pco.v[10], &dns1, sizeof(dns1));
	pco.v[14] = 0x83;
	pco.v[15] = 0x06;	/* DNS 2 */
	memcpy(&pco.v[16], &dns2, sizeof(dns2));

	/* ipup */
	ipup = args_info.ipup_arg;

	/* ipdown */
	ipdown = args_info.ipdown_arg;

	/* Timelimit                                                       */
	timelimit = args_info.timelimit_arg;
	starttime = time(NULL);

	/* qos                                                             */
	qos.l = 3;
	qos.v[2] = (args_info.qos_arg) & 0xff;
	qos.v[1] = ((args_info.qos_arg) >> 8) & 0xff;
	qos.v[0] = ((args_info.qos_arg) >> 16) & 0xff;

	/* apn                                                             */
	if (strlen(args_info.apn_arg) > (sizeof(apn.v) - 1)) {
		printf("Invalid APN\n");
		return -1;
	}
	apn.l = strlen(args_info.apn_arg) + 1;
	apn.v[0] = (char)strlen(args_info.apn_arg);
	strncpy((char *)&apn.v[1], args_info.apn_arg, sizeof(apn.v) - 1);

	/* foreground                                                   */
	/* If flag not given run as a daemon                            */
	if (!args_info.fg_flag) {
		FILE *f;
		int rc;
		closelog();
		/* Close the standard file descriptors. */
		/* Is this really needed ? */
		f = freopen("/dev/null", "w", stdout);
		if (f == NULL) {
			sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
				"Could not redirect stdout to /dev/null");
		}
		f = freopen("/dev/null", "w", stderr);
		if (f == NULL) {
			sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
				"Could not redirect stderr to /dev/null");
		}
		f = freopen("/dev/null", "r", stdin);
		if (f == NULL) {
			sys_err(LOG_WARNING, __FILE__, __LINE__, 0,
				"Could not redirect stdin to /dev/null");
		}
		rc = daemon(0, 0);
		if (rc != 0) {
			sys_err(LOG_ERR, __FILE__, __LINE__, rc,
				"Could not daemonize");
			exit(1);
		}
		/* Open log again. This time with new pid */
		openlog(PACKAGE, LOG_PID, LOG_DAEMON);
	}

	/* pidfile */
	/* This has to be done after we have our final pid */
	if (args_info.pidfile_arg) {
		log_pid(args_info.pidfile_arg);
	}

	if (debug)
		printf("gtpclient: Initialising GTP tunnel\n");

	if (gtp_new(&gsn, args_info.statedir_arg, &listen_, GTP_MODE_GGSN)) {
		sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Failed to create gtp");
		exit(1);
	}
	if (gsn->fd0 > maxfd)
		maxfd = gsn->fd0;
	if (gsn->fd1c > maxfd)
		maxfd = gsn->fd1c;
	if (gsn->fd1u > maxfd)
		maxfd = gsn->fd1u;

	gtp_set_cb_data_ind(gsn, encaps_tun);
	gtp_set_cb_delete_context(gsn, delete_context);
	gtp_set_cb_create_context_ind(gsn, create_context_ind);

	/* Create a tunnel interface */
	if (debug)
		printf("Creating tun interface\n");
	if (tun_new((struct tun_t **)&tun)) {
		sys_err(LOG_ERR, __FILE__, __LINE__, 0, "Failed to create tun");
		if (debug)
			printf("Failed to create tun\n");
		exit(1);
	}

	if (debug)
		printf("Setting tun IP address\n");
	if (tun_setaddr(tun, &netaddr, &destaddr, &mask)) {
		sys_err(LOG_ERR, __FILE__, __LINE__, 0,
			"Failed to set tun IP address");
		if (debug)
			printf("Failed to set tun IP address\n");
		exit(1);
	}

	tun_set_cb_ind(tun, cb_tun_ind);
	if (tun->fd > maxfd)
		maxfd = tun->fd;

	if (ipup)
		tun_runscript(tun, ipup);

  /******************************************************************/
	/* Main select loop                                               */
  /******************************************************************/

	while ((((starttime + timelimit) > time(NULL)) || (0 == timelimit))
	       && (!end)) {

		FD_ZERO(&fds);
		if (tun)
			FD_SET(tun->fd, &fds);
		FD_SET(gsn->fd0, &fds);
		FD_SET(gsn->fd1c, &fds);
		FD_SET(gsn->fd1u, &fds);

		gtp_retranstimeout(gsn, &idleTime);
		switch (select(maxfd + 1, &fds, NULL, NULL, &idleTime)) {
		case -1:	/* errno == EINTR : unblocked signal */
			sys_err(LOG_ERR, __FILE__, __LINE__, 0,
				"select() returned -1");
			/* On error, select returns without modifying fds */
			FD_ZERO(&fds);
			break;
		case 0:
			/* printf("Select returned 0\n"); */
			gtp_retrans(gsn);	/* Only retransmit if nothing else */
			break;
		default:
			break;
		}

		if (tun->fd != -1 && FD_ISSET(tun->fd, &fds) &&
		    tun_decaps(tun) < 0) {
			sys_err(LOG_ERR, __FILE__, __LINE__, 0,
				"TUN read failed (fd)=(%d)", tun->fd);
		}

		if (FD_ISSET(gsn->fd0, &fds))
			gtp_decaps0(gsn);

		if (FD_ISSET(gsn->fd1c, &fds))
			gtp_decaps1c(gsn);

		if (FD_ISSET(gsn->fd1u, &fds))
			gtp_decaps1u(gsn);

	}

	cmdline_parser_free(&args_info);
	ippool_free(ippool);
	gtp_free(gsn);
	tun_free(tun);

	return 1;

}
