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); }
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); }