📄 dhclient.c
字号:
/* dhclient.c DHCP Client. *//* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1995-2003 by Internet Software Consortium * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Internet Systems Consortium, Inc. * 950 Charter Street * Redwood City, CA 94063 * <info@isc.org> * http://www.isc.org/ * * 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.19 2004/07/10 00:11:16 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";#endif /* not lint */#include "dhcpd.h"#include "version.h"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 2004 Internet Systems Consortium.";static char arr [] = "All rights reserved.";static char message [] = "Internet Systems Consortium DHCP Client";static char url [] = "For info, please visit http://www.isc.org/products/DHCP";u_int16_t local_port=0;u_int16_t remote_port=0;int no_daemon=0;struct string_list *client_env=NULL;int client_env_count=0;int onetry=0;int quiet=0;int nowait=0;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], "-nw")) { nowait = 1; } 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 (!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 (argv [i][0] == '-') { usage (); } 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) { FILE *pidfd; pid_t oldpid; long temp; int e; oldpid = 0; if ((pidfd = fopen(path_dhclient_pid, "r")) != NULL) { e = fscanf(pidfd, "%ld\n", &temp); oldpid = (pid_t)temp; if (e != 0 && e != EOF) { if (oldpid) { if (kill(oldpid, SIGTERM) == 0) unlink(path_dhclient_pid); } } fclose(pidfd); } } 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 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(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, we're using the server port, not the client port. */ if (relay && giaddr.s_addr != htonl (INADDR_LOOPBACK)) { 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;#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL) || \ defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) dmalloc_cutoff_generation = dmalloc_generation;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -