📄 confpars.c
字号:
parse_warn (cfile, "pools with failover peers %s", "may not permit dynamic bootp."); log_error ("Either write a \"no failover\" %s", "statement and use disjoint"); log_error ("pools, or don't permit dynamic%s", " bootp."); log_error ("This is a protocol limitation,%s", " not an ISC DHCP limitation, so"); log_error ("please don't request an %s", "enhancement or ask why this is."); goto clash_testing_done; } } if (!pool -> permit_list) { if (!pool -> prohibit_list) goto dynamic_bootp_clash; for (permit = pool -> prohibit_list; permit; permit = permit -> next) { if (permit -> type == permit_dynamic_bootp_clients || permit -> type == permit_all_clients) goto clash_testing_done; } } } clash_testing_done: #endif /* FAILOVER_PROTOCOL */ /* See if there's already a pool into which we can merge this one. */ for (pp = pool -> shared_network -> pools; pp; pp = pp -> next) { struct lease *l; if (pp -> group -> statements != pool -> group -> statements) continue;#if defined (FAILOVER_PROTOCOL) if (pool -> failover_peer != pp -> failover_peer) continue;#endif if (!permit_list_match (pp -> permit_list, pool -> permit_list) || !permit_list_match (pool -> permit_list, pp -> permit_list) || !permit_list_match (pp -> prohibit_list, pool -> prohibit_list) || !permit_list_match (pool -> prohibit_list, pp -> prohibit_list)) continue; /* Okay, we can merge these two pools. All we have to do is fix up the leases, which all point to their pool. */ for (lp = lpchain; lp; lp = lp -> next) { pool_dereference (&lp -> pool, MDL); pool_reference (&lp -> pool, pp, MDL); } break; } /* If we didn't succeed in merging this pool into another, put it on the list. */ if (!pp) { p = &pool -> shared_network -> pools; for (; *p; p = &((*p) -> next)) ; pool_reference (p, pool, MDL); } /* Don't allow a pool declaration with no addresses, since it is probably a configuration error. */ if (!lpchain) { parse_warn (cfile, "Pool declaration with no address range."); log_error ("Pool declarations must always contain at least"); log_error ("one range statement."); } /* Dereference the lease chain. */ lp = (struct lease *)0; while (lpchain) { lease_reference (&lp, lpchain, MDL); lease_dereference (&lpchain, MDL); if (lp -> next) { lease_reference (&lpchain, lp -> next, MDL); lease_dereference (&lp -> next, MDL); lease_dereference (&lp, MDL); } } pool_dereference (&pool, MDL);}/* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */int parse_boolean (cfile) struct parse *cfile;{ enum dhcp_token token; const char *val; int rv; token = next_token (&val, (unsigned *)0, cfile); if (!strcasecmp (val, "true") || !strcasecmp (val, "on")) rv = 1; else if (!strcasecmp (val, "false") || !strcasecmp (val, "off")) rv = 0; else { parse_warn (cfile, "boolean value (true/false/on/off) expected"); skip_to_semi (cfile); return 0; } parse_semi (cfile); return rv;}/* Expect a left brace; if there isn't one, skip over the rest of the statement and return zero; otherwise, return 1. */int parse_lbrace (cfile) struct parse *cfile;{ enum dhcp_token token; const char *val; token = next_token (&val, (unsigned *)0, cfile); if (token != LBRACE) { parse_warn (cfile, "expecting left brace."); skip_to_semi (cfile); return 0; } return 1;}/* host-declaration :== hostname RBRACE parameters declarations LBRACE */void parse_host_declaration (cfile, group) struct parse *cfile; struct group *group;{ const char *val; enum dhcp_token token; struct host_decl *host; char *name; int declaration = 0; int dynamicp = 0; int deleted = 0; isc_result_t status; name = parse_host_name (cfile); if (!name) { parse_warn (cfile, "expecting a name for host declaration."); skip_to_semi (cfile); return; } host = (struct host_decl *)0; status = host_allocate (&host, MDL); if (status != ISC_R_SUCCESS) log_fatal ("can't allocate host decl struct %s: %s", name, isc_result_totext (status)); host -> name = name; if (!clone_group (&host -> group, group, MDL)) { log_fatal ("can't clone group for host %s", name); boom: host_dereference (&host, MDL); return; } if (!parse_lbrace (cfile)) goto boom; do { token = peek_token (&val, (unsigned *)0, cfile); if (token == RBRACE) { token = next_token (&val, (unsigned *)0, cfile); break; } if (token == END_OF_FILE) { token = next_token (&val, (unsigned *)0, cfile); parse_warn (cfile, "unexpected end of file"); break; } /* If the host declaration was created by the server, remember to save it. */ if (token == DYNAMIC) { dynamicp = 1; token = next_token (&val, (unsigned *)0, cfile); if (!parse_semi (cfile)) break; continue; } /* If the host declaration was created by the server, remember to save it. */ if (token == TOKEN_DELETED) { deleted = 1; token = next_token (&val, (unsigned *)0, cfile); if (!parse_semi (cfile)) break; continue; } if (token == GROUP) { struct group_object *go; token = next_token (&val, (unsigned *)0, cfile); token = next_token (&val, (unsigned *)0, cfile); if (token != STRING && !is_identifier (token)) { parse_warn (cfile, "expecting string or identifier."); skip_to_rbrace (cfile, 1); break; } go = (struct group_object *)0; if (!group_hash_lookup (&go, group_name_hash, val, strlen (val), MDL)) { parse_warn (cfile, "unknown group %s in host %s", val, host -> name); } else { if (host -> named_group) group_object_dereference (&host -> named_group, MDL); group_object_reference (&host -> named_group, go, MDL); group_object_dereference (&go, MDL); } if (!parse_semi (cfile)) break; continue; } if (token == UID) { const char *s; unsigned char *t = 0; unsigned len; token = next_token (&val, (unsigned *)0, cfile); data_string_forget (&host -> client_identifier, MDL); /* See if it's a string or a cshl. */ token = peek_token (&val, (unsigned *)0, cfile); if (token == STRING) { token = next_token (&val, &len, cfile); s = val; host -> client_identifier.terminated = 1; } else { len = 0; t = parse_numeric_aggregate (cfile, (unsigned char *)0, &len, ':', 16, 8); if (!t) { parse_warn (cfile, "expecting hex list."); skip_to_semi (cfile); } s = (const char *)t; } if (!buffer_allocate (&host -> client_identifier.buffer, len + host -> client_identifier.terminated, MDL)) log_fatal ("no memory for uid for host %s.", host -> name); host -> client_identifier.data = host -> client_identifier.buffer -> data; host -> client_identifier.len = len; memcpy (host -> client_identifier.buffer -> data, s, len + host -> client_identifier.terminated); if (t) dfree (t, MDL); if (!parse_semi (cfile)) break; continue; } declaration = parse_statement (cfile, host -> group, HOST_DECL, host, declaration); } while (1); if (deleted) { struct host_decl *hp = (struct host_decl *)0; if (host_hash_lookup (&hp, host_name_hash, (unsigned char *)host -> name, strlen (host -> name), MDL)) { delete_host (hp, 0); host_dereference (&hp, MDL); } } else { if (host -> named_group && host -> named_group -> group) { if (host -> group -> statements || (host -> group -> authoritative != host -> named_group -> group -> authoritative)) { if (host -> group -> next) group_dereference (&host -> group -> next, MDL); group_reference (&host -> group -> next, host -> named_group -> group, MDL); } else { group_dereference (&host -> group, MDL); group_reference (&host -> group, host -> named_group -> group, MDL); } } if (dynamicp) host -> flags |= HOST_DECL_DYNAMIC; else host -> flags |= HOST_DECL_STATIC; status = enter_host (host, dynamicp, 0); if (status != ISC_R_SUCCESS) parse_warn (cfile, "host %s: %s", host -> name, isc_result_totext (status)); } host_dereference (&host, MDL);}/* class-declaration :== STRING LBRACE parameters declarations RBRACE*/int parse_class_declaration (cp, cfile, group, type) struct class **cp; struct parse *cfile; struct group *group; int type;{ const char *val; enum dhcp_token token; struct class *class = (struct class *)0, *pc = (struct class *)0; int declaration = 0; int lose = 0; struct data_string data; char *name; const char *tname; struct executable_statement *stmt = (struct executable_statement *)0; struct expression *expr; int new = 1; isc_result_t status; token = next_token (&val, (unsigned *)0, cfile); if (token != STRING) { parse_warn (cfile, "Expecting class name"); skip_to_semi (cfile); return 0; } /* See if there's already a class with the specified name. */ find_class (&pc, val, MDL); /* If this isn't a subclass, we're updating an existing class. */ if (pc && type != 0 && type != 1 && type != 3) { class_reference (&class, pc, MDL); new = 0; class_dereference (&pc, MDL); } /* If this _is_ a subclass, there _must_ be a class with the same name. */ if (!pc && (type == 0 || type == 1 || type == 3)) { parse_warn (cfile, "no class named %s", val); skip_to_semi (cfile); return 0; } /* The old vendor-class and user-class declarations had an implicit match. We don't do the implicit match anymore. Instead, for backward compatibility, we have an implicit-vendor-class and an implicit-user-class. vendor-class and user-class declarations are turned into subclasses of the implicit classes, and the submatch expression of the implicit classes extracts the contents of the vendor class or user class. */ if (type == 0 || type == 1) { data.len = strlen (val); data.buffer = (struct buffer *)0; if (!buffer_allocate (&data.buffer, data.len + 1, MDL)) log_fatal ("no memory for class name."); data.data = &data.buffer -> data [0]; data.terminated = 1; tname = type ? "implicit-vendor-class" : "implicit-user-class"; } else if (type == 2) { tname = val; } else { tname = (const char *)0; } if (tname) { name = dmalloc (strlen (tname) + 1, MDL); if (!name) log_fatal ("No memory for class name %s.", tname); strcpy (name, val); } else name = (char *)0; /* If this is a straight subclass, parse the hash string. */ if (type == 3) { token = peek_token (&val, (unsigned *)0, cfile); if (token == STRING) { token = next_token (&val, &data.len, cfile); data.buffer = (struct buffer *)0; if (!buffer_allocate (&data.buffer, data.len + 1, MDL)) { if (pc) class_dereference (&pc, MDL); return 0; } data.terminated = 1; data.data = &data.buffer -> data [0]; memcpy ((char *)data.buffer -> data, val, data.len + 1); } else if (token == NUMBER_OR_NAME || token == NUMBER) { memset (&data, 0, sizeof data); if (!parse_cshl (&data, cfile)) { class_dereference (&pc, MDL); return 0; } } else { parse_warn (cfile, "Expecting string or hex list."); if (pc) class_dereference (&pc, MDL); return 0; } } /* See if there's already a class in the hash table matching the hash data. */ if (type == 0 || type == 1 || type == 3) class_hash_lookup (&class, pc -> hash, (const char *)data.data, data.len, MDL); /* If we didn't find an existing class, allocate a new one. */ if (!class) { /* Allocate the class structure... */ status = class_allocate (&class, MDL); if (pc) { group_reference (&class -> group, pc -> group, MDL); class_reference (&class -> superclass, pc, MDL); class -> lease_limit = pc -> lease_limit; if (class -> lease_limit) { class -> billed_leases = dmalloc (class -> lease_limit * sizeof (struct lease *), MDL); if (!class -> billed_leases) log_fatal ("no memory for billing"); memset (class -> billed_leases, 0, (class -> lease_limit * sizeof class -> billed_leases)); } data_string_copy (&class -> hash_string, &data, MDL); if (!pc -> hash && !class_new_hash (&pc -> hash, 0, MDL)) log_fatal ("No memory for subclass hash."); class_hash_add (pc -> hash, (const char *)class -> hash_string.data, class -> hash_string.len, (void *)class, MDL); } else { if (!clone_group (&class -> group, group, MDL)) log_fatal ("no memory to clone class group."); } /* If this is an implicit vendor or user class, add a statement that causes the vendor or user class ID to be sent back in the reply. */ if (type == 0 || type == 1) { stmt = (struct executable_statement *)0; if (!executable_statement_allocate (&stmt, MDL)) log_fatal ("no memory for class statement."); stmt -> op = supersede_option_statement; if (option_cache_allocate (&stmt -> data.option, MDL)) { stmt -> data.option -> data = data; stmt -> data.option -> option = dhcp_universe.options [type ? DHO_VENDOR_CLASS_IDENTIFIER : DHO_USER_CLASS]; } class -> statements = stmt; } /* Save the name, if there is one. */ class -> name = name; } if (type == 0 || type == 1 || type == 3)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -