📄 dhcp.c
字号:
/* Report what we're sending... */ log_info ("DHCPACK to %s", inet_ntoa (raw.ciaddr));#ifdef DEBUG_PACKET dump_packet (&outgoing); dump_raw ((unsigned char *)&raw, outgoing.packet_length);#endif /* Set up the common stuff... */ to.sin_family = AF_INET;#ifdef HAVE_SA_LEN to.sin_len = sizeof to;#endif memset (to.sin_zero, 0, sizeof to.sin_zero); /* Use the IP address we derived for the client. */ memcpy (&to.sin_addr, cip.iabuf, 4); to.sin_port = remote_port; errno = 0; send_packet ((fallback_interface ? fallback_interface : packet -> interface), &outgoing, &raw, outgoing.packet_length, from, &to, (struct hardware *)0); if (subnet) subnet_dereference (&subnet, MDL);}void nak_lease (packet, cip) struct packet *packet; struct iaddr *cip;{ struct sockaddr_in to; struct in_addr from; int result; struct dhcp_packet raw; unsigned char nak = DHCPNAK; struct packet outgoing; struct hardware hto; unsigned i; struct data_string data; struct option_state *options = (struct option_state *)0; struct expression *expr; struct option_cache *oc = (struct option_cache *)0; struct iaddr myfrom; option_state_allocate (&options, MDL); memset (&outgoing, 0, sizeof outgoing); memset (&raw, 0, sizeof raw); outgoing.raw = &raw; /* Set DHCP_MESSAGE_TYPE to DHCPNAK */ if (!option_cache_allocate (&oc, MDL)) { log_error ("No memory for DHCPNAK message type."); option_state_dereference (&options, MDL); return; } if (!make_const_data (&oc -> expression, &nak, sizeof nak, 0, 0, MDL)) { log_error ("No memory for expr_const expression."); option_cache_dereference (&oc, MDL); option_state_dereference (&options, MDL); return; } oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE_TYPE]; save_option (&dhcp_universe, options, oc); option_cache_dereference (&oc, MDL); /* Set DHCP_MESSAGE to whatever the message is */ if (!option_cache_allocate (&oc, MDL)) { log_error ("No memory for DHCPNAK message type."); option_state_dereference (&options, MDL); return; } if (!make_const_data (&oc -> expression, (unsigned char *)dhcp_message, strlen (dhcp_message), 1, 0, MDL)) { log_error ("No memory for expr_const expression."); option_cache_dereference (&oc, MDL); option_state_dereference (&options, MDL); return; } oc -> option = dhcp_universe.options [DHO_DHCP_MESSAGE]; save_option (&dhcp_universe, options, oc); option_cache_dereference (&oc, MDL); i = DHO_DHCP_SERVER_IDENTIFIER; if (!(oc = lookup_option (&dhcp_universe, options, i))) { use_primary: oc = (struct option_cache *)0; if (option_cache_allocate (&oc, MDL)) { if (make_const_data (&oc -> expression, ((unsigned char *) &packet -> interface -> primary_address), sizeof packet -> interface -> primary_address, 0, 0, MDL)) { oc -> option = dhcp_universe.options [i]; save_option (&dhcp_universe, options, oc); } option_cache_dereference (&oc, MDL); } myfrom.len = sizeof packet -> interface -> primary_address; memcpy (myfrom.iabuf, &packet -> interface -> primary_address, myfrom.len); } else { memset (&data, 0, sizeof data); if (evaluate_option_cache (&data, packet, (struct lease *)0, (struct client_state *)0, packet -> options, options, &global_scope, oc, MDL)) { if (!data.len || data.len > sizeof myfrom.iabuf) { data_string_forget (&data, MDL); goto use_primary; } memcpy (myfrom.iabuf, data.data, data.len); myfrom.len = data.len; data_string_forget (&data, MDL); } else goto use_primary; } /* If there were agent options in the incoming packet, return them. */ if (packet -> raw -> giaddr.s_addr && packet -> options -> universe_count > agent_universe.index && packet -> options -> universes [agent_universe.index]) { option_chain_head_reference ((struct option_chain_head **) &(options -> universes [agent_universe.index]), (struct option_chain_head *) packet -> options -> universes [agent_universe.index], MDL); } /* Do not use the client's requested parameter list. */ delete_option (&dhcp_universe, packet -> options, DHO_DHCP_PARAMETER_REQUEST_LIST); /* Set up the option buffer... */ outgoing.packet_length = cons_options (packet, outgoing.raw, (struct lease *)0, (struct client_state *)0, 0, packet -> options, options, &global_scope, 0, 0, 0, (struct data_string *)0, (char *)0); option_state_dereference (&options, MDL);/* memset (&raw.ciaddr, 0, sizeof raw.ciaddr);*/ raw.siaddr = packet -> interface -> primary_address; raw.giaddr = packet -> raw -> giaddr; memcpy (raw.chaddr, packet -> raw -> chaddr, sizeof raw.chaddr); raw.hlen = packet -> raw -> hlen; raw.htype = packet -> raw -> htype; raw.xid = packet -> raw -> xid; raw.secs = packet -> raw -> secs; raw.flags = packet -> raw -> flags | htons (BOOTP_BROADCAST); raw.hops = packet -> raw -> hops; raw.op = BOOTREPLY; /* Report what we're sending... */ log_info ("DHCPNAK on %s to %s via %s", piaddr (*cip), print_hw_addr (packet -> raw -> htype, packet -> raw -> hlen, packet -> raw -> chaddr), packet -> raw -> giaddr.s_addr ? inet_ntoa (packet -> raw -> giaddr) : packet -> interface -> name);#ifdef DEBUG_PACKET dump_packet (packet); dump_raw ((unsigned char *)packet -> raw, packet -> packet_length); dump_packet (&outgoing); dump_raw ((unsigned char *)&raw, outgoing.packet_length);#endif#if 0 hto.hbuf [0] = packet -> raw -> htype; hto.hlen = packet -> raw -> hlen; memcpy (&hto.hbuf [1], packet -> raw -> chaddr, hto.hlen); hto.hlen++;#endif /* Set up the common stuff... */ to.sin_family = AF_INET;#ifdef HAVE_SA_LEN to.sin_len = sizeof to;#endif memset (to.sin_zero, 0, sizeof to.sin_zero); memcpy (&from, myfrom.iabuf, sizeof from); /* Make sure that the packet is at least as big as a BOOTP packet. */ if (outgoing.packet_length < BOOTP_MIN_LEN) outgoing.packet_length = BOOTP_MIN_LEN; /* If this was gatewayed, send it back to the gateway. Otherwise, broadcast it on the local network. */ if (raw.giaddr.s_addr) { to.sin_addr = raw.giaddr; if (raw.giaddr.s_addr != htonl (INADDR_LOOPBACK)) to.sin_port = local_port; else to.sin_port = remote_port; /* for testing. */ if (fallback_interface) { result = send_packet (fallback_interface, packet, &raw, outgoing.packet_length, from, &to, &hto); return; } } else { to.sin_addr = limited_broadcast; to.sin_port = remote_port; } errno = 0; result = send_packet (packet -> interface, packet, &raw, outgoing.packet_length, from, &to, (struct hardware *)0);}void ack_lease (packet, lease, offer, when, msg, ms_nulltp) struct packet *packet; struct lease *lease; unsigned int offer; TIME when; char *msg; int ms_nulltp;{ struct lease *lt; struct lease_state *state; struct lease *next; TIME lease_time; TIME offered_lease_time; struct data_string d1; TIME min_lease_time; TIME max_lease_time; TIME default_lease_time; struct option_cache *oc; struct expression *expr; int status; isc_result_t result; int did_ping = 0; TIME ping_timeout; unsigned i, j; int s1, s2; int val; int ignorep; /* If we're already acking this lease, don't do it again. */ if (lease -> state) return; /* Allocate a lease state structure... */ state = new_lease_state (MDL); if (!state) log_fatal ("unable to allocate lease state!"); state -> got_requested_address = packet -> got_requested_address; shared_network_reference (&state -> shared_network, packet -> interface -> shared_network, MDL); /* See if we got a server identifier option. */ if (lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_SERVER_IDENTIFIER)) state -> got_server_identifier = 1; /* If there were agent options in the incoming packet, return them. Do not return the agent options if they were stashed on the lease. */ if (packet -> raw -> giaddr.s_addr && packet -> options -> universe_count > agent_universe.index && packet -> options -> universes [agent_universe.index] && (state -> options -> universe_count <= agent_universe.index || !state -> options -> universes [agent_universe.index]) && lease -> agent_options != ((struct option_chain_head *) packet -> options -> universes [agent_universe.index])) { option_chain_head_reference ((struct option_chain_head **) &(state -> options -> universes [agent_universe.index]), (struct option_chain_head *) packet -> options -> universes [agent_universe.index], MDL); } /* If we are offering a lease that is still currently valid, preserve the events. We need to do this because if the client does not REQUEST our offer, it will expire in 2 minutes, overriding the expire time in the currently in force lease. We want the expire events to be executed at that point. */ if (lease -> ends <= cur_time && offer != DHCPOFFER) { /* Get rid of any old expiry or release statements - by executing the statements below, we will be inserting new ones if there are any to insert. */ if (lease -> on_expiry) executable_statement_dereference (&lease -> on_expiry, MDL); if (lease -> on_commit) executable_statement_dereference (&lease -> on_commit, MDL); if (lease -> on_release) executable_statement_dereference (&lease -> on_release, MDL); } /* Execute statements in scope starting with the subnet scope. */ execute_statements_in_scope ((struct binding_value **)0, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, lease -> subnet -> group, (struct group *)0); /* If the lease is from a pool, run the pool scope. */ if (lease -> pool) (execute_statements_in_scope ((struct binding_value **)0, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, lease -> pool -> group, lease -> pool -> shared_network -> group)); /* Execute statements from class scopes. */ for (i = packet -> class_count; i > 0; i--) { execute_statements_in_scope ((struct binding_value **)0, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, packet -> classes [i - 1] -> group, (lease -> pool ? lease -> pool -> group : lease -> subnet -> group)); } /* See if the client is only supposed to have one lease at a time, and if so, find its other leases and release them. We can only do this on DHCPREQUEST. It's a little weird to do this before looking at permissions, because the client might not actually _get_ a lease after we've done the permission check, but the assumption for this option is that the client has exactly one network interface, and will only ever remember one lease. So if it sends a DHCPREQUEST, and doesn't get the lease, it's already forgotten about its old lease, so we can too. */ if (packet -> packet_type == DHCPREQUEST && (oc = lookup_option (&server_universe, state -> options, SV_ONE_LEASE_PER_CLIENT)) && evaluate_boolean_option_cache (&ignorep, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { struct lease *seek; if (lease -> uid_len) { do { seek = (struct lease *)0; find_lease_by_uid (&seek, lease -> uid, lease -> uid_len, MDL); if (!seek) break; if (seek == lease && !seek -> n_uid) { lease_dereference (&seek, MDL); break; } next = (struct lease *)0; /* Don't release expired leases, and don't release the lease we're going to assign. */ next = (struct lease *)0; while (seek) { if (seek -> n_uid) lease_reference (&next, seek -> n_uid, MDL); if (seek != lease && seek -> binding_state != FTS_RELEASED && seek -> binding_state != FTS_EXPIRED && seek -> binding_state != FTS_RESET && seek -> binding_state != FTS_FREE && seek -> binding_state != FTS_BACKUP) break; lease_dereference (&seek, MDL); if (next) { lease_reference (&seek, next, MDL); lease_dereference (&next, MDL); } } if (next) lease_dereference (&next, MDL); if (seek) { release_lease (seek, packet); lease_dereference (&seek, MDL); } else break; } while (1); } if (!lease -> uid_len || (lease -> host && !lease -> host -> client_identifier.len && (oc = lookup_option (&server_universe, state -> options, SV_DUPLICATES)) && !evaluate_boolean_option_cache (&ignorep, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL))) { do { seek = (struct lease *)0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -