예제 #1
0
파일: aiccu_main.c 프로젝트: keenser/Maiccu
int main(int argc, char *argv[])
{
	enum AICCU_MODES	mode = A_NONE;

	struct TIC_Tunnel	*hTunnel;
#ifdef _WIN32
	WSADATA			wsadata;
	unsigned int		i;

	/* Initialize Winsock so that we can do network functions */
	WSAStartup(WINSOCK_VERSION, &wsadata);
#endif

	/* Initialize Configuration */
	aiccu_InitConfig();

	/* Make sure we actually have an IPv6 stack */
	aiccu_install();

	/* Require start/stop/test */
	if (argc == 2 || argc == 3)
	{
		     if (strcasecmp(argv[1], "start")	== 0) mode = A_START;
		else if (strcasecmp(argv[1], "stop")	== 0) mode = A_STOP;
		else if (strcasecmp(argv[1], "brokers") == 0) mode = A_BROKERS;
		else if (strcasecmp(argv[1], "tunnels") == 0) mode = A_TUNNELS;
		else if (strcasecmp(argv[1], "test")	== 0) mode = A_TEST;
		else if (strcasecmp(argv[1], "autotest")== 0) mode = A_AUTOTEST;
		else if (strcasecmp(argv[1], "license")	== 0) mode = A_LICENSE;
#ifdef _WIN32
		else if (strcasecmp(argv[1], "listtaps") == 0) mode = A_LISTTAPS;
#endif
		else if (strcasecmp(argv[1], "version")	== 0) mode = A_VERSION;
	}

	/* Optionally we want a second argument: a config file */
	if ((	argc != 2 &&
		argc != 3) ||
		mode == A_NONE)
	{
		dolog(LOG_ERR, "%s", options);
		return -1;
	}

	if (	mode == A_LICENSE)
	{
		printf("%s\n", aiccu_license());
		return 0;
	}

	if (	mode == A_VERSION)
	{
		printf("AICCU %s by Jeroen Massar\n", AICCU_VERSION);
		return 0;
	}

#ifdef _WIN32
	if (	mode == A_LISTTAPS)
	{
		tun_list_tap_adapters();
		return 0;
	}
#endif

	if (	mode == A_BROKERS)
	{
		int ret = list_brokers();
		aiccu_FreeConfig();
		return ret == 0 ? -1 : 0;
	}

	if (!aiccu_LoadConfig(argc <= 2 ? NULL : argv[2]))
	{
		return -1;
	}

#ifndef _WIN32
	/* start or stop? */
	if (	mode != A_TEST &&
		mode != A_AUTOTEST)
	{
		/* Already running? */
		if (sigrunning(mode == A_STOP ? SIGTERM : 0) == 1)
		{
			dolog(LOG_ERR, "Already running instance HUP'ed, exiting\n");
			return 0;
		}
	}
#endif

	/* Verify required parameters */
	if (!g_aiccu || !g_aiccu->username || !g_aiccu->password)
	{
		dolog(LOG_ERR, "Required parameters missing, make sure that username and password are given\n");
		aiccu_FreeConfig();
		return -1;
	}

	if (mode == A_TUNNELS)
	{
		int ret = list_tunnels();
		aiccu_FreeConfig();
		return ret == 0 ? -1 : 0;
	}

	/* Get our tunnel */
	hTunnel = get_tunnel();
	
	if (!hTunnel)
	{
		dolog(LOG_ERR, "Couldn't retrieve first tunnel for the above reason, aborting\n");
		aiccu_FreeConfig();
		return -1;
	}

	/* 
	 * We now have sufficient information.
	 * Thus we can logout from the TIC server
	 */
	tic_Logout(g_aiccu->tic, NULL);
	g_aiccu->tic = NULL;

	if (g_aiccu->verbose)
	{
		printf("Tunnel Information for %s:\n",hTunnel->sId);
		printf("POP Id      : %s\n", hTunnel->sPOP_Id);
		printf("IPv6 Local  : %s/%u\n", hTunnel->sIPv6_Local,hTunnel->nIPv6_PrefixLength);
		printf("IPv6 Remote : %s/%u\n", hTunnel->sIPv6_POP,hTunnel->nIPv6_PrefixLength);
		printf("Tunnel Type : %s\n", hTunnel->sType);
		printf("Adminstate  : %s\n", hTunnel->sAdminState);
		printf("Userstate   : %s\n", hTunnel->sUserState);
	}

	/* One can always try to stop it */
	if (mode == A_STOP)
	{
		aiccu_delete(hTunnel);

		/* Free stuff and exit */
		tic_Free_Tunnel(hTunnel);
		aiccu_FreeConfig();
		return 0;
	}

	if (	(strcmp(hTunnel->sAdminState,	"enabled") != 0) ||
		(strcmp(hTunnel->sUserState,	"enabled") != 0))
	{
		dolog(LOG_ERR, "Tunnel is not enabled (UserState: %s, AdminState: %s)\n", hTunnel->sAdminState, hTunnel->sUserState);
		return -1;
	}

	/* Do the test thing */
	if (	mode == A_TEST ||
		mode == A_AUTOTEST)
	{
#ifdef _WIN32
		SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigterm_testing, true);
#endif
		/* Setup the tunnel */
		if (aiccu_setup(hTunnel, true))
		{
			aiccu_test(hTunnel, strcasecmp(argv[1], "autotest") == 0 ? true : false);

			/* Tear the tunnel down again */
			aiccu_delete(hTunnel);
		}
		else
		{
			dolog(LOG_ERR, "Tunnel Setup Failed\n");
		}

		/* exit as all is done */
		tic_Free_Tunnel(hTunnel);
		aiccu_FreeConfig();
		return 0;
	}

