📄 dhcp.c
字号:
find_lease_by_hw_addr (&seek, lease -> hardware_addr.hbuf, lease -> hardware_addr.hlen, MDL); if (!seek) break; if (seek == lease && !seek -> n_hw) { lease_dereference (&seek, MDL); break; } next = (struct lease *)0; while (seek) { if (seek -> n_hw) lease_reference (&next, seek -> n_hw, 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); } } /* Make sure this packet satisfies the configured minimum number of seconds. */ memset (&d1, 0, sizeof d1); if (offer == DHCPOFFER && (oc = lookup_option (&server_universe, state -> options, SV_MIN_SECS))) { if (evaluate_option_cache (&d1, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (d1.len && ntohs (packet -> raw -> secs) < d1.data [0]) { log_info ("%s: %d secs < %d", msg, ntohs (packet -> raw -> secs), d1.data [0]); data_string_forget (&d1, MDL); free_lease_state (state, MDL); return; } data_string_forget (&d1, MDL); } } /* Try to find a matching host declaration for this lease. */ if (!lease -> host) { struct host_decl *hp = (struct host_decl *)0; struct host_decl *h; /* Try to find a host_decl that matches the client identifier or hardware address on the packet, and has no fixed IP address. If there is one, hang it off the lease so that its option definitions can be used. */ oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_CLIENT_IDENTIFIER); if (oc && evaluate_option_cache (&d1, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { find_hosts_by_uid (&hp, d1.data, d1.len, MDL); data_string_forget (&d1, MDL); if (hp) host_reference (&lease -> host, hp, MDL); } if (!hp) { find_hosts_by_haddr (&hp, packet -> raw -> htype, packet -> raw -> chaddr, packet -> raw -> hlen, MDL); for (h = hp; h; h = h -> n_ipaddr) { if (!h -> fixed_addr) break; } if (h) host_reference (&lease -> host, h, MDL); } if (hp) host_dereference (&hp, MDL); } /* If we have a host_decl structure, run the options associated with its group. Wether the host decl struct is old or not. */ if (lease -> host) execute_statements_in_scope ((struct binding_value **)0, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, lease -> host -> group, (lease -> pool ? lease -> pool -> group : lease -> subnet -> group)); /* Drop the request if it's not allowed for this client. By default, unknown clients are allowed. */ if (!lease -> host && (oc = lookup_option (&server_universe, state -> options, SV_BOOT_UNKNOWN_CLIENTS)) && !evaluate_boolean_option_cache (&ignorep, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (!ignorep) log_info ("%s: unknown client", msg); free_lease_state (state, MDL); return; } /* Drop the request if it's not allowed for this client. */ if (!offer && (oc = lookup_option (&server_universe, state -> options, SV_ALLOW_BOOTP)) && !evaluate_boolean_option_cache (&ignorep, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (!ignorep) log_info ("%s: bootp disallowed", msg); free_lease_state (state, MDL); return; } /* Drop the request if booting is specifically denied. */ oc = lookup_option (&server_universe, state -> options, SV_ALLOW_BOOTING); if (oc && !evaluate_boolean_option_cache (&ignorep, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (!ignorep) log_info ("%s: booting disallowed", msg); free_lease_state (state, MDL); return; } /* If we are configured to do per-class billing, do it. */ if (have_billing_classes && !(lease -> flags & STATIC_LEASE)) { /* See if the lease is currently being billed to a class, and if so, whether or not it can continue to be billed to that class. */ if (lease -> billing_class) { for (i = 0; i < packet -> class_count; i++) if (packet -> classes [i] == lease -> billing_class) break; if (i == packet -> class_count) unbill_class (lease, lease -> billing_class); } /* If we don't have an active billing, see if we need one, and if we do, try to do so. */ if (!lease -> billing_class) { for (i = 0; i < packet -> class_count; i++) { if (packet -> classes [i] -> lease_limit) break; } if (i != packet -> class_count) { for (i = 0; i < packet -> class_count; i++) if ((packet -> classes [i] -> lease_limit) && bill_class (lease, packet -> classes [i])) break; if (i == packet -> class_count) { log_info ("%s: no available billing", msg); free_lease_state (state, MDL); /* XXX probably not necessary: */ return; } } } } /* Figure out the filename. */ oc = lookup_option (&server_universe, state -> options, SV_FILENAME); if (oc) evaluate_option_cache (&state -> filename, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL); /* Choose a server name as above. */ oc = lookup_option (&server_universe, state -> options, SV_SERVER_NAME); if (oc) evaluate_option_cache (&state -> server_name, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL); /* At this point, we have a lease that we can offer the client. Now we construct a lease structure that contains what we want, and call supersede_lease to do the right thing with it. */ lt = (struct lease *)0; result = lease_allocate (<, MDL); if (result != ISC_R_SUCCESS) { log_info ("%s: can't allocate temporary lease structure: %s", msg, isc_result_totext (result)); free_lease_state (state, MDL); return; } /* Use the ip address of the lease that we finally found in the database. */ lt -> ip_addr = lease -> ip_addr; /* Start now. */ lt -> starts = cur_time; /* Figure out how long a lease to assign. If this is a dynamic BOOTP lease, its duration must be infinite. */ if (offer) { default_lease_time = DEFAULT_DEFAULT_LEASE_TIME; if ((oc = lookup_option (&server_universe, state -> options, SV_DEFAULT_LEASE_TIME))) { if (evaluate_option_cache (&d1, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (d1.len == sizeof (u_int32_t)) default_lease_time = getULong (d1.data); data_string_forget (&d1, MDL); } } if ((oc = lookup_option (&dhcp_universe, packet -> options, DHO_DHCP_LEASE_TIME))) s1 = evaluate_option_cache (&d1, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL); else s1 = 0; if (s1 && d1.len == sizeof (u_int32_t)) { lease_time = getULong (d1.data); data_string_forget (&d1, MDL); } else { if (s1) data_string_forget (&d1, MDL); lease_time = default_lease_time; } /* See if there's a maximum lease time. */ max_lease_time = DEFAULT_MAX_LEASE_TIME; if ((oc = lookup_option (&server_universe, state -> options, SV_MAX_LEASE_TIME))) { if (evaluate_option_cache (&d1, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (d1.len == sizeof (u_int32_t)) max_lease_time = getULong (d1.data); data_string_forget (&d1, MDL); } } /* Enforce the maximum lease length. */ if (lease_time < 0 /* XXX */ || lease_time > max_lease_time) lease_time = max_lease_time; min_lease_time = DEFAULT_MIN_LEASE_TIME; if (min_lease_time > max_lease_time) min_lease_time = max_lease_time; if ((oc = lookup_option (&server_universe, state -> options, SV_MIN_LEASE_TIME))) { if (evaluate_option_cache (&d1, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (d1.len == sizeof (u_int32_t)) min_lease_time = getULong (d1.data); data_string_forget (&d1, MDL); } } if (lease_time < min_lease_time) { if (min_lease_time) lease_time = min_lease_time; else lease_time = default_lease_time; }#if defined (FAILOVER_PROTOCOL) /* Okay, we know the lease duration. Now check the failover state, if any. */ if (lease -> tsfp) { lt ->tsfp = lease ->tsfp; } if (lease -> pool && lease -> pool -> failover_peer) { dhcp_failover_state_t *peer = lease -> pool -> failover_peer; /* If the lease time we arrived at exceeds what the peer has, we can only issue a lease of peer -> mclt, but we can tell the peer we want something longer in the future. */ /* XXX This may result in updates that only push XXX the peer's expiry time for this lease up XXX by a few seconds - think about this again XXX later. */ if (lease_time > peer -> mclt && cur_time + lease_time > lease -> tsfp) { /* Here we're assuming that if we don't have to update tstp, there's already an update queued. May want to revisit this. */ if (peer -> me.state != partner_down && cur_time + lease_time > lease -> tstp) lt -> tstp = (cur_time + lease_time + peer -> mclt / 2); /* Now choose a lease time that is either MCLT, for a lease that's never before been assigned, or TSFP + MCLT for a lease that has. XXX Note that TSFP may be < cur_time. XXX What do we do in this case? XXX should the expiry timer on the lease XXX set tsfp and tstp to zero? */ if (lease -> tsfp < cur_time) { lease_time = peer -> mclt; } else { lease_time = (lease -> tsfp - cur_time + peer -> mclt); } } else { if (cur_time + lease_time > lease -> tsfp && lease_time > peer -> mclt / 2) { lt -> tstp = (cur_time + lease_time + peer -> mclt / 2); } else { lt -> tstp = (cur_time + lease_time + lease_time / 2); } } lt -> cltt = cur_time; }#endif /* FAILOVER_PROTOCOL */ /* If the lease duration causes the time value to wrap, use the maximum expiry time. */ if (cur_time + lease_time < cur_time) state -> offered_expiry = MAX_TIME - 1; else state -> offered_expiry = cur_time + lease_time; if (when) lt -> ends = when; else lt -> ends = state -> offered_expiry; /* Don't make lease active until we actually get a DHCPREQUEST. */ if (offer == DHCPACK) lt -> next_binding_state = FTS_ACTIVE; else lt -> next_binding_state = lease -> binding_state; } else { lease_time = MAX_TIME - cur_time; if ((oc = lookup_option (&server_universe, state -> options, SV_BOOTP_LEASE_LENGTH))) { if (evaluate_option_cache (&d1, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope, oc, MDL)) { if (d1.len == sizeof (u_int32_t)) lease_time = getULong (d1.data); data_string_forget (&d1, MDL); } } if ((oc = lookup_option (&server_universe, state -> options, SV_BOOTP_LEASE_CUTOFF))) { if (evaluate_option_cache (&d1, packet, lease, (struct client_state *)0, packet -> options, state -> options, &lease -> scope,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -