40 #include <dns/result.h>
50 extern int asprintf(
char **strp,
const char *fmt, ...);
81 #define ASSERT_STATE(state_is, state_shouldbe) {}
83 static const char copyright[] =
"Copyright 2004-2015 Internet Systems Consortium.";
84 static const char arr [] =
"All rights reserved.";
85 static const char message [] =
"Internet Systems Consortium DHCP Client";
86 static const char url [] =
"For info, please visit https://www.isc.org/software/dhcp/";
107 static void usage(
void);
109 static isc_result_t write_duid(
struct data_string *duid);
112 static int check_domain_name(
const char *ptr,
size_t len,
int dots);
113 static int check_domain_name_list(
const char *ptr,
size_t len,
int dots);
115 const char *ptr,
size_t len);
133 int release_mode = 0;
138 int no_dhclient_conf = 0;
139 int no_dhclient_db = 0;
140 int no_dhclient_pid = 0;
141 int no_dhclient_script = 0;
143 int local_family_set = 0;
146 char *dhcp_client_identifier_arg = NULL;
147 char *dhcp_host_name_arg = NULL;
148 char *dhcp_fqdn_arg = NULL;
149 char *dhcp_vendor_class_identifier_arg = NULL;
150 char *dhclient_request_options = NULL;
153 char *arg_conf = NULL;
154 int arg_conf_len = 0;
155 #ifdef HAVE_LIBCAP_NG
156 int keep_capabilities = 0;
165 fd = open(
"/dev/null", O_RDWR | O_CLOEXEC);
167 fd = open(
"/dev/null", O_RDWR | O_CLOEXEC);
169 fd = open(
"/dev/null", O_RDWR | O_CLOEXEC);
177 #if !(defined(DEBUG) || defined(__CYGWIN32__))
178 setlogmask(LOG_UPTO(LOG_INFO));
184 if (status != ISC_R_SUCCESS)
185 log_fatal(
"Can't initialize context: %s",
186 isc_result_totext(status));
190 if (status != ISC_R_SUCCESS)
192 isc_result_totext(status));
202 for (i = 1; i < argc; i++) {
203 if (!strcmp(argv[i],
"-r")) {
207 }
else if (!strcmp(argv[i],
"-4")) {
209 log_fatal(
"Client can only do v4 or v6, not "
211 local_family_set = 1;
213 }
else if (!strcmp(argv[i],
"-6")) {
215 log_fatal(
"Client can only do v4 or v6, not "
217 local_family_set = 1;
220 }
else if (!strcmp(argv[i],
"-x")) {
224 }
else if (!strcmp(argv[i],
"-p")) {
228 log_debug(
"binding to user-specified port %d",
230 }
else if (!strcmp(argv[i],
"-d")) {
233 }
else if (!strcmp(argv[i],
"-pf")) {
238 }
else if (!strcmp(argv[i],
"--no-pid")) {
240 }
else if (!strcmp(argv[i],
"-cf")) {
244 no_dhclient_conf = 1;
245 }
else if (!strcmp(argv[i],
"-df")) {
249 }
else if (!strcmp(argv[i],
"-lf")) {
254 }
else if (!strcmp(argv[i],
"-sf")) {
258 no_dhclient_script = 1;
259 }
else if (!strcmp(argv[i],
"-1")) {
261 }
else if (!strcmp(argv[i],
"-q")) {
263 }
else if (!strcmp(argv[i],
"-s")) {
267 }
else if (!strcmp(argv[i],
"-g")) {
271 }
else if (!strcmp(argv[i],
"-nw")) {
273 }
else if (!strcmp(argv[i],
"-n")) {
276 }
else if (!strcmp(argv[i],
"-w")) {
279 }
else if (!strcmp(argv[i],
"-e")) {
283 tmp =
dmalloc(strlen(argv[i]) +
sizeof *tmp,
MDL);
286 strcpy(tmp->
string, argv[i]);
291 }
else if (!strcmp(argv[i],
"-S")) {
295 local_family_set = 1;
299 }
else if (!strcmp(argv[i],
"-N")) {
303 local_family_set = 1;
309 }
else if (!strcmp(argv[i],
"-T")) {
313 local_family_set = 1;
319 }
else if (!strcmp(argv[i],
"-P")) {
323 local_family_set = 1;
330 }
else if (!strcmp(argv[i],
"-D")) {
334 if (!strcasecmp(argv[i],
"LL")) {
336 }
else if (!strcasecmp(argv[i],
"LLT")) {
341 }
else if (!strcmp(argv[i],
"-i")) {
344 }
else if (!strcmp(argv[i],
"-I")) {
347 }
else if (!strcmp(argv[i],
"-v")) {
349 }
else if (!strcmp(argv[i],
"--version")) {
350 const char vstring[] =
"isc-dhclient-";
358 }
else if (!strcmp(argv[i],
"-C")) {
359 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])==
'\0')) {
369 dhcp_client_identifier_arg = argv[i];
370 }
else if (!strcmp(argv[i],
"-B")) {
372 }
else if (!strcmp(argv[i],
"-H")) {
373 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])==
'\0')) {
383 if (dhcp_host_name_arg != NULL) {
384 log_error(
"The -H <host-name> and -F <fqdn> arguments are mutually exclusive");
388 dhcp_host_name_arg = argv[i];
389 }
else if (!strcmp(argv[i],
"-F")) {
390 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])==
'\0')) {
400 if (dhcp_fqdn_arg != NULL) {
401 log_error(
"Only one -F <fqdn> argument can be specified");
405 if (dhcp_host_name_arg != NULL) {
406 log_error(
"The -F <fqdn> and -H <host-name> arguments are mutually exclusive");
410 dhcp_fqdn_arg = argv[i];
411 }
else if (!strcmp(argv[i],
"-timeout")) {
412 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])==
'\0')) {
417 if ((timeout_arg = atoi(argv[i])) <= 0) {
418 log_error(
"timeout option must be > 0 - bad value: %s",argv[i]);
421 }
else if (!strcmp(argv[i],
"-V")) {
422 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])==
'\0')) {
432 dhcp_vendor_class_identifier_arg = argv[i];
433 }
else if (!strcmp(argv[i],
"-R")) {
434 if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])==
'\0')) {
439 dhclient_request_options = argv[i];
440 }
else if (!strcmp(argv[i],
"-nc")) {
441 #ifdef HAVE_LIBCAP_NG
442 keep_capabilities = 1;
444 }
else if (argv[i][0] ==
'-') {
451 status = interface_allocate(&tmp,
MDL);
452 if (status != ISC_R_SUCCESS)
453 log_fatal(
"Can't record interface %s:%s",
454 argv[i], isc_result_totext(status));
455 if (strlen(argv[i]) >=
sizeof(tmp->
name))
456 log_fatal(
"%s: interface name too long (is %ld)",
457 argv[i], (
long)strlen(argv[i]));
458 strcpy(tmp->
name, argv[i]);
460 interface_reference(&tmp->
next,
479 if (!no_dhclient_conf && (s = getenv(
"PATH_DHCLIENT_CONF"))) {
482 if (!no_dhclient_db && (s = getenv(
"PATH_DHCLIENT_DB"))) {
485 if (!no_dhclient_pid && (s = getenv(
"PATH_DHCLIENT_PID"))) {
488 if (!no_dhclient_script && (s = getenv(
"PATH_DHCLIENT_SCRIPT"))) {
492 #ifdef HAVE_LIBCAP_NG
494 if (!keep_capabilities) {
495 capng_clear(CAPNG_SELECT_CAPS);
496 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
498 capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
499 CAP_NET_ADMIN, CAP_NET_RAW,
500 CAP_NET_BIND_SERVICE, CAP_SYS_ADMIN, -1);
501 capng_apply(CAPNG_SELECT_CAPS);
526 log_fatal(
"Failed to get realpath for %s: %s", old_path, strerror(errno));
533 log_fatal(
"Failed to get realpath for %s: %s", old_path, strerror(errno));
542 if ((release_mode || exit_mode) && (
no_pid_file == ISC_FALSE)) {
549 e = fscanf(pidfd,
"%ld\n", &temp);
550 oldpid = (pid_t)temp;
552 if (e != 0 && e != EOF && oldpid) {
553 if (kill(oldpid, SIGTERM) == 0) {
554 log_info(
"Killed old client process");
564 }
else if (errno == ESRCH) {
578 char *new_path_dhclient_pid;
597 int n_len = strlen(ip->
name);
599 new_path_dhclient_pid = (
char*) malloc(pfx + n_len + 6);
601 sprintf(new_path_dhclient_pid + pfx,
"-%s.pid", ip->
name);
603 if ((pidfd = fopen(new_path_dhclient_pid,
"re")) != NULL) {
604 e = fscanf(pidfd,
"%ld\n", &temp);
605 oldpid = (pid_t)temp;
607 if (e != 0 && e != EOF) {
609 if (kill(oldpid, SIGTERM) == 0)
617 free(new_path_dhclient_pid);
626 char procfn[256] =
"";
629 if ((fscanf(pidfp,
"%ld", &temp)==1) && ((dhcpid=(pid_t)temp) > 0)) {
630 snprintf(procfn,256,
"/proc/%u",dhcpid);
631 dhc_running = (access(procfn, F_OK) == 0);
638 log_fatal(
"dhclient(%u) is already running - exiting. ", dhcpid);
663 memcpy(&
giaddr, he->h_addr_list[0],
672 gettimeofday(&
cur_tv, NULL);
679 he = gethostbyname(server);
712 if ((dhcp_client_identifier_arg != NULL) && (*dhcp_client_identifier_arg !=
'\0')) {
713 arg_conf_len =
asprintf(&arg_conf,
"send dhcp-client-identifier \"%s\";", dhcp_client_identifier_arg);
715 if ((arg_conf == 0) || (arg_conf_len <= 0))
716 log_fatal(
"Unable to send -C option dhcp-client-identifier");
719 if ((dhcp_host_name_arg != NULL) && (*dhcp_host_name_arg !=
'\0')) {
721 arg_conf_len =
asprintf(&arg_conf,
"send host-name \"%s\";", dhcp_host_name_arg);
723 if ((arg_conf == 0) || (arg_conf_len <= 0))
724 log_fatal(
"Unable to send -H option host-name");
726 char *last_arg_conf = arg_conf;
728 arg_conf_len =
asprintf(&arg_conf,
"%s\nsend host-name \"%s\";", last_arg_conf, dhcp_host_name_arg);
730 if ((arg_conf == 0) || (arg_conf_len <= 0))
731 log_fatal(
"Unable to send -H option host-name");
737 if ((dhcp_fqdn_arg != NULL) && (*dhcp_fqdn_arg !=
'\0')) {
739 arg_conf_len =
asprintf(&arg_conf,
"send fqdn.fqdn \"%s\";", dhcp_fqdn_arg);
741 if ((arg_conf == 0) || (arg_conf_len <= 0))
742 log_fatal(
"Unable to send -F option fqdn.fqdn");
744 char *last_arg_conf = arg_conf;
746 arg_conf_len =
asprintf(&arg_conf,
"%s\nsend fqdn.fqdn \"%s\";", last_arg_conf, dhcp_fqdn_arg);
748 if ((arg_conf == 0) || (arg_conf_len <= 0))
749 log_fatal(
"Unable to send -F option fqdn.fqdn");
757 arg_conf_len =
asprintf(&arg_conf,
"timeout %d;", timeout_arg);
759 if ((arg_conf == 0) || (arg_conf_len <= 0))
760 log_fatal(
"Unable to process -timeout timeout argument");
762 char *last_arg_conf = arg_conf;
764 arg_conf_len =
asprintf(&arg_conf,
"%s\ntimeout %d;", last_arg_conf, timeout_arg);
766 if ((arg_conf == 0) || (arg_conf_len == 0))
767 log_fatal(
"Unable to process -timeout timeout argument");
773 if ((dhcp_vendor_class_identifier_arg != NULL) && (*dhcp_vendor_class_identifier_arg !=
'\0')) {
775 arg_conf_len =
asprintf(&arg_conf,
"send vendor-class-identifier \"%s\";", dhcp_vendor_class_identifier_arg);
777 if ((arg_conf == 0) || (arg_conf_len <= 0))
778 log_fatal(
"Unable to send -V option vendor-class-identifier");
780 char *last_arg_conf = arg_conf;
782 arg_conf_len =
asprintf(&arg_conf,
"%s\nsend vendor-class-identifier \"%s\";", last_arg_conf, dhcp_vendor_class_identifier_arg);
784 if ((arg_conf == 0) || (arg_conf_len <= 0))
785 log_fatal(
"Unable to send -V option vendor-class-identifier");
791 if (dhclient_request_options != NULL) {
793 arg_conf_len =
asprintf(&arg_conf,
"request %s;", dhclient_request_options);
795 if ((arg_conf == 0) || (arg_conf_len <= 0))
796 log_fatal(
"Unable to parse -R <request options list> argument");
798 char *last_arg_conf = arg_conf;
800 arg_conf_len =
asprintf(&arg_conf,
"%s\nrequest %s;", last_arg_conf, dhclient_request_options);
802 if ((arg_conf == 0) || (arg_conf_len <= 0))
803 log_fatal(
"Unable to parse -R <request options list> argument");
810 if (arg_conf_len == 0)
811 if ((arg_conf_len = strlen(arg_conf)) == 0)
813 log_fatal(
"Unable to process -C/-H/-F/-timeout/-V/-R configuration arguments");
818 const char *val = NULL;
821 status =
new_parse(&cfile, -1, arg_conf, arg_conf_len,
"extra dhclient -C/-H/-F/-timeout/-V/-R configuration arguments", 0);
824 log_fatal(
"Cannot parse -C/-H/-F/-timeout/-V/-R configuration arguments !");
828 token =
peek_token(&val, (
unsigned *)0, cfile);
836 log_fatal(
"Cannot parse -C/-H/-F/-timeout/-V/-R configuration arguments !");
893 log_info(
"No broadcast interfaces found - exiting.");
896 }
else if (!release_mode && !exit_mode) {
930 unsigned backup_seed = 0;
933 if ( ip -> hw_address.hlen <=
sizeof seed )
936 &ip -> hw_address.hbuf [ip -> hw_address.hlen -
937 sizeof seed],
sizeof seed);
959 if ( ip -> hw_address.hlen <=
sizeof seed )
963 sizeof seed],
sizeof seed);
967 if ( seed_flag == 0 ) {
968 if ( backup_seed != 0 ) {
970 log_info (
"xid: rand init seed (0x%x) built using all"
971 " available interfaces",seed);
974 seed =
cur_time^((unsigned) gethostid()) ;
975 log_info (
"xid: warning: no netdev with useable HWADDR found"
976 " for seed's uniqueness enforcement");
977 log_info (
"xid: rand init seed (0x%x) built using gethostid",
982 srandom(seed + ((
unsigned)(
cur_tv.tv_usec * 1000000)) + (
unsigned)getpid());
985 srandom(seed + ((
unsigned)(
cur_tv.tv_usec * 1000000)) + (
unsigned)getpid());
991 setup_ib_interface(ip);
1014 for (client = ip->
client ; client != NULL ;
1015 client = client->
next) {
1019 }
else if (exit_mode) {
1039 for (client = ip->
client ; client ;
1040 client = client->
next) {
1043 else if (release_mode)
1057 tv.tv_usec = random()
1092 if (result != ISC_R_SUCCESS)
1093 log_fatal(
"Can't allocate new generic object: %s\n",
1094 isc_result_totext(result));
1099 if (result != ISC_R_SUCCESS)
1100 log_fatal(
"Can't start OMAPI protocol: %s",
1101 isc_result_totext (result));
1110 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
1111 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1112 dmalloc_cutoff_generation = dmalloc_generation;
1113 dmalloc_longterm = dmalloc_outstanding;
1114 dmalloc_outstanding = 0;
1117 #if defined(ENABLE_GENTLE_SHUTDOWN)
1152 "[-4|-6] [-SNTPI1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
1154 "[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
1156 " [-s server-addr] [-cf config-file]\n"
1157 " [-df duid-file] [-lf lease-file]\n"
1158 " [-pf pid-file] [--no-pid] [-e VAR=val]\n"
1159 " [-C <dhcp-client-identifier>] [-B]\n"
1160 " [-H <host-name> | -F <fqdn.fqdn>] [-timeout <timeout>]\n"
1161 " [-V <vendor-class-identifier>]\n"
1162 " [-R <request option list>]\n"
1163 " [-sf script-file] [interface]");
1171 isc_result_t result;
1211 client = client->
next) {
1225 if (result != ISC_R_SUCCESS)
1226 log_fatal(
"Can't allocate new generic object: %s\n",
1227 isc_result_totext(result));
1232 if (result != ISC_R_SUCCESS)
1233 log_fatal(
"Can't start OMAPI protocol: %s",
1234 isc_result_totext(result));
1240 #if defined(DEBUG_MEMORY_LEAKAGE) || defined(DEBUG_MALLOC_POOL) || \
1241 defined(DEBUG_MEMORY_LEAKAGE_ON_EXIT)
1242 dmalloc_cutoff_generation = dmalloc_generation;
1243 dmalloc_longterm = dmalloc_outstanding;
1244 dmalloc_outstanding = 0;
1265 const char *s,
const char *
file,
int line)
1309 "dhcp-client-identifier") == 0)) {
1354 client ->
active -> is_bootp ||
1368 client ->
xid = random ();
1401 client -> xid = client ->
packet.xid;
1404 client -> first_sending =
cur_time;
1405 client -> interval = client -> config -> initial_interval;
1448 for (lp = client -> offered_leases; lp; lp =
next) {
1457 picked -> next = NULL;
1462 client -> offered_leases = NULL;
1469 client -> state =
S_INIT;
1476 client ->
new = picked;
1494 client -> first_sending =
cur_time;
1495 client -> interval = client -> config -> initial_interval;
1499 client -> xid = client ->
packet.xid;
1522 for (client = ip -> client; client; client = client -> next) {
1523 if (client -> xid == packet -> raw -> xid)
1527 (packet -> interface -> hw_address.hlen - 1 !=
1528 packet -> raw -> hlen) ||
1529 (memcmp (&packet -> interface -> hw_address.hbuf [1],
1530 packet -> raw -> chaddr, packet -> raw -> hlen))) {
1532 log_debug (
"DHCPACK in wrong transaction.");
1547 log_info (
"DHCPACK from %s (xid=0x%x)",
piaddr (packet -> client_addr), ntohl(client -> xid));
1551 log_info (
"packet_to_lease failed.");
1555 client ->
new = lease;
1563 memset (&ds, 0,
sizeof ds);
1566 packet -> options, client ->
new -> options,
1571 client ->
new -> expiry = 0;
1574 client ->
new -> expiry = 0;
1579 log_error (
"no expiry time on offered lease.");
1585 tv.tv_sec =
cur_tv.tv_sec;
1586 tv.tv_usec =
cur_tv.tv_usec + 500000;
1588 if (tv.tv_usec >= 1000000) {
1590 tv.tv_usec -= 1000000;
1609 packet -> options, client ->
new -> options,
1614 client ->
new -> renewal = 0;
1617 client ->
new -> renewal = 0;
1620 if (!client ->
new -> renewal)
1621 client ->
new -> renewal = client ->
new -> expiry / 2 + 1;
1623 if (client ->
new -> renewal <= 0)
1624 client ->
new -> renewal =
TIME_MAX;
1629 (((random() % client->
new->
renewal) + 3) / 4);
1636 packet -> options, client ->
new -> options,
1641 client ->
new -> rebind = 0;
1644 client ->
new -> rebind = 0;
1646 if (client ->
new -> rebind <= 0) {
1647 if (client ->
new -> expiry <=
TIME_MAX / 7)
1648 client ->
new -> rebind =
1649 client ->
new -> expiry * 7 / 8;
1651 client ->
new -> rebind =
1652 client ->
new -> expiry / 8 * 7;
1657 if (client ->
new -> renewal > client ->
new -> rebind) {
1658 if (client ->
new -> rebind <=
TIME_MAX / 3)
1659 client ->
new -> renewal =
1660 client ->
new -> rebind * 3 / 4;
1662 client ->
new -> renewal =
1663 client ->
new -> rebind / 4 * 3;
1666 client ->
new -> expiry +=
cur_time;
1668 if (client ->
new -> expiry <
cur_time)
1669 client ->
new -> expiry =
TIME_MAX;
1670 client ->
new -> renewal +=
cur_time;
1671 if (client ->
new -> renewal <
cur_time)
1672 client ->
new -> renewal =
TIME_MAX;
1673 client ->
new -> rebind +=
cur_time;
1674 if (client ->
new -> rebind <
cur_time)
1675 client ->
new -> rebind =
TIME_MAX;
1693 client->new->medium);
1694 if (client->active && client->state !=
S_REBOOTING)
1711 log_info(
"Unable to obtain a lease on first "
1712 "try (declined). Exiting.");
1722 if (!client->last_write ||
1729 client->active = client->new;
1733 tv.tv_sec = client->active->renewal;
1734 tv.tv_usec = ((client->active->renewal -
cur_tv.tv_sec) > 1) ?
1735 random() % 1000000 :
cur_tv.tv_usec;
1738 log_info(
"bound to %s -- renewal in %ld seconds.",
1739 piaddr(client->active->address),
1740 (
long)(client->active->renewal -
cur_time));
1744 #if defined (NSUPDATE)
1745 if (client->config->do_forward_update)
1766 client -> xid = client ->
packet.xid;
1768 memset (&ds, 0,
sizeof ds);
1774 client -> active -> options,
1777 memcpy (client -> destination.iabuf, ds.
data, 4);
1778 client -> destination.len = 4;
1786 client -> first_sending =
cur_time;
1787 client -> interval = client -> config -> initial_interval;
1853 for (ap = packet -> interface -> client -> config -> reject_list;
1854 ap; ap = ap ->
next) {
1863 log_info(
"BOOTREPLY from %s rejected by rule %s "
1864 "mask %s.",
piaddr(packet->client_addr),
1878 void (*handler) (
struct packet *);
1905 for (ap = packet ->
interface -> client -> config -> reject_list;
1906 ap; ap = ap -> next) {
1915 log_info(
"%s from %s rejected by rule %s mask %s.",
1916 type,
piaddr(packet->client_addr),
1921 (*handler) (packet);
1929 char addrbuf[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")];
1937 ap ; ap = ap->
next) {
1940 log_info(
"%s from %s rejected by rule %s",
1956 log_info(
"RCV: %s message on %s from %s.",
1967 client = client->
next) {
1976 log_info(
"Packet received, but nothing done with it.");
1981 struct packet *packet;
1989 const char *
name = packet -> packet_type ?
"DHCPOFFER" :
"BOOTREPLY";
1998 for (client = ip -> client; client; client = client -> next)
1999 if (client -> xid == packet -> raw -> xid)
2006 (packet -> interface -> hw_address.hlen - 1 !=
2007 packet -> raw -> hlen) ||
2008 (memcmp (&packet -> interface -> hw_address.hbuf [1],
2009 packet -> raw -> chaddr, packet -> raw -> hlen))) {
2011 log_debug (
"%s in wrong transaction.", name);
2016 sprintf (obuf,
"%s from %s", name,
piaddr (packet -> client_addr));
2024 for (i = 0 ; req[i] != NULL ; i++) {
2031 option_code_hash_lookup(&option,
2036 log_info(
"%s: no %s option.", obuf,
2039 log_info(
"%s: no unknown-%u option.",
2050 for (lease = client -> offered_leases; lease; lease = lease -> next) {
2051 if (lease -> address.len ==
sizeof packet -> raw -> yiaddr &&
2052 !memcmp (lease -> address.iabuf,
2053 &packet -> raw -> yiaddr, lease -> address.len)) {
2061 log_info (
"%s: packet_to_lease failed.", obuf);
2067 if (!packet -> options_valid || !packet -> packet_type)
2068 lease -> is_bootp = 1;
2071 lease -> medium = client -> medium;
2074 stop_selecting = (client -> first_sending +
2075 client -> config -> select_interval);
2079 if (lease -> address.len == client -> requested_address.len &&
2080 !memcmp (lease -> address.iabuf,
2081 client -> requested_address.iabuf,
2082 client -> requested_address.len)) {
2083 lease -> next = client -> offered_leases;
2084 client -> offered_leases = lease;
2088 if (!client -> offered_leases)
2089 client -> offered_leases = lease;
2091 for (lp = client -> offered_leases; lp ->
next;
2101 if (stop_selecting <=
cur_tv.tv_sec)
2104 tv.tv_sec = stop_selecting;
2105 tv.tv_usec =
cur_tv.tv_usec;
2116 struct packet *packet;
2128 log_error(
"packet_to_lease: no memory to record lease.\n");
2132 memset(lease, 0,
sizeof(*lease));
2137 lease->address.len =
sizeof(packet->raw->yiaddr);
2138 memcpy(lease->address.iabuf, &packet->raw->yiaddr,
2139 lease->address.len);
2141 lease->next_srv_addr.len =
sizeof(packet->raw->siaddr);
2142 memcpy(lease->next_srv_addr.iabuf, &packet->raw->siaddr,
2143 lease->next_srv_addr.len);
2145 memset(&data, 0,
sizeof(data));
2147 if (client -> config -> vendor_space_name) {
2153 client -> config -> vendor_space_name &&
2155 (
struct lease *)0, client,
2159 if (!option_code_hash_lookup(&option,
2163 "option (%s:%d).",
MDL);
2167 client -> config -> vendor_space_name
2193 if (!(i & 2) && packet -> raw -> sname [0]) {
2197 if (!packet -> raw -> sname [len])
2201 log_error (
"dhcpoffer: no memory for server name.\n");
2206 packet -> raw -> sname, len);
2212 if (!(i & 1) && packet -> raw ->
file [0]) {
2216 if (!packet -> raw ->
file [len])
2220 log_error (
"dhcpoffer: no memory for filename.\n");
2225 packet -> raw ->
file, len);
2231 client, lease->options, lease->options,
2239 struct packet *packet;
2245 for (client = ip -> client; client; client = client ->
next)
2246 if (client ->
xid == packet -> raw ->
xid)
2252 (packet ->
interface -> hw_address.hlen - 1 !=
2253 packet -> raw -> hlen) ||
2254 (memcmp (&packet ->
interface -> hw_address.hbuf [1],
2255 packet -> raw -> chaddr, packet -> raw -> hlen))) {
2257 log_debug (
"DHCPNAK in wrong transaction.");
2272 log_info (
"DHCPNAK from %s (xid=0x%x)",
piaddr (packet -> client_addr), ntohl(client ->
xid));
2276 log_info (
"DHCPNAK with no active lease.\n");
2309 client -> state =
S_INIT;
2328 interval =
cur_time - client -> first_sending;
2332 if (interval > client -> config ->
timeout) {
2340 if (!client -> offered_leases &&
2341 client -> config -> media) {
2344 if (client -> medium) {
2345 client -> medium = client -> medium -> next;
2348 if (!client -> medium) {
2350 log_fatal (
"No valid media types for %s!",
2351 client -> interface -> name);
2353 client -> config -> media;
2357 log_info (
"Trying medium \"%s\" %d",
2358 client -> medium ->
string, increase);
2386 if (
cur_time + client -> interval >
2387 client -> first_sending + client -> config ->
timeout)
2388 client -> interval =
2389 (client -> first_sending +
2393 if (interval < 65536)
2394 client -> packet.secs = htons (interval);
2396 client -> packet.secs = htons (65535);
2397 client -> secs = client -> packet.secs;
2399 log_info (
"DHCPDISCOVER on %s to %s port %d interval %ld (xid=0x%x)",
2400 client -> name ? client -> name : client -> interface -> name,
2402 ntohs (
sockaddr_broadcast.sin_port), (
long)(client -> interval), ntohl(client -> xid));
2409 log_error(
"%s:%d: Failed to send %d byte long packet over %s "
2421 tv.tv_usec = client->
interval > 1 ? random() % 1000000 :
cur_tv.tv_usec;
2438 loop = lp = client -> active;
2440 log_info (
"No DHCPOFFERS received.");
2444 if (!client -> active && client -> leases)
2448 while (client -> active) {
2449 if (client -> active -> expiry >
cur_time) {
2450 log_info (
"Trying recorded lease %s",
2451 piaddr (client -> active -> address));
2455 client -> active -> medium);
2458 if (client -> alias)
2466 if (cur_time < client -> active -> renewal) {
2468 log_info (
"bound: renewal in %ld %s.",
2469 (
long)(client -> active -> renewal -
2474 random() % 1000000 :
2479 log_info (
"bound: immediate renewal.");
2489 if (!client -> leases) {
2490 client -> leases = client -> active;
2498 for (lp = client -> leases; lp ->
next; lp = lp ->
next)
2500 lp ->
next = client -> active;
2504 client -> active = client -> leases;
2505 client -> leases = client -> leases ->
next;
2510 if (client -> active == loop)
2513 loop = client -> active;
2521 log_info (
"Unable to obtain a lease on first try.%s",
2526 log_info (
"No working leases in persistent database - sleeping.");
2528 if (client -> alias)
2531 client -> state =
S_INIT;
2534 tv.tv_usec = ((tv.tv_sec -
cur_tv.tv_sec) > 1) ?
2535 random() % 1000000 :
cur_tv.tv_usec;
2547 struct sockaddr_in destination;
2548 struct in_addr from;
2552 interval =
cur_time - client -> first_sending;
2566 interval > client -> config -> reboot_timeout) {
2568 client -> state =
S_INIT;
2577 !client -> medium &&
2578 client -> active -> medium ) {
2579 script_init (client,
"MEDIUM", client -> active -> medium);
2586 client -> medium = client -> active -> medium;
2592 cur_time > client -> active -> expiry) {
2597 if (client -> alias)
2605 if (client -> alias)
2610 client -> state =
S_INIT;
2616 if (!client -> interval)
2617 client -> interval = client -> config -> initial_interval;
2619 client -> interval += ((random () >> 2) %
2620 (2 * client -> interval));
2624 if (client -> interval >
2625 client -> config -> backoff_cutoff)
2626 client -> interval =
2627 ((client -> config -> backoff_cutoff / 2)
2628 + ((random () >> 2) %
2629 client -> config -> backoff_cutoff));
2634 cur_time + client -> interval > client -> active -> expiry)
2635 client -> interval =
2636 client -> active -> expiry -
cur_time + 1;
2642 cur_time > client -> active -> rebind)
2645 memcpy (&destination.sin_addr.s_addr,
2646 client -> destination.iabuf,
2647 sizeof destination.sin_addr.s_addr);
2649 destination.sin_family = AF_INET;
2651 destination.sin_len =
sizeof destination;
2656 memcpy (&from, client -> active -> address.iabuf,
2659 from.s_addr = INADDR_ANY;
2663 client -> packet.secs = client -> secs;
2665 if (interval < 65536)
2666 client -> packet.secs = htons (interval);
2668 client -> packet.secs = htons (65535);
2671 log_info (
"DHCPREQUEST on %s to %s port %d (xid=0x%x)",
2672 client -> name ? client -> name : client -> interface -> name,
2673 inet_ntoa (destination.sin_addr),
2674 ntohs (destination.sin_port), ntohl(client -> xid));
2676 if (destination.sin_addr.s_addr != INADDR_BROADCAST &&
2678 #if defined(SO_BINDTODEVICE)
2682 log_error(
"%s:%d: Failed to bind fallback interface"
2690 log_error(
"%s:%d: Failed to send %d byte long packet "
2691 "over %s interface.",
MDL,
2695 #if defined(SO_BINDTODEVICE)
2697 SO_BINDTODEVICE, NULL, 0) < 0) {
2698 log_fatal(
"%s:%d: Failed to unbind fallback interface:"
2709 log_error(
"%s:%d: Failed to send %d byte long packet"
2710 " over %s interface.",
MDL,
2717 tv.tv_usec = ((tv.tv_sec -
cur_tv.tv_sec) > 1) ?
2718 random() % 1000000 :
cur_tv.tv_usec;
2729 log_info (
"DHCPDECLINE on %s to %s port %d (xid=0x%x)",
2739 log_error(
"%s:%d: Failed to send %d byte long packet over %s"
2751 struct sockaddr_in destination;
2752 struct in_addr from;
2754 memcpy (&from, client -> active -> address.iabuf,
2756 memcpy (&destination.sin_addr.s_addr,
2757 client -> destination.iabuf,
2758 sizeof destination.sin_addr.s_addr);
2760 destination.sin_family = AF_INET;
2762 destination.sin_len =
sizeof destination;
2767 client -> active -> expiry =
2768 client -> active -> renewal =
2769 client -> active -> rebind =
cur_time;
2771 log_error (
"Can't release lease: lease write failed.");
2775 log_info (
"DHCPRELEASE on %s to %s port %d (xid=0x%x)",
2776 client -> name ? client -> name : client -> interface -> name,
2777 inet_ntoa (destination.sin_addr),
2778 ntohs (destination.sin_port), ntohl(client -> xid));
2781 #if defined(SO_BINDTODEVICE)
2785 log_error(
"%s:%d: Failed to bind fallback interface"
2793 log_error(
"%s:%d: Failed to send %d byte long packet"
2794 " over %s interface.",
MDL,
2798 #if defined(SO_BINDTODEVICE)
2800 SO_BINDTODEVICE, NULL, 0) < 0) {
2801 log_fatal(
"%s:%d: Failed to unbind fallback interface:"
2811 log_error (
"%s:%d: Failed to send %d byte long packet"
2812 " over %s interface.",
MDL,
2829 struct buffer *bp = NULL;
2852 log_error (
"can't make requested address cache.");
2878 for (i = 0 ; prl[i] != NULL ; i++)
2883 log_error(
"can't make parameter list buffer.");
2888 for (i = 0 ; prl[i] != NULL ; i++)
2892 if (!(option_code_hash_lookup(&option,
2917 memset(&client_identifier, 0,
sizeof(client_identifier));
2920 client_identifier.
len,
MDL))
2921 log_fatal(
"no memory for default DUID!");
2939 memcpy(&client_identifier.
buffer->
data + 5 - hw_len,
2944 memcpy(&client_identifier.
buffer->
data+(1+4),
2951 (u_int8_t *)client_identifier.
data,
2952 client_identifier.
len,
2954 log_error (
"can't make requested client id cache..");
2965 (lease ? lease->
options : NULL),
2978 memset (&client -> packet, 0,
sizeof (client -> packet));
2982 lease ? &lease -> address : (
struct iaddr *)0,
2983 client -> config -> requested_options,
2987 client -> packet_length =
2989 (
struct lease *)0, client,
2998 client -> config -> vendor_space_name);
3005 client -> packet.htype = client ->
interface -> hw_address.hbuf [0];
3006 client -> packet.hlen = client ->
interface -> hw_address.hlen - 1;
3007 client -> packet.hops = 0;
3008 client -> packet.xid = random ();
3009 client -> packet.secs = 0;
3013 client -> packet.flags = 0;
3017 memset (&(client -> packet.ciaddr),
3018 0,
sizeof client -> packet.ciaddr);
3019 memset (&(client -> packet.yiaddr),
3020 0,
sizeof client -> packet.yiaddr);
3021 memset (&(client -> packet.siaddr),
3022 0,
sizeof client -> packet.siaddr);
3023 client -> packet.giaddr =
giaddr;
3024 if (client -> interface -> hw_address.hlen > 0)
3025 memcpy (client -> packet.chaddr,
3026 &client -> interface -> hw_address.hbuf [1],
3027 (
unsigned)(client -> interface -> hw_address.hlen - 1));
3030 dump_raw ((
unsigned char *)&client -> packet, client -> packet_length);
3042 memset (&client -> packet, 0,
sizeof (client -> packet));
3050 if (client -> sent_options)
3057 : (
struct iaddr *)0),
3058 client -> config -> requested_options,
3059 &client -> sent_options);
3062 client -> packet_length =
3064 (
struct lease *)0, client,
3067 client -> sent_options,
3073 client -> config -> vendor_space_name);
3079 client -> packet.htype = client ->
interface -> hw_address.hbuf [0];
3080 client -> packet.hlen = client ->
interface -> hw_address.hlen - 1;
3081 client -> packet.hops = 0;
3082 client -> packet.xid = client -> xid;
3083 client -> packet.secs = 0;
3087 if (client -> state ==
S_BOUND ||
3090 memcpy (&client -> packet.ciaddr,
3091 lease -> address.iabuf, lease -> address.len);
3092 client -> packet.flags = 0;
3094 memset (&client -> packet.ciaddr, 0,
3095 sizeof client -> packet.ciaddr);
3097 client ->config->bootp_broadcast_always)) &&
3099 client -> packet.flags = 0;
3104 memset (&client -> packet.yiaddr, 0,
3105 sizeof client -> packet.yiaddr);
3106 memset (&client -> packet.siaddr, 0,
3107 sizeof client -> packet.siaddr);
3108 if (client -> state !=
S_BOUND &&
3110 client -> packet.giaddr =
giaddr;
3112 memset (&client -> packet.giaddr, 0,
3113 sizeof client -> packet.giaddr);
3114 if (client -> interface -> hw_address.hlen > 0)
3115 memcpy (client -> packet.chaddr,
3116 &client -> interface -> hw_address.hbuf [1],
3117 (
unsigned)(client -> interface -> hw_address.hlen - 1));
3120 dump_raw ((
unsigned char *)&client -> packet, client -> packet_length);
3140 memset (&client -> packet, 0,
sizeof (client -> packet));
3141 client -> packet_length =
3143 (
struct lease *)0, client, 0,
3146 client -> config -> vendor_space_name);
3155 client -> packet.htype = client ->
interface -> hw_address.hbuf [0];
3156 client -> packet.hlen = client ->
interface -> hw_address.hlen - 1;
3157 client -> packet.hops = 0;
3158 client -> packet.xid = client -> xid;
3159 client -> packet.secs = 0;
3162 client -> packet.flags = 0;
3167 memset (&client -> packet.ciaddr, 0,
3168 sizeof client -> packet.ciaddr);
3169 memset (&client -> packet.yiaddr, 0,
3170 sizeof client -> packet.yiaddr);
3171 memset (&client -> packet.siaddr, 0,
3172 sizeof client -> packet.siaddr);
3173 client -> packet.giaddr =
giaddr;
3174 memcpy (client -> packet.chaddr,
3175 &client -> interface -> hw_address.hbuf [1],
3176 client -> interface -> hw_address.hlen);
3179 dump_raw ((
unsigned char *)&client -> packet, client -> packet_length);
3192 memset (&client -> packet, 0,
sizeof (client -> packet));
3199 client -> packet_length =
3201 (
struct lease *)0, client,
3210 client -> config -> vendor_space_name);
3217 client -> packet.htype = client ->
interface -> hw_address.hbuf [0];
3218 client -> packet.hlen = client ->
interface -> hw_address.hlen - 1;
3219 client -> packet.hops = 0;
3220 client -> packet.xid = random ();
3221 client -> packet.secs = 0;
3222 client -> packet.flags = 0;
3223 memcpy (&client -> packet.ciaddr,
3224 lease -> address.iabuf, lease -> address.len);
3225 memset (&client -> packet.yiaddr, 0,
3226 sizeof client -> packet.yiaddr);
3227 memset (&client -> packet.siaddr, 0,
3228 sizeof client -> packet.siaddr);
3229 client -> packet.giaddr =
giaddr;
3230 memcpy (client -> packet.chaddr,
3231 &client -> interface -> hw_address.hbuf [1],
3232 client -> interface -> hw_address.hlen);
3235 dump_raw ((
unsigned char *)&client -> packet, client -> packet_length);
3242 if (lease -> server_name)
3244 if (lease -> filename)
3259 if (leaseFile != NULL)
3262 if (leaseFile == NULL) {
3274 for (client = ip -> client; client; client = client ->
next) {
3275 for (lp = client -> leases; lp; lp = lp ->
next) {
3278 if (client -> active)
3280 client -> active, 1, 0);
3295 for (client = ip -> client; client; client = client ->
next) {
3296 for (lp = client -> leases; lp; lp = lp ->
next) {
3299 if (client -> active)
3301 client -> active, 1, 0);
3323 const char *name, *dot;
3325 char *preamble = stuff;
3327 memset (&ds, 0,
sizeof ds);
3337 in_options, cfg_options, scope, oc,
MDL)) {
3339 fprintf(leaseFile,
"%soption %s%s%s", preamble,
3345 fprintf(leaseFile,
" %s",
3351 fprintf(leaseFile,
";\n");
3360 const char *preamble)
3400 log_debug(
"Cannot form default DUID from interface %s.", ip->
name);
3404 return ISC_R_UNEXPECTED;
3409 log_fatal(
"Impossible hardware address length at %s:%d.",
MDL);
3425 log_fatal(
"no memory for default DUID!");
3451 return ISC_R_SUCCESS;
3461 if ((duid == NULL) || (duid->
len <= 2))
3464 if (leaseFile == NULL) {
3466 if (leaseFile == NULL) {
3468 return ISC_R_IOERROR;
3479 return ISC_R_NOMEMORY;
3481 stat = fprintf(leaseFile,
"default-duid \"%s\";\n", str);
3484 return ISC_R_IOERROR;
3486 if (fflush(leaseFile) != 0)
3487 return ISC_R_IOERROR;
3489 return ISC_R_SUCCESS;
3495 int rewrite,
int sync)
3503 if (!rewrite && (leases_written++ > 20)) {
3506 return ISC_R_SUCCESS;
3509 if (client == NULL || lease == NULL)
3512 if (leaseFile == NULL) {
3514 if (leaseFile == NULL) {
3516 return ISC_R_IOERROR;
3520 stat = fprintf(leaseFile,
"lease6 {\n");
3522 return ISC_R_IOERROR;
3524 stat = fprintf(leaseFile,
" interface \"%s\";\n",
3527 return ISC_R_IOERROR;
3529 for (ia = lease->
bindings ; ia != NULL ; ia = ia->
next) {
3542 stat = fprintf(leaseFile,
" %s %s {\n",
3545 return ISC_R_IOERROR;
3548 stat = fprintf(leaseFile,
" starts %d;\n"
3553 stat = fprintf(leaseFile,
" starts %d;\n",
3556 return ISC_R_IOERROR;
3558 for (addr = ia->
addrs ; addr != NULL ; addr = addr->
next) {
3560 stat = fprintf(leaseFile,
3564 stat = fprintf(leaseFile,
3565 " iaprefix %s/%d {\n",
3569 return ISC_R_IOERROR;
3571 stat = fprintf(leaseFile,
" starts %d;\n"
3572 " preferred-life %u;\n"
3577 return ISC_R_IOERROR;
3580 write_options(client, addr->
options,
" ");
3582 stat = fprintf(leaseFile,
" }\n");
3584 return ISC_R_IOERROR;
3588 write_options(client, ia->
options,
" ");
3590 stat = fprintf(leaseFile,
" }\n");
3592 return ISC_R_IOERROR;
3596 stat = fprintf(leaseFile,
" released;\n");
3598 return ISC_R_IOERROR;
3602 write_options(client, lease->
options,
" ");
3604 stat = fprintf(leaseFile,
"}\n");
3606 return ISC_R_IOERROR;
3608 if (fflush(leaseFile) != 0)
3609 return ISC_R_IOERROR;
3612 if (fsync(fileno(leaseFile)) < 0) {
3613 log_error(
"write_client_lease: fsync(): %m");
3614 return ISC_R_IOERROR;
3618 return ISC_R_SUCCESS;
3633 if (leases_written++ > 20) {
3641 if (lease -> is_static)
3644 if (leaseFile == NULL) {
3646 if (leaseFile == NULL) {
3653 fprintf (leaseFile,
"lease {\n");
3654 if (lease -> is_bootp) {
3655 fprintf (leaseFile,
" bootp;\n");
3661 fprintf (leaseFile,
" interface \"%s\";\n",
3662 client -> interface -> name);
3667 if (client -> name) {
3668 fprintf (leaseFile,
" name \"%s\";\n", client -> name);
3674 fprintf (leaseFile,
" fixed-address %s;\n",
3675 piaddr (lease -> address));
3680 if (lease -> filename) {
3683 fprintf (leaseFile,
" filename \"%s\";\n", s);
3696 fprintf(leaseFile,
" server-name \"%s\";\n", s);
3705 if (lease -> medium) {
3708 fprintf (leaseFile,
" medium \"%s\";\n", s);
3722 memset (&ds, 0,
sizeof ds);
3724 write_options(client, lease->
options,
" ");
3728 fprintf(leaseFile,
" renew %s\n", tval) < 0)
3733 fprintf(leaseFile,
" rebind %s\n", tval) < 0)
3738 fprintf(leaseFile,
" expire %s\n", tval) < 0)
3741 if (fprintf(leaseFile,
"}\n") < 0)
3744 if (fflush(leaseFile) != 0)
3749 if (!errors && makesure) {
3750 if (fsync (fileno (leaseFile)) < 0) {
3751 log_info (
"write_client_lease: %m");
3756 return errors ? 0 : 1;
3773 for (sl = client -> env; sl; sl =
next) {
3780 if (client -> interface) {
3782 client -> interface -> name);
3786 "",
"client",
"%s", client -> name);
3789 "",
"medium",
"%s", medium ->
string);
3792 client_envadd (client,
"",
"pid",
"%ld", (
long int)getpid ());
3806 memset (&data, 0,
sizeof data);
3809 in_options, cfg_options, scope, oc,
MDL)) {
3819 length = strlen(value);
3823 value, length) == 0) {
3828 "option - discarded",
3851 prefix,
"ip_address",
"%s",
piaddr (lease -> address));
3867 memset (&data, 0,
sizeof data);
3870 (
struct lease *)0, client,
3875 struct iaddr netmask, subnet, broadcast;
3898 (&data, (
struct packet *)0,
3899 (
struct lease *)0, client,
3904 if (broadcast.
len) {
3906 prefix,
"broadcast_address",
3907 "%s",
piaddr (broadcast));
3923 "option - discarded",
3936 "option - discarded",
3948 client_envadd (client, prefix,
"expiry",
"%d", (
int)(lease -> expiry));
3963 req = client->config->requested_options;
3968 for (i = 0 ; req[i] != NULL ; i++) {
3982 char reason [] =
"REASON=NBI";
3983 static char client_path [] = CLIENT_PATH;
3986 int pid, wpid, wstatus;
3989 scriptName = client -> config -> script_name;
3993 envp =
dmalloc (((client ? client -> envc : 2) +
3996 log_error (
"No memory for client script environment.");
4002 for (sp = client_env; sp; sp = sp ->
next) {
4003 envp [i++] = sp ->
string;
4007 for (sp = client -> env; sp; sp = sp ->
next) {
4008 envp [i++] = sp ->
string;
4011 envp [i++] = reason;
4014 envp [i++] = client_path;
4015 envp [i] = (
char *)0;
4018 argv [1] = (
char *)0;
4026 wpid = wait (&wstatus);
4027 }
while (wpid != pid && wpid > 0);
4036 if (leaseFile != NULL)
4038 execve (scriptName, argv, envp);
4039 log_error (
"execve (%s, ...): %m", scriptName);
4044 for (sp = client -> env; sp; sp =
next) {
4052 gettimeofday(&
cur_tv, NULL);
4053 return (WIFEXITED (wstatus) ?
4054 WEXITSTATUS (wstatus) : -WTERMSIG (wstatus));
4058 const char *prefix,
const char *name,
const char *fmt, ...)
4066 va_start (list, fmt);
4067 len = vsnprintf (spbuf,
sizeof spbuf, fmt, list);
4070 val =
dmalloc (strlen (prefix) + strlen (name) + 1 +
4071 len +
sizeof *val,
MDL);
4079 if (len >=
sizeof spbuf) {
4080 va_start (list, fmt);
4081 vsnprintf (s, len + 1, fmt, list);
4085 val ->
next = client -> env;
4086 client -> env = val;
4109 if (j + 1 == buflen)
4119 if (j + 1 == buflen)
4132 static int state = 0;
4150 if ((pid = fork ()) < 0)
4163 (void) open(
"/dev/null", O_RDWR | O_CLOEXEC);
4164 (void) open(
"/dev/null", O_RDWR | O_CLOEXEC);
4165 (void) open(
"/dev/null", O_RDWR | O_CLOEXEC);
4182 pfdesc = open (
path_dhclient_pid, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644);
4189 pf = fdopen (pfdesc,
"we");
4194 fprintf (pf,
"%ld\n", (
long)getpid ());
4205 for (client = ip -> client; client; client = client ->
next) {
4206 switch (client ->
state) {
4240 client -> xid = random ();
4243 if (client -> active) {
4248 memset (&ds, 0,
sizeof ds);
4250 client -> active -> options,
4254 (
struct lease *)0, client,
4256 client -> active -> options,
4259 memcpy (client -> destination.iabuf,
4261 client -> destination.len = 4;
4268 client -> first_sending =
cur_time;
4269 client -> interval = client -> config -> initial_interval;
4280 if (client -> alias)
4310 if (!strcmp (ip ->
name, tmp ->
name)) {
4314 interface_reference (&ip, last ->
next,
MDL);
4315 interface_dereference (&last ->
next,
MDL);
4317 interface_reference (&last ->
next,
4319 interface_dereference (&ip ->
next,
4324 interface_reference (&ip,
4330 interface_dereference (&ip ->
next,
4336 tmp -> client = ip ->
client;
4337 tmp -> client ->
interface = tmp;
4339 interface_dereference (&ip,
MDL);
4374 if (ip -> client ->
alias)
4376 ip -> client ->
alias);
4388 for (client = ip->
client ; client ; client = client->
next) {
4393 return ISC_R_SUCCESS;
4400 struct packet *packet;
4419 static void shutdown_exit (
void *foo)
4427 #if defined (NSUPDATE)
4444 isc_result_t eresult)
4447 isc_result_t result;
4449 if ((eresult == ISC_R_SUCCESS) &&
4455 if (result == ISC_R_SUCCESS) {
4461 dhclient_ddns_cb_free(ddns_cb,
MDL);
4470 isc_result_t result;
4473 if (client->
ddns_cb != NULL) {
4479 if (ddns_cb != NULL) {
4485 ddns_cb->
cur_func = client_dns_remove_action;
4489 if (result != ISC_R_TIMEDOUT) {
4490 dhclient_ddns_cb_free(ddns_cb,
MDL);
4506 return ISC_R_SUCCESS;
4510 log_info(
"Received signal %d, initiating shutdown.",
4519 for (client = ip -> client; client; client = client -> next) {
4522 return ISC_R_SUCCESS;
4525 return ISC_R_SUCCESS;
4528 if (client -> active &&
4529 client -> active -> expiry >
cur_time) {
4530 #if defined (NSUPDATE)
4552 tv.tv_sec =
cur_tv.tv_sec;
4553 tv.tv_usec =
cur_tv.tv_usec + 1;
4556 return ISC_R_SUCCESS;
4559 #if defined (NSUPDATE)
4570 isc_result_t status = ISC_R_FAILURE;
4572 if ((client != NULL) &&
4573 ((client->
active != NULL) ||
4586 if (status != ISC_R_TIMEDOUT) {
4587 dhclient_ddns_cb_free(ddns_cb,
MDL);
4622 isc_result_t eresult)
4624 isc_result_t result;
4641 ddns_cb->
cur_func = client_dns_update_action;
4644 if (result == ISC_R_SUCCESS) {
4650 case ISC_R_TIMEDOUT:
4658 if (ddns_cb->
zone != NULL) {
4664 ddns_cb->
cur_func = client_dns_update_action;
4670 tv.tv_usec =
cur_tv.tv_usec;
4672 ddns_cb, NULL, NULL);
4676 dhclient_ddns_cb_free(ddns_cb,
MDL);
4694 if (!client -> sent_options)
4695 return ISC_R_SUCCESS;
4699 return ISC_R_SUCCESS;
4705 (
struct lease *)0, client,
4706 client -> sent_options,
4709 return ISC_R_SUCCESS;
4716 (
struct lease *)0, client,
4717 client -> sent_options,
4720 return ISC_R_SUCCESS;
4726 (
struct lease *)0, client,
4727 client -> sent_options,
4730 return ISC_R_SUCCESS;
4742 memset(&client_identifier, 0,
sizeof(client_identifier));
4766 client_identifier.data,
4767 client_identifier.len);
4785 (client_identifier.data[0] == 255)) {
4790 if (client_identifier.len <= 5)
4791 log_fatal(
"Impossible condition at %s:%d.",
4794 client_identifier.data + 5,
4795 client_identifier.len - 5);
4797 result =
get_dhcid(ddns_cb, ddns_v4_type,
4798 client_identifier.data,
4799 client_identifier.len);
4809 return ISC_R_SUCCESS;
4818 rcode = ISC_R_FAILURE;
4824 if (rcode == ISC_R_SUCCESS) {
4825 rcode = ISC_R_TIMEDOUT;
4848 if (client->
ddns_cb != NULL) {
4855 if (ddns_cb != NULL) {
4856 ddns_cb->
lease = (
void *)client;
4869 ddns_cb->
cur_func = client_dns_update_action;
4873 tv.tv_sec =
cur_tv.tv_sec + offset;
4874 tv.tv_usec =
cur_tv.tv_usec;
4876 ddns_cb, NULL, NULL);
4878 log_error(
"Unable to allocate dns update state for %s",
4887 struct servent *ent;
4901 ent = getservbyname(
"dhcpc",
"udp");
4903 ent = getservbyname(
"bootpc",
"udp");
4908 #ifndef __CYGWIN32__
4932 static int check_domain_name(
const char *ptr,
size_t len,
int dots)
4937 if ((len == 0) || (len > 256))
4942 for (p=ptr; (*p != 0) && (len-- > 0); p++) {
4943 if ((*p ==
'-') || (*p ==
'_')) {
4945 if (((p - ptr) == 0) || (len == 0) || (p[1] ==
'.'))
4947 }
else if (*p ==
'.') {
4951 if ((d <= 0) || (d >= 64))
4954 if ((dots > 0) && (len > 0))
4956 }
else if (isalnum((
unsigned char)*p) == 0) {
4961 return(dots ? -1 : 0);
4964 static int check_domain_name_list(
const char *ptr,
size_t len,
int dots)
4969 if ((ptr == NULL) || (len == 0))
4972 for (p=ptr; (*p != 0) && (len > 0); p++, len--) {
4976 if (check_domain_name(ptr, p - ptr, dots) != 0)
4983 return(check_domain_name(ptr, p - ptr, dots));
5000 #ifdef ACCEPT_LIST_IN_DOMAIN_NAME
5001 return check_domain_name_list(ptr, len, 0);
5003 return check_domain_name(ptr, len, 0);
5008 return check_domain_name(ptr, len, 0);
5011 return check_domain_name_list(ptr, len, 0);
5016 for (; (*ptr != 0) && (len-- > 0); ptr++) {
5017 if(!(isalnum((
unsigned char)*ptr) ||
5018 *ptr ==
'#' || *ptr ==
'%' ||
5019 *ptr ==
'+' || *ptr ==
'-' ||
5020 *ptr ==
'_' || *ptr ==
':' ||
5021 *ptr ==
'.' || *ptr ==
',' ||
5022 *ptr ==
'@' || *ptr ==
'~' ||
5023 *ptr ==
'\\' || *ptr ==
'/' ||
5024 *ptr ==
'[' || *ptr ==
']' ||
5025 *ptr ==
'=' || *ptr ==
' '))
5040 return check_domain_name_list(ptr, len, 0);
5050 add_reject(
struct packet *packet) {
5055 log_fatal (
"no memory for reject list!");
5074 log_info(
"Server added to list of rejected servers.");
5083 if (client != NULL) {
void do_packet6(struct interface_info *, const char *, int, int, const struct iaddr *, isc_boolean_t)
void state_selecting(void *cpp)
#define _PATH_DHCLIENT_CONF
void(* dhcpv6_packet_handler)(struct interface_info *, const char *, int, int, const struct iaddr *, isc_boolean_t)
void send_discover(void *cpp)
void unbill_class(struct lease *lease)
struct client_lease * alias
int parse_encapsulated_suboptions(struct option_state *options, struct option *eopt, const unsigned char *buffer, unsigned len, struct universe *eu, const char *uname)
isc_result_t omapi_protocol_listen(omapi_object_t *, unsigned, int)
struct binding_scope * global_scope
#define _PATH_DHCLIENT_PID
struct universe * universe
void make_client_options(struct client_state *client, struct client_lease *lease, u_int8_t *type, struct option_cache *sid, struct iaddr *rip, struct option **prl, struct option_state **op)
struct group * on_receipt
unsigned char dhcpv6_transaction_id[3]
#define _PATH_DHCLIENT_SCRIPT
void save_option(struct universe *universe, struct option_state *options, struct option_cache *oc)
char * quotify_buf(const unsigned char *s, unsigned len, const char *file, int line)
struct client_lease * new
void do_release(struct client_state *client)
const char * piaddr(const struct iaddr addr)
void rewrite_client_leases()
#define FQDN_NO_CLIENT_UPDATE
#define DHO_DOMAIN_SEARCH
#define DDNS_STATE_ADD_FW_NXDOMAIN
void dhcpoffer(struct packet *packet)
unsigned char dhcpv6_transaction_id[3]
int make_const_option_cache(struct option_cache **oc, struct buffer **buffer, u_int8_t *data, unsigned len, struct option *option, const char *file, int line)
void dhcpnak(struct packet *packet)
int get_dhcid(dhcp_ddns_cb_t *, int, const u_int8_t *, unsigned)
isc_result_t end_parse(struct parse **cfile)
const char * path_dhclient_db
void(* bootp_packet_handler)(struct interface_info *, struct dhcp_packet *, unsigned, unsigned int, struct iaddr, struct hardware *)
void start_release6(struct client_state *client)
void * dmalloc(unsigned, const char *, int)
char * piaddrmask(struct iaddr *addr, struct iaddr *mask)
struct iaddr next_srv_addr
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
void start_info_request6(struct client_state *client)
void send_decline(void *cpp)
void client_dns_update_timeout(void *cp)
void cancel_timeout(void(*)(void *) where, void *what)
#define print_hex_1(len, data, limit)
#define DHO_DHCP_PARAMETER_REQUEST_LIST
int dhcp_max_agent_option_packet_length
struct client_lease * packet_to_lease(struct packet *packet, struct client_state *client)
#define DHCP_R_INVALIDARG
struct group * on_transmission
#define DISCOVER_REQUESTED
int script_go(struct client_state *client)
struct iaddr requested_address
const char * dhcpv6_type_names[]
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
int write_client_lease(struct client_state *client, struct client_lease *lease, int rewrite, int makesure)
struct client_state * client
int can_receive_unicast_unconfigured(struct interface_info *)
struct iaddr iaddr_broadcast
void reinitialize_interfaces()
#define DHCPV6_RECONFIGURE
struct client_state * next
#define DHCP_CONTEXT_PRE_DB
#define DHO_DHCP_LEASE_TIME
void dhcpack(struct packet *packet)
unsigned cons_agent_information_options(struct option_state *cfg_options, struct dhcp_packet *outpacket, unsigned agentix, unsigned length)
struct universe dhcp_universe
struct option_state * options
dhcp_ddns_cb_t * ddns_cb_alloc(const char *file, int line)
void data_string_forget(struct data_string *data, const char *file, int line)
void bootp(struct packet *packet)
const char * pretty_print_option(struct option *option, const unsigned char *data, unsigned len, int emit_commas, int emit_quotes)
#define INTERFACE_RUNNING
void send_release(void *cpp)
int log_error(const char *,...) __attribute__((__format__(__printf__
struct string_list * client_env
#define DDNS_INCLUDE_RRSET
void client_envadd(struct client_state *client, const char *prefix, const char *name, const char *fmt,...)
void add_timeout(struct timeval *when, void(*)(void *) where, void *what, tvref_t ref, tvunref_t unref)
void dump_packet(struct packet *)
#define DDNS_STATE_REM_FW_YXDHCID
#define DHO_DHCP_REBINDING_TIME
#define DHO_NETBIOS_SCOPE
struct dhc6_ia * bindings
const char * path_dhclient_duid
enum dhcp_token peek_token(const char **rval, unsigned *rlen, struct parse *cfile)
struct data_string fwd_name
void write_client_pid_file()
void state_panic(void *cpp)
void forget_zone(struct dns_zone **)
struct data_string default_duid
void ddns_cb_free(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
void do_packet(struct interface_info *interface, struct dhcp_packet *packet, unsigned len, unsigned int from_port, struct iaddr from, struct hardware *hfrom)
#define D6O_NIS_DOMAIN_NAME
unsigned char dhcpv6_msg_type
#define DHO_DHCP_SERVER_IDENTIFIER
void log_fatal(const char *,...) __attribute__((__format__(__printf__
void(* v6_handler)(struct packet *, struct client_state *)
#define DHCP_CONTEXT_POST_DB
isc_result_t form_duid(struct data_string *duid, const char *file, int line)
struct executable_statement * statements
void state_init(void *cpp)
#define INTERFACE_AUTOMATIC
int option_state_reference(struct option_state **ptr, struct option_state *bp, const char *file, int line)
const char * print_time(TIME t)
struct option * default_requested_options[]
void read_client_leases()
struct option_state * options
struct iaddr subnet_number(struct iaddr addr, struct iaddr mask)
u_int16_t validate_port(char *port)
void dhcp_signal_handler(int signal)
int find_subnet(struct subnet **sp, struct iaddr addr, const char *file, int line)
void execute_statements_in_scope(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct group *group, struct group *limiting_group, struct on_star *on_star)
void make_request(struct client_state *client, struct client_lease *lease)
struct interface_info * fallback_interface
isc_result_t dhclient_interface_startup_hook(struct interface_info *interface)
int option_state_allocate(struct option_state **ptr, const char *file, int line)
const char * path_dhclient_pid
struct iaddrmatchlist * next
void client_option_envadd(struct option_cache *oc, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *u, void *stuff)
isc_result_t dhcp_context_create(int flags, struct in_addr *local4, struct in6_addr *local6)
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
int write_host(struct host_decl *host)
struct option_state * options
struct option ** requested_options
void classify(struct packet *packet, struct class *class)
void script_init(struct client_state *client, const char *reason, struct string_list *medium)
#define DHCP_MAX_OPTION_LEN
int main(int argc, char **argv)
dns_rdataclass_t dhcid_class
void make_decline(struct client_state *client, struct client_lease *lease)
void bind_lease(struct client_state *client)
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
#define DHO_BROADCAST_ADDRESS
struct option_cache * option
struct interface_info * interface
int write_lease(struct lease *lease)
void putULong(unsigned char *, u_int32_t)
void run_stateless(int exit_mode)
void send_request(void *cpp)
isc_result_t omapi_generic_new(omapi_object_t **, const char *, int)
#define D6O_DOMAIN_SEARCH
ssize_t send_packet(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
int cons_options(struct packet *inpacket, struct dhcp_packet *outpacket, struct lease *lease, struct client_state *client_state, int mms, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, int overload_avail, int terminate, int bootpp, struct data_string *prl, const char *vuname)
void start_confirm6(struct client_state *client)
void dfree(void *, const char *, int)
isc_boolean_t no_pid_file
struct client_lease * next
void ddns_cancel(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
struct option_state * sent_options
const char * path_dhclient_conf
struct hardware hw_address
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
int dhclient_interface_discovery_hook(struct interface_info *tmp)
struct client_state * client
struct option_state * options
int asprintf(char **strp, const char *fmt,...)
int int log_info(const char *,...) __attribute__((__format__(__printf__
int bootp_broadcast_always
struct interface_info * interfaces
void free_client_lease(struct client_lease *lease, const char *file, int line)
#define _PATH_DHCLIENT_DB
u_int32_t getULong(const unsigned char *)
struct client_config top_level_config
struct iaddr broadcast_addr(struct iaddr subnet, struct iaddr mask)
struct option ** required_options
union executable_statement::@7 data
void state_reboot(void *cpp)
int check_collection(struct packet *packet, struct lease *lease, struct collection *collection)
void destroy_client_lease(struct client_lease *lease)
void db_startup(int testp)
int parse_agent_information_option(struct packet *packet, int len, u_int8_t *data)
#define ASSERT_STATE(state_is, state_shouldbe)
char * path_dhclient_script
void parse_client_statement(struct parse *cfile, struct interface_info *ip, struct client_config *config)
struct universe ** universes
int quiet_interface_discovery
isc_result_t(* dhcp_interface_startup_hook)(struct interface_info *)
#define DISCOVER_UNCONFIGURED
struct client_lease * active
isc_result_t client_dns_update(struct client_state *client, dhcp_ddns_cb_t *ddns_cb)
int option_state_dereference(struct option_state **ptr, const char *file, int line)
void start_init6(struct client_state *client)
void option_space_foreach(struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *u, void *stuff, void(*func)(struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *))
void initialize_common_option_spaces()
void make_discover(struct client_state *client, struct client_lease *lease)
void dhcpv6(struct packet *)
void unconfigure6(struct client_state *client, const char *reason)
void client_dns_remove(struct client_state *client, struct iaddr *addr)
const int dhcpv6_type_name_max
int addr_match(struct iaddr *addr, struct iaddrmatch *match)
struct dhcp_packet packet
void state_bound(void *cpp)
struct interface_info * next
struct universe dhcpv6_universe
int evaluate_boolean_option_cache(int *ignorep, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
void make_release(struct client_state *client, struct client_lease *lease)
struct string_list * next
isc_result_t read_client_conf()
struct interface_info * dummy_interfaces
isc_result_t find_class(struct class **c, const char *s, const char *file, int line)
void script_write_requested(struct client_state *client)
#define FQDN_SERVER_UPDATE
struct client_lease * new_client_lease(char *file, int line) const
#define DDNS_STATE_ADD_FW_YXDHCID
void dhcpv4_client_assignments(void)
void dump_raw(unsigned char *buf, unsigned len) const
void dhcpv6_client_assignments(void)
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
struct iaddrmatchlist * reject_list
struct string_list * medium
struct client_config * config
#define D6O_SIP_SERVERS_DNS
struct sockaddr_in sockaddr_broadcast
void dhclient_schedule_updates(struct client_state *client, struct iaddr *addr, int offset)
int dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
int(* dhcp_interface_discovery_hook)(struct interface_info *)
struct in_addr inaddr_any
struct universe fqdn_universe
void dhcp(struct packet *packet)
#define DHO_DHCP_OPTION_OVERLOAD
#define D6O_NISP_DOMAIN_NAME
option_code_hash_t * code_hash
#define DHO_DHCP_RENEWAL_TIME
struct string_list * medium
#define DHO_DHCP_CLIENT_IDENTIFIER
struct dhcp_ddns_cb * ddns_cb
void putUShort(unsigned char *, u_int32_t)
isc_result_t dhcp_set_control_state(control_object_state_t oldstate, control_object_state_t newstate)
char * quotify_string(const char *s, const char *file, int line)
const unsigned char * data
struct interface_info * interface
#define DHO_DHCP_MESSAGE_TYPE
void dhcp_common_objects_setup(void)
void write_lease_option(struct option_cache *oc, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *u, void *stuff)
#define DDNS_STATE_REM_FW_NXRR
int(* dhcp_interface_shutdown_hook)(struct interface_info *)
void discover_interfaces(int state)
isc_result_t new_parse(struct parse **cfile, int file, char *inbuf, unsigned buflen, const char *name, int eolp)
struct dhc6_lease * active_lease
#define INTERFACE_REQUESTED
int dhclient_interface_shutdown_hook(struct interface_info *interface)
void script_write_params(struct client_state *client, const char *prefix, struct client_lease *lease)
int option_dereference(struct option **dest, const char *file, int line)
#define DHO_VENDOR_ENCAPSULATED_OPTIONS
void client_location_changed()
void state_stop(void *cpp)
isc_result_t omapi_init(void)
#define DHO_DHCP_REQUESTED_ADDRESS
int buffer_dereference(struct buffer **ptr, const char *file, int line)
isc_result_t ddns_modify_fwd(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
isc_result_t write_client6_lease(struct client_state *client, struct dhc6_lease *lease, int rewrite, int sync)
int bootp_broadcast_always