ISC DHCP  4.4.2b1
A reference DHCPv4 and DHCPv6 implementation
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 ... */
42  MDL))
43  log_fatal ("Can't allocate check of default collection");
45 
46  /* check-collection "default" */
48  MDL))
49  log_fatal ("Can't allocate default check expression");
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,
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  if (!class -> hash)
178  class_new_hash(&class->hash,
180  class_hash_add (class -> hash,
181  (const char *)
182  nc -> hash_string.data,
183  nc -> hash_string.len,
184  nc, MDL);
185  classify (packet, nc);
186  class_dereference (&nc, MDL);
187  }
188 
189  data_string_forget (&data, MDL);
190  }
191  }
192  return matched;
193 }
194 
195 void classify (packet, class)
196  struct packet *packet;
197  struct class *class;
198 {
199  if (packet -> class_count < PACKET_MAX_CLASSES)
200  class_reference (&packet -> classes [packet -> class_count++],
201  class, MDL);
202  else
203  log_error ("too many classes match %s",
204  print_hw_addr (packet -> raw -> htype,
205  packet -> raw -> hlen,
206  packet -> raw -> chaddr));
207 }
208 
209 
210 isc_result_t unlink_class(struct class **class) {
211  struct collection *lp;
212  struct class *cp, *pp;
213 
214  for (lp = collections; lp; lp = lp -> next) {
215  for (pp = 0, cp = lp -> classes; cp; pp = cp, cp = cp -> nic)
216  if (cp == *class) {
217  if (pp == 0) {
218  lp->classes = cp->nic;
219  } else {
220  pp->nic = cp->nic;
221  }
222  cp->nic = 0;
223  class_dereference(class, MDL);
224 
225  return ISC_R_SUCCESS;
226  }
227  }
228  return ISC_R_NOTFOUND;
229 }
230 
231 
232 isc_result_t find_class (struct class **class, const char *name,
233  const char *file, int line)
234 {
235  struct collection *lp;
236  struct class *cp;
237 
238  for (lp = collections; lp; lp = lp -> next) {
239  for (cp = lp -> classes; cp; cp = cp -> nic)
240  if (cp -> name && !strcmp (name, cp -> name)) {
241  return class_reference (class, cp, file, line);
242  }
243  }
244  return ISC_R_NOTFOUND;
245 }
246 
247 /* Removes the billing class from a lease
248  *
249  * Note that because classes can be created and removed dynamically, it is
250  * possible that the class to which a lease was billed has since been deleted.
251  * To cover the case where the lease is the last reference to a deleted class
252  * we remove the lease reference from the class first, then the class from the
253  * lease. To protect ourselves from the reverse situation, where the class is
254  * the last reference to the lease (unlikely), we create a guard reference to
255  * the lease, then remove it at the end.
256  */
258  struct lease *lease;
259 {
260  int i;
261  struct class* class = lease->billing_class;
262  struct lease* refholder = NULL;
263 
264  /* if there's no billing to remove, nothing to do */
265  if (class == NULL) {
266  return;
267  }
268 
269  /* Find the lease in the list of the class's billed leases */
270  for (i = 0; i < class->lease_limit; i++) {
271  if (class->billed_leases[i] == lease)
272  break;
273  }
274 
275  /* Create guard reference, so class cannot be last reference to lease */
276  lease_reference(&refholder, lease, MDL);
277 
278  /* If the class doesn't have the lease, then something is broken
279  * programmatically. We'll log it but skip the lease dereference. */
280  if (i == class->lease_limit) {
281  log_error ("lease %s unbilled with no billing arrangement.",
282  piaddr(lease->ip_addr));
283  } else {
284  /* Remove the lease from the class */
285  lease_dereference(&class->billed_leases[i], MDL);
286  class->leases_consumed--;
287  }
288 
289  /* Remove the class from the lease */
290  class_dereference(&lease->billing_class, MDL);
291 
292  /* Ditch our guard reference */
293  lease_dereference(&refholder, MDL);
294 }
295 
296 int bill_class (lease, class)
297  struct lease *lease;
298  struct class *class;
299 {
300  int i;
301 
302  if (lease -> billing_class) {
303  log_error ("lease billed with existing billing arrangement.");
305  }
306 
307  if (class -> leases_consumed == class -> lease_limit)
308  return 0;
309 
310  for (i = 0; i < class -> lease_limit; i++)
311  if (!class -> billed_leases [i])
312  break;
313 
314  if (i == class -> lease_limit) {
315  log_error ("class billing consumption disagrees with leases.");
316  return 0;
317  }
318 
319  lease_reference (&class -> billed_leases [i], lease, MDL);
320  class_reference (&lease -> billing_class, class, MDL);
321  class -> leases_consumed++;
322  return 1;
323 }
void classification_setup()
Definition: class.c:37
isc_result_t find_class(struct class **class, const char *name, const char *file, int line)
Definition: class.c:232
int bill_class(struct lease *lease, struct class *class)
Definition: class.c:296
int check_collection(struct packet *packet, struct lease *lease, struct collection *collection)
Definition: class.c:62
int have_billing_classes
Definition: class.c:33
struct executable_statement * default_classification_rules
Definition: class.c:31
void classify(struct packet *packet, struct class *class)
Definition: class.c:195
isc_result_t unlink_class(struct class **class)
Definition: class.c:210
void unbill_class(struct lease *lease)
Definition: class.c:257
void classify_client(struct packet *packet)
Definition: class.c:55
int expression_allocate(struct expression **cptr, const char *file, int line)
Definition: alloc.c:426
void data_string_forget(struct data_string *data, const char *file, int line)
Definition: alloc.c:1339
int group_reference(struct group **ptr, struct group *bp, const char *file, int line)
Definition: alloc.c:177
void data_string_copy(struct data_string *dest, const struct data_string *src, const char *file, int line)
Definition: alloc.c:1323
int executable_statement_allocate(struct executable_statement **ptr, const char *file, int line)
Definition: alloc.c:958
struct collection default_collection
Definition: parse.c:33
struct collection * collections
Definition: parse.c:34
char * print_hw_addr(int htype, const int hlen, const unsigned char *data) const
Definition: print.c:171
#define SCLASS_HASH_SIZE
Definition: dhcpd.h:203
#define PACKET_MAX_CLASSES
Definition: dhcpd.h:452
const char int line
Definition: dhcpd.h:3793
const char * file
Definition: dhcpd.h:3793
#define print_hex_1(len, data, limit)
Definition: dhcpd.h:2633
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
const char * piaddr(const struct iaddr addr)
Definition: inet.c:579
#define ISC_R_SUCCESS
@ eval_statement
Definition: keama.h:165
#define MDL
Definition: omapip.h:567
void * dmalloc(size_t, const char *, int)
Definition: alloc.c:57
int log_error(const char *,...) __attribute__((__format__(__printf__
void log_fatal(const char *,...) __attribute__((__format__(__printf__
int int log_info(const char *,...) __attribute__((__format__(__printf__
Definition: dhcpd.h:1098
struct class * nic
Definition: dhcpd.h:1100
struct expression * submatch
Definition: dhcpd.h:1122
struct lease ** billed_leases
Definition: dhcpd.h:1107
struct expression * expr
Definition: dhcpd.h:1118
struct class * superclass
Definition: dhcpd.h:1101
class_hash_t * hash
Definition: dhcpd.h:1114
int spawning
Definition: dhcpd.h:1123
struct data_string hash_string
Definition: dhcpd.h:1115
char * name
Definition: dhcpd.h:1102
int lease_limit
Definition: dhcpd.h:1105
int dirty
Definition: dhcpd.h:1111
struct class * classes
Definition: dhcpd.h:1088
const unsigned char * data
Definition: tree.h:78
unsigned len
Definition: tree.h:79
enum executable_statement::statement_op op
union executable_statement::@7 data
Definition: dhcpd.h:958
Definition: dhcpd.h:560
struct iaddr ip_addr
Definition: dhcpd.h:569
struct class * billing_class
Definition: dhcpd.h:579
Definition: dhcpd.h:405
struct option_state * options
Definition: dhcpd.h:449
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
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 binding_scope * global_scope
Definition: tree.c:38
@ expr_check
Definition: tree.h:134