📄 options.c
字号:
/* Do we add a NUL? */ if (terminate && dhcp_options [code].format [0] == 't') { length++; tto = 1; } else { tto = 0; } /* Try to store the option. */ /* If the option's length is more than 255, we must store it in multiple hunks. Store 255-byte hunks first. However, in any case, if the option data will cross a buffer boundary, split it across that boundary. */ ix = 0; optstart = bufix; while (length) { unsigned char incr = length > 255 ? 255 : length; int consumed = 0; /* If this hunk of the buffer will cross a boundary, only go up to the boundary in this pass. */ if (bufix < first_cutoff && bufix + incr > first_cutoff) incr = first_cutoff - bufix; else if (bufix < second_cutoff && bufix + incr > second_cutoff) incr = second_cutoff - bufix; /* If this option is going to overflow the buffer, skip it. */ if (bufix + 2 + incr > buflen) { bufix = optstart; break; } /* Everything looks good - copy it in! */ buffer [bufix] = code; buffer [bufix + 1] = incr; if (tto && incr == length) { memcpy (buffer + bufix + 2, od.data + ix, (unsigned)(incr - 1)); buffer [bufix + 2 + incr - 1] = 0; } else { memcpy (buffer + bufix + 2, od.data + ix, (unsigned)incr); } length -= incr; ix += incr; bufix += 2 + incr; } data_string_forget (&od, MDL); } return bufix;}/* Format the specified option so that a human can easily read it. */const char *pretty_print_option (option, data, len, emit_commas, emit_quotes) struct option *option; const unsigned char *data; unsigned len; int emit_commas; int emit_quotes;{ static char optbuf [32768]; /* XXX */ int hunksize = 0; int opthunk = 0; int hunkinc = 0; int numhunk = -1; int numelem = 0; char fmtbuf [32]; struct enumeration *enumbuf [32]; int i, j, k, l; char *op = optbuf; const unsigned char *dp = data; struct in_addr foo; char comma; unsigned long tval; if (emit_commas) comma = ','; else comma = ' '; memset (enumbuf, 0, sizeof enumbuf); /* Figure out the size of the data. */ for (l = i = 0; option -> format [i]; i++, l++) { if (!numhunk) { log_error ("%s: Extra codes in format string: %s", option -> name, &(option -> format [i])); break; } numelem++; fmtbuf [l] = option -> format [i]; switch (option -> format [i]) { case 'a': --numelem; fmtbuf [l] = 0; numhunk = 0; break; case 'A': --numelem; fmtbuf [l] = 0; numhunk = 0; break; case 'E': /* Skip the universe name. */ while (option -> format [i] && option -> format [i] != '.') i++; case 'X': for (k = 0; k < len; k++) { if (!isascii (data [k]) || !isprint (data [k])) break; } /* If we found no bogus characters, or the bogus character we found is a trailing NUL, it's okay to print this option as text. */ if (k == len || (k + 1 == len && data [k] == 0)) { fmtbuf [l] = 't'; numhunk = -2; } else { fmtbuf [l] = 'x'; hunksize++; comma = ':'; numhunk = 0; } fmtbuf [l + 1] = 0; break; case 'd': case 't': fmtbuf [l] = 't'; fmtbuf [l + 1] = 0; numhunk = -2; break; case 'N': k = i; while (option -> format [i] && option -> format [i] != '.') i++; enumbuf [l] = find_enumeration (&option -> format [k] + 1, i - k - 1); hunksize += 1; hunkinc = 1; break; case 'I': case 'l': case 'L': case 'T': hunksize += 4; hunkinc = 4; break; case 's': case 'S': hunksize += 2; hunkinc = 2; break; case 'b': case 'B': case 'f': hunksize++; hunkinc = 1; break; case 'e': break; case 'o': opthunk += hunkinc; break; default: log_error ("%s: garbage in format string: %s", option -> name, &(option -> format [i])); break; } } /* Check for too few bytes... */ if (hunksize - opthunk > len) { log_error ("%s: expecting at least %d bytes; got %d", option -> name, hunksize, len); return "<error>"; } /* Check for too many bytes... */ if (numhunk == -1 && hunksize < len) log_error ("%s: %d extra bytes", option -> name, len - hunksize); /* If this is an array, compute its size. */ if (!numhunk) numhunk = len / hunksize; /* See if we got an exact number of hunks. */ if (numhunk > 0 && numhunk * hunksize < len) log_error ("%s: %d extra bytes at end of array\n", option -> name, len - numhunk * hunksize); /* A one-hunk array prints the same as a single hunk. */ if (numhunk < 0) numhunk = 1; /* Cycle through the array (or hunk) printing the data. */ for (i = 0; i < numhunk; i++) { for (j = 0; j < numelem; j++) { switch (fmtbuf [j]) { case 't': if (emit_quotes) *op++ = '"'; for (; dp < data + len; dp++) { if (!isascii (*dp) || !isprint (*dp)) { /* Skip trailing NUL. */ if (dp + 1 != data + len || *dp != 0) { sprintf (op, "\\%03o", *dp); op += 4; } } else if (*dp == '"' || *dp == '\'' || *dp == '$' || *dp == '`' || *dp == '\\') { *op++ = '\\'; *op++ = *dp; } else *op++ = *dp; } if (emit_quotes) *op++ = '"'; *op = 0; break; /* pretty-printing an array of enums is going to get ugly. */ case 'N': if (!enumbuf [j]) goto enum_as_num; for (i = 0; ;i++) { if (!enumbuf [j] -> values [i].name) goto enum_as_num; if (enumbuf [j] -> values [i].value == *dp) break; } strcpy (op, enumbuf [j] -> values [i].name); op += strlen (op); break; case 'I': foo.s_addr = htonl (getULong (dp)); strcpy (op, inet_ntoa (foo)); dp += 4; break; case 'l': sprintf (op, "%ld", (long)getLong (dp)); dp += 4; break; case 'T': tval = getULong (dp); if (tval == -1) sprintf (op, "%s", "infinite"); else sprintf (op, "%ld", tval); break; case 'L': sprintf (op, "%ld", (unsigned long)getULong (dp)); dp += 4; break; case 's': sprintf (op, "%d", (int)getShort (dp)); dp += 2; break; case 'S': sprintf (op, "%d", (unsigned)getUShort (dp)); dp += 2; break; case 'b': sprintf (op, "%d", *(const char *)dp++); break; case 'B': enum_as_num: sprintf (op, "%d", *dp++); break; case 'x': sprintf (op, "%x", *dp++); break; case 'f': strcpy (op, *dp++ ? "true" : "false"); break; default: log_error ("Unexpected format code %c", fmtbuf [j]); } op += strlen (op); if (dp == data + len) break; if (j + 1 < numelem && comma != ':') *op++ = ' '; } if (i + 1 < numhunk) { *op++ = comma; } if (dp == data + len) break; } return optbuf;}int get_option (result, universe, packet, lease, client_state, in_options, cfg_options, options, scope, code, file, line) struct data_string *result; struct universe *universe; struct packet *packet; struct lease *lease; struct client_state *client_state; struct option_state *in_options; struct option_state *cfg_options; struct option_state *options; struct binding_scope **scope; unsigned code; const char *file; int line;{ struct option_cache *oc; if (!universe -> lookup_func) return 0; oc = ((*universe -> lookup_func) (universe, options, code)); if (!oc) return 0; if (!evaluate_option_cache (result, packet, lease, client_state, in_options, cfg_options, scope, oc, file, line)) return 0; return 1;}void set_option (universe, options, option, op) struct universe *universe; struct option_state *options; struct option_cache *option; enum statement_op op;{ struct option_cache *oc, *noc; switch (op) { case if_statement: case add_statement: case eval_statement: case break_statement: default: log_error ("bogus statement type in do_option_set."); break; case default_option_statement: oc = lookup_option (universe, options, option -> option -> code); if (oc) break; save_option (universe, options, option); break; case supersede_option_statement: case send_option_statement: /* Install the option, replacing any existing version. */ save_option (universe, options, option); break; case append_option_statement: case prepend_option_statement: oc = lookup_option (universe, options, option -> option -> code); if (!oc) { save_option (universe, options, option); break; } /* If it's not an expression, make it into one. */ if (!oc -> expression && oc -> data.len) { if (!expression_allocate (&oc -> expression, MDL)) { log_error ("Can't allocate const expression."); break; } oc -> expression -> op = expr_const_data; data_string_copy (&oc -> expression -> data.const_data, &oc -> data, MDL); data_string_forget (&oc -> data, MDL); } noc = (struct option_cache *)0; if (!option_cache_allocate (&noc, MDL)) break; if (op == append_option_statement) { if (!make_concat (&noc -> expression, oc -> expression, option -> expression)) { option_cache_dereference (&noc, MDL); break; } } else { if (!make_concat (&noc -> expression, option -> expression, oc -> expression)) { option_cache_dereference (&noc, MDL); break; } } noc -> option = oc -> option; save_option (universe, options, noc); option_cache_dereference (&noc, MDL); break; }}struct option_cache *lookup_option (universe, options, code) struct universe *universe; struct option_state *options; unsigned code;{ if (!options) return (struct option_cache *)0; if (universe -> lookup_func) return (*universe -> lookup_func) (universe, options, code); else log_error ("can't look up options in %s space.", universe -> name); return (struct option_cache *)0;}struct option_cache *lookup_hashed_option (universe, options, code) struct universe *universe; struct option_state *options; unsigned code;{ int hashix; pair bptr; pair *hash; /* Make sure there's a hash table. */ if (universe -> index >= options -> universe_count || !(options -> universes [universe -> index]))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -