📄 options.c
字号:
return (struct option_cache *)0; hash = options -> universes [universe -> index]; hashix = compute_option_hash (code); for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) { if (((struct option_cache *)(bptr -> car)) -> option -> code == code) return (struct option_cache *)(bptr -> car); } return (struct option_cache *)0;}int save_option_buffer (struct universe *universe, struct option_state *options, struct buffer *bp, unsigned char *buffer, unsigned length, struct option *option, int tp){ struct buffer *lbp = (struct buffer *)0; struct option_cache *op = (struct option_cache *)0; if (!option_cache_allocate (&op, MDL)) { log_error ("No memory for option %s.%s.", universe -> name, option -> name); return 0; } /* If we weren't passed a buffer in which the data are saved and refcounted, allocate one now. */ if (!bp) { if (!buffer_allocate (&lbp, length, MDL)) { log_error ("no memory for option buffer."); option_cache_dereference (&op, MDL); return 0; } memcpy (lbp -> data, buffer, length + tp); bp = lbp; buffer = &bp -> data [0]; /* Refer to saved buffer. */ } /* Reference buffer copy to option cache. */ op -> data.buffer = (struct buffer *)0; buffer_reference (&op -> data.buffer, bp, MDL); /* Point option cache into buffer. */ op -> data.data = buffer; op -> data.len = length; if (tp) { /* NUL terminate (we can get away with this because we (or the caller!) allocated one more than the buffer size, and because the byte following the end of an option is always the code of the next option, which the caller is getting out of the *original* buffer. */ buffer [length] = 0; op -> data.terminated = 1; } else op -> data.terminated = 0; op -> option = option; /* Now store the option. */ save_option (universe, options, op); /* And let go of our reference. */ option_cache_dereference (&op, MDL); return 1;}void save_option (struct universe *universe, struct option_state *options, struct option_cache *oc){ if (universe -> save_func) (*universe -> save_func) (universe, options, oc); else log_error ("can't store options in %s space.", universe -> name);}void save_hashed_option (universe, options, oc) struct universe *universe; struct option_state *options; struct option_cache *oc;{ int hashix; pair bptr; pair *hash = options -> universes [universe -> index]; if (oc -> refcnt == 0) abort (); /* Compute the hash. */ hashix = compute_option_hash (oc -> option -> code); /* If there's no hash table, make one. */ if (!hash) { hash = (pair *)dmalloc (OPTION_HASH_SIZE * sizeof *hash, MDL); if (!hash) { log_error ("no memory to store %s.%s", universe -> name, oc -> option -> name); return; } memset (hash, 0, OPTION_HASH_SIZE * sizeof *hash); options -> universes [universe -> index] = (VOIDPTR)hash; } else { /* Try to find an existing option matching the new one. */ for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) { if (((struct option_cache *) (bptr -> car)) -> option -> code == oc -> option -> code) break; } /* If we find one, dereference it and put the new one in its place. */ if (bptr) { option_cache_dereference ((struct option_cache **)&bptr -> car, MDL); option_cache_reference ((struct option_cache **)&bptr -> car, oc, MDL); return; } } /* Otherwise, just put the new one at the head of the list. */ bptr = new_pair (MDL); if (!bptr) { log_error ("No memory for option_cache reference."); return; } bptr -> cdr = hash [hashix]; bptr -> car = 0; option_cache_reference ((struct option_cache **)&bptr -> car, oc, MDL); hash [hashix] = bptr;}void delete_option (universe, options, code) struct universe *universe; struct option_state *options; int code;{ if (universe -> delete_func) (*universe -> delete_func) (universe, options, code); else log_error ("can't delete options from %s space.", universe -> name);}void delete_hashed_option (universe, options, code) struct universe *universe; struct option_state *options; int code;{ int hashix; pair bptr, prev = (pair)0; pair *hash = options -> universes [universe -> index]; /* There may not be any options in this space. */ if (!hash) return; /* Try to find an existing option matching the new one. */ hashix = compute_option_hash (code); for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) { if (((struct option_cache *)(bptr -> car)) -> option -> code == code) break; prev = bptr; } /* If we found one, wipe it out... */ if (bptr) { if (prev) prev -> cdr = bptr -> cdr; else hash [hashix] = bptr -> cdr; option_cache_dereference ((struct option_cache **)(&bptr -> car), MDL); free_pair (bptr, MDL); }}extern struct option_cache *free_option_caches; /* XXX */int option_cache_dereference (ptr, file, line) struct option_cache **ptr; const char *file; int line;{ if (!ptr || !*ptr) { log_error ("Null pointer in option_cache_dereference: %s(%d)", file, line);#if defined (POINTER_DEBUG) abort ();#else return 0;#endif } (*ptr) -> refcnt--; rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC); if (!(*ptr) -> refcnt) { if ((*ptr) -> data.buffer) data_string_forget (&(*ptr) -> data, file, line); if ((*ptr) -> expression) expression_dereference (&(*ptr) -> expression, file, line); if ((*ptr) -> next) option_cache_dereference (&((*ptr) -> next), file, line); /* Put it back on the free list... */ (*ptr) -> expression = (struct expression *)free_option_caches; free_option_caches = *ptr; dmalloc_reuse (free_option_caches, (char *)0, 0, 0); } if ((*ptr) -> refcnt < 0) { log_error ("%s(%d): negative refcnt!", file, line);#if defined (DEBUG_RC_HISTORY) dump_rc_history (*ptr);#endif#if defined (POINTER_DEBUG) abort ();#else *ptr = (struct option_cache *)0; return 0;#endif } *ptr = (struct option_cache *)0; return 1;}int hashed_option_state_dereference (universe, state, file, line) struct universe *universe; struct option_state *state; const char *file; int line;{ pair *heads; pair cp, next; int i; /* Get the pointer to the array of hash table bucket heads. */ heads = (pair *)(state -> universes [universe -> index]); if (!heads) return 0; /* For each non-null head, loop through all the buckets dereferencing the attached option cache structures and freeing the buckets. */ for (i = 0; i < OPTION_HASH_SIZE; i++) { for (cp = heads [i]; cp; cp = next) { next = cp -> cdr; option_cache_dereference ((struct option_cache **)&cp -> car, file, line); free_pair (cp, file, line); } } dfree (heads, file, line); state -> universes [universe -> index] = (void *)0; return 1;}int store_option (result, universe, packet, lease, client_state, in_options, cfg_options, scope, oc) 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 binding_scope **scope; struct option_cache *oc;{ struct data_string d1, d2; memset (&d1, 0, sizeof d1); memset (&d2, 0, sizeof d2); if (evaluate_option_cache (&d2, packet, lease, client_state, in_options, cfg_options, scope, oc, MDL)) { if (!buffer_allocate (&d1.buffer, (result -> len + universe -> length_size + universe -> tag_size + d2.len), MDL)) { data_string_forget (result, MDL); data_string_forget (&d2, MDL); return 0; } d1.data = &d1.buffer -> data [0]; if (result -> len) memcpy (d1.buffer -> data, result -> data, result -> len); d1.len = result -> len; (*universe -> store_tag) (&d1.buffer -> data [d1.len], oc -> option -> code); d1.len += universe -> tag_size; (*universe -> store_length) (&d1.buffer -> data [d1.len], d2.len); d1.len += universe -> length_size; memcpy (&d1.buffer -> data [d1.len], d2.data, d2.len); d1.len += d2.len; data_string_forget (&d2, MDL); data_string_forget (result, MDL); data_string_copy (result, &d1, MDL); data_string_forget (&d1, MDL); return 1; } return 0;} int option_space_encapsulate (result, packet, lease, client_state, in_options, cfg_options, scope, name) struct data_string *result; struct packet *packet; struct lease *lease; struct client_state *client_state; struct option_state *in_options; struct option_state *cfg_options; struct binding_scope **scope; struct data_string *name;{ struct universe *u; u = (struct universe *)0; universe_hash_lookup (&u, universe_hash, (const char *)name -> data, name -> len, MDL); if (!u) return 0; if (u -> encapsulate) return (*u -> encapsulate) (result, packet, lease, client_state, in_options, cfg_options, scope, u); log_error ("encapsulation requested for %s with no support.", name -> data); return 0;}int hashed_option_space_encapsulate (result, packet, lease, client_state, in_options, cfg_options, scope, universe) struct data_string *result; struct packet *packet; struct lease *lease; struct client_state *client_state; struct option_state *in_options; struct option_state *cfg_options; struct binding_scope **scope; struct universe *universe;{ pair p, *hash; int status; int i; if (universe -> index >= cfg_options -> universe_count) return 0; hash = cfg_options -> universes [universe -> index]; if (!hash) return 0; status = 0; for (i = 0; i < OPTION_HASH_SIZE; i++) { for (p = hash [i]; p; p = p -> cdr) { if (store_option (result, universe, packet, lease, client_state, in_options, cfg_options, scope, (struct option_cache *)p -> car)) status = 1; } } return status;}int nwip_option_space_encapsulate (result, packet, lease, client_state, in_options, cfg_options, scope, universe) struct data_string *result; struct packet *packet; struct lease *lease; struct client_state *client_state; struct option_state *in_options; struct option_state *cfg_options; struct binding_scope **scope; struct universe *universe;{ pair ocp; int status; int i; static struct option_cache *no_nwip; struct data_string ds; struct option_chain_head *head; if (universe -> index >= cfg_options -> universe_count) return 0; head = ((struct option_chain_head *) cfg_options -> universes [fqdn_universe.index]); if (!head) return 0; status = 0; for (ocp = head -> first; ocp; ocp = ocp -> cdr) { struct option_cache *oc = (struct option_cache *)(ocp -> car); if (store_option (result, universe, packet, lease, client_state, in_options, cfg_options, scope, (struct option_cache *)ocp -> car)) status = 1; } /* If there's no data, the nwip suboption is supposed to contain a suboption saying there's no data. */ if (!status) { if (!no_nwip) { static unsigned char nni [] = { 1, 0 }; memset (&ds, 0, sizeof ds); ds.data = nni; ds.len = 2; if (option_cache_allocate (&no_nwip, MDL)) data_string_copy (&no_nwip -> data, &ds, MDL); no_nwip -> option = nwip_universe.options [1]; } if (no_nwip) { if (store_option (result, universe, packet, lease, client_state, in_options, cfg_options, scope, no_nwip)) status = 1; } } else { memset (&ds, 0, sizeof ds); /* If we have nwip options, the first one has to be the nwip-exists-in-option-area option. */ if (!buffer_allocate (&ds.buffer, result -> len + 2, MDL)) { data_string_forget (result, MDL); return 0; } ds.data = &ds.buffer -> data [0]; ds.buffer -> data [0] = 2; ds.buffer -> data [1] = 0; memcpy (&ds.buffer -> data [2], result -> data, result -> len); data_string_forget (result, MDL); data_string_copy (result, &ds, MDL); data_string_forget (&ds, MDL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -