ISC DHCP  4.4.1
A reference DHCPv4 and DHCPv6 implementation
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
class.c
Go to the documentation of this file.
1 /* class.c
2 
3  Handling for client classes. */
4 
5 /*
6  * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1998-2003 by Internet Software Consortium
8  *
9  * This Source Code Form is subject to the terms of the Mozilla Public
10  * License, v. 2.0. If a copy of the MPL was not distributed with this
11  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  *
21  * Internet Systems Consortium, Inc.
22  * 950 Charter Street
23  * Redwood City, CA 94063
24  * <info@isc.org>
25  * https://www.isc.org/
26  *
27  */
28 
29 #include "dhcpd.h"
30 
32 
34 
35 /* Build the default classification rule tree. */
36 
38 {
39  /* eval ... */
40  default_classification_rules = (struct executable_statement *)0;
41  if (!executable_statement_allocate (&default_classification_rules,
42  MDL))
43  log_fatal ("Can't allocate check of default collection");
44  default_classification_rules -> op = eval_statement;
45 
46  /* check-collection "default" */
47  if (!expression_allocate (&default_classification_rules -> data.eval,
48  MDL))
49  log_fatal ("Can't allocate default check expression");
50  default_classification_rules -> data.eval -> op = expr_check;
51  default_classification_rules -> data.eval -> data.check =
53 }
54 
56  struct packet *packet;
57 {
58  execute_statements (NULL, packet, NULL, NULL, packet->options, NULL,
59  &global_scope, default_classification_rules, NULL);
60 }
61 
63  struct packet *packet;
64  struct lease *lease;
65  struct collection *collection;
66 {
67  struct class *class, *nc;
68  struct data_string data;
69  int matched = 0;
70  int status;
71  int ignorep;
72  int classfound;
73 
74  for (class = collection -> classes; class; class = class -> nic) {
75 #if defined (DEBUG_CLASS_MATCHING)
76  log_info ("checking against class %s...", class -> name);
77 #endif
78  memset (&data, 0, sizeof data);
79 
80  /* If there is a "match if" expression, check it. If
81  we get a match, and there's no subclass expression,
82  it's a match. If we get a match and there is a subclass
83  expression, then we check the submatch. If it's not a
84  match, that's final - we don't check the submatch. */
85 
86  if (class -> expr) {
88  (&ignorep, packet, lease,
89  (struct client_state *)0,
90  packet -> options, (struct option_state *)0,
91  lease ? &lease -> scope : &global_scope,
92  class -> expr));
93  if (status) {
94  if (!class -> submatch) {
95  matched = 1;
96 #if defined (DEBUG_CLASS_MATCHING)
97  log_info ("matches class.");
98 #endif
99  classify (packet, class);
100  continue;
101  }
102  } else
103  continue;
104  }
105 
106  /* Check to see if the client matches an existing subclass.
107  If it doesn't, and this is a spawning class, spawn a new
108  subclass and put the client in it. */
109  if (class -> submatch) {
110  status = (evaluate_data_expression
111  (&data, packet, lease,
112  (struct client_state *)0,
113  packet -> options, (struct option_state *)0,
114  lease ? &lease -> scope : &global_scope,
115  class -> submatch, MDL));
116  if (status && data.len) {
117  nc = (struct class *)0;
118  classfound = class_hash_lookup (&nc, class -> hash,
119  (const char *)data.data, data.len, MDL);
120 
121 #ifdef LDAP_CONFIGURATION
122  if (!classfound && find_subclass_in_ldap (class, &nc, &data))
123  classfound = 1;
124 #endif
125 
126  if (classfound) {
127 #if defined (DEBUG_CLASS_MATCHING)
128  log_info ("matches subclass %s.",
129  print_hex_1 (data.len,
130  data.data, 60));
131 #endif
132  data_string_forget (&data, MDL);
133  classify (packet, nc);
134  matched = 1;
135  class_dereference (&nc, MDL);
136  continue;
137  }
138  if (!class -> spawning) {
139  data_string_forget (&data, MDL);
140  continue;
141  }
142  /* XXX Write out the spawned class? */
143 #if defined (DEBUG_CLASS_MATCHING)
144  log_info ("spawning subclass %s.",
145  print_hex_1 (data.len, data.data, 60));
146 #endif
147  status = class_allocate (&nc, MDL);
148  group_reference (&nc -> group,
149  class -> group, MDL);
150  class_reference (&nc -> superclass,
151  class, MDL);
152  nc -> lease_limit = class -> lease_limit;
153  nc -> dirty = 1;
154  if (nc -> lease_limit) {
155  nc -> billed_leases =
156  (dmalloc
157  (nc -> lease_limit *
158  sizeof (struct lease *),
159  MDL));
160  if (!nc -> billed_leases) {
161  log_error ("no memory for%s",
162  " billing");
164  (&nc -> hash_string,
165  MDL);
166  class_dereference (&nc, MDL);
167  data_string_forget (&data,
168  MDL);
169  continue;
170  }
171  memset (nc -> billed_leases, 0,
172  (nc -> lease_limit *
173  sizeof (struct lease *)));
174  }
175  data_string_copy (&nc -> hash_string, &data,
176  MDL);
177  data_string_forget (&data, MDL);
178  if (!class -> hash)
179  class_new_hash(&class->hash,
181  class_hash_add (class -> hash,
182  (const char *)
183  nc -> hash_string.data,
184  nc -> hash_string.len,
185  nc, MDL);
186  classify (packet, nc);
187  class_dereference (&nc, MDL);
188  }
189  }
190  }
191  return matched;
192 }
193 
194 void classify (packet, class)
195  struct packet *packet;
196  struct class *class;
197 {
198  if (packet -> class_count < PACKET_MAX_CLASSES)
199  class_reference (&packet -> classes [packet -> class_count++],
200  class, MDL);
201  else
202  log_error ("too many classes match %s",
203  print_hw_addr (packet -> raw -> htype,
204  packet -> raw -> hlen,
205  packet -> raw -> chaddr));
206 }
207 
208 
209 isc_result_t unlink_class(struct class **class) {
210  struct collection *lp;
211  struct class *cp, *pp;
212 
213  for (lp = collections; lp; lp = lp -> next) {
214  for (pp = 0, cp = lp -> classes; cp; pp = cp, cp = cp -> nic)
215  if (cp == *class) {
216  if (pp == 0) {
217  lp->classes = cp->nic;
218  } else {
219  pp->nic = cp->nic;
220  }
221  cp->nic = 0;
222  class_dereference(class, MDL);
223 
224  return ISC_R_SUCCESS;
225  }
226  }
227  return ISC_R_NOTFOUND;
228 }
229 
230 
231 isc_result_t find_class (struct class **class, const char *name,
232  const char *file, int line)
233 {
234  struct collection *lp;
235  struct class *cp;
236 
237  for (lp = collections; lp; lp = lp -> next) {
238  for (cp = lp -> classes; cp; cp = cp -> nic)
239  if (cp -> name && !strcmp (name, cp -> name)) {
240  return class_reference (class, cp, file, line);
241  }
242  }
243  return ISC_R_NOTFOUND;
244 }
245 
246 /* Removes the billing class from a lease
247  *
248  * Note that because classes can be created and removed dynamically, it is
249  * possible that the class to which a lease was billed has since been deleted.
250  * To cover the case where the lease is the last reference to a deleted class
251  * we remove the lease reference from the class first, then the class from the
252  * lease. To protect ourselves from the reverse situation, where the class is
253  * the last reference to the lease (unlikely), we create a guard reference to
254  * the lease, then remove it at the end.
255  */
257  struct lease *lease;
258 {
259  int i;
260  struct class* class = lease->billing_class;
261  struct lease* refholder = NULL;
262 
263  /* if there's no billing to remove, nothing to do */
264  if (class == NULL) {
265  return;
266  }
267 
268  /* Find the lease in the list of the class's billed leases */
269  for (i = 0; i < class->lease_limit; i++) {
270  if (class->billed_leases[i] == lease)
271  break;
272  }
273 
274  /* Create guard reference, so class cannot be last reference to lease */
275  lease_reference(&refholder, lease, MDL);
276 
277  /* If the class doesn't have the lease, then something is broken
278  * programmatically. We'll log it but skip the lease dereference. */
279  if (i == class->lease_limit) {
280  log_error ("lease %s unbilled with no billing arrangement.",
281  piaddr(lease->ip_addr));
282  } else {
283  /* Remove the lease from the class */
284  lease_dereference(&class->billed_leases[i], MDL);
285  class->leases_consumed--;
286  }
287 
288  /* Remove the class from the lease */
289  class_dereference(&lease->billing_class, MDL);
290 
291  /* Ditch our guard reference */
292  lease_dereference(&refholder, MDL);
293 }
294 
295 int bill_class (lease, class)
296  struct lease *lease;
297  struct class *class;
298 {
299  int i;
300 
301  if (lease -> billing_class) {
302  log_error ("lease billed with existing billing arrangement.");
303  unbill_class (lease);
304  }
305 
306  if (class -> leases_consumed == class -> lease_limit)
307  return 0;
308 
309  for (i = 0; i < class -> lease_limit; i++)
310  if (!class -> billed_leases [i])
311  break;
312 
313  if (i == class -> lease_limit) {
314  log_error ("class billing consumption disagrees with leases.");
315  return 0;
316  }
317 
318  lease_reference (&class -> billed_leases [i], lease, MDL);
319  class_reference (&lease -> billing_class, class, MDL);
320  class -> leases_consumed++;
321  return 1;
322 }
int executable_statement_allocate(struct executable_statement **ptr, const char *file, int line)
Definition: alloc.c:958
struct class * nic
Definition: dhcpd.h:1090
void unbill_class(struct lease *lease)
Definition: dhclient.c:1532
const char int line
Definition: dhcpd.h:3782
struct binding_scope * global_scope
Definition: tree.c:38
Definition: dhcpd.h:560
unsigned len
Definition: tree.h:79
const char * piaddr(const struct iaddr addr)
Definition: inet.c:579
struct executable_statement * default_classification_rules
Definition: class.c:31
struct class * superclass
Definition: dhcpd.h:1091
int expression_allocate(struct expression **cptr, const char *file, int line)
Definition: alloc.c:426
int execute_statements(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct executable_statement *statements, struct on_star *on_star)
Definition: execute.c:35
isc_result_t unlink_class(struct class **class)
Definition: class.c:209
#define MDL
Definition: omapip.h:567
#define print_hex_1(len, data, limit)
Definition: dhcpd.h:2622
class_hash_t * hash
Definition: dhcpd.h:1104
enum executable_statement::statement_op op
int group_reference(struct group **ptr, struct group *bp, const char *file, int line)
Definition: alloc.c:177
return ISC_R_SUCCESS
Definition: parse.c:1341
void data_string_forget(struct data_string *data, const char *file, int line)
Definition: alloc.c:1339
struct class * billing_class
Definition: dhcpd.h:579
struct data_string hash_string
Definition: dhcpd.h:1105
#define SCLASS_HASH_SIZE
Definition: dhcpd.h:203
int log_error(const char *,...) __attribute__((__format__(__printf__
log_fatal("no memory for uname information.")
char * name
Definition: dhcpd.h:1092
int evaluate_boolean_expression_result(int *ignorep, 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 expression *expr)
Definition: tree.c:2780
void classify(struct packet *packet, struct class *class)
Definition: dhclient.c:1526
struct expression * expr
Definition: dhcpd.h:1108
Definition: dhcpd.h:405
struct expression * submatch
Definition: dhcpd.h:1112
int lease_limit
Definition: dhcpd.h:1095
int int log_info(const char *,...) __attribute__((__format__(__printf__
int evaluate_data_expression(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 expression *expr, const char *file, int line)
Definition: tree.c:1126
struct class * classes
Definition: dhcpd.h:1078
void * dmalloc(size_t, const char *, int)
Definition: alloc.c:57
union executable_statement::@7 data
int check_collection(struct packet *packet, struct lease *lease, struct collection *collection)
Definition: dhclient.c:1518
struct lease ** billed_leases
Definition: dhcpd.h:1097
int have_billing_classes
Definition: class.c:33
Definition: dhcpd.h:948
isc_result_t find_class(struct class **c, const char *s, const char *file, int line)
Definition: dhclient.c:1512
return ISC_R_NOTFOUND
Definition: parse.c:1336
struct collection * collections
Definition: parse.c:34
void classification_setup(void)
Definition: class.c:37
struct collection default_collection
Definition: parse.c:33
const char * file
Definition: dhcpd.h:3782
int bill_class(struct lease *, struct class *)
Definition: class.c:295
Definition: dhcpd.h:1088
const unsigned char * data
Definition: tree.h:78
void data_string_copy(struct data_string *dest, const struct data_string *src, const char *file, int line)
Definition: alloc.c:1323
int dirty
Definition: dhcpd.h:1101
void classify_client(struct packet *)
Definition: class.c:55
#define PACKET_MAX_CLASSES
Definition: dhcpd.h:452
int spawning
Definition: dhcpd.h:1113