Ejemplo n.º 1
0
/*
 * Converts the internet address plus port string in 'St'
 * into their network byte order representations.
 *
 * returns: - 0 -> conversion failed
 *          - 1 -> only address part returned (inaddrPt)
 *          - 2 -> address and port returned
 *
 */
static void getSockAdr(struct sockaddr *SaPt, socklen_t * SaLenPt, char *AddrSt, char *PortSt)
{
	struct sockaddr_in *Sin4;
	struct sockaddr_in6 *Sin6;

	if (strchr(AddrSt, ':') == NULL) {
		Sin4 = SIN4(SaPt);
		memset(Sin4, 0, sizeof(*Sin4));

		Sin4->sin_family = AF_INET;
		Sin4->sin_port = htons(atoi(PortSt));

		if (inet_pton(AF_INET, AddrSt, &Sin4->sin_addr) <= 0) {
			smclog(LOG_ERR, "inet_pton failed for address %s: %m", AddrSt);
			exit(255);
		}

		*SaLenPt = sizeof(struct sockaddr_in);
	} else {
		Sin6 = SIN6(SaPt);
		memset(Sin6, 0, sizeof(*Sin6));

		Sin6->sin6_family = AF_INET6;
		Sin6->sin6_port = htons(atoi(PortSt));

		if (inet_pton(AF_INET6, AddrSt, &Sin6->sin6_addr) <= 0) {
			smclog(LOG_ERR, "inet_pton failed for address %s: %m", AddrSt);
			exit(255);
		}

		*SaLenPt = sizeof(struct sockaddr_in6);
	}
}
Ejemplo n.º 2
0
static void SetOif4(int Sock, char *ifname)
{
	struct ifreq IfReq;
	struct sockaddr_in *Sin4 = NULL;

	memset(&IfReq, 0, sizeof(IfReq));
	strncpy(IfReq.ifr_name, ifname, sizeof(IfReq.ifr_name));

	if (ioctl(Sock, SIOCGIFADDR, &IfReq) < 0) {
		smclog(LOG_ERR, "ioctl SIOCGIFADDR: %m");
		exit(255);
	}

	switch (IfReq.ifr_addr.sa_family) {
	case AF_INET:
		Sin4 = SIN4(&IfReq.ifr_addr);
		break;

	default:
		fprintf(stderr, "SetOif4 - invalid address family: %d\n", IfReq.ifr_addr.sa_family);
		exit(1);
	}

	if (setsockopt(Sock, IPPROTO_IP, IP_MULTICAST_IF, &Sin4->sin_addr, sizeof(struct in_addr))) {
		smclog(LOG_ERR, "set IP_MULTICAST_IF: %m");
		exit(255);
	}
}
Ejemplo n.º 3
0
/* Parse .conf file and setup routes */
static void read_conf_file(const char *conf_file)
{
	if (access(conf_file, R_OK)) {
		smclog(LOG_WARNING, errno, "Failed loading %s", conf_file);
		return;
	}

	if (parse_conf_file(conf_file))
		smclog(LOG_WARNING, errno, "Failed reading %s", conf_file);
}
Ejemplo n.º 4
0
Archivo: ifvc.c Proyecto: fipn/smcroute
/**
 * iface_init - Setup vector of active interfaces
 *
 * Builds up a vector with active system interfaces.  Must be called
 * before any other interface functions in this module!
 */
