Exemplo n.º 1
0
static void
reconf_reboot(int action, int argc, char **argv, int oi)
{
	struct if_head *ifs;
	struct interface *ifn, *ifp;

	ifs = discover_interfaces(argc - oi, argv + oi);
	if (ifs == NULL)
		return;

	while ((ifp = TAILQ_FIRST(ifs))) {
		TAILQ_REMOVE(ifs, ifp, next);
		ifn = find_interface(ifp->name);
		if (ifn) {
			if (action)
				if_reboot(ifn, argc, argv);
			else
				ipv4_applyaddr(ifn);
			free_interface(ifp);
		} else {
			init_state(ifp, argc, argv);
			TAILQ_INSERT_TAIL(ifaces, ifp, next);
			start_interface(ifp);
		}
	}
	free(ifs);

	sort_interfaces();
}
Exemplo n.º 2
0
void
handle_interface(int action, const char *ifname)
{
	struct if_head *ifs;
	struct interface *ifp, *ifn, *ifl = NULL;
	const char * const argv[] = { ifname };
	int i;

	if (action == -1) {
		ifp = find_interface(ifname);
		if (ifp != NULL) {
			ifp->options->options |= DHCPCD_DEPARTED;
			stop_interface(ifp);
		}
		return;
	}

	/* If running off an interface list, check it's in it. */
	if (ifc) {
		for (i = 0; i < ifc; i++)
			if (strcmp(ifv[i], ifname) == 0)
				break;
		if (i >= ifc)
			return;
	}

	ifs = discover_interfaces(-1, UNCONST(argv));
	TAILQ_FOREACH_SAFE(ifp, ifs, next, ifn) {
		if (strcmp(ifp->name, ifname) != 0)
			continue;
		/* Check if we already have the interface */
		ifl = find_interface(ifp->name);
		if (ifl) {
			/* The flags and hwaddr could have changed */
			ifl->flags = ifp->flags;
			ifl->hwlen = ifp->hwlen;
			if (ifp->hwlen != 0)
				memcpy(ifl->hwaddr, ifp->hwaddr, ifl->hwlen);
		} else {
			TAILQ_REMOVE(ifs, ifp, next);
			TAILQ_INSERT_TAIL(ifaces, ifp, next);
		}
		if (action == 1) {
			init_state(ifp, margc, margv);
			start_interface(ifp);
		}
	}

	/* Free our discovered list */
	while ((ifp = TAILQ_FIRST(ifs))) {
		TAILQ_REMOVE(ifs, ifp, next);
		free_interface(ifp);
	}
	free(ifs);
}
Exemplo n.º 3
0
int 
main(int argc, char **argv) {
	int fd;
	int i;
	struct servent *ent;
	struct server_list *sp = NULL;
	int no_daemon = 0;
	int quiet = 0;
	isc_result_t status;
	char *s;

        /* Make sure that file descriptors 0 (stdin), 1, (stdout), and
           2 (stderr) are open. To do this, we assume that when we
           open a file the lowest available file descriptor is used. */
        fd = open("/dev/null", O_RDWR);
        if (fd == 0)
                fd = open("/dev/null", O_RDWR);
        if (fd == 1)
                fd = open("/dev/null", O_RDWR);
        if (fd == 2)
                log_perror = 0; /* No sense logging to /dev/null. */
        else if (fd != -1)
                close(fd);

	openlog ("dhcrelay", LOG_NDELAY|LOG_PID, LOG_DAEMON);

#if !defined(DEBUG)
	setlogmask (LOG_UPTO (LOG_INFO));
#endif	

	/* Set up the OMAPI. */
	status = omapi_init ();
	if (status != ISC_R_SUCCESS)
		log_fatal ("Can't initialize OMAPI: %s",
			   isc_result_totext (status));

	/* Set up the OMAPI wrappers for the interface object. */
	interface_setup ();

	for (i = 1; i < argc; i++) {
		if (!strcmp (argv [i], "-p")) {
			if (++i == argc)
				usage ();
			local_port = htons (atoi (argv [i]));
			log_debug ("binding to user-specified port %d",
			       ntohs (local_port));
		} else if (!strcmp (argv [i], "-d")) {
			no_daemon = 1;
 		} else if (!strcmp (argv [i], "-i")) {
			struct interface_info *tmp =
				(struct interface_info *)0;
			status = interface_allocate (&tmp, MDL);
			if (status != ISC_R_SUCCESS)
				log_fatal ("%s: interface_allocate: %s",
					   argv [i],
					   isc_result_totext (status));
			if (++i == argc) {
				usage ();
			}
			strcpy (tmp -> name, argv [i]);
			interface_snorf (tmp, INTERFACE_REQUESTED);
			interface_dereference (&tmp, MDL);
		} else if (!strcmp (argv [i], "-q")) {
			quiet = 1;
			quiet_interface_discovery = 1;
		} else if (!strcmp (argv [i], "-a")) {
			add_agent_options = 1;
		} else if (!strcmp (argv [i], "-c")) {
			int hcount;
			if (++i == argc)
				usage ();
			hcount = atoi(argv[i]);
			if (hcount <= 255)
				max_hop_count= hcount;
			else
				usage ();
		} else if (!strcmp (argv [i], "-A")) {
			if (++i == argc)
				usage ();
			dhcp_max_agent_option_packet_length = atoi (argv [i]);
		} else if (!strcmp (argv [i], "-m")) {
			if (++i == argc)
				usage ();
			if (!strcasecmp (argv [i], "append")) {
				agent_relay_mode = forward_and_append;
			} else if (!strcasecmp (argv [i], "replace")) {
				agent_relay_mode = forward_and_replace;
			} else if (!strcasecmp (argv [i], "forward")) {
				agent_relay_mode = forward_untouched;
			} else if (!strcasecmp (argv [i], "discard")) {
				agent_relay_mode = discard;
			} else
				usage ();
		} else if (!strcmp (argv [i], "-D")) {
			drop_agent_mismatches = 1;
 		} else if (argv [i][0] == '-') {
 		    usage ();
		} else if (!strcmp (argv [i], "--version")) {
			log_info ("isc-dhcrelay-%s", PACKAGE_VERSION);
			exit (0);
 		} else {
			struct hostent *he;
			struct in_addr ia, *iap = (struct in_addr *)0;
			if (inet_aton (argv [i], &ia)) {
				iap = &ia;
			} else {
				he = gethostbyname (argv [i]);
				if (!he) {
					log_error ("%s: host unknown",
						   argv [i]);
				} else {
					iap = ((struct in_addr *)
					       he -> h_addr_list [0]);
				}
			}
			if (iap) {
				sp = ((struct server_list *)
				      dmalloc (sizeof *sp, MDL));
				if (!sp)
					log_fatal ("no memory for server.\n");
				sp -> next = servers;
				servers = sp;
				memcpy (&sp -> to.sin_addr,
					iap, sizeof *iap);
			}
 		}
	}

	if ((s = getenv ("PATH_DHCRELAY_PID"))) {
		path_dhcrelay_pid = s;
	}

	if (!quiet) {
		log_info ("%s %s", message, PACKAGE_VERSION);
		log_info (copyright);
		log_info (arr);
		log_info (url);
	} else {
		quiet = 0;
		log_perror = 0;
	}

	/* Default to the DHCP/BOOTP port. */
	if (!local_port) {
		ent = getservbyname ("dhcps", "udp");
		if (!ent)
			local_port = htons (67);
		else
			local_port = ent -> s_port;
		endservent ();
	}
	remote_port = htons (ntohs (local_port) + 1);
  
	/* We need at least one server. */
	if (!sp) {
		usage ();
	}

	/* Set up the server sockaddrs. */
	for (sp = servers; sp; sp = sp -> next) {
		sp -> to.sin_port = local_port;
		sp -> to.sin_family = AF_INET;
#ifdef HAVE_SA_LEN
		sp -> to.sin_len = sizeof sp -> to;
#endif
	}

	/* Get the current time... */
	time(&cur_time);

	/* Discover all the network interfaces. */
	discover_interfaces (DISCOVER_RELAY);

	/* Set up the bootp packet handler... */
	bootp_packet_handler = relay;

	/* Become a daemon... */
	if (!no_daemon) {
		int pid;
		FILE *pf;
		int pfdesc;

		log_perror = 0;

#ifdef __uClinux__
		if ((pid = vfork()) < 0)
#else
		if ((pid = fork()) < 0)
#endif
			log_fatal ("can't fork daemon: %m");
		else if (pid)
			exit (0);

		pfdesc = open (path_dhcrelay_pid,
			       O_CREAT | O_TRUNC | O_WRONLY, 0644);

		if (pfdesc < 0) {
			log_error ("Can't create %s: %m", path_dhcrelay_pid);
		} else {
			pf = fdopen (pfdesc, "w");
			if (!pf)
				log_error ("Can't fdopen %s: %m",
				      path_dhcrelay_pid);
			else {
				fprintf (pf, "%ld\n", (long)getpid ());
				fclose (pf);
			}	
		}

		close (0);
		close (1);
		close (2);
		pid = setsid ();

                chdir("/");
	}

	/* Start dispatching packets and timeouts... */
	dispatch ();

	/*NOTREACHED*/
	return 0;
}
Exemplo n.º 4
0
int
main(int argc, char *argv[])
{
	int			 ch, no_daemon = 0, opt, rdomain;
	extern char		*__progname;
	struct server_list	*sp = NULL;
	struct passwd		*pw;
	struct sockaddr_in	 laddr;

	/* Initially, log errors to stderr as well as to syslogd. */
	openlog(__progname, LOG_NDELAY, DHCPD_LOG_FACILITY);
	setlogmask(LOG_UPTO(LOG_INFO));

	while ((ch = getopt(argc, argv, "adi:o")) != -1) {
		switch (ch) {
		case 'd':
			no_daemon = 1;
			break;
		case 'i':
			if (interfaces != NULL)
				usage();
			if ((interfaces = calloc(1,
			    sizeof(struct interface_info))) == NULL)
				error("calloc");
			strlcpy(interfaces->name, optarg,
			    sizeof(interfaces->name));
			break;
		case 'o':
			/* add the relay agent information option */
			oflag++;
			break;
			
		default:
			usage();
			/* not reached */
		}
	}

	argc -= optind;
	argv += optind;

	if (argc < 1)
		usage();

	while (argc > 0) {
		struct hostent		*he;
		struct in_addr		 ia, *iap = NULL;

		if (inet_aton(argv[0], &ia))
			iap = &ia;
		else {
			he = gethostbyname(argv[0]);
			if (!he)
				warning("%s: host unknown", argv[0]);
			else
				iap = ((struct in_addr *)he->h_addr_list[0]);
		}
		if (iap) {
			if ((sp = calloc(1, sizeof *sp)) == NULL)
				error("calloc");
			sp->next = servers;
			servers = sp;
			memcpy(&sp->to.sin_addr, iap, sizeof *iap);
		}
		argc--;
		argv++;
	}

	if (!no_daemon)
		log_perror = 0;

	if (interfaces == NULL)
		error("no interface given");

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

	/* We need at least one server. */
	if (!sp)
		usage();

	discover_interfaces(interfaces);

	rdomain = get_rdomain(interfaces->name);

	/* Enable the relay agent option by default for enc0 */
	if (interfaces->hw_address.htype == HTYPE_IPSEC_TUNNEL)
		oflag++;

	bzero(&laddr, sizeof laddr);
	laddr.sin_len = sizeof laddr;
	laddr.sin_family = AF_INET;
	laddr.sin_port = server_port;
	laddr.sin_addr.s_addr = interfaces->primary_address.s_addr;
	/* Set up the server sockaddrs. */
	for (sp = servers; sp; sp = sp->next) {
		sp->to.sin_port = server_port;
		sp->to.sin_family = AF_INET;
		sp->to.sin_len = sizeof sp->to;
		sp->fd = socket(AF_INET, SOCK_DGRAM, 0);
		if (sp->fd == -1)
			error("socket: %m");
		opt = 1;
		if (setsockopt(sp->fd, SOL_SOCKET, SO_REUSEPORT,
		    &opt, sizeof(opt)) == -1)
			error("setsockopt: %m");
		if (setsockopt(sp->fd, SOL_SOCKET, SO_RTABLE, &rdomain,
		    sizeof(rdomain)) == -1)
			error("setsockopt: %m");
		if (bind(sp->fd, (struct sockaddr *)&laddr, sizeof laddr) == -1)
			error("bind: %m");
		if (connect(sp->fd, (struct sockaddr *)&sp->to,
		    sizeof sp->to) == -1)
			error("connect: %m");
		add_protocol("server", sp->fd, got_response, sp);
	}

	/* Socket used to forward packets to the DHCP client */
	if (interfaces->hw_address.htype == HTYPE_IPSEC_TUNNEL) {
		laddr.sin_addr.s_addr = INADDR_ANY;
		server_fd = socket(AF_INET, SOCK_DGRAM, 0);
		if (server_fd == -1)
			error("socket: %m");
		opt = 1;
		if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEPORT,
		    &opt, sizeof(opt)) == -1)
			error("setsockopt: %m");
		if (setsockopt(server_fd, SOL_SOCKET, SO_RTABLE, &rdomain,
		    sizeof(rdomain)) == -1)
			error("setsockopt: %m");
		if (bind(server_fd, (struct sockaddr *)&laddr,
		    sizeof(laddr)) == -1)
			error("bind: %m");
	}

	tzset();

	time(&cur_time);
	bootp_packet_handler = relay;
	if (!no_daemon)
		daemon(0, 0);

	if ((pw = getpwnam("_dhcp")) == NULL)
		error("user \"_dhcp\" not found");
	if (chroot(_PATH_VAREMPTY) == -1)
		error("chroot: %m");
	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");

	dispatch();
	/* not reached */

	exit(0);
}
Exemplo n.º 5
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);
}
Exemplo n.º 6
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);
}