#ifndef _WIN32
	if (	mode == A_START &&
		g_aiccu->daemonize != 0)
	{
		FILE	*f;

		/* Daemonize */
		int i = fork();
		if (i < 0)
		{
			fprintf(stderr, "Couldn't fork\n");
			return -1;
		}
		/* Exit the mother fork */
		if (i != 0) return 0;

		/* Child fork */
		setsid();

		/* Chdir to minimise disruption to FS umounts */
		(void)chdir("/");

		/* Cleanup stdin/out/err */
		freopen("/dev/null","r",stdin);
		freopen("/dev/null","w",stdout);
		freopen("/dev/null","w",stderr);

		/* */
		f = fopen(g_aiccu->pidfile, "w");
		if (!f)
		{
			dolog(LOG_ERR, "Could not store PID in file %s\n", g_aiccu->pidfile);
			return 0;
		}

		fprintf(f, "%d", getpid());
		fclose(f);

		dolog(LOG_INFO, "AICCU running as PID %d\n", getpid());
	}

#endif /* !_WIN32 */

	/* mode == A_START */

#ifndef _WIN32
	/*
	 * Install a signal handler so that
	 * one can disable beating with SIGUSR1
	 */
	signal(SIGUSR1, &sigusr1);

	/*
	 * Install a signal handler so that
	 * one can stop this program with SIGTERM
	 */
	signal(SIGTERM, &sigterm);
	signal(SIGINT, &sigterm);
#else
	SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigterm, true);
#endif

	/* 
	 * Setup our tunnel
	 * This also spawns required threads for AYIYA
	 */
	if (aiccu_setup(hTunnel, true))
	{
		/* We need to stay running when doing Heartbeat or AYIYA */
		if (	strcasecmp(hTunnel->sType, "6in4-heartbeat") == 0 ||
			strcasecmp(hTunnel->sType, "ayiya") == 0)
		{
			/* We are spawned, now just beat once in a while. */
			while (g_aiccu->running)
			{
				aiccu_beat(hTunnel);
#ifndef _WIN32
				sleep(hTunnel->nHeartbeat_Interval);
#else
				for (i=0; g_aiccu->running && i <= hTunnel->nHeartbeat_Interval; i++) Sleep(1000);
#endif
			}

			/* Clean up the the tunnel, no beat anyway */
			aiccu_delete(hTunnel);
		}

#ifndef _WIN32
		/* Remove our PID file */
		if (g_aiccu) unlink(g_aiccu->pidfile);
#endif
	}

	/* Free our resources */
	aiccu_FreeConfig();

	return 0;
}
예제 #2
0
파일: tic.c 프로젝트: twikz/maiccu
struct TIC_Tunnel *tic_GetTunnel(struct TIC_conf *tic, const char *sId)
{
	char			buf[1024];
	struct TIC_Tunnel	*tun;

	/* Get a Tunnel */
	sock_printf(tic->sock, "tunnel show %s\n", sId);

	/* Fetch the answer */
	if (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) == -1)
	{
		return NULL;
	}

	/* 201 (start of information) ? */
	if (buf[0] != '2' || buf[1] != '0' || buf[2] != '1')
	{
		dolog(LOG_ERR, "Couldn't show tunnel %s: %s.\n", sId, buf);
		return NULL;
	}

	/* Allocate a new struct */
	tun = (struct TIC_Tunnel *)malloc(sizeof(*tun));
	if (!tun)
	{
		dolog(LOG_ERR, "Memory problem while getting tunnel %s\n", sId);
		return NULL;
	}
	memset(tun, 0, sizeof(*tun));

	/* Gather the information */
	while (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) != -1)
	{
		/* 202 (end of list) ? */
		if (buf[0] == '2' && buf[1] == '0' && buf[2] == '2') break;
		
		parseline(buf, ": ", tunnel_rules, tun);
	}
	/* All went okay? */
	if (buf[0] == '2' && buf[1] == '0' && buf[2] == '2')
	{
		struct in6_addr ipv6_ll, ipv6_local;
		char ll[100];

		/* Log that the fetch was succesful */
#ifndef AICCU_PATCH
		dolog(LOG_INFO, "Succesfully retrieved tunnel information for %s\n", sId);
#endif

		/*
		 * Some TUN/TAP devices don't have any
		 * link local addresses and we want multicast and MLD to work
		 * thus we invent one based on the following:
		 *
		 * ipv6_us = 2001:0db8:1234:5678:    :    :    :0001
		 * ipv6_ll = fe80:    :    :    :0db8:1234:5678:0001
		 *
		 * Thus we ignore the first 16bits, take the following 48 bits
		 * and then add the last 16bits.
		 *
		 * As we are not 100% sure that this LL is unique we clear that bit.
                */

		inet_pton(AF_INET6, tun->sIPv6_Local, &ipv6_local);

		/* Link Local (fe80::/64) */
		ipv6_ll.s6_addr[ 0] = 0xfe;
		ipv6_ll.s6_addr[ 1] = 0x80;
		ipv6_ll.s6_addr[ 2] = 0x00;
		ipv6_ll.s6_addr[ 3] = 0x00;
		ipv6_ll.s6_addr[ 4] = 0x00;
		ipv6_ll.s6_addr[ 5] = 0x00;
		ipv6_ll.s6_addr[ 6] = 0x00;
		ipv6_ll.s6_addr[ 7] = 0x00;
		ipv6_ll.s6_addr[ 8] = ipv6_local.s6_addr[ 2] & 0xfc; /* Clear the LL Unique Bit */
		ipv6_ll.s6_addr[ 9] = ipv6_local.s6_addr[ 3];
		ipv6_ll.s6_addr[10] = ipv6_local.s6_addr[ 4];
		ipv6_ll.s6_addr[11] = ipv6_local.s6_addr[ 5];
		ipv6_ll.s6_addr[12] = ipv6_local.s6_addr[ 6];
		ipv6_ll.s6_addr[13] = ipv6_local.s6_addr[ 7];
		ipv6_ll.s6_addr[14] = ipv6_local.s6_addr[14];
		ipv6_ll.s6_addr[15] = ipv6_local.s6_addr[15];

		inet_ntop(AF_INET6, &ipv6_ll, ll, sizeof(ll));
		if (tun->sIPv6_LinkLocal) free(tun->sIPv6_LinkLocal);
		tun->sIPv6_LinkLocal = strdup(ll);

		if (	strcmp(tun->sType, "ayiya") == 0 ||
			strcmp(tun->sType, "l2tp") == 0)
		{
			tun->uses_tundev = 1;
#ifdef NO_IFHEAD
			dolog(LOG_ERR, "This build doesn't support the Tun/TAP device and thus can't instantiate tunnels of type %s, please fix your OS and recompile\n", tun->sType);
			tic_Free_Tunnel(tun);
			return NULL;
#endif
		}
		else tun->uses_tundev = 0;

		/* Need to override the local IPv4 address? */
#ifndef AICCU_PATCH
		if (g_aiccu->local_ipv4_override)
		{
			dolog(LOG_INFO, "Overriding Local IPv4 address from %s to %s\n", tun->sIPv4_Local, g_aiccu->local_ipv4_override);
			free(tun->sIPv4_Local);
			tun->sIPv4_Local = strdup(g_aiccu->local_ipv4_override);
		}
#endif
		return tun;
	}

	/* Free the structure, it is broken anyway */
	tic_Free_Tunnel(tun);

	dolog(LOG_ERR, "Tunnel Get for %s went wrong: %s\n", sId, buf);
	return NULL;
}