void iface_init(void)
{
	int family;
	struct iface *iface;
	struct ifaddrs *ifaddr, *ifa;

	num_ifaces = 0;

	if (iface_list)
		free(iface_list);

	iface_list = calloc(MAX_IF, sizeof(struct iface));
	if (!iface_list) {
		smclog(LOG_ERR, "Failed allocating space for interfaces: %m");
		exit(255);
	}

	if (getifaddrs(&ifaddr) == -1) {
		smclog(LOG_ERR, "Failed retrieving interface addresses: %m");
		exit(255);
	}

	for (ifa = ifaddr; ifa && num_ifaces < MAX_IF; ifa = ifa->ifa_next) {
		/* Check if already added? */
		if (iface_find_by_name(ifa->ifa_name))
			continue;

		/* Copy data from interface iterator 'ifa' */
		iface = &iface_list[num_ifaces++];
		strncpy(iface->name, ifa->ifa_name, IFNAMSIZ);
		iface->name[IFNAMSIZ] = 0;

		/*
		 * Only copy interface address if inteface has one.  On
		 * Linux we can enumerate VIFs using ifindex, useful for
		 * DHCP interfaces w/o any address yet.  Other UNIX
		 * systems will fail on the MRT_ADD_VIF ioctl. if the
		 * kernel cannot find a matching interface.
		 */
		if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET)
			iface->inaddr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
		iface->flags = ifa->ifa_flags;
		iface->ifindex = if_nametoindex(iface->name);
		iface->vif = -1;
		iface->mif = -1;
		iface->threshold = DEFAULT_THRESHOLD;
	}
	freeifaddrs(ifaddr);
}
Ejemplo n.º 5
0
static void SetTtl4(int Sock, unsigned Ttl)
{
	if (setsockopt(Sock, IPPROTO_IP, IP_MULTICAST_TTL, &Ttl, sizeof(Ttl))) {
		smclog(LOG_ERR, "set IP_MULTICAST_TTL: %m");
		exit(255);
	}
}
Ejemplo n.º 6
0
static void SetTtl6(int Sock, unsigned Ttl)
{
	if (setsockopt(Sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &Ttl, sizeof(Ttl))) {
		smclog(LOG_ERR, "set IPV6_MULTICAST_HOPS: %m");
		exit(255);
	}
}
Ejemplo n.º 7
0
/* Cleans up, i.e. releases allocated resources. Called via atexit() */
static void clean(void)
{
	mroute4_disable();
	mroute6_disable();
	ipc_exit();
	smclog(LOG_NOTICE, 0, "Exiting.");
}
Ejemplo n.º 8
0
static int daemonize(void)
{
	int pid;

	pid = fork();
	if (pid < 0)
		smclog(LOG_ERR, errno, "Cannot start in background");
	if (!pid) {
		/* Detach deamon from terminal */
		if (close(0) < 0 || close(1) < 0 || close(2) < 0
		    || open("/dev/null", 0) != 0 || dup2(0, 1) < 0
		    || dup2(0, 2) < 0 || setpgrp() < 0)
			smclog(LOG_ERR, errno, "Failed detaching deamon");
	}

	return pid;
}
Ejemplo n.º 9
0
/* Cleans up, i.e. releases allocated resources. Called via atexit() */
static void clean(void)
{
	mroute4_disable(1);
	mroute6_disable(1);
	mcgroup4_disable();
	mcgroup6_disable();
	ipc_exit();
	iface_exit();
	smclog(LOG_NOTICE, "Exiting.");
}
Ejemplo n.º 10
0
/*
 * Creates and connects a simple UDP socket to the target
 * 'inaddr':'Port'
 *
 * returns: - the opened socket
 */
int udp_socket_open(uint32 inaddr, uint16 port)
{
	int sd;
	struct sockaddr_in sa;

	sd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sd < 0)
		smclog(LOG_ERR, errno, "UDP socket open");

	sa.sin_family = AF_INET;
	sa.sin_port = port;
	sa.sin_addr.s_addr = inaddr;
	memset(&sa.sin_zero, 0, sizeof(sa.sin_zero));

	if (connect(sd, (struct sockaddr *)&sa, sizeof(sa)))
		smclog(LOG_ERR, errno, "UDP socket connect");

	return sd;
}
Ejemplo n.º 11
0
static void SetOif6(int Sock, char *ifname)
{
	unsigned ifindex;

	ifindex = if_nametoindex(ifname);

	if (setsockopt(Sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex))) {
		smclog(LOG_ERR, "set IPV6_MULTICAST_IF: %m");
		exit(255);
	}
}
Ejemplo n.º 12
0
static void signal_init(void)
{
	struct sigaction sa;

	sa.sa_handler = handler;
	sa.sa_flags = 0;	/* Interrupt system calls */
	sigemptyset(&sa.sa_mask);
	if (sigaction(SIGHUP,  &sa, NULL)  ||
	    sigaction(SIGTERM, &sa, NULL) ||
	    sigaction(SIGINT,  &sa, NULL))
		smclog(LOG_WARNING, "Failed setting up signal handlers: %s", strerror(errno));
}
Ejemplo n.º 13
0
/* Init everything before forking, so we can fail and return an
 * error code in the parent and the initscript will fail */
static void start_server(int background)
{
	int sd, api = 0;

	if (background && daemonize())
		return;

	smclog(LOG_NOTICE, 0, "%s", version_info);

	/* Build list of multicast-capable physical interfaces that
	 * are currently assigned an IP address. */
	iface_init();

	if (!mroute4_enable())
		api++;

	if (!mroute6_enable())
		api++;

	/* At least one API (IPv4 or IPv6) must have initialized successfully
	 * otherwise we abort the server initialization. */
	if (!api) {
		smclog(LOG_INIT, ENOPROTOOPT, "Kernel does not support multicast routing");
		exit(1);
	}

	sd = ipc_server_init();
	if (sd < 0)
		smclog(LOG_WARNING, errno, "Failed setting up IPC socket, client communication disabled");

	atexit(clean);
	signal_init();
	read_conf_file(conf_file);

	/* Everything setup, notify any clients by creating the pidfile */
	if (pidfile(NULL))
		smclog(LOG_WARNING, errno, "Failed creating pidfile");

	server_loop(sd);
}
Ejemplo n.º 14
0
const char *cmd_convert_to_mroute4(struct mroute4 *mroute, const struct cmd *packet)
{
	char *arg = (char *)packet->argv;

	memset(mroute, 0, sizeof(*mroute));

	/* -a eth0 1.1.1.1 239.1.1.1 eth1 eth2
	 *
	 *  +----+-----+---+--------------------------------------------+
	 *  | 42 | 'a' | 5 | "eth0\01.1.1.1\0239.1.1.1\0eth1\0eth2\0\0" |
	 *  +----+-----+---+--------------------------------------------+
	 *  ^              ^
	 *  |              |
	 *  |              |
	 *  +-----cmd------+
	 */

	/* get input interface index */
	if (!*arg || (mroute->inbound = iface_get_vif_by_name(arg)) < 0)
		return "Invalid input interface";

	/* get origin */
	arg += strlen(arg) + 1;
	if (!*arg || (inet_pton(AF_INET, arg, &mroute->sender) <= 0))
		return "Invalid origin IPv4 address";

	/* get multicast group */
	arg += strlen(arg) + 1;
	if (!*arg || (inet_pton(AF_INET, arg, &mroute->group) <= 0) || !IN_MULTICAST(ntohl(mroute->group.s_addr)))
		return "Invalid multicast group";

	/*
	 * Scan output interfaces for the 'add' command only, just ignore it
	 * for the 'remove' command to be compatible to the first release.
	 */
	if (packet->cmd == 'a') {
		for (arg += strlen(arg) + 1; *arg; arg += strlen(arg) + 1) {
			int vif;

			if ((vif = iface_get_vif_by_name(arg)) < 0)
				return "Invalid output interface";

			if (vif == mroute->inbound)
				smclog(LOG_WARNING, 0, "Same outbound interface as inbound %s?", arg);

			mroute->ttl[vif] = 1;	/* Use a TTL threashold */
		}
	}

	return NULL;
}
Ejemplo n.º 15
0
/*
 * Signal handler.  Take note of the fact that the signal arrived
 * so that the main loop can take care of it.
 */
