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