📄 dhclient.c
字号:
/* dhclient.c DHCP Client. *//* * Copyright (c) 1995-2001 Internet Software Consortium. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Internet Software Consortium nor the names * of its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This code is based on the original client state machine that was * written by Elliot Poger. The code has been extensively hacked on * by Ted Lemon since then, so any mistakes you find are probably his * fault and not Elliot's. */#ifndef lintstatic char ocopyright[] ="$Id: dhclient.c,v 1.129.2.7 2001/08/08 14:46:14 mellon Exp $ Copyright (c) 1995-2001 Internet Software Consortium. All rights reserved.\n";#endif /* not lint */#include "dhcpd.h"#include "version.h"TIME cur_time;TIME default_lease_time = 43200; /* 12 hours... */TIME max_lease_time = 86400; /* 24 hours... */const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;const char *path_dhclient_db = _PATH_DHCLIENT_DB;const char *path_dhclient_pid = _PATH_DHCLIENT_PID;static char path_dhclient_script_array [] = _PATH_DHCLIENT_SCRIPT;char *path_dhclient_script = path_dhclient_script_array;int dhcp_max_agent_option_packet_length = 0;int interfaces_requested = 0;struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };struct iaddr iaddr_any = { 4, { 0, 0, 0, 0 } };struct in_addr inaddr_any;struct sockaddr_in sockaddr_broadcast;struct in_addr giaddr;/* ASSERT_STATE() does nothing now; it used to be assert (state_is == state_shouldbe). */#define ASSERT_STATE(state_is, state_shouldbe) {}static char copyright[] = "Copyright 1995-2001 Internet Software Consortium.";static char arr [] = "All rights reserved.";static char message [] = "Internet Software Consortium DHCP Client";static char url [] = "For info, please visit http://www.isc.org/products/DHCP";u_int16_t local_port;u_int16_t remote_port;int no_daemon;struct string_list *client_env;int client_env_count;int onetry;int quiet;int nowait;static void usage PROTO ((void));void do_release(struct client_state *);int main (argc, argv, envp) int argc; char **argv, **envp;{ int i; struct servent *ent; struct interface_info *ip; struct client_state *client; unsigned seed; char *server = (char *)0; char *relay = (char *)0; isc_result_t status; int release_mode = 0; omapi_object_t *listener; isc_result_t result; int persist = 0; int omapi_port; int no_dhclient_conf = 0; int no_dhclient_db = 0; int no_dhclient_pid = 0; int no_dhclient_script = 0; char *s; /* Make sure we have stdin, stdout and stderr. */ i = open ("/dev/null", O_RDWR); if (i == 0) i = open ("/dev/null", O_RDWR); if (i == 1) { i = open ("/dev/null", O_RDWR); log_perror = 0; /* No sense logging to /dev/null. */ } else if (i != -1) close (i);#ifdef SYSLOG_4_2 openlog ("dhclient", LOG_NDELAY); log_priority = LOG_DAEMON;#else openlog ("dhclient", LOG_NDELAY, LOG_DAEMON);#endif#if !(defined (DEBUG) || defined (SYSLOG_4_2) || defined (__CYGWIN32__)) 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 various server database internal objects. */ dhcp_common_objects_setup (); dhcp_interface_discovery_hook = dhclient_interface_discovery_hook; dhcp_interface_shutdown_hook = dhclient_interface_shutdown_hook; dhcp_interface_startup_hook = dhclient_interface_startup_hook; for (i = 1; i < argc; i++) { if (!strcmp (argv [i], "-r")) { release_mode = 1; no_daemon = 1; } else 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], "-pf")) { if (++i == argc) usage (); path_dhclient_pid = argv [i]; no_dhclient_pid = 1; } else if (!strcmp (argv [i], "-cf")) { if (++i == argc) usage (); path_dhclient_conf = argv [i]; no_dhclient_conf = 1; } else if (!strcmp (argv [i], "-lf")) { if (++i == argc) usage (); path_dhclient_db = argv [i]; no_dhclient_db = 1; } else if (!strcmp (argv [i], "-sf")) { if (++i == argc) usage (); path_dhclient_script = argv [i]; no_dhclient_script = 1; } else if (!strcmp (argv [i], "-1")) { onetry = 1; } else if (!strcmp (argv [i], "-q")) { quiet = 1; quiet_interface_discovery = 1; } else if (!strcmp (argv [i], "-s")) { if (++i == argc) usage (); server = argv [i]; } else if (!strcmp (argv [i], "-g")) { if (++i == argc) usage (); relay = argv [i]; } else if (!strcmp (argv [i], "-n")) { /* do not start up any interfaces */ interfaces_requested = 1; } else if (!strcmp (argv [i], "-w")) { /* do not exit if there are no broadcast interfaces. */ persist = 1; } else if (argv [i][0] == '-') { usage (); } else if (!strcmp (argv [i], "-e")) { struct string_list *tmp; if (++i == argc) usage (); tmp = dmalloc (strlen (argv [i]) + sizeof *tmp, MDL); if (!tmp) log_fatal ("No memory for %s", argv [i]); strcpy (tmp -> string, argv [i]); tmp -> next = client_env; client_env = tmp; client_env_count++; } else if (!strcmp (argv [i], "--version")) { log_info ("isc-dhclient-%s", DHCP_VERSION); exit (0); } else if (!strcmp (argv [i], "-nw")) { nowait = 1; } else { struct interface_info *tmp = (struct interface_info *)0; status = interface_allocate (&tmp, MDL); if (status != ISC_R_SUCCESS) log_fatal ("Can't record interface %s:%s", argv [i], isc_result_totext (status)); if (strlen (argv [i]) > sizeof tmp -> name) log_fatal ("%s: interface name too long (max %ld)", argv [i], (long)strlen (argv [i])); strcpy (tmp -> name, argv [i]); if (interfaces) { interface_reference (&tmp -> next, interfaces, MDL); interface_dereference (&interfaces, MDL); } interface_reference (&interfaces, tmp, MDL); tmp -> flags = INTERFACE_REQUESTED; interfaces_requested = 1; } } if (!no_dhclient_conf && (s = getenv ("PATH_DHCLIENT_CONF"))) { path_dhclient_conf = s; } if (!no_dhclient_db && (s = getenv ("PATH_DHCLIENT_DB"))) { path_dhclient_db = s; } if (!no_dhclient_pid && (s = getenv ("PATH_DHCLIENT_PID"))) { path_dhclient_pid = s; } if (!no_dhclient_script && (s = getenv ("PATH_DHCLIENT_SCRIPT"))) { path_dhclient_script = s; } /* first kill of any currently running client */ if (release_mode) { /* XXX inelegant hack to prove concept */ char command[1024];#if !defined (NO_SNPRINTF) snprintf (command, 1024, "kill `cat %s`", path_dhclient_pid);#else sprintf (command, "kill `cat %s`", path_dhclient_pid);#endif system (command); } if (!quiet) { log_info ("%s %s", message, DHCP_VERSION); log_info (copyright); log_info (arr); log_info (url); log_info ("%s", ""); } else log_perror = 0; /* If we're given a relay agent address to insert, for testing purposes, figure out what it is. */ if (relay) { if (!inet_aton (relay, &giaddr)) { struct hostent *he; he = gethostbyname (relay); if (he) { memcpy (&giaddr, he -> h_addr_list [0], sizeof giaddr); } else { log_fatal ("%s: no such host", relay); } } } /* Default to the DHCP/BOOTP port. */ if (!local_port) { if (relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) { local_port = htons (67); } else { ent = getservbyname ("dhcpc", "udp"); if (!ent) local_port = htons (68); else local_port = ent -> s_port;#ifndef __CYGWIN32__ endservent ();#endif } } /* If we're faking a relay agent, and we're not using loopback, use the server port, not the client port. */ if (relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) { local_port = htons (ntohs (local_port) - 1); remote_port = local_port; } else remote_port = htons (ntohs (local_port) - 1); /* XXX */ /* Get the current time... */ GET_TIME (&cur_time); sockaddr_broadcast.sin_family = AF_INET; sockaddr_broadcast.sin_port = remote_port; if (server) { if (!inet_aton (server, &sockaddr_broadcast.sin_addr)) { struct hostent *he; he = gethostbyname (server); if (he) { memcpy (&sockaddr_broadcast.sin_addr, he -> h_addr_list [0], sizeof sockaddr_broadcast.sin_addr); } else sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST; } } else { sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST; } inaddr_any.s_addr = INADDR_ANY; /* Discover all the network interfaces. */ discover_interfaces (DISCOVER_UNCONFIGURED); /* Parse the dhclient.conf file. */ read_client_conf (); /* Parse the lease database. */ read_client_leases (); /* Rewrite the lease database... */ rewrite_client_leases (); /* XXX *//* config_counter(&snd_counter, &rcv_counter); */ /* If no broadcast interfaces were discovered, call the script and tell it so. */ if (!interfaces) { /* Call dhclient-script with the NBI flag, in case somebody cares. */ script_init ((struct client_state *)0, "NBI", (struct string_list *)0); script_go ((struct client_state *)0); /* If we haven't been asked to persist, waiting for new interfaces, then just exit. */ if (!persist) { /* Nothing more to do. */ log_info ("No broadcast interfaces found - exiting."); exit (0); } } else if (!release_mode) { /* Call the script with the list of interfaces. */ for (ip = interfaces; ip; ip = ip -> next) { /* If interfaces were specified, don't configure interfaces that weren't specified! */ if (interfaces_requested && ((ip -> flags & (INTERFACE_REQUESTED | INTERFACE_AUTOMATIC)) != INTERFACE_REQUESTED)) continue; script_init (ip -> client, "PREINIT", (struct string_list *)0); if (ip -> client -> alias) script_write_params (ip -> client, "alias_", ip -> client -> alias); script_go (ip -> client); } } /* At this point, all the interfaces that the script thinks are relevant should be running, so now we once again call discover_interfaces(), and this time ask it to actually set up the interfaces. */ discover_interfaces (interfaces_requested ? DISCOVER_REQUESTED : DISCOVER_RUNNING); /* Make up a seed for the random number generator from current time plus the sum of the last four bytes of each interface's hardware address interpreted as an integer. Not much entropy, but we're booting, so we're not likely to find anything better. */ seed = 0; for (ip = interfaces; ip; ip = ip -> next) { int junk; memcpy (&junk, &ip -> hw_address.hbuf [ip -> hw_address.hlen - sizeof seed], sizeof seed); seed += junk; } srandom (seed + cur_time); /* Start a configuration state machine for each interface. */ for (ip = interfaces; ip; ip = ip -> next) { ip -> flags |= INTERFACE_RUNNING; for (client = ip -> client; client; client = client -> next) { if (release_mode) do_release (client); else { client -> state = S_INIT; /* Set up a timeout to start the initialization process. */ add_timeout (cur_time + random () % 5, state_reboot, client, 0, 0); } } } if (release_mode) return 0; /* Start up a listener for the object management API protocol. */ if (top_level_config.omapi_port != -1) { listener = (omapi_object_t *)0; result = omapi_generic_new (&listener, MDL); if (result != ISC_R_SUCCESS) log_fatal ("Can't allocate new generic object: %s\n", isc_result_totext (result)); result = omapi_protocol_listen (listener, (unsigned) top_level_config.omapi_port, 1); if (result != ISC_R_SUCCESS) log_fatal ("Can't start OMAPI protocol: %s", isc_result_totext (result)); } /* Set up the bootp packet handler... */ bootp_packet_handler = do_packet;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -