dhcp.c
来自「open source dhcp server client etc...」· C语言 代码 · 共 2,079 行 · 第 1/5 页
C
2,079 行
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); } /* 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 -> 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, oc, MDL)) { if (d1.len == sizeof (u_int32_t)) lease_time = (getULong (d1.data) - cur_time); data_string_forget (&d1, MDL); } } lt -> ends = state -> offered_expiry = cur_time + lease_time; lt -> next_binding_state = FTS_BOOTP; } lt -> timestamp = cur_time; /* Record the uid, if given... */ 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)) { if (d1.len <= sizeof lt -> uid_buf) { memcpy (lt -> uid_buf, d1.data, d1.len); lt -> uid = lt -> uid_buf; lt -> uid_max = sizeof lt -> uid_buf; lt -> uid_len = d1.len; } else { unsigned char *tuid; lt -> uid_max = d1.len; lt -> uid_len = d1.len; tuid = (unsigned char *)dmalloc (lt -> uid_max, MDL); /* XXX inelegant */ if (!tuid) log_fatal ("no memory for large uid."); memcpy (tuid, d1.data, lt -> uid_len); lt -> uid = tuid; } data_string_forget (&d1, MDL); } if (lease -> host) host_reference (< -> host, lease -> host, MDL); if (lease -> subnet) subnet_reference (< -> subnet, lease -> subnet, MDL); if (lease -> billing_class) class_reference (< -> billing_class, lease -> billing_class, MDL); /* Set a flag if this client is a broken client that NUL terminates string options and expects us to do likewise. */ if (ms_nulltp) lease -> flags |= MS_NULL_TERMINATION; else lease -> flags &= ~MS_NULL_TERMINATION; /* Save any bindings. */ if (lease -> scope) { binding_scope_reference (< -> scope, lease -> scope, MDL); binding_scope_dereference (&lease -> scope, MDL); } if (lease -> agent_options) option_chain_head_reference (< -> agent_options, lease -> agent_options, MDL); /* If we got relay agent information options, and the packet really looks like it came through a relay agent, and if this feature is not disabled, save the relay agent information options that came in with the packet, so that we can use them at renewal time when the packet won't have gone through a relay agent. */ if (p
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?