static void handler(int sig)
{
	switch (sig) {
	case SIGINT:
	case SIGTERM:
		running = 0;
		break;

	case SIGHUP:
		smclog(LOG_NOTICE, 0, "Got SIGHUP, reloading %s ...", conf_file);
		restart();
		read_conf_file(conf_file);
		break;
	}
}
Ejemplo n.º 16
0
static void server_loop(int sd)
{
	int result;
	fd_set fds;
#ifdef HAVE_IPV6_MULTICAST_ROUTING
	int max_fd_num = MAX(sd, MAX(mroute4_socket, mroute6_socket));
#else
	int max_fd_num = MAX(sd, mroute4_socket);
#endif

	/* Watch the MRouter and the IPC socket to the smcroute client */
	while (running) {
		FD_ZERO(&fds);
		FD_SET(sd, &fds);
		FD_SET(mroute4_socket, &fds);
#ifdef HAVE_IPV6_MULTICAST_ROUTING
		if (-1 != mroute6_socket)
			FD_SET(mroute6_socket, &fds);
#endif

		/* wait for input */
		result = select(max_fd_num + 1, &fds, NULL, NULL, NULL);
		if (result <= 0) {
			/* Log all errors, except when signalled, ignore failures. */
			if (EINTR != errno)
				smclog(LOG_WARNING, errno, "select() failure");
			continue;
		}

		if (FD_ISSET(mroute4_socket, &fds))
			read_mroute4_socket();

#ifdef HAVE_IPV6_MULTICAST_ROUTING
		if (-1 != mroute6_socket && FD_ISSET(mroute6_socket, &fds))
			read_mroute6_socket();
#endif

		/* loop back to select if there is no smcroute command */
		if (FD_ISSET(sd, &fds))
			read_ipc_command();
	}
}
Ejemplo n.º 17
0
const char *cmd_convert_to_mroute6(struct mroute6 *mroute, const struct cmd *packet)
{
	const char *arg = (const char *)(packet + 1);

	memset(mroute, 0, sizeof(*mroute));

	/* get input interface index */
	if (!*arg || (mroute->inbound = iface_get_mif_by_name(arg)) < 0)
		return "Invalid input interface";

	/* get origin */
	arg += strlen(arg) + 1;
	if (!*arg || (inet_pton(AF_INET6, arg, &mroute->sender.sin6_addr) <= 0))
		return "Invalid origin IPv6 address";

	/* get multicast group */
	arg += strlen(arg) + 1;

	if (!*arg || (inet_pton(AF_INET6, arg, &mroute->group.sin6_addr) <= 0)
	    || !IN6_IS_ADDR_MULTICAST(&mroute->group.sin6_addr))
		return "Invalid multicast group";

	/*
	 * Scan output interfaces for the 'add' command only, just ignore it
	 * for the 'remove' command to be compatible to the first release.
	 */
	if (packet->cmd == 'a') {
		for (arg += strlen(arg) + 1; *arg; arg += strlen(arg) + 1) {
			int mif;

			if ((mif = iface_get_mif_by_name(arg)) < 0)
				return "Invalid output interface";

			if (mif == mroute->inbound)
				smclog(LOG_WARNING, 0, "Same outbound interface as inbound %s?", arg);

			mroute->ttl[mif] = 1;	/* Use a TTL threashold */
		}
	}

	return NULL;
}
Ejemplo n.º 18
0
static int compose_paths(void)
{
	/* Default .conf file path: "/etc" + '/' + "smcroute" + ".conf" */
	if (!conf_file) {
		size_t len = strlen(SYSCONFDIR) + strlen(ident) + 7;

		conf_file = malloc(len);
		if (!conf_file) {
			smclog(LOG_ERR, "Failed allocating memory, exiting: %s", strerror(errno));
			exit(1);
		}

		snprintf(conf_file, len, "%s/%s.conf", SYSCONFDIR, ident);
	}

	/* Default is to let pidfile() API construct PID file from ident */
	if (!pid_file)
		pid_file = ident;

	return 0;
}
Ejemplo n.º 19
0
int main(int ArgCn, char *ArgVc[])
{
	unsigned TtlVal = 0;
	char *OifVal = NULL;
	char *AddrSt = NULL;
	char *PortSt = NULL;
	char *Pt;
	void (*SetTtl) (int, unsigned) = NULL;
	void (*SetOif) (int, char *) = NULL;
	struct sockaddr_storage TarAdr;
	socklen_t TarAdrLen = 0;

	if (ArgCn < 2) {
		usage();
		exit(1);
	}

	while (*++ArgVc) {
		Pt = *ArgVc;

		/* option */
		if (*Pt == '-') {
			switch (*++Pt) {

			case 'D':
				log_level = LOG_DEBUG;
				break;

			case 't':
				if (sscanf(Pt + 1, " %3u", &TtlVal) != 1 || TtlVal < 1) {
					usage();
					exit(1);
				}
				break;

			case 'i':
				OifVal = Pt + 1;
				break;

			default:
				usage();
				exit(1);
			}
		} else {	/* argument */

			memset(&TarAdr, 0, sizeof(TarAdr));

			AddrSt = Pt;

			Pt = strrchr(AddrSt, ':');
			if (Pt == NULL) {
				usage();
				exit(1);
			}

			*Pt++ = '\0';
			PortSt = Pt;

			getSockAdr(SA(&TarAdr), &TarAdrLen, AddrSt, PortSt);

			SetTtl = (TarAdr.ss_family == AF_INET) ? SetTtl4 : SetTtl6;
			SetOif = (TarAdr.ss_family == AF_INET) ? SetOif4 : SetOif6;
		}
	}

	if (TarAdrLen) {
		int UdpSock;


		UdpSock = socket(TarAdr.ss_family, SOCK_DGRAM, IPPROTO_UDP);
		if (UdpSock < 0) {
			smclog(LOG_ERR, "UDP socket open: %m");
			exit(255);
		}

		if (TtlVal)
			(*SetTtl) (UdpSock, TtlVal);
		if (OifVal)
			(*SetOif) (UdpSock, OifVal);

		while (1) {
			if (sendto(UdpSock, McMsg, sizeof(McMsg), 0, SA(&TarAdr), TarAdrLen) != sizeof(McMsg))
				smclog(LOG_WARNING, "send to UDP socket: %m");

			sleep(1);
		}
	}

	return 0;
}
Ejemplo n.º 20
0
/* Receive command from the smcroute client */
static int read_ipc_command(void)
{
	const char *str;
	struct cmd *packet;
	struct mroute mroute;
	uint8 buf[MX_CMDPKT_SZ];

	memset(buf, 0, sizeof(buf));
	packet = ipc_server_read(buf, sizeof(buf));
	if (!packet) {
		/* Skip logging client disconnects */
		if (errno != ECONNRESET)
			smclog(LOG_WARNING, errno, "Failed receving IPC message from client");
		return 1;
	}

	switch (packet->cmd) {
	case 'a':
	case 'r':
		if ((str = cmd_convert_to_mroute(&mroute, packet))) {
			smclog(LOG_WARNING, 0, str);
			ipc_send(log_last_message, strlen(log_last_message) + 1);
			break;
		}

		if (mroute.version == 4) {
			if ((packet->cmd == 'a' && mroute4_add(&mroute.u.mroute4))
			    || (packet->cmd == 'r' && mroute4_del(&mroute.u.mroute4))) {
				ipc_send(log_last_message, strlen(log_last_message) + 1);
				break;
			}
		} else {
#ifndef HAVE_IPV6_MULTICAST_ROUTING
			smclog(LOG_WARNING, 0, "IPv6 multicast routing support disabled.");
#else
			if ((packet->cmd == 'a' && mroute6_add(&mroute.u.mroute6))
			    || (packet->cmd == 'r' && mroute6_del(&mroute.u.mroute6))) {
				ipc_send(log_last_message, strlen(log_last_message) + 1);
				break;
			}
#endif /* HAVE_IPV6_MULTICAST_ROUTING */
		}

		ipc_send("", 1);
		break;

	case 'j':	/* j <InputIntf> <McGroupAdr> */
	case 'l':	/* l <InputIntf> <McGroupAdr> */
	{
		int result = -1;
		const char *ifname = (const char *)(packet + 1);
		const char *groupstr = ifname + strlen(ifname) + 1;

		if (strchr(groupstr, ':') == NULL) {
			struct in_addr group;

			/* check multicast address */
			if (!*groupstr
			    || !inet_aton(groupstr, &group)
			    || !IN_MULTICAST(ntohl(group.s_addr))) {
				smclog(LOG_WARNING, 0, "Invalid multicast group: %s", groupstr);
				ipc_send(log_last_message, strlen(log_last_message) + 1);
				break;
			}

			/* join or leave */
			if (packet->cmd == 'j')
				result = mcgroup4_join(ifname, group);
			else
				result = mcgroup4_leave(ifname, group);
		} else {	/* IPv6 */
#ifndef HAVE_IPV6_MULTICAST_HOST
			smclog(LOG_WARNING, 0, "IPv6 multicast support disabled.");
#else
			struct in6_addr group;

			/* check multicast address */
			if (!*groupstr
			    || (inet_pton(AF_INET6, groupstr, &group) <= 0)
			    || !IN6_IS_ADDR_MULTICAST(&group)) {
				smclog(LOG_WARNING, 0, "Invalid multicast group: %s", groupstr);
				ipc_send(log_last_message, strlen(log_last_message) + 1);
				break;
			}

			/* join or leave */
			if (packet->cmd == 'j')
				result = mcgroup6_join(ifname, group);
			else
				result = mcgroup6_leave(ifname, group);
#endif /* HAVE_IPV6_MULTICAST_HOST */
		}

		/* failed */
		if (result) {
			ipc_send(log_last_message, strlen(log_last_message) + 1);
			break;
		}

		ipc_send("", 1);
		break;
	}

	case 'k':
		ipc_send("", 1);
		exit(0);
	}

	return 0;
}
Ejemplo n.º 21
0
/**
 * main - Main program
 *
 * Parses command line options and enters either daemon or client mode.
 *
 * In daemon mode, acquires multicast routing sockets, opens IPC socket
 * and goes in receive-execute command loop.
 *
 * In client mode, creates commands from command line and sends them to
 * the daemon.
 */
int main(int argc, const char *argv[])
{
	int i, num_opts, result = 0;
	int start_daemon = 0;
	int background = 1;
	uint8 buf[MX_CMDPKT_SZ];
	const char *arg;
	unsigned int cmdnum = 0;
	struct cmd *cmdv[16];

	/* init syslog */
	openlog(__progname, LOG_PID, LOG_DAEMON);

	if (argc <= 1)
		return usage();

	/* Parse command line options */
	for (num_opts = 1; (num_opts = num_option_arguments(argv += num_opts));) {
		if (num_opts < 0)	/* error */
			return usage();

		/* handle option */
		arg = argv[0];
		switch (arg[1]) {
		case 'a':	/* add route */
			if (num_opts < 5)
				return usage();
			break;

		case 'r':	/* remove route */
			if (num_opts < 4)
				return usage();
			break;

		case 'j':	/* join */
		case 'l':	/* leave */
			if (num_opts != 3)
				return usage();
			break;

		case 'k':	/* kill daemon */
			if (num_opts != 1)
				return usage();
			break;

		case 'h':	/* help */
			return usage();

		case 'v':	/* verbose */
			fputs(version_info, stderr);
			log_stderr = LOG_DEBUG;
			continue;

		case 'd':	/* daemon */
			start_daemon = 1;
			continue;

		case 'n':	/* run daemon in foreground, i.e., do not fork */
			background = 0;
			continue;

		case 'f':
			if (num_opts != 2)
				return usage();
			conf_file = argv[1];
			continue;

		case 'D':
			do_debug_logging = 1;
			continue;

		default:	/* unknown option */
			return usage();
		}

		/* Check and build command argument list. */
		if (cmdnum >= ARRAY_ELEMENTS(cmdv)) {
			fprintf(stderr, "Too many command options\n");
			return usage();
		}

		cmdv[cmdnum] = cmd_build(arg[1], argv + 1, num_opts - 1);
		if (!cmdv[cmdnum]) {
			perror("Failed parsing command");
			for (i = 0; i < cmdnum; i++)
				free(cmdv[i]);
			return 1;
		}
		cmdnum++;
	}

	if (start_daemon) {	/* only daemon parent enters */
		if (geteuid() != 0) {
			smclog(LOG_ERR, 0, "Need root privileges to start %s", __progname);
			return 1;
		}

		start_server(background);
		if (!background)
			return 0;
	}

	/* Client or daemon parent only, the daemon never reaches this point */

	/* send commands */
	if (cmdnum) {
		int retry_count = 30;

		openlog(argv[0], LOG_PID, LOG_USER);

		/* connect to daemon */
		while (ipc_client_init()) {
			switch (errno) {
			case EACCES:
				smclog(LOG_ERR, EACCES, "Need root privileges to connect to daemon");
				break;

			case ENOENT:
			case ECONNREFUSED:
				/* When starting daemon, give it 30 times a 1/10 second to get ready */
				if (start_daemon && --retry_count) {
					usleep(100000);
					continue;
				}

				smclog(LOG_WARNING, errno, "Daemon not running");
				result = 1;
				break;

			default:
				smclog(LOG_WARNING, errno, "Failed connecting to daemon");
				result = 1;
				break;
			}
		}

		for (i = 0; !result && i < cmdnum; i++) {
			int slen, rlen;
			struct cmd *command = cmdv[i];

			/* Send command */
			slen = ipc_send(command, command->len);

			/* Wait here for reply */
			rlen = ipc_receive(buf, sizeof(buf));
			if (slen < 0 || rlen < 0) {
				smclog(LOG_WARNING, errno, "Communication with daemon failed");
				result = 1;
			}

			if (rlen != 1 || *buf != '\0') {
				fprintf(stderr, "Daemon error: %s\n", buf);
				result = 1;
			}
		}

		for (i = 0; i < cmdnum; i++)
			free(cmdv[i]);
	}

	return result;
}
Ejemplo n.º 22
0
/* Init everything before forking, so we can fail and return an
 * error code in the parent and the initscript will fail */
