📄 dhclient.c
字号:
client -> dns_update_timeout = 1; add_timeout (cur_time + 1, client_dns_update_timeout, client, 0, 0); }} /* state_bound is called when we've successfully bound to a particular lease, but the renewal time on that lease has expired. We are expected to unicast a DHCPREQUEST to the server that gave us our original lease. */void state_bound (cpp) void *cpp;{ struct client_state *client = cpp; int i; struct option_cache *oc; struct data_string ds; ASSERT_STATE(state, S_BOUND); /* T1 has expired. */ make_request (client, client -> active); client -> xid = client -> packet.xid; memset (&ds, 0, sizeof ds); oc = lookup_option (&dhcp_universe, client -> active -> options, DHO_DHCP_SERVER_IDENTIFIER); if (oc && evaluate_option_cache (&ds, (struct packet *)0, (struct lease *)0, client, (struct option_state *)0, client -> active -> options, &global_scope, oc, MDL)) { if (ds.len > 3) { memcpy (client -> destination.iabuf, ds.data, 4); client -> destination.len = 4; } else client -> destination = iaddr_broadcast; } else client -> destination = iaddr_broadcast; client -> first_sending = cur_time; client -> interval = client -> config -> initial_interval; client -> state = S_RENEWING; /* Send the first packet immediately. */ send_request (client);} /* state_stop is called when we've been told to shut down. We unconfigure the interfaces, and then stop operating until told otherwise. */void state_stop (cpp) void *cpp;{ struct client_state *client = cpp; int i; /* Cancel all timeouts. */ cancel_timeout (state_selecting, client); cancel_timeout (send_discover, client); cancel_timeout (send_request, client); cancel_timeout (state_bound, client); /* If we have an address, unconfigure it. */ if (client -> active) { script_init (client, "STOP", client -> active -> medium); script_write_params (client, "old_", client -> active); if (client -> alias) script_write_params (client, "alias_", client -> alias); script_go (client); }} int commit_leases (){ return 0;}int write_lease (lease) struct lease *lease;{ return 0;}int write_host (host) struct host_decl *host;{ return 0;}void db_startup (testp) int testp;{}void bootp (packet) struct packet *packet;{ struct iaddrlist *ap; if (packet -> raw -> op != BOOTREPLY) return; /* If there's a reject list, make sure this packet's sender isn't on it. */ for (ap = packet -> interface -> client -> config -> reject_list; ap; ap = ap -> next) { if (addr_eq (packet -> client_addr, ap -> addr)) { log_info ("BOOTREPLY from %s rejected.", piaddr (ap -> addr)); return; } } dhcpoffer (packet);}void dhcp (packet) struct packet *packet;{ struct iaddrlist *ap; void (*handler) PROTO ((struct packet *)); const char *type; switch (packet -> packet_type) { case DHCPOFFER: handler = dhcpoffer; type = "DHCPOFFER"; break; case DHCPNAK: handler = dhcpnak; type = "DHCPNACK"; break; case DHCPACK: handler = dhcpack; type = "DHCPACK"; break; default: return; } /* If there's a reject list, make sure this packet's sender isn't on it. */ for (ap = packet -> interface -> client -> config -> reject_list; ap; ap = ap -> next) { if (addr_eq (packet -> client_addr, ap -> addr)) { log_info ("%s from %s rejected.", type, piaddr (ap -> addr)); return; } } (*handler) (packet);}void dhcpoffer (packet) struct packet *packet;{ struct interface_info *ip = packet -> interface; struct client_state *client; struct client_lease *lease, *lp; int i; int stop_selecting; const char *name = packet -> packet_type ? "DHCPOFFER" : "BOOTREPLY"; struct iaddrlist *ap; struct option_cache *oc; char obuf [1024]; #ifdef DEBUG_PACKET dump_packet (packet);#endif /* Find a client state that matches the xid... */ for (client = ip -> client; client; client = client -> next) if (client -> xid == packet -> raw -> xid) break; /* If we're not receptive to an offer right now, or if the offer has an unrecognizable transaction id, then just drop it. */ if (!client || client -> state != S_SELECTING || (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 ("%s in wrong transaction.", name);#endif return; } sprintf (obuf, "%s from %s", name, piaddr (packet -> client_addr)); /* If this lease doesn't supply the minimum required parameters, blow it off. */ if (client -> config -> required_options) { for (i = 0; client -> config -> required_options [i]; i++) { if (!lookup_option (&dhcp_universe, packet -> options, client -> config -> required_options [i])) { log_info ("%s: no %s option.", obuf, (dhcp_universe.options [client -> config -> required_options [i]] -> name)); return; } } } /* If we've already seen this lease, don't record it again. */ for (lease = client -> offered_leases; lease; lease = lease -> next) { if (lease -> address.len == sizeof packet -> raw -> yiaddr && !memcmp (lease -> address.iabuf, &packet -> raw -> yiaddr, lease -> address.len)) { log_debug ("%s: already seen.", obuf); return; } } lease = packet_to_lease (packet, client); if (!lease) { log_info ("%s: packet_to_lease failed.", obuf); return; } /* If this lease was acquired through a BOOTREPLY, record that fact. */ if (!packet -> options_valid || !packet -> packet_type) lease -> is_bootp = 1; /* Record the medium under which this lease was offered. */ lease -> medium = client -> medium; /* Figure out when we're supposed to stop selecting. */ stop_selecting = (client -> first_sending + client -> config -> select_interval); /* If this is the lease we asked for, put it at the head of the list, and don't mess with the arp request timeout. */ if (lease -> address.len == client -> requested_address.len && !memcmp (lease -> address.iabuf, client -> requested_address.iabuf, client -> requested_address.len)) { lease -> next = client -> offered_leases; client -> offered_leases = lease; } else { /* Put the lease at the end of the list. */ lease -> next = (struct client_lease *)0; if (!client -> offered_leases) client -> offered_leases = lease; else { for (lp = client -> offered_leases; lp -> next; lp = lp -> next) ; lp -> next = lease; } } /* If the selecting interval has expired, go immediately to state_selecting(). Otherwise, time out into state_selecting at the select interval. */ if (stop_selecting <= 0) state_selecting (client); else { add_timeout (stop_selecting, state_selecting, client, 0, 0); cancel_timeout (send_discover, client); } log_info ("%s", obuf);}/* Allocate a client_lease structure and initialize it from the parameters in the specified packet. */struct client_lease *packet_to_lease (packet, client) struct packet *packet; struct client_state *client;{ struct client_lease *lease; unsigned i; struct option_cache *oc; struct data_string data; lease = (struct client_lease *)new_client_lease (MDL); if (!lease) { log_error ("packet_to_lease: no memory to record lease.\n"); return (struct client_lease *)0; } memset (lease, 0, sizeof *lease); /* Copy the lease options. */ option_state_reference (&lease -> options, packet -> options, MDL); lease -> address.len = sizeof (packet -> raw -> yiaddr); memcpy (lease -> address.iabuf, &packet -> raw -> yiaddr, lease -> address.len); memset (&data, 0, sizeof data); if (client -> config -> vendor_space_name) { i = DHO_VENDOR_ENCAPSULATED_OPTIONS; /* See if there was a vendor encapsulation option. */ oc = lookup_option (&dhcp_universe, lease -> options, i); if (oc && client -> config -> vendor_space_name && evaluate_option_cache (&data, packet, (struct lease *)0, client, packet -> options, lease -> options, &global_scope, oc, MDL)) { if (data.len) { parse_encapsulated_suboptions (packet -> options, &dhcp_options [i], data.data, data.len, &dhcp_universe, client -> config -> vendor_space_name ); } data_string_forget (&data, MDL); } } else i = 0; /* Figure out the overload flag. */ oc = lookup_option (&dhcp_universe, lease -> options, DHO_DHCP_OPTION_OVERLOAD); if (oc && evaluate_option_cache (&data, packet, (struct lease *)0, client, packet -> options, lease -> options, &global_scope, oc, MDL)) { if (data.len > 0) i = data.data [0]; else i = 0; data_string_forget (&data, MDL); } else i = 0; /* If the server name was filled out, copy it. */ if (!(i & 2) && packet -> raw -> sname [0]) { unsigned len; /* Don't count on the NUL terminator. */ for (len = 0; len < 64; len++) if (!packet -> raw -> sname [len]) break; lease -> server_name = dmalloc (len + 1, MDL); if (!lease -> server_name) { log_error ("dhcpoffer: no memory for filename.\n"); destroy_client_lease (lease); return (struct client_lease *)0; } else { memcpy (lease -> server_name, packet -> raw -> sname, len); lease -> server_name [len] = 0; } } /* Ditto for the filename. */ if (!(i & 1) && packet -> raw -> file [0]) { unsigned len; /* Don't count on the NUL terminator. */ for (len = 0; len < 64; len++) if (!packet -> raw -> file [len]) break; lease -> filename = dmalloc (len + 1, MDL); if (!lease -> filename) { log_error ("dhcpoffer: no memory for filename.\n"); destroy_client_lease (lease); return (struct client_lease *)0; } else { memcpy (lease -> filename, packet -> raw -> file, len); lease -> filename [len] = 0; } } execute_statements_in_scope ((struct binding_value **)0, (struct packet *)packet, (struct lease *)0, client, lease -> options, lease -> options, &global_scope, client -> config -> on_receipt, (struct group *)0); return lease;} void dhcpnak (packet) struct packet *packet;{ struct interface_info *ip = packet -> interface; struct client_state *client; /* Find a client state that matches the xid... */ for (client = ip -> client; client; client = client -> next) if (client -> xid == packet -> raw -> xid) break; /* If we're not receptive to an offer right now, or if the offer has an unrecognizable transaction id, then just drop it. */ 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 ("DHCPNAK 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 ("DHCPNAK in wrong state.");#endif return; } log_info ("DHCPNAK from %s", piaddr (packet -> client_addr)); if (!client -> active) {#if defined (DEBUG) log_info ("DHCPNAK with no active lease.\n");#endif return; } destroy_client_lease (client -> active); client -> active = (struct client_lease *)0; /* Stop sending DHCPREQUEST packets... */ cancel_timeout (send_request, client); client -> state = S_INIT; state_init (client);}/* Send out a DHCPDISCOVER packet, and set a timeout to send out another one after the right interval has expired. If we don't get an offer by the time we reach the panic interval, call the panic function. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -