📄 dhclient.c
字号:
dmalloc_longterm = dmalloc_outstanding; dmalloc_outstanding = 0;#endif /* If we're not supposed to wait before getting the address, don't. */ if (nowait) go_daemon (); /* If we're not going to daemonize, write the pid file now. */ if (no_daemon || nowait) write_client_pid_file (); /* Start dispatching packets and timeouts... */ dispatch (); /*NOTREACHED*/ return 0;}static void usage (){ log_info ("%s %s", message, DHCP_VERSION); log_info (copyright); log_info (arr); log_info (url); log_error ("Usage: dhclient [-1dqr] [-nw] [-p <port>] %s", "[-s server]"); log_error (" [-cf config-file] [-lf lease-file]%s", "[-pf pid-file] [-e VAR=val]"); log_fatal (" [-sf script-file] [interface]");}isc_result_t find_class (struct class **c, const char *s, const char *file, int line){ return 0;}int check_collection (packet, lease, collection) struct packet *packet; struct lease *lease; struct collection *collection;{ return 0;}void classify (packet, class) struct packet *packet; struct class *class;{}int unbill_class (lease, class) struct lease *lease; struct class *class;{ return 0;}int find_subnet (struct subnet **sp, struct iaddr addr, const char *file, int line){ return 0;}/* Individual States: * * Each routine is called from the dhclient_state_machine() in one of * these conditions: * -> entering INIT state * -> recvpacket_flag == 0: timeout in this state * -> otherwise: received a packet in this state * * Return conditions as handled by dhclient_state_machine(): * Returns 1, sendpacket_flag = 1: send packet, reset timer. * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone). * Returns 0: finish the nap which was interrupted for no good reason. * * Several per-interface variables are used to keep track of the process: * active_lease: the lease that is being used on the interface * (null pointer if not configured yet). * offered_leases: leases corresponding to DHCPOFFER messages that have * been sent to us by DHCP servers. * acked_leases: leases corresponding to DHCPACK messages that have been * sent to us by DHCP servers. * sendpacket: DHCP packet we're trying to send. * destination: IP address to send sendpacket to * In addition, there are several relevant per-lease variables. * T1_expiry, T2_expiry, lease_expiry: lease milestones * In the active lease, these control the process of renewing the lease; * In leases on the acked_leases list, this simply determines when we * can no longer legitimately use the lease. */void state_reboot (cpp) void *cpp;{ struct client_state *client = cpp; /* If we don't remember an active lease, go straight to INIT. */ if (!client -> active || client -> active -> is_bootp || client -> active -> expiry <= cur_time) { state_init (client); return; } /* We are in the rebooting state. */ client -> state = S_REBOOTING; /* make_request doesn't initialize xid because it normally comes from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER, so pick an xid now. */ client -> xid = random (); /* Make a DHCPREQUEST packet, and set appropriate per-interface flags. */ make_request (client, client -> active); client -> destination = iaddr_broadcast; client -> first_sending = cur_time; client -> interval = client -> config -> initial_interval; /* Zap the medium list... */ client -> medium = (struct string_list *)0; /* Send out the first DHCPREQUEST packet. */ send_request (client);}/* Called when a lease has completely expired and we've been unable to renew it. */void state_init (cpp) void *cpp;{ struct client_state *client = cpp; ASSERT_STATE(state, S_INIT); /* Make a DHCPDISCOVER packet, and set appropriate per-interface flags. */ make_discover (client, client -> active); client -> xid = client -> packet.xid; client -> destination = iaddr_broadcast; client -> state = S_SELECTING; client -> first_sending = cur_time; client -> interval = client -> config -> initial_interval; /* Add an immediate timeout to cause the first DHCPDISCOVER packet to go out. */ send_discover (client);}/* state_selecting is called when one or more DHCPOFFER packets have been received and a configurable period of time has passed. */void state_selecting (cpp) void *cpp;{ struct client_state *client = cpp; struct client_lease *lp, *next, *picked; ASSERT_STATE(state, S_SELECTING); /* Cancel state_selecting and send_discover timeouts, since either one could have got us here. */ cancel_timeout (state_selecting, client); cancel_timeout (send_discover, client); /* We have received one or more DHCPOFFER packets. Currently, the only criterion by which we judge leases is whether or not we get a response when we arp for them. */ picked = (struct client_lease *)0; for (lp = client -> offered_leases; lp; lp = next) { next = lp -> next; /* Check to see if we got an ARPREPLY for the address in this particular lease. */ if (!picked) { picked = lp; picked -> next = (struct client_lease *)0; } else { freeit: destroy_client_lease (lp); } } client -> offered_leases = (struct client_lease *)0; /* If we just tossed all the leases we were offered, go back to square one. */ if (!picked) { client -> state = S_INIT; state_init (client); return; } /* If it was a BOOTREPLY, we can just take the address right now. */ if (picked -> is_bootp) { client -> new = picked; /* Make up some lease expiry times XXX these should be configurable. */ client -> new -> expiry = cur_time + 12000; client -> new -> renewal += cur_time + 8000; client -> new -> rebind += cur_time + 10000; client -> state = S_REQUESTING; /* Bind to the address we received. */ bind_lease (client); return; } /* Go to the REQUESTING state. */ client -> destination = iaddr_broadcast; client -> state = S_REQUESTING; client -> first_sending = cur_time; client -> interval = client -> config -> initial_interval; /* Make a DHCPREQUEST packet from the lease we picked. */ make_request (client, picked); client -> xid = client -> packet.xid; /* Toss the lease we picked - we'll get it back in a DHCPACK. */ destroy_client_lease (picked); /* Add an immediate timeout to send the first DHCPREQUEST packet. */ send_request (client);} /* state_requesting is called when we receive a DHCPACK message after having sent out one or more DHCPREQUEST packets. */void dhcpack (packet) struct packet *packet;{ struct interface_info *ip = packet -> interface; struct client_state *client; struct client_lease *lease; struct option_cache *oc; struct data_string ds; int i; /* If we're not receptive to an offer right now, or if the offer has an unrecognizable transaction id, then just drop it. */ for (client = ip -> client; client; client = client -> next) { if (client -> xid == packet -> raw -> xid) break; } if (!client || (packet -> interface -> hw_address.hlen - 1 != packet -> raw -> hlen) || (memcmp (&packet -> interface -> hw_address.hbuf [1], packet -> raw -> chaddr, packet -> raw -> hlen))) {#if defined (DEBUG) log_debug ("DHCPACK in wrong transaction.");#endif return; } if (client -> state != S_REBOOTING && client -> state != S_REQUESTING && client -> state != S_RENEWING && client -> state != S_REBINDING) {#if defined (DEBUG) log_debug ("DHCPACK in wrong state.");#endif return; } log_info ("DHCPACK from %s", piaddr (packet -> client_addr)); lease = packet_to_lease (packet, client); if (!lease) { log_info ("packet_to_lease failed."); return; } client -> new = lease; /* Stop resending DHCPREQUEST. */ cancel_timeout (send_request, client); /* Figure out the lease time. */ oc = lookup_option (&dhcp_universe, client -> new -> options, DHO_DHCP_LEASE_TIME); memset (&ds, 0, sizeof ds); if (oc && evaluate_option_cache (&ds, packet, (struct lease *)0, client, packet -> options, client -> new -> options, &global_scope, oc, MDL)) { if (ds.len > 3) client -> new -> expiry = getULong (ds.data); else client -> new -> expiry = 0; data_string_forget (&ds, MDL); } else client -> new -> expiry = 0; if (!client -> new -> expiry) { log_error ("no expiry time on offered lease."); /* XXX this is going to be bad - if this _does_ XXX happen, we should probably dynamically XXX disqualify the DHCP server that gave us the XXX bad packet from future selections and XXX then go back into the init state. */ state_init (client); return; } /* A number that looks negative here is really just very large, because the lease expiry offset is unsigned. */ if (client -> new -> expiry < 0) client -> new -> expiry = TIME_MAX; /* Take the server-provided renewal time if there is one. */ oc = lookup_option (&dhcp_universe, client -> new -> options, DHO_DHCP_RENEWAL_TIME); if (oc && evaluate_option_cache (&ds, packet, (struct lease *)0, client, packet -> options, client -> new -> options, &global_scope, oc, MDL)) { if (ds.len > 3) client -> new -> renewal = getULong (ds.data); else client -> new -> renewal = 0; data_string_forget (&ds, MDL); } else client -> new -> renewal = 0; /* If it wasn't specified by the server, calculate it. */ if (!client -> new -> renewal) client -> new -> renewal = client -> new -> expiry / 2 + 1; if (client -> new -> renewal <= 0) client -> new -> renewal = TIME_MAX; /* Now introduce some randomness to the renewal time: */ if (client -> new -> renewal <= TIME_MAX / 3 - 3) client -> new -> renewal = (((client -> new -> renewal + 3) * 3 / 4) + (random () % /* XXX NUMS */ ((client -> new -> renewal + 3) / 4))); /* Same deal with the rebind time. */ oc = lookup_option (&dhcp_universe, client -> new -> options, DHO_DHCP_REBINDING_TIME); if (oc && evaluate_option_cache (&ds, packet, (struct lease *)0, client, packet -> options, client -> new -> options, &global_scope, oc, MDL)) { if (ds.len > 3) client -> new -> rebind = getULong (ds.data); else client -> new -> rebind = 0; data_string_forget (&ds, MDL); } else client -> new -> rebind = 0; if (client -> new -> rebind <= 0) { if (client -> new -> expiry <= TIME_MAX / 7) client -> new -> rebind = client -> new -> expiry * 7 / 8; else client -> new -> rebind = client -> new -> expiry / 8 * 7; } /* Make sure our randomness didn't run the renewal time past the rebind time. */ if (client -> new -> renewal > client -> new -> rebind) { if (client -> new -> rebind <= TIME_MAX / 3) client -> new -> renewal = client -> new -> rebind * 3 / 4; else client -> new -> renewal = client -> new -> rebind / 4 * 3; } client -> new -> expiry += cur_time; /* Lease lengths can never be negative. */ if (client -> new -> expiry < cur_time) client -> new -> expiry = TIME_MAX; client -> new -> renewal += cur_time; if (client -> new -> renewal < cur_time) client -> new -> renewal = TIME_MAX; client -> new -> rebind += cur_time; if (client -> new -> rebind < cur_time) client -> new -> rebind = TIME_MAX; bind_lease (client);}void bind_lease (client) struct client_state *client;{ struct interface_info *ip = client -> interface; /* Remember the medium. */ client -> new -> medium = client -> medium; /* Run the client script with the new parameters. */ script_init (client, (client -> state == S_REQUESTING ? "BOUND" : (client -> state == S_RENEWING ? "RENEW" : (client -> state == S_REBOOTING ? "REBOOT" : "REBIND"))), client -> new -> medium); if (client -> active && client -> state != S_REBOOTING) script_write_params (client, "old_", client -> active); script_write_params (client, "new_", client -> new); if (client -> alias) script_write_params (client, "alias_", client -> alias); /* If the BOUND/RENEW code detects another machine using the offered address, it exits nonzero. We need to send a DHCPDECLINE and toss the lease. */ if (script_go (client)) { make_decline (client, client -> new); send_decline (client); destroy_client_lease (client -> new); client -> new = (struct client_lease *)0; state_init (client); return; } /* Write out the new lease. */ write_client_lease (client, client -> new, 0, 0); /* Replace the old active lease with the new one. */ if (client -> active) destroy_client_lease (client -> active); client -> active = client -> new; client -> new = (struct client_lease *)0; /* Set up a timeout to start the renewal process. */ add_timeout (client -> active -> renewal, state_bound, client, 0, 0); log_info ("bound to %s -- renewal in %ld seconds.", piaddr (client -> active -> address), (long)(client -> active -> renewal - cur_time)); client -> state = S_BOUND; reinitialize_interfaces (); go_daemon (); if (client -> config -> do_forward_update) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -