00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "dhcpd.h"
00030 #include <errno.h>
00031
00032 struct client_config top_level_config;
00033
00034 #define NUM_DEFAULT_REQUESTED_OPTS 15
00035 struct option *default_requested_options[NUM_DEFAULT_REQUESTED_OPTS + 1];
00036
00037 static void parse_client_default_duid(struct parse *cfile);
00038 static void parse_client6_lease_statement(struct parse *cfile);
00039 #ifdef DHCPv6
00040 static struct dhc6_ia *parse_client6_ia_na_statement(struct parse *cfile);
00041 static struct dhc6_ia *parse_client6_ia_ta_statement(struct parse *cfile);
00042 static struct dhc6_ia *parse_client6_ia_pd_statement(struct parse *cfile);
00043 static struct dhc6_addr *parse_client6_iaaddr_statement(struct parse *cfile);
00044 static struct dhc6_addr *parse_client6_iaprefix_statement(struct parse *cfile);
00045 #endif
00046
00047
00048
00049
00050
00051
00052 isc_result_t read_client_conf ()
00053 {
00054 struct client_config *config;
00055 struct interface_info *ip;
00056 isc_result_t status;
00057 unsigned code;
00058
00059
00060
00061
00062
00063
00064 #ifdef LATER
00065 struct parse *parse = NULL;
00066 #endif
00067
00068
00069 memset(default_requested_options, 0, sizeof(default_requested_options));
00070
00071
00072 code = DHO_SUBNET_MASK;
00073 option_code_hash_lookup(&default_requested_options[0],
00074 dhcp_universe.code_hash, &code, 0, MDL);
00075
00076
00077 code = DHO_BROADCAST_ADDRESS;
00078 option_code_hash_lookup(&default_requested_options[1],
00079 dhcp_universe.code_hash, &code, 0, MDL);
00080
00081
00082 code = DHO_TIME_OFFSET;
00083 option_code_hash_lookup(&default_requested_options[2],
00084 dhcp_universe.code_hash, &code, 0, MDL);
00085
00086
00087
00088
00089
00090
00091 code = DHO_CLASSLESS_STATIC_ROUTES;
00092 option_code_hash_lookup(&default_requested_options[3],
00093 dhcp_universe.code_hash, &code, 0, MDL);
00094
00095
00096 code = DHO_DOMAIN_NAME;
00097 option_code_hash_lookup(&default_requested_options[4],
00098 dhcp_universe.code_hash, &code, 0, MDL);
00099
00100
00101 code = DHO_DOMAIN_NAME_SERVERS;
00102 option_code_hash_lookup(&default_requested_options[5],
00103 dhcp_universe.code_hash, &code, 0, MDL);
00104
00105
00106 code = DHO_HOST_NAME;
00107 option_code_hash_lookup(&default_requested_options[6],
00108 dhcp_universe.code_hash, &code, 0, MDL);
00109
00110
00111 code = D6O_NAME_SERVERS;
00112 option_code_hash_lookup(&default_requested_options[7],
00113 dhcpv6_universe.code_hash, &code, 0, MDL);
00114
00115
00116 code = D6O_DOMAIN_SEARCH;
00117 option_code_hash_lookup(&default_requested_options[8],
00118 dhcpv6_universe.code_hash, &code, 0, MDL);
00119
00120
00121 code = DHO_NIS_DOMAIN;
00122 option_code_hash_lookup(&default_requested_options[9],
00123 dhcp_universe.code_hash, &code, 0, MDL);
00124
00125
00126 code = DHO_NIS_SERVERS;
00127 option_code_hash_lookup(&default_requested_options[10],
00128 dhcp_universe.code_hash, &code, 0, MDL);
00129
00130
00131 code = DHO_NTP_SERVERS;
00132 option_code_hash_lookup(&default_requested_options[11],
00133 dhcp_universe.code_hash, &code, 0, MDL);
00134
00135
00136 code = DHO_INTERFACE_MTU;
00137 option_code_hash_lookup(&default_requested_options[12],
00138 dhcp_universe.code_hash, &code, 0, MDL);
00139
00140
00141 code = DHO_DOMAIN_SEARCH;
00142 option_code_hash_lookup(&default_requested_options[13],
00143 dhcp_universe.code_hash, &code, 0, MDL);
00144
00145
00146 code = DHO_ROUTERS;
00147 option_code_hash_lookup(&default_requested_options[14],
00148 dhcp_universe.code_hash, &code, 0, MDL);
00149
00150 for (code = 0 ; code < NUM_DEFAULT_REQUESTED_OPTS ; code++) {
00151 if (default_requested_options[code] == NULL)
00152 log_fatal("Unable to find option definition for "
00153 "index %u during default parameter request "
00154 "assembly.", code);
00155 }
00156
00157
00158 memset (&top_level_config, 0, sizeof top_level_config);
00159
00160
00161 top_level_config.timeout = 60;
00162 top_level_config.select_interval = 0;
00163 top_level_config.reboot_timeout = 10;
00164 top_level_config.retry_interval = 300;
00165 top_level_config.backoff_cutoff = 15;
00166 top_level_config.initial_interval = 3;
00167
00168
00169
00170
00171
00172
00173
00174
00175 top_level_config.initial_delay = 0;
00176
00177 top_level_config.bootp_policy = P_ACCEPT;
00178 top_level_config.script_name = path_dhclient_script;
00179 top_level_config.requested_options = default_requested_options;
00180 top_level_config.omapi_port = -1;
00181 top_level_config.do_forward_update = 1;
00182
00183
00184 top_level_config.requested_lease = 7200;
00185 top_level_config.bootp_broadcast_always = 0;
00186
00187 group_allocate (&top_level_config.on_receipt, MDL);
00188 if (!top_level_config.on_receipt)
00189 log_fatal ("no memory for top-level on_receipt group");
00190
00191 group_allocate (&top_level_config.on_transmission, MDL);
00192 if (!top_level_config.on_transmission)
00193 log_fatal ("no memory for top-level on_transmission group");
00194
00195 status = read_client_conf_file (path_dhclient_conf,
00196 (struct interface_info *)0,
00197 &top_level_config);
00198
00199 if (status != ISC_R_SUCCESS) {
00200 ;
00201 #ifdef LATER
00202
00203 status = new_parse(&parse, -1, default_client_config,
00204 sizeof(default_client_config) - 1,
00205 "default client configuration", 0);
00206 if (status != ISC_R_SUCCESS)
00207 log_fatal ("can't begin default client config!");
00208 }
00209
00210 if (parse != NULL) {
00211 do {
00212 token = peek_token(&val, NULL, cfile);
00213 if (token == END_OF_FILE)
00214 break;
00215 parse_client_statement(cfile, NULL, &top_level_config);
00216 } while (1);
00217 end_parse(&parse);
00218 #endif
00219 }
00220
00221
00222
00223 config = (struct client_config *)0;
00224 for (ip = interfaces; ip; ip = ip -> next) {
00225 if (!ip -> client) {
00226 ip -> client = (struct client_state *)
00227 dmalloc (sizeof (struct client_state), MDL);
00228 if (!ip -> client)
00229 log_fatal ("no memory for client state.");
00230 memset (ip -> client, 0, sizeof *(ip -> client));
00231 ip -> client -> interface = ip;
00232 }
00233
00234 if (!ip -> client -> config) {
00235 if (!config) {
00236 config = (struct client_config *)
00237 dmalloc (sizeof (struct client_config),
00238 MDL);
00239 if (!config)
00240 log_fatal ("no memory for client config.");
00241 memcpy (config, &top_level_config,
00242 sizeof top_level_config);
00243 }
00244 ip -> client -> config = config;
00245 }
00246 }
00247 return status;
00248 }
00249
00250 int read_client_conf_file (const char *name, struct interface_info *ip,
00251 struct client_config *client)
00252 {
00253 int file;
00254 struct parse *cfile;
00255 const char *val;
00256 int token;
00257 isc_result_t status;
00258
00259 if ((file = open (name, O_RDONLY | O_CLOEXEC)) < 0)
00260 return uerr2isc (errno);
00261
00262 cfile = NULL;
00263 status = new_parse(&cfile, file, NULL, 0, path_dhclient_conf, 0);
00264 if (status != ISC_R_SUCCESS || cfile == NULL)
00265 return status;
00266
00267 do {
00268 token = peek_token (&val, (unsigned *)0, cfile);
00269 if (token == END_OF_FILE)
00270 break;
00271 parse_client_statement (cfile, ip, client);
00272 } while (1);
00273 skip_token(&val, (unsigned *)0, cfile);
00274 status = (cfile -> warnings_occurred
00275 ? DHCP_R_BADPARSE
00276 : ISC_R_SUCCESS);
00277 end_parse (&cfile);
00278 return status;
00279 }
00280
00281
00282
00283
00284
00285
00286 void read_client_leases ()
00287 {
00288 int file;
00289 isc_result_t status;
00290 struct parse *cfile;
00291 const char *val;
00292 int token;
00293
00294
00295
00296 if ((file = open (path_dhclient_db, O_RDONLY | O_CLOEXEC)) < 0)
00297 return;
00298
00299 cfile = NULL;
00300 status = new_parse(&cfile, file, NULL, 0, path_dhclient_db, 0);
00301 if (status != ISC_R_SUCCESS || cfile == NULL)
00302 return;
00303
00304 do {
00305 token = next_token (&val, (unsigned *)0, cfile);
00306 if (token == END_OF_FILE)
00307 break;
00308
00309 switch (token) {
00310 case DEFAULT_DUID:
00311 parse_client_default_duid(cfile);
00312 break;
00313
00314 case LEASE:
00315 parse_client_lease_statement(cfile, 0);
00316 break;
00317
00318 case LEASE6:
00319 parse_client6_lease_statement(cfile);
00320 break;
00321
00322 default:
00323 log_error ("Corrupt lease file - possible data loss!");
00324 skip_to_semi (cfile);
00325 break;
00326 }
00327 } while (1);
00328
00329 end_parse (&cfile);
00330 }
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 void parse_client_statement (cfile, ip, config)
00356 struct parse *cfile;
00357 struct interface_info *ip;
00358 struct client_config *config;
00359 {
00360 int token;
00361 const char *val;
00362 struct option *option = NULL;
00363 struct executable_statement *stmt;
00364 int lose;
00365 char *name;
00366 enum policy policy;
00367 int known;
00368 int tmp, i;
00369 isc_result_t status;
00370 struct option ***append_list, **new_list, **cat_list;
00371
00372 switch (peek_token (&val, (unsigned *)0, cfile)) {
00373 case INCLUDE:
00374 skip_token(&val, (unsigned *)0, cfile);
00375 token = next_token (&val, (unsigned *)0, cfile);
00376 if (token != STRING) {
00377 parse_warn (cfile, "filename string expected.");
00378 skip_to_semi (cfile);
00379 } else {
00380 status = read_client_conf_file (val, ip, config);
00381 if (status != ISC_R_SUCCESS)
00382 parse_warn (cfile, "%s: bad parse.", val);
00383 parse_semi (cfile);
00384 }
00385 return;
00386
00387 case KEY:
00388 skip_token(&val, (unsigned *)0, cfile);
00389 if (ip) {
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402 parse_warn (cfile, "key definition not allowed here.");
00403 skip_to_semi (cfile);
00404 break;
00405 }
00406 parse_key (cfile);
00407 return;
00408
00409 case TOKEN_ALSO:
00410
00411 skip_token(&val, NULL, cfile);
00412
00413
00414 token = next_token(&val, NULL, cfile);
00415
00416 if (token == REQUEST) {
00417 append_list = &config->requested_options;
00418 } else if (token == REQUIRE) {
00419 append_list = &config->required_options;
00420 } else {
00421 parse_warn(cfile, "expected REQUEST or REQUIRE list");
00422 skip_to_semi(cfile);
00423 return;
00424 }
00425
00426
00427 if (*append_list == NULL) {
00428 parse_option_list(cfile, append_list);
00429 return;
00430 }
00431
00432
00433 for (i = 0 ; (*append_list)[i] != NULL ; i++)
00434 ;
00435
00436
00437 if (i == 0) {
00438 parse_option_list(cfile, append_list);
00439 return;
00440 }
00441
00442 tmp = parse_option_list(cfile, &new_list);
00443
00444 if (tmp == 0 || new_list == NULL)
00445 return;
00446
00447
00448 cat_list = dmalloc(sizeof(struct option *) * (i + tmp + 1),
00449 MDL);
00450
00451 if (cat_list == NULL) {
00452 log_error("Unable to allocate memory for new "
00453 "request list.");
00454 skip_to_semi(cfile);
00455 return;
00456 }
00457
00458 for (i = 0 ; (*append_list)[i] != NULL ; i++)
00459 option_reference(&cat_list[i], (*append_list)[i], MDL);
00460
00461 tmp = i;
00462
00463 for (i = 0 ; new_list[i] != 0 ; i++)
00464 option_reference(&cat_list[tmp++], new_list[i], MDL);
00465
00466 cat_list[tmp] = 0;
00467
00468
00469
00470
00471
00472 *append_list = cat_list;
00473
00474 return;
00475
00476
00477
00478 case REQUIRE:
00479 skip_token(&val, (unsigned *)0, cfile);
00480 token = peek_token (&val, (unsigned *)0, cfile);
00481 if (token == AUTHENTICATION) {
00482 policy = P_REQUIRE;
00483 goto do_policy;
00484 }
00485 parse_option_list (cfile, &config -> required_options);
00486 return;
00487
00488 case IGNORE:
00489 skip_token(&val, (unsigned *)0, cfile);
00490 policy = P_IGNORE;
00491 goto do_policy;
00492
00493 case ACCEPT:
00494 skip_token(&val, (unsigned *)0, cfile);
00495 policy = P_ACCEPT;
00496 goto do_policy;
00497
00498 case PREFER:
00499 skip_token(&val, (unsigned *)0, cfile);
00500 policy = P_PREFER;
00501 goto do_policy;
00502
00503 case DONT:
00504 skip_token(&val, (unsigned *)0, cfile);
00505 policy = P_DONT;
00506 goto do_policy;
00507
00508 do_policy:
00509 token = next_token (&val, (unsigned *)0, cfile);
00510 if (token == AUTHENTICATION) {
00511 if (policy != P_PREFER &&
00512 policy != P_REQUIRE &&
00513 policy != P_DONT) {
00514 parse_warn (cfile,
00515 "invalid authentication policy.");
00516 skip_to_semi (cfile);
00517 return;
00518 }
00519 config -> auth_policy = policy;
00520 } else if (token != TOKEN_BOOTP) {
00521 if (policy != P_PREFER &&
00522 policy != P_IGNORE &&
00523 policy != P_ACCEPT) {
00524 parse_warn (cfile, "invalid bootp policy.");
00525 skip_to_semi (cfile);
00526 return;
00527 }
00528 config -> bootp_policy = policy;
00529 } else {
00530 parse_warn (cfile, "expecting a policy type.");
00531 skip_to_semi (cfile);
00532 return;
00533 }
00534 break;
00535
00536 case OPTION:
00537 skip_token(&val, (unsigned *)0, cfile);
00538 token = peek_token (&val, (unsigned *)0, cfile);
00539 if (token == SPACE) {
00540 if (ip) {
00541 parse_warn (cfile,
00542 "option space definitions %s",
00543 " may not be scoped.");
00544 skip_to_semi (cfile);
00545 break;
00546 }
00547 parse_option_space_decl (cfile);
00548 return;
00549 }
00550
00551 known = 0;
00552 status = parse_option_name(cfile, 1, &known, &option);
00553 if (status != ISC_R_SUCCESS || option == NULL)
00554 return;
00555
00556 token = next_token (&val, (unsigned *)0, cfile);
00557 if (token != CODE) {
00558 parse_warn (cfile, "expecting \"code\" keyword.");
00559 skip_to_semi (cfile);
00560 option_dereference(&option, MDL);
00561 return;
00562 }
00563 if (ip) {
00564 parse_warn (cfile,
00565 "option definitions may only appear in %s",
00566 "the outermost scope.");
00567 skip_to_semi (cfile);
00568 option_dereference(&option, MDL);
00569 return;
00570 }
00571
00572
00573
00574
00575
00576 if (known) {
00577 option_name_hash_delete(option->universe->name_hash,
00578 option->name, 0, MDL);
00579 option_code_hash_delete(option->universe->code_hash,
00580 &option->code, 0, MDL);
00581 }
00582
00583 parse_option_code_definition(cfile, option);
00584 option_dereference(&option, MDL);
00585 return;
00586
00587 case MEDIA:
00588 skip_token(&val, (unsigned *)0, cfile);
00589 parse_string_list (cfile, &config -> media, 1);
00590 return;
00591
00592 case HARDWARE:
00593 skip_token(&val, (unsigned *)0, cfile);
00594 if (ip) {
00595 parse_hardware_param (cfile, &ip -> hw_address);
00596 } else {
00597 parse_warn (cfile, "hardware address parameter %s",
00598 "not allowed here.");
00599 skip_to_semi (cfile);
00600 }
00601 return;
00602
00603 case ANYCAST_MAC:
00604 skip_token(&val, NULL, cfile);
00605 if (ip != NULL) {
00606 parse_hardware_param(cfile, &ip->anycast_mac_addr);
00607 } else {
00608 parse_warn(cfile, "anycast mac address parameter "
00609 "not allowed here.");
00610 skip_to_semi (cfile);
00611 }
00612 return;
00613
00614 case REQUEST:
00615 skip_token(&val, (unsigned *)0, cfile);
00616 if (config -> requested_options == default_requested_options)
00617 config -> requested_options = NULL;
00618 parse_option_list (cfile, &config -> requested_options);
00619 return;
00620
00621 case TIMEOUT:
00622 skip_token(&val, (unsigned *)0, cfile);
00623 parse_lease_time (cfile, &config -> timeout);
00624 return;
00625
00626 case RETRY:
00627 skip_token(&val, (unsigned *)0, cfile);
00628 parse_lease_time (cfile, &config -> retry_interval);
00629 return;
00630
00631 case SELECT_TIMEOUT:
00632 skip_token(&val, (unsigned *)0, cfile);
00633 parse_lease_time (cfile, &config -> select_interval);
00634 return;
00635
00636 case OMAPI:
00637 skip_token(&val, (unsigned *)0, cfile);
00638 token = next_token (&val, (unsigned *)0, cfile);
00639 if (token != PORT) {
00640 parse_warn (cfile,
00641 "unexpected omapi subtype: %s", val);
00642 skip_to_semi (cfile);
00643 return;
00644 }
00645 token = next_token (&val, (unsigned *)0, cfile);
00646 if (token != NUMBER) {
00647 parse_warn (cfile, "invalid port number: `%s'", val);
00648 skip_to_semi (cfile);
00649 return;
00650 }
00651 tmp = atoi (val);
00652 if (tmp < 0 || tmp > 65535)
00653 parse_warn (cfile, "invalid omapi port %d.", tmp);
00654 else if (config != &top_level_config)
00655 parse_warn (cfile,
00656 "omapi port only works at top level.");
00657 else
00658 config -> omapi_port = tmp;
00659 parse_semi (cfile);
00660 return;
00661
00662 case DO_FORWARD_UPDATE:
00663 skip_token(&val, (unsigned *)0, cfile);
00664 token = next_token (&val, (unsigned *)0, cfile);
00665 if (!strcasecmp (val, "on") ||
00666 !strcasecmp (val, "true"))
00667 config -> do_forward_update = 1;
00668 else if (!strcasecmp (val, "off") ||
00669 !strcasecmp (val, "false"))
00670 config -> do_forward_update = 0;
00671 else {
00672 parse_warn (cfile, "expecting boolean value.");
00673 skip_to_semi (cfile);
00674 return;
00675 }
00676 parse_semi (cfile);
00677 return;
00678
00679 case REBOOT:
00680 skip_token(&val, (unsigned *)0, cfile);
00681 parse_lease_time (cfile, &config -> reboot_timeout);
00682 return;
00683
00684 case BACKOFF_CUTOFF:
00685 skip_token(&val, (unsigned *)0, cfile);
00686 parse_lease_time (cfile, &config -> backoff_cutoff);
00687 return;
00688
00689 case INITIAL_INTERVAL:
00690 skip_token(&val, (unsigned *)0, cfile);
00691 parse_lease_time (cfile, &config -> initial_interval);
00692 return;
00693
00694 case INITIAL_DELAY:
00695 skip_token(&val, (unsigned *)0, cfile);
00696 parse_lease_time (cfile, &config -> initial_delay);
00697 return;
00698
00699 case SCRIPT:
00700 skip_token(&val, (unsigned *)0, cfile);
00701 parse_string (cfile, &config -> script_name, (unsigned *)0);
00702 return;
00703
00704 case VENDOR:
00705 skip_token(&val, (unsigned *)0, cfile);
00706 token = next_token (&val, (unsigned *)0, cfile);
00707 if (token != OPTION) {
00708 parse_warn (cfile, "expecting 'vendor option space'");
00709 skip_to_semi (cfile);
00710 return;
00711 }
00712 token = next_token (&val, (unsigned *)0, cfile);
00713 if (token != SPACE) {
00714 parse_warn (cfile, "expecting 'vendor option space'");
00715 skip_to_semi (cfile);
00716 return;
00717 }
00718 token = next_token (&val, (unsigned *)0, cfile);
00719 if (!is_identifier (token)) {
00720 parse_warn (cfile, "expecting an identifier.");
00721 skip_to_semi (cfile);
00722 return;
00723 }
00724 config -> vendor_space_name = dmalloc (strlen (val) + 1, MDL);
00725 if (!config -> vendor_space_name)
00726 log_fatal ("no memory for vendor option space name.");
00727 strcpy (config -> vendor_space_name, val);
00728 for (i = 0; i < universe_count; i++)
00729 if (!strcmp (universes [i] -> name,
00730 config -> vendor_space_name))
00731 break;
00732 if (i == universe_count) {
00733 log_error ("vendor option space %s not found.",
00734 config -> vendor_space_name);
00735 }
00736 parse_semi (cfile);
00737 return;
00738
00739 case INTERFACE:
00740 skip_token(&val, (unsigned *)0, cfile);
00741 if (ip)
00742 parse_warn (cfile, "nested interface declaration.");
00743 parse_interface_declaration (cfile, config, (char *)0);
00744 return;
00745
00746 case PSEUDO:
00747 skip_token(&val, (unsigned *)0, cfile);
00748 token = next_token (&val, (unsigned *)0, cfile);
00749 name = dmalloc (strlen (val) + 1, MDL);
00750 if (!name)
00751 log_fatal ("no memory for pseudo interface name");
00752 strcpy (name, val);
00753 parse_interface_declaration (cfile, config, name);
00754 return;
00755
00756 case LEASE:
00757 skip_token(&val, (unsigned *)0, cfile);
00758 parse_client_lease_statement (cfile, 1);
00759 return;
00760
00761 case ALIAS:
00762 skip_token(&val, (unsigned *)0, cfile);
00763 parse_client_lease_statement (cfile, 2);
00764 return;
00765
00766 case REJECT:
00767 skip_token(&val, (unsigned *)0, cfile);
00768 parse_reject_statement (cfile, config);
00769 return;
00770
00771 case BOOTP_BROADCAST_ALWAYS:
00772 token = next_token(&val, (unsigned*)0, cfile);
00773 config -> bootp_broadcast_always = 1;
00774 parse_semi (cfile);
00775 return;
00776
00777 default:
00778 lose = 0;
00779 stmt = (struct executable_statement *)0;
00780 if (!parse_executable_statement (&stmt,
00781 cfile, &lose, context_any)) {
00782 if (!lose) {
00783 parse_warn (cfile, "expecting a statement.");
00784 skip_to_semi (cfile);
00785 }
00786 } else {
00787 struct executable_statement **eptr, *sptr;
00788 if (stmt &&
00789 (stmt -> op == send_option_statement ||
00790 (stmt -> op == on_statement &&
00791 (stmt -> data.on.evtypes & ON_TRANSMISSION)))) {
00792 eptr = &config -> on_transmission -> statements;
00793 if (stmt -> op == on_statement) {
00794 sptr = (struct executable_statement *)0;
00795 executable_statement_reference
00796 (&sptr,
00797 stmt -> data.on.statements, MDL);
00798 executable_statement_dereference (&stmt,
00799 MDL);
00800 executable_statement_reference (&stmt,
00801 sptr,
00802 MDL);
00803 executable_statement_dereference (&sptr,
00804 MDL);
00805 }
00806 } else
00807 eptr = &config -> on_receipt -> statements;
00808
00809 if (stmt) {
00810 for (; *eptr; eptr = &(*eptr) -> next)
00811 ;
00812 executable_statement_reference (eptr,
00813 stmt, MDL);
00814 }
00815 return;
00816 }
00817 break;
00818 }
00819 parse_semi (cfile);
00820 }
00821
00822
00823
00824
00825 int
00826 parse_option_list(struct parse *cfile, struct option ***list)
00827 {
00828 int ix;
00829 int token;
00830 const char *val;
00831 pair p = (pair)0, q = (pair)0, r;
00832 struct option *option = NULL;
00833 isc_result_t status;
00834
00835 ix = 0;
00836 do {
00837 token = peek_token (&val, (unsigned *)0, cfile);
00838 if (token == SEMI) {
00839 token = next_token (&val, (unsigned *)0, cfile);
00840 break;
00841 }
00842 if (!is_identifier (token)) {
00843 parse_warn (cfile, "%s: expected option name.", val);
00844 skip_token(&val, (unsigned *)0, cfile);
00845 skip_to_semi (cfile);
00846 return 0;
00847 }
00848 status = parse_option_name(cfile, 0, NULL, &option);
00849 if (status != ISC_R_SUCCESS || option == NULL) {
00850 parse_warn (cfile, "%s: expected option name.", val);
00851 return 0;
00852 }
00853 r = new_pair (MDL);
00854 if (!r)
00855 log_fatal ("can't allocate pair for option code.");
00856
00857 r->car = (caddr_t)option;
00858 option_dereference(&option, MDL);
00859 r -> cdr = (pair)0;
00860 if (p)
00861 q -> cdr = r;
00862 else
00863 p = r;
00864 q = r;
00865 ++ix;
00866 token = next_token (&val, (unsigned *)0, cfile);
00867 } while (token == COMMA);
00868 if (token != SEMI) {
00869 parse_warn (cfile, "expecting semicolon.");
00870 skip_to_semi (cfile);
00871 return 0;
00872 }
00873
00874
00875 *list = NULL;
00876 if (ix) {
00877 *list = dmalloc ((ix + 1) * sizeof(struct option *), MDL);
00878 if (!*list)
00879 log_error ("no memory for option list.");
00880 else {
00881 ix = 0;
00882 for (q = p; q; q = q -> cdr)
00883 option_reference(&(*list)[ix++],
00884 (struct option *)q->car, MDL);
00885 (*list)[ix] = NULL;
00886 }
00887 while (p) {
00888 q = p -> cdr;
00889 free_pair (p, MDL);
00890 p = q;
00891 }
00892 }
00893
00894 return ix;
00895 }
00896
00897
00898
00899
00900 void parse_interface_declaration (cfile, outer_config, name)
00901 struct parse *cfile;
00902 struct client_config *outer_config;
00903 char *name;
00904 {
00905 int token;
00906 const char *val;
00907 struct client_state *client, **cp;
00908 struct interface_info *ip = (struct interface_info *)0;
00909
00910 token = next_token (&val, (unsigned *)0, cfile);
00911 if (token != STRING) {
00912 parse_warn (cfile, "expecting interface name (in quotes).");
00913 skip_to_semi (cfile);
00914 return;
00915 }
00916
00917 if (!interface_or_dummy (&ip, val))
00918 log_fatal ("Can't allocate interface %s.", val);
00919
00920
00921 if (name) {
00922 make_client_state (&client);
00923 client -> name = name;
00924 client -> interface = ip;
00925 for (cp = &ip -> client; *cp; cp = &((*cp) -> next))
00926 ;
00927 *cp = client;
00928 } else {
00929 if (!ip -> client) {
00930 make_client_state (&ip -> client);
00931 ip -> client -> interface = ip;
00932 }
00933 client = ip -> client;
00934 }
00935
00936 if (!client -> config)
00937 make_client_config (client, outer_config);
00938
00939 ip -> flags &= ~INTERFACE_AUTOMATIC;
00940 interfaces_requested = 1;
00941
00942 token = next_token (&val, (unsigned *)0, cfile);
00943 if (token != LBRACE) {
00944 parse_warn (cfile, "expecting left brace.");
00945 skip_to_semi (cfile);
00946 return;
00947 }
00948
00949 do {
00950 token = peek_token (&val, (unsigned *)0, cfile);
00951 if (token == END_OF_FILE) {
00952 parse_warn (cfile,
00953 "unterminated interface declaration.");
00954 return;
00955 }
00956 if (token == RBRACE)
00957 break;
00958 parse_client_statement (cfile, ip, client -> config);
00959 } while (1);
00960 skip_token(&val, (unsigned *)0, cfile);
00961 }
00962
00963 int interface_or_dummy (struct interface_info **pi, const char *name)
00964 {
00965 struct interface_info *i;
00966 struct interface_info *ip = (struct interface_info *)0;
00967 isc_result_t status;
00968
00969
00970 for (i = interfaces; i; i = i -> next) {
00971 if (!strcmp (i -> name, name)) {
00972 interface_reference (&ip, i, MDL);
00973 break;
00974 }
00975 }
00976
00977
00978 if (!ip) {
00979 for (ip = dummy_interfaces; ip; ip = ip -> next) {
00980 if (!strcmp (ip -> name, name)) {
00981 interface_reference (&ip, i, MDL);
00982 break;
00983 }
00984 }
00985 }
00986
00987
00988
00989 if (!ip) {
00990 if ((status = interface_allocate (&ip, MDL)) != ISC_R_SUCCESS)
00991 log_fatal ("Can't record interface %s: %s",
00992 name, isc_result_totext (status));
00993
00994 if (strlen(name) >= sizeof(ip->name)) {
00995 interface_dereference(&ip, MDL);
00996 return 0;
00997 }
00998 strcpy(ip->name, name);
00999
01000 if (dummy_interfaces) {
01001 interface_reference (&ip -> next,
01002 dummy_interfaces, MDL);
01003 interface_dereference (&dummy_interfaces, MDL);
01004 }
01005 interface_reference (&dummy_interfaces, ip, MDL);
01006 }
01007 if (pi)
01008 status = interface_reference (pi, ip, MDL);
01009 else
01010 status = ISC_R_FAILURE;
01011 interface_dereference (&ip, MDL);
01012 if (status != ISC_R_SUCCESS)
01013 return 0;
01014 return 1;
01015 }
01016
01017 void make_client_state (state)
01018 struct client_state **state;
01019 {
01020 *state = ((struct client_state *)dmalloc (sizeof **state, MDL));
01021 if (!*state)
01022 log_fatal ("no memory for client state\n");
01023 memset (*state, 0, sizeof **state);
01024 }
01025
01026 void make_client_config (client, config)
01027 struct client_state *client;
01028 struct client_config *config;
01029 {
01030 client -> config = (((struct client_config *)
01031 dmalloc (sizeof (struct client_config), MDL)));
01032 if (!client -> config)
01033 log_fatal ("no memory for client config\n");
01034 memcpy (client -> config, config, sizeof *config);
01035 if (!clone_group (&client -> config -> on_receipt,
01036 config -> on_receipt, MDL) ||
01037 !clone_group (&client -> config -> on_transmission,
01038 config -> on_transmission, MDL))
01039 log_fatal ("no memory for client state groups.");
01040 }
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051 void parse_client_lease_statement (cfile, is_static)
01052 struct parse *cfile;
01053 int is_static;
01054 {
01055 struct client_lease *lease, *lp, *pl, *next;
01056 struct interface_info *ip = (struct interface_info *)0;
01057 int token;
01058 const char *val;
01059 struct client_state *client = (struct client_state *)0;
01060
01061 token = next_token (&val, (unsigned *)0, cfile);
01062 if (token != LBRACE) {
01063 parse_warn (cfile, "expecting left brace.");
01064 skip_to_semi (cfile);
01065 return;
01066 }
01067
01068 lease = ((struct client_lease *)
01069 dmalloc (sizeof (struct client_lease), MDL));
01070 if (!lease)
01071 log_fatal ("no memory for lease.\n");
01072 memset (lease, 0, sizeof *lease);
01073 lease -> is_static = is_static;
01074 if (!option_state_allocate (&lease -> options, MDL))
01075 log_fatal ("no memory for lease options.\n");
01076
01077 do {
01078 token = peek_token (&val, (unsigned *)0, cfile);
01079 if (token == END_OF_FILE) {
01080 parse_warn (cfile, "unterminated lease declaration.");
01081 return;
01082 }
01083 if (token == RBRACE)
01084 break;
01085 parse_client_lease_declaration (cfile, lease, &ip, &client);
01086 } while (1);
01087 skip_token(&val, (unsigned *)0, cfile);
01088
01089
01090
01091 if (!ip) {
01092 destroy_client_lease (lease);
01093 return;
01094 }
01095
01096
01097 if (!ip -> client) {
01098 make_client_state (&ip -> client);
01099 ip -> client -> interface = ip;
01100 }
01101 if (!client)
01102 client = ip -> client;
01103
01104
01105 if (is_static == 2) {
01106 ip -> client -> alias = lease;
01107 return;
01108 }
01109
01110
01111
01112
01113
01114 pl = (struct client_lease *)0;
01115 for (lp = client -> leases; lp; lp = next) {
01116 next = lp -> next;
01117 if (lp -> address.len == lease -> address.len &&
01118 !memcmp (lp -> address.iabuf, lease -> address.iabuf,
01119 lease -> address.len)) {
01120 if (pl)
01121 pl -> next = next;
01122 else
01123 client -> leases = next;
01124 destroy_client_lease (lp);
01125 break;
01126 } else
01127 pl = lp;
01128 }
01129
01130
01131
01132 if (is_static) {
01133 lease -> next = client -> leases;
01134 client -> leases = lease;
01135 return;
01136 }
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149 if (client -> active) {
01150 if (client -> active -> expiry < cur_time)
01151 destroy_client_lease (client -> active);
01152 else if (client -> active -> address.len ==
01153 lease -> address.len &&
01154 !memcmp (client -> active -> address.iabuf,
01155 lease -> address.iabuf,
01156 lease -> address.len))
01157 destroy_client_lease (client -> active);
01158 else {
01159 client -> active -> next = client -> leases;
01160 client -> leases = client -> active;
01161 }
01162 }
01163 client -> active = lease;
01164
01165
01166 }
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180 void parse_client_lease_declaration (cfile, lease, ipp, clientp)
01181 struct parse *cfile;
01182 struct client_lease *lease;
01183 struct interface_info **ipp;
01184 struct client_state **clientp;
01185 {
01186 int token;
01187 const char *val;
01188 struct interface_info *ip;
01189 struct option_cache *oc;
01190 struct client_state *client = (struct client_state *)0;
01191
01192 switch (next_token (&val, (unsigned *)0, cfile)) {
01193 case KEY:
01194 token = next_token (&val, (unsigned *)0, cfile);
01195 if (token != STRING && !is_identifier (token)) {
01196 parse_warn (cfile, "expecting key name.");
01197 skip_to_semi (cfile);
01198 break;
01199 }
01200 if (omapi_auth_key_lookup_name (&lease -> key, val) !=
01201 ISC_R_SUCCESS)
01202 parse_warn (cfile, "unknown key %s", val);
01203 parse_semi (cfile);
01204 break;
01205 case TOKEN_BOOTP:
01206 lease -> is_bootp = 1;
01207 break;
01208
01209 case INTERFACE:
01210 token = next_token (&val, (unsigned *)0, cfile);
01211 if (token != STRING) {
01212 parse_warn (cfile,
01213 "expecting interface name (in quotes).");
01214 skip_to_semi (cfile);
01215 break;
01216 }
01217 if (!interface_or_dummy (ipp, val))
01218 log_fatal ("Can't allocate interface %s.", val);
01219 break;
01220
01221 case NAME:
01222 token = next_token (&val, (unsigned *)0, cfile);
01223 ip = *ipp;
01224 if (!ip) {
01225 parse_warn (cfile, "state name precedes interface.");
01226 break;
01227 }
01228 for (client = ip -> client; client; client = client -> next)
01229 if (client -> name && !strcmp (client -> name, val))
01230 break;
01231 if (!client)
01232 parse_warn (cfile,
01233 "lease specified for unknown pseudo.");
01234 *clientp = client;
01235 break;
01236
01237 case FIXED_ADDR:
01238 if (!parse_ip_addr (cfile, &lease -> address))
01239 return;
01240 break;
01241
01242 case MEDIUM:
01243 parse_string_list (cfile, &lease -> medium, 0);
01244 return;
01245
01246 case FILENAME:
01247 parse_string (cfile, &lease -> filename, (unsigned *)0);
01248 return;
01249
01250 case SERVER_NAME:
01251 parse_string (cfile, &lease -> server_name, (unsigned *)0);
01252 return;
01253
01254 case RENEW:
01255 lease -> renewal = parse_date (cfile);
01256 return;
01257
01258 case REBIND:
01259 lease -> rebind = parse_date (cfile);
01260 return;
01261
01262 case EXPIRE:
01263 lease -> expiry = parse_date (cfile);
01264 return;
01265
01266 case OPTION:
01267 oc = (struct option_cache *)0;
01268 if (parse_option_decl (&oc, cfile)) {
01269 save_option(oc->option->universe, lease->options, oc);
01270 option_cache_dereference (&oc, MDL);
01271 }
01272 return;
01273
01274 default:
01275 parse_warn (cfile, "expecting lease declaration.");
01276 skip_to_semi (cfile);
01277 break;
01278 }
01279 token = next_token (&val, (unsigned *)0, cfile);
01280 if (token != SEMI) {
01281 parse_warn (cfile, "expecting semicolon.");
01282 skip_to_semi (cfile);
01283 }
01284 }
01285
01286
01287
01288 static void
01289 parse_client_default_duid(struct parse *cfile)
01290 {
01291 struct data_string new_duid;
01292 const char *val = NULL;
01293 unsigned len;
01294 int token;
01295
01296 memset(&new_duid, 0, sizeof(new_duid));
01297
01298 token = next_token(&val, &len, cfile);
01299 if (token != STRING) {
01300 parse_warn(cfile, "Expected DUID string.");
01301 skip_to_semi(cfile);
01302 return;
01303 }
01304
01305 if (len <= 2) {
01306 parse_warn(cfile, "Invalid DUID contents.");
01307 skip_to_semi(cfile);
01308 return;
01309 }
01310
01311 if (!buffer_allocate(&new_duid.buffer, len, MDL)) {
01312 parse_warn(cfile, "Out of memory parsing default DUID.");
01313 skip_to_semi(cfile);
01314 return;
01315 }
01316 new_duid.data = new_duid.buffer->data;
01317 new_duid.len = len;
01318
01319 memcpy(new_duid.buffer->data, val, len);
01320
01321
01322 if (default_duid.buffer != NULL)
01323 data_string_forget(&default_duid, MDL);
01324 data_string_copy(&default_duid, &new_duid, MDL);
01325 data_string_forget(&new_duid, MDL);
01326
01327 parse_semi(cfile);
01328 }
01329
01330
01331
01332
01333
01334
01335
01336 static void
01337 parse_client6_lease_statement(struct parse *cfile)
01338 {
01339 #if !defined(DHCPv6)
01340 parse_warn(cfile, "No DHCPv6 support.");
01341 skip_to_semi(cfile);
01342 #else
01343 struct option_cache *oc = NULL;
01344 struct dhc6_lease *lease;
01345 struct dhc6_ia **ia;
01346 struct client_state *client = NULL;
01347 struct interface_info *iface = NULL;
01348 struct data_string ds;
01349 const char *val;
01350 unsigned len;
01351 int token, has_ia, no_semi, has_name;
01352
01353 token = next_token(NULL, NULL, cfile);
01354 if (token != LBRACE) {
01355 parse_warn(cfile, "Expecting open curly brace.");
01356 skip_to_semi(cfile);
01357 return;
01358 }
01359
01360 lease = dmalloc(sizeof(*lease), MDL);
01361 if (lease == NULL) {
01362 parse_warn(cfile, "Unable to allocate lease state.");
01363 skip_to_rbrace(cfile, 1);
01364 return;
01365 }
01366
01367 option_state_allocate(&lease->options, MDL);
01368 if (lease->options == NULL) {
01369 parse_warn(cfile, "Unable to allocate option cache.");
01370 skip_to_rbrace(cfile, 1);
01371 dfree(lease, MDL);
01372 return;
01373 }
01374
01375 has_ia = 0;
01376 has_name = 0;
01377 ia = &lease->bindings;
01378 token = next_token(&val, NULL, cfile);
01379 while (token != RBRACE) {
01380 no_semi = 0;
01381
01382 switch(token) {
01383 case IA_NA:
01384 *ia = parse_client6_ia_na_statement(cfile);
01385 if (*ia != NULL) {
01386 ia = &(*ia)->next;
01387 has_ia = 1;
01388 }
01389
01390 no_semi = 1;
01391
01392 break;
01393
01394 case IA_TA:
01395 *ia = parse_client6_ia_ta_statement(cfile);
01396 if (*ia != NULL) {
01397 ia = &(*ia)->next;
01398 has_ia = 1;
01399 }
01400
01401 no_semi = 1;
01402
01403 break;
01404
01405 case IA_PD:
01406 *ia = parse_client6_ia_pd_statement(cfile);
01407 if (*ia != NULL) {
01408 ia = &(*ia)->next;
01409 has_ia = 1;
01410 }
01411
01412 no_semi = 1;
01413
01414 break;
01415
01416 case INTERFACE:
01417 if (iface != NULL) {
01418 parse_warn(cfile, "Multiple interface names?");
01419 skip_to_semi(cfile);
01420 no_semi = 1;
01421 break;
01422 }
01423
01424 token = next_token(&val, &len, cfile);
01425 if (token != STRING) {
01426 strerror:
01427 parse_warn(cfile, "Expecting a string.");
01428 skip_to_semi(cfile);
01429 no_semi = 1;
01430 break;
01431 }
01432
01433 for (iface = interfaces ; iface != NULL ;
01434 iface = iface->next) {
01435 if (strcmp(iface->name, val) == 0)
01436 break;
01437 }
01438
01439 if (iface == NULL) {
01440 parse_warn(cfile, "Unknown interface.");
01441 break;
01442 }
01443
01444 break;
01445
01446 case NAME:
01447 has_name = 1;
01448
01449 if (client != NULL) {
01450 parse_warn(cfile, "Multiple state names?");
01451 skip_to_semi(cfile);
01452 no_semi = 1;
01453 break;
01454 }
01455
01456 if (iface == NULL) {
01457 parse_warn(cfile, "Client name without "
01458 "interface.");
01459 skip_to_semi(cfile);
01460 no_semi = 1;
01461 break;
01462 }
01463
01464 token = next_token(&val, &len, cfile);
01465 if (token != STRING)
01466 goto strerror;
01467
01468 for (client = iface->client ; client != NULL ;
01469 client = client->next) {
01470 if ((client->name != NULL) &&
01471 (strcmp(client->name, val) == 0))
01472 break;
01473 }
01474
01475 if (client == NULL) {
01476 parse_warn(cfile, "Unknown client state %s.",
01477 val);
01478 break;
01479 }
01480
01481 break;
01482
01483 case OPTION:
01484 if (parse_option_decl(&oc, cfile)) {
01485 save_option(oc->option->universe,
01486 lease->options, oc);
01487 option_cache_dereference(&oc, MDL);
01488 }
01489 no_semi = 1;
01490 break;
01491
01492 case TOKEN_RELEASED:
01493 case TOKEN_ABANDONED:
01494 lease->released = ISC_TRUE;
01495 break;
01496
01497 default:
01498 parse_warn(cfile, "Unexpected token, %s.", val);
01499 no_semi = 1;
01500 skip_to_semi(cfile);
01501 break;
01502 }
01503
01504 if (!no_semi)
01505 parse_semi(cfile);
01506
01507 token = next_token(&val, NULL, cfile);
01508
01509 if (token == END_OF_FILE) {
01510 parse_warn(cfile, "Unexpected end of file.");
01511 break;
01512 }
01513 }
01514
01515 if (!has_ia) {
01516 log_debug("Lease with no IA's discarded from lease db.");
01517 dhc6_lease_destroy(&lease, MDL);
01518 return;
01519 }
01520
01521 if (iface == NULL)
01522 parse_warn(cfile, "Lease has no interface designation.");
01523 else if (!has_name && (client == NULL)) {
01524 for (client = iface->client ; client != NULL ;
01525 client = client->next) {
01526 if (client->name == NULL)
01527 break;
01528 }
01529 }
01530
01531 if (client == NULL) {
01532 parse_warn(cfile, "No matching client state.");
01533 dhc6_lease_destroy(&lease, MDL);
01534 return;
01535 }
01536
01537
01538 memset(&ds, 0, sizeof(ds));
01539 oc = lookup_option(&dhcpv6_universe, lease->options, D6O_PREFERENCE);
01540 if ((oc != NULL) &&
01541 evaluate_option_cache(&ds, NULL, NULL, NULL, lease->options,
01542 NULL, &global_scope, oc, MDL)) {
01543 if (ds.len != 1) {
01544 log_error("Invalid length of DHCPv6 Preference option "
01545 "(%d != 1)", ds.len);
01546 data_string_forget(&ds, MDL);
01547 dhc6_lease_destroy(&lease, MDL);
01548 return;
01549 } else
01550 lease->pref = ds.data[0];
01551
01552 data_string_forget(&ds, MDL);
01553 }
01554
01555
01556 oc = lookup_option(&dhcpv6_universe, lease->options, D6O_SERVERID);
01557 if ((oc == NULL) ||
01558 !evaluate_option_cache(&lease->server_id, NULL, NULL, NULL,
01559 lease->options, NULL, &global_scope, oc,
01560 MDL) ||
01561 (lease->server_id.len == 0)) {
01562
01563 log_error("Invalid SERVERID option cache.");
01564 dhc6_lease_destroy(&lease, MDL);
01565 return;
01566 }
01567
01568 if (client->active_lease != NULL)
01569 dhc6_lease_destroy(&client->active_lease, MDL);
01570
01571 client->active_lease = lease;
01572 #endif
01573 }
01574
01575
01576
01577 #ifdef DHCPv6
01578 static struct dhc6_ia *
01579 parse_client6_ia_na_statement(struct parse *cfile)
01580 {
01581 struct option_cache *oc = NULL;
01582 struct dhc6_ia *ia;
01583 struct dhc6_addr **addr;
01584 const char *val;
01585 int token, no_semi, len;
01586 u_int8_t buf[5];
01587
01588 ia = dmalloc(sizeof(*ia), MDL);
01589 if (ia == NULL) {
01590 parse_warn(cfile, "Out of memory allocating IA_NA state.");
01591 skip_to_semi(cfile);
01592 return NULL;
01593 }
01594 ia->ia_type = D6O_IA_NA;
01595
01596
01597 len = parse_X(cfile, buf, 5);
01598 if (len == 4) {
01599 memcpy(ia->iaid, buf, 4);
01600 } else {
01601 parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
01602 skip_to_semi(cfile);
01603 dfree(ia, MDL);
01604 return NULL;
01605 }
01606
01607 token = next_token(NULL, NULL, cfile);
01608 if (token != LBRACE) {
01609 parse_warn(cfile, "Expecting open curly brace.");
01610 skip_to_semi(cfile);
01611 dfree(ia, MDL);
01612 return NULL;
01613 }
01614
01615 option_state_allocate(&ia->options, MDL);
01616 if (ia->options == NULL) {
01617 parse_warn(cfile, "Unable to allocate option state.");
01618 skip_to_rbrace(cfile, 1);
01619 dfree(ia, MDL);
01620 return NULL;
01621 }
01622
01623 addr = &ia->addrs;
01624 token = next_token(&val, NULL, cfile);
01625 while (token != RBRACE) {
01626 no_semi = 0;
01627
01628 switch (token) {
01629 case STARTS:
01630 token = next_token(&val, NULL, cfile);
01631 if (token == NUMBER) {
01632 ia->starts = atoi(val);
01633 } else {
01634 parse_warn(cfile, "Expecting a number.");
01635 skip_to_semi(cfile);
01636 no_semi = 1;
01637 }
01638 break;
01639
01640 case RENEW:
01641 token = next_token(&val, NULL, cfile);
01642 if (token == NUMBER) {
01643 ia->renew = atoi(val);
01644 } else {
01645 parse_warn(cfile, "Expecting a number.");
01646 skip_to_semi(cfile);
01647 no_semi = 1;
01648 }
01649 break;
01650
01651 case REBIND:
01652 token = next_token(&val, NULL, cfile);
01653 if (token == NUMBER) {
01654 ia->rebind = atoi(val);
01655 } else {
01656 parse_warn(cfile, "Expecting a number.");
01657 skip_to_semi(cfile);
01658 no_semi = 1;
01659 }
01660 break;
01661
01662 case IAADDR:
01663 *addr = parse_client6_iaaddr_statement(cfile);
01664
01665 if (*addr != NULL)
01666 addr = &(*addr)->next;
01667
01668 no_semi = 1;
01669
01670 break;
01671
01672 case OPTION:
01673 if (parse_option_decl(&oc, cfile)) {
01674 save_option(oc->option->universe,
01675 ia->options, oc);
01676 option_cache_dereference(&oc, MDL);
01677 }
01678 no_semi = 1;
01679 break;
01680
01681 default:
01682 parse_warn(cfile, "Unexpected token.");
01683 no_semi = 1;
01684 skip_to_semi(cfile);
01685 break;
01686 }
01687
01688 if (!no_semi)
01689 parse_semi(cfile);
01690
01691 token = next_token(&val, NULL, cfile);
01692
01693 if (token == END_OF_FILE) {
01694 parse_warn(cfile, "Unexpected end of file.");
01695 break;
01696 }
01697 }
01698
01699 return ia;
01700 }
01701 #endif
01702
01703
01704
01705 #ifdef DHCPv6
01706 static struct dhc6_ia *
01707 parse_client6_ia_ta_statement(struct parse *cfile)
01708 {
01709 struct option_cache *oc = NULL;
01710 struct dhc6_ia *ia;
01711 struct dhc6_addr **addr;
01712 const char *val;
01713 int token, no_semi, len;
01714 u_int8_t buf[5];
01715
01716 ia = dmalloc(sizeof(*ia), MDL);
01717 if (ia == NULL) {
01718 parse_warn(cfile, "Out of memory allocating IA_TA state.");
01719 skip_to_semi(cfile);
01720 return NULL;
01721 }
01722 ia->ia_type = D6O_IA_TA;
01723
01724
01725 len = parse_X(cfile, buf, 5);
01726 if (len == 4) {
01727 memcpy(ia->iaid, buf, 4);
01728 } else {
01729 parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
01730 skip_to_semi(cfile);
01731 dfree(ia, MDL);
01732 return NULL;
01733 }
01734
01735 token = next_token(NULL, NULL, cfile);
01736 if (token != LBRACE) {
01737 parse_warn(cfile, "Expecting open curly brace.");
01738 skip_to_semi(cfile);
01739 dfree(ia, MDL);
01740 return NULL;
01741 }
01742
01743 option_state_allocate(&ia->options, MDL);
01744 if (ia->options == NULL) {
01745 parse_warn(cfile, "Unable to allocate option state.");
01746 skip_to_rbrace(cfile, 1);
01747 dfree(ia, MDL);
01748 return NULL;
01749 }
01750
01751 addr = &ia->addrs;
01752 token = next_token(&val, NULL, cfile);
01753 while (token != RBRACE) {
01754 no_semi = 0;
01755
01756 switch (token) {
01757 case STARTS:
01758 token = next_token(&val, NULL, cfile);
01759 if (token == NUMBER) {
01760 ia->starts = atoi(val);
01761 } else {
01762 parse_warn(cfile, "Expecting a number.");
01763 skip_to_semi(cfile);
01764 no_semi = 1;
01765 }
01766 break;
01767
01768
01769
01770 case IAADDR:
01771 *addr = parse_client6_iaaddr_statement(cfile);
01772
01773 if (*addr != NULL)
01774 addr = &(*addr)->next;
01775
01776 no_semi = 1;
01777
01778 break;
01779
01780 case OPTION:
01781 if (parse_option_decl(&oc, cfile)) {
01782 save_option(oc->option->universe,
01783 ia->options, oc);
01784 option_cache_dereference(&oc, MDL);
01785 }
01786 no_semi = 1;
01787 break;
01788
01789 default:
01790 parse_warn(cfile, "Unexpected token.");
01791 no_semi = 1;
01792 skip_to_semi(cfile);
01793 break;
01794 }
01795
01796 if (!no_semi)
01797 parse_semi(cfile);
01798
01799 token = next_token(&val, NULL, cfile);
01800
01801 if (token == END_OF_FILE) {
01802 parse_warn(cfile, "Unexpected end of file.");
01803 break;
01804 }
01805 }
01806
01807 return ia;
01808 }
01809 #endif
01810
01811
01812
01813 #ifdef DHCPv6
01814 static struct dhc6_ia *
01815 parse_client6_ia_pd_statement(struct parse *cfile)
01816 {
01817 struct option_cache *oc = NULL;
01818 struct dhc6_ia *ia;
01819 struct dhc6_addr **pref;
01820 const char *val;
01821 int token, no_semi, len;
01822 u_int8_t buf[5];
01823
01824 ia = dmalloc(sizeof(*ia), MDL);
01825 if (ia == NULL) {
01826 parse_warn(cfile, "Out of memory allocating IA_PD state.");
01827 skip_to_semi(cfile);
01828 return NULL;
01829 }
01830 ia->ia_type = D6O_IA_PD;
01831
01832
01833 len = parse_X(cfile, buf, 5);
01834 if (len == 4) {
01835 memcpy(ia->iaid, buf, 4);
01836 } else {
01837 parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
01838 skip_to_semi(cfile);
01839 dfree(ia, MDL);
01840 return NULL;
01841 }
01842
01843 token = next_token(NULL, NULL, cfile);
01844 if (token != LBRACE) {
01845 parse_warn(cfile, "Expecting open curly brace.");
01846 skip_to_semi(cfile);
01847 dfree(ia, MDL);
01848 return NULL;
01849 }
01850
01851 option_state_allocate(&ia->options, MDL);
01852 if (ia->options == NULL) {
01853 parse_warn(cfile, "Unable to allocate option state.");
01854 skip_to_rbrace(cfile, 1);
01855 dfree(ia, MDL);
01856 return NULL;
01857 }
01858
01859 pref = &ia->addrs;
01860 token = next_token(&val, NULL, cfile);
01861 while (token != RBRACE) {
01862 no_semi = 0;
01863
01864 switch (token) {
01865 case STARTS:
01866 token = next_token(&val, NULL, cfile);
01867 if (token == NUMBER) {
01868 ia->starts = atoi(val);
01869 } else {
01870 parse_warn(cfile, "Expecting a number.");
01871 skip_to_semi(cfile);
01872 no_semi = 1;
01873 }
01874 break;
01875
01876 case RENEW:
01877 token = next_token(&val, NULL, cfile);
01878 if (token == NUMBER) {
01879 ia->renew = atoi(val);
01880 } else {
01881 parse_warn(cfile, "Expecting a number.");
01882 skip_to_semi(cfile);
01883 no_semi = 1;
01884 }
01885 break;
01886
01887 case REBIND:
01888 token = next_token(&val, NULL, cfile);
01889 if (token == NUMBER) {
01890 ia->rebind = atoi(val);
01891 } else {
01892 parse_warn(cfile, "Expecting a number.");
01893 skip_to_semi(cfile);
01894 no_semi = 1;
01895 }
01896 break;
01897
01898 case IAPREFIX:
01899 *pref = parse_client6_iaprefix_statement(cfile);
01900
01901 if (*pref != NULL)
01902 pref = &(*pref)->next;
01903
01904 no_semi = 1;
01905
01906 break;
01907
01908 case OPTION:
01909 if (parse_option_decl(&oc, cfile)) {
01910 save_option(oc->option->universe,
01911 ia->options, oc);
01912 option_cache_dereference(&oc, MDL);
01913 }
01914 no_semi = 1;
01915 break;
01916
01917 default:
01918 parse_warn(cfile, "Unexpected token.");
01919 no_semi = 1;
01920 skip_to_semi(cfile);
01921 break;
01922 }
01923
01924 if (!no_semi)
01925 parse_semi(cfile);
01926
01927 token = next_token(&val, NULL, cfile);
01928
01929 if (token == END_OF_FILE) {
01930 parse_warn(cfile, "Unexpected end of file.");
01931 break;
01932 }
01933 }
01934
01935 return ia;
01936 }
01937 #endif
01938
01939
01940 #ifdef DHCPv6
01941 static struct dhc6_addr *
01942 parse_client6_iaaddr_statement(struct parse *cfile)
01943 {
01944 struct option_cache *oc = NULL;
01945 struct dhc6_addr *addr;
01946 const char *val;
01947 int token, no_semi;
01948
01949 addr = dmalloc(sizeof(*addr), MDL);
01950 if (addr == NULL) {
01951 parse_warn(cfile, "Unable to allocate IAADDR state.");
01952 skip_to_semi(cfile);
01953 return NULL;
01954 }
01955
01956
01957 if (!parse_ip6_addr(cfile, &addr->address)) {
01958 skip_to_semi(cfile);
01959 dfree(addr, MDL);
01960 return NULL;
01961 }
01962
01963 token = next_token(NULL, NULL, cfile);
01964 if (token != LBRACE) {
01965 parse_warn(cfile, "Expecting open curly bracket.");
01966 skip_to_semi(cfile);
01967 dfree(addr, MDL);
01968 return NULL;
01969 }
01970
01971 option_state_allocate(&addr->options, MDL);
01972 if (addr->options == NULL) {
01973 parse_warn(cfile, "Unable to allocate option state.");
01974 skip_to_semi(cfile);
01975 dfree(addr, MDL);
01976 return NULL;
01977 }
01978
01979 token = next_token(&val, NULL, cfile);
01980 while (token != RBRACE) {
01981 no_semi = 0;
01982
01983 switch (token) {
01984 case STARTS:
01985 token = next_token(&val, NULL, cfile);
01986 if (token == NUMBER) {
01987 addr->starts = atoi(val);
01988 } else {
01989 parse_warn(cfile, "Expecting a number.");
01990 skip_to_semi(cfile);
01991 no_semi = 1;
01992 }
01993 break;
01994
01995 case PREFERRED_LIFE:
01996 token = next_token(&val, NULL, cfile);
01997 if (token == NUMBER) {
01998 addr->preferred_life = atoi(val);
01999 } else {
02000 parse_warn(cfile, "Expecting a number.");
02001 skip_to_semi(cfile);
02002 no_semi = 1;
02003 }
02004 break;
02005
02006 case MAX_LIFE:
02007 token = next_token(&val, NULL, cfile);
02008 if (token == NUMBER) {
02009 addr->max_life = atoi(val);
02010 } else {
02011 parse_warn(cfile, "Expecting a number.");
02012 skip_to_semi(cfile);
02013 no_semi = 1;
02014 }
02015 break;
02016
02017 case OPTION:
02018 if (parse_option_decl(&oc, cfile)) {
02019 save_option(oc->option->universe,
02020 addr->options, oc);
02021 option_cache_dereference(&oc, MDL);
02022 }
02023 no_semi = 1;
02024 break;
02025
02026 default:
02027 parse_warn(cfile, "Unexpected token.");
02028 skip_to_rbrace(cfile, 1);
02029 no_semi = 1;
02030 break;
02031 }
02032
02033 if (!no_semi)
02034 parse_semi(cfile);
02035
02036 token = next_token(&val, NULL, cfile);
02037 if (token == END_OF_FILE) {
02038 parse_warn(cfile, "Unexpected end of file.");
02039 break;
02040 }
02041 }
02042
02043 return addr;
02044 }
02045 #endif
02046
02047
02048 #ifdef DHCPv6
02049 static struct dhc6_addr *
02050 parse_client6_iaprefix_statement(struct parse *cfile)
02051 {
02052 struct option_cache *oc = NULL;
02053 struct dhc6_addr *pref;
02054 const char *val;
02055 int token, no_semi;
02056
02057 pref = dmalloc(sizeof(*pref), MDL);
02058 if (pref == NULL) {
02059 parse_warn(cfile, "Unable to allocate IAPREFIX state.");
02060 skip_to_semi(cfile);
02061 return NULL;
02062 }
02063
02064
02065 if (!parse_ip6_prefix(cfile, &pref->address, &pref->plen)) {
02066 skip_to_semi(cfile);
02067 dfree(pref, MDL);
02068 return NULL;
02069 }
02070
02071 token = next_token(NULL, NULL, cfile);
02072 if (token != LBRACE) {
02073 parse_warn(cfile, "Expecting open curly bracket.");
02074 skip_to_semi(cfile);
02075 dfree(pref, MDL);
02076 return NULL;
02077 }
02078
02079 option_state_allocate(&pref->options, MDL);
02080 if (pref->options == NULL) {
02081 parse_warn(cfile, "Unable to allocate option state.");
02082 skip_to_semi(cfile);
02083 dfree(pref, MDL);
02084 return NULL;
02085 }
02086
02087 token = next_token(&val, NULL, cfile);
02088 while (token != RBRACE) {
02089 no_semi = 0;
02090
02091 switch (token) {
02092 case STARTS:
02093 token = next_token(&val, NULL, cfile);
02094 if (token == NUMBER) {
02095 pref->starts = atoi(val);
02096 } else {
02097 parse_warn(cfile, "Expecting a number.");
02098 skip_to_semi(cfile);
02099 no_semi = 1;
02100 }
02101 break;
02102
02103 case PREFERRED_LIFE:
02104 token = next_token(&val, NULL, cfile);
02105 if (token == NUMBER) {
02106 pref->preferred_life = atoi(val);
02107 } else {
02108 parse_warn(cfile, "Expecting a number.");
02109 skip_to_semi(cfile);
02110 no_semi = 1;
02111 }
02112 break;
02113
02114 case MAX_LIFE:
02115 token = next_token(&val, NULL, cfile);
02116 if (token == NUMBER) {
02117 pref->max_life = atoi(val);
02118 } else {
02119 parse_warn(cfile, "Expecting a number.");
02120 skip_to_semi(cfile);
02121 no_semi = 1;
02122 }
02123 break;
02124
02125 case OPTION:
02126 if (parse_option_decl(&oc, cfile)) {
02127 save_option(oc->option->universe,
02128 pref->options, oc);
02129 option_cache_dereference(&oc, MDL);
02130 }
02131 no_semi = 1;
02132 break;
02133
02134 default:
02135 parse_warn(cfile, "Unexpected token.");
02136 skip_to_rbrace(cfile, 1);
02137 no_semi = 1;
02138 break;
02139 }
02140
02141 if (!no_semi)
02142 parse_semi(cfile);
02143
02144 token = next_token(&val, NULL, cfile);
02145 if (token == END_OF_FILE) {
02146 parse_warn(cfile, "Unexpected end of file.");
02147 break;
02148 }
02149 }
02150
02151 return pref;
02152 }
02153 #endif
02154
02155 void parse_string_list (cfile, lp, multiple)
02156 struct parse *cfile;
02157 struct string_list **lp;
02158 int multiple;
02159 {
02160 int token;
02161 const char *val;
02162 struct string_list *cur, *tmp;
02163
02164
02165 if (*lp) {
02166 for (cur = *lp; cur -> next; cur = cur -> next)
02167 ;
02168 } else {
02169 cur = (struct string_list *)0;
02170 }
02171
02172 do {
02173 token = next_token (&val, (unsigned *)0, cfile);
02174 if (token != STRING) {
02175 parse_warn (cfile, "Expecting media options.");
02176 skip_to_semi (cfile);
02177 return;
02178 }
02179
02180 tmp = ((struct string_list *)
02181 dmalloc (strlen (val) + sizeof (struct string_list),
02182 MDL));
02183 if (!tmp)
02184 log_fatal ("no memory for string list entry.");
02185
02186 strcpy (tmp -> string, val);
02187 tmp -> next = (struct string_list *)0;
02188
02189
02190 if (cur)
02191 cur -> next = tmp;
02192 else
02193 *lp = tmp;
02194 cur = tmp;
02195
02196 token = next_token (&val, (unsigned *)0, cfile);
02197 } while (multiple && token == COMMA);
02198
02199 if (token != SEMI) {
02200 parse_warn (cfile, "expecting semicolon.");
02201 skip_to_semi (cfile);
02202 }
02203 }
02204
02205 void parse_reject_statement (cfile, config)
02206 struct parse *cfile;
02207 struct client_config *config;
02208 {
02209 int token;
02210 const char *val;
02211 struct iaddrmatch match;
02212 struct iaddrmatchlist *list;
02213 int i;
02214
02215 do {
02216 if (!parse_ip_addr_with_subnet (cfile, &match)) {
02217
02218 skip_to_semi (cfile);
02219 return;
02220 }
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233 for (i=0 ; i < match.mask.len ; i++) {
02234 if (match.mask.iabuf[i]) {
02235 break;
02236 }
02237 }
02238
02239 if (i == match.mask.len) {
02240
02241 parse_warn(cfile, "zero-length prefix is not permitted "
02242 "for reject statement");
02243 skip_to_semi(cfile);
02244 return;
02245 }
02246
02247 list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
02248 if (!list)
02249 log_fatal ("no memory for reject list!");
02250
02251 list->match = match;
02252 list->next = config->reject_list;
02253 config->reject_list = list;
02254
02255 token = next_token (&val, (unsigned *)0, cfile);
02256 } while (token == COMMA);
02257
02258 if (token != SEMI) {
02259 parse_warn (cfile, "expecting semicolon.");
02260 skip_to_semi (cfile);
02261 }
02262 }
02263
02264
02265
02266
02267
02268
02269 int parse_allow_deny (oc, cfile, flag)
02270 struct option_cache **oc;
02271 struct parse *cfile;
02272 int flag;
02273 {
02274 parse_warn (cfile, "allow/deny/ignore not permitted here.");
02275 skip_to_semi (cfile);
02276 return 0;
02277 }