static int start_server(void)
{
	int api = 2, busy = 0;

	if (geteuid() != 0) {
		smclog(LOG_ERR, "Need root privileges to start %s", prognm);
		return 1;
	}

	if (background) {
		if (daemon(0, 0) < 0) {
			smclog(LOG_ERR, "Failed daemonizing: %s", strerror(errno));
			return 1;
		}
	}

	/* Hello world! */
	smclog(LOG_NOTICE, "%s", version_info);

	if (startup_delay > 0) {
		smclog(LOG_INFO, "Startup delay requested, waiting %d sec before continuing.", startup_delay);
		sleep(startup_delay);
	}

	/*
	 * Timer API needs to be initilized before mroute4_enable()
	 */
	timer_init();

	/*
	 * Build list of multicast-capable physical interfaces
	 */
	iface_init();

	if (mroute4_enable(do_vifs, table_id, cache_tmo)) {
		if (errno == EADDRINUSE)
			busy++;
		api--;
	}

	if (mroute6_enable(do_vifs, table_id)) {
		if (errno == EADDRINUSE)
			busy++;
		api--;
	}

	/* At least one API (IPv4 or IPv6) must have initialized successfully
	 * otherwise we abort the server initialization. */
	if (!api) {
		if (busy)
			smclog(LOG_ERR, "Another multicast routing application is already running.");
		else
			smclog(LOG_ERR, "Kernel does not support multicast routing.");
		exit(1);
	}

	atexit(clean);
	signal_init();
	ipc_init();

	conf_read(conf_file, do_vifs);

	/* Everything setup, notify any clients waiting for us */
	notify_ready(pid_file, uid, gid);

	/* Drop root privileges before entering the server loop */
	cap_drop_root(uid, gid);

	return server_loop();
}
Ejemplo n.º 23
0
/**
 * main - Main program
 *
 * Parses command line options and enters either daemon or client mode.
 *
 * In daemon mode, acquires multicast routing sockets, opens IPC socket
 * and goes in receive-execute command loop.
 *
 * In client mode, creates commands from command line and sends them to
 * the daemon.
 */
