Пример #1
0
int
main(int argc, char *argv[])
{
	int ch, cftest = 0, daemonize = 1, rdomain = -1, udpsockmode = 0;
	char *sync_iface = NULL;
	char *sync_baddr = NULL;
	u_short sync_port = 0;
	struct servent *ent;
	struct in_addr udpaddr;

	/* Initially, log errors to stderr as well as to syslogd. */

	progname = argv[0]; /* XXX: yeah, ugly. */
	opterr = 0;
	while ((ch = getopt(argc, argv, "A:C:L:c:dfl:nu::Y:y:")) != -1)
		switch (ch) {
		case 'Y':
			syncsend = 1;
			break;
		case 'y':
			syncrecv = 1;
			break;
		}
	if (syncsend || syncrecv) {
		if ((ent = getservbyname("dhcpd-sync", "udp")) == NULL)
			errx(1, "Can't find service \"dhcpd-sync\" in "
			    "/etc/services");
		sync_port = ntohs(ent->s_port);
	}
	udpaddr.s_addr = htonl(INADDR_BROADCAST);

	optreset = optind = opterr = 1;
	while ((ch = getopt(argc, argv, "A:C:L:c:dfl:nu::Y:y:")) != -1)
		switch (ch) {
		case 'A':
			abandoned_tab = optarg;
			break;
		case 'C':
			changedmac_tab = optarg;
			break;
		case 'L':
			leased_tab = optarg;
			break;
		case 'c':
			path_dhcpd_conf = optarg;
			break;
		case 'd':
			daemonize = 0;
			log_perror = 1;
			break;
		case 'f':
			daemonize = 0;
			break;
		case 'l':
			path_dhcpd_db = optarg;
			break;
		case 'n':
			daemonize = 0;
			cftest = 1;
			log_perror = 1;
			break;
		case 'u':
			udpsockmode = 1;
			if (optarg != NULL) {
				if (inet_aton(optarg, &udpaddr) != 1)
					errx(1, "Cannot parse binding IP "
					    "address: %s", optarg);
			}
			break;
		case 'Y':
			if (sync_addhost(optarg, sync_port) != 0)
				sync_iface = optarg;
			syncsend = 1;
			break;
		case 'y':
			sync_baddr = optarg;
			syncrecv = 1;
			break;
		default:
			usage();
		}

	argc -= optind;
	argv += optind;

	while (argc > 0) {
		struct interface_info *tmp = calloc(1, sizeof(*tmp));
		if (!tmp)
			error("calloc");
		(void)strlcpy(tmp->name, argv[0], sizeof(tmp->name));
		tmp->next = interfaces;
		interfaces = tmp;
		argc--;
		argv++;
	}

	/* Default DHCP/BOOTP ports. */
	server_port = htons(SERVER_PORT);
	client_port = htons(CLIENT_PORT);

	tzset();

	(void)time(&cur_time);
	if (!readconf())
		error("Configuration file errors encountered");

	if (cftest)
		exit(0);

	db_startup();
	if (!udpsockmode || argc > 0)
		discover_interfaces(&rdomain);
	if (rdomain != -1) {
		if (setfib(rdomain) == -1)
			error("setfib (%m)");
	}
	if (udpsockmode)
		udpsock_startup(udpaddr);
	icmp_startup(1, lease_pinged);

	if (syncsend || syncrecv) {
		syncfd = sync_init(sync_iface, sync_baddr, sync_port);
		if (syncfd == -1)
			err(1, "sync init");
	}

	if ((pw = getpwnam("_dhcp")) == NULL)
		error("user \"_dhcp\" not found");

	if (daemonize)
		(void)daemon(0, 0);

	/* don't go near /dev/pf unless we actually intend to use it */
	if ((abandoned_tab != NULL) ||
	    (changedmac_tab != NULL) ||
	    (leased_tab != NULL)) {
		if (pipe(pfpipe) == -1)
			error("pipe (%m)");
		switch (pfproc_pid = fork()) {
		case -1:
			error("fork (%m)");
			/* NOTREACHED */
			exit(1);
		case 0:
			/* child process. start up table engine */
			(void)close(pfpipe[1]);
			pftable_handler();
			/* NOTREACHED */
			exit(1);
		default:
			(void)close(pfpipe[0]);
			gotpipe = 1;
			break;
		}
	}

	if (chroot("/var/empty") == -1)
		error("chroot %s: %m", "/var/empty");

	if (chdir("/") == -1)
		error("chdir(\"/\"): %m");
	if (setgroups(1, &pw->pw_gid) ||
	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
		error("can't drop privileges: %m");

	add_timeout(cur_time + 5, periodic_scan, NULL);
	dispatch();

	/* not reached */
	exit(0);
}
Пример #2
0
int
main(int argc, char *argv[])
{
	int ch, cftest = 0, daemonize = 1, rdomain = -1;
	extern char *__progname;
	char *sync_iface = NULL;
	char *sync_baddr = NULL;
	u_short sync_port = 0;
	struct servent *ent;

	/* Initially, log errors to stderr as well as to syslogd. */
	openlog_r(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY, &sdata);

	opterr = 0;
	while ((ch = getopt(argc, argv, "A:C:L:c:dfl:nY:y:")) != -1)
		switch (ch) {
		case 'Y':
			syncsend = 1;
			break;
		case 'y':
			syncrecv = 1;
			break;
		}
	if (syncsend || syncrecv) {
		if ((ent = getservbyname("dhcpd-sync", "udp")) == NULL)
			errx(1, "Can't find service \"dhcpd-sync\" in "
			    "/etc/services");
		sync_port = ntohs(ent->s_port);
	}

	optreset = optind = opterr = 1;
	while ((ch = getopt(argc, argv, "A:C:L:c:dfl:nY:y:")) != -1)
		switch (ch) {
		case 'A':
			abandoned_tab = optarg;
			break;
		case 'C':
			changedmac_tab = optarg;
			break;
		case 'L':
			leased_tab = optarg;
			break;
		case 'c':
			path_dhcpd_conf = optarg;
			break;
		case 'd':
			daemonize = 0;
			log_perror = 1;
			break;
		case 'f':
			daemonize = 0;
			break;
		case 'l':
			path_dhcpd_db = optarg;
			break;
		case 'n':
			daemonize = 0;
			cftest = 1;
			log_perror = 1;
			break;
		case 'Y':
			if (sync_addhost(optarg, sync_port) != 0)
				sync_iface = optarg;
			syncsend = 1;
			break;
		case 'y':
			sync_baddr = optarg;
			syncrecv = 1;
			break;
		default:
			usage();
		}

	argc -= optind;
	argv += optind;

	while (argc > 0) {
		struct interface_info *tmp = calloc(1, sizeof(*tmp));
		if (!tmp)
			error("calloc");
		strlcpy(tmp->name, argv[0], sizeof(tmp->name));
		tmp->next = interfaces;
		interfaces = tmp;
		argc--;
		argv++;
	}

	/* Default DHCP/BOOTP ports. */
	server_port = htons(SERVER_PORT);
	client_port = htons(CLIENT_PORT);

	tzset();

	time(&cur_time);
	if (!readconf())
		error("Configuration file errors encountered");

	if (cftest)
		exit(0);

	db_startup();
	discover_interfaces(&rdomain);

	if (rdomain != -1)
		if (setrtable(rdomain) == -1)
			error("setrtable (%m)");

	icmp_startup(1, lease_pinged);

	if (syncsend || syncrecv) {
		syncfd = sync_init(sync_iface, sync_baddr, sync_port);
		if (syncfd == -1)
			err(1, "sync init");
	}

	if ((pw = getpwnam("_dhcp")) == NULL)
		error("user \"_dhcp\" not found");

	if (daemonize)
		daemon(0, 0);

	/* don't go near /dev/pf unless we actually intend to use it */
	if ((abandoned_tab != NULL) ||
	    (changedmac_tab != NULL) ||
	    (leased_tab != NULL)){
		if (pipe(pfpipe) == -1)
			error("pipe (%m)");
		switch (pfproc_pid = fork()){
		case -1:
			error("fork (%m)");
			/* NOTREACHED */
			exit(1);
		case 0:
			/* child process. start up table engine */
			pftable_handler();
			/* NOTREACHED */
			exit(1);
		default:
			gotpipe = 1;
			break;
		}
	}

	if (chroot(_PATH_VAREMPTY) == -1)
		error("chroot %s: %m", _PATH_VAREMPTY);
	if (chdir("/") == -1)
		error("chdir(\"/\"): %m");
	if (setgroups(1, &pw->pw_gid) ||
	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
		error("can't drop privileges: %m");

	bootp_packet_handler = do_packet;
	add_timeout(cur_time + 5, periodic_scan, NULL);
	dispatch();

	/* not reached */
	exit(0);
}