int main(int argc, char *argv[])
{
	int log_opts = LOG_NDELAY | LOG_PID;
	int c, new_log_level = -1;

	prognm = progname(argv[0]);
	while ((c = getopt(argc, argv, "c:d:e:f:F:hI:l:m:nNp:P:st:v")) != EOF) {
		switch (c) {
		case 'c':	/* cache timeout */
			cache_tmo = atoi(optarg);
			break;

		case 'd':
			startup_delay = atoi(optarg);
			break;

		case 'e':
			script = optarg;
			break;

#ifndef ENABLE_DOTCONF
		case 'F':
		case 'f':
			warnx("Built without .conf file support.");
			break;
#else
		case 'F':
			log_level = LOG_INFO; /* Raise log level for verify */
			conf_vrfy = 1;
			/* fallthrough */
		case 'f':
			conf_file = optarg;
			break;
#endif

		case 'h':	/* help */
			return usage(0);

		case 'I':
			ident = optarg;
			break;

		case 'l':
			new_log_level = loglvl(optarg);
			break;

		case 'm':
#ifndef ENABLE_MRDISC
			warnx("Built without mrdisc support.");
#else
			interval = atoi(optarg);
			if (interval < 4 || interval > 180)
				errx(1, "Invalid mrdisc announcement interval, 4-180.");
#endif
			break;

		case 'n':	/* run daemon in foreground, i.e., do not fork */
			background = 0;
			do_syslog--;
			break;

		case 'N':
#ifndef ENABLE_DOTCONF
			errx(1, "Built without .conf file, no way to enable individual interfaces.");
#else
			do_vifs = 0;
#endif
			break;

		case 'p':
			cap_set_user(optarg, &uid, &gid);
			break;

		case 'P':
			pid_file = optarg;
			break;

		case 's':	/* Force syslog even though in foreground */
			do_syslog++;
			break;

		case 't':
#ifndef __linux__
			errx(1, "Different multicast routing tables only available on Linux.");
#else
			table_id = atoi(optarg);
			if (table_id < 0)
				return usage(1);
#endif
			break;

		case 'v':	/* version */
			fprintf(stderr, "%s\n", version_info);
			return 0;

		default:	/* unknown option */
			return usage(1);
		}
	}

	if (new_log_level != -1)
		log_level = new_log_level;

	compose_paths();

	if (conf_vrfy) {
		smclog(LOG_INFO, "Verifying configuration file %s ...", conf_file);
		c = conf_read(conf_file, do_vifs);
		smclog(LOG_INFO, "Configuration file %s.", c ? "has unrecoverable errors" : "is OK");

		return c;
	}

	if (!background && do_syslog < 1)
		log_opts |= LOG_PERROR;

	openlog(ident, log_opts, LOG_DAEMON);
	setlogmask(LOG_UPTO(log_level));

	return start_server();
}