Annotation of embedaddon/dhcp/server/class.c, revision 1.1.1.1
1.1 misho 1: /* class.c
2:
3: Handling for client classes. */
4:
5: /*
6: * Copyright (c) 2004,2007,2009 by Internet Systems Consortium, Inc. ("ISC")
7: * Copyright (c) 1998-2003 by Internet Software Consortium
8: *
9: * Permission to use, copy, modify, and distribute this software for any
10: * purpose with or without fee is hereby granted, provided that the above
11: * copyright notice and this permission notice appear in all copies.
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: * This software has been written for Internet Systems Consortium
28: * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29: * To learn more about Internet Systems Consortium, see
30: * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
31: * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32: * ``http://www.nominum.com''.
33: */
34:
35: #include "dhcpd.h"
36:
37: struct collection default_collection = {
38: (struct collection *)0,
39: "default",
40: (struct class *)0,
41: };
42:
43: struct collection *collections = &default_collection;
44: struct executable_statement *default_classification_rules;
45:
46: int have_billing_classes;
47:
48: /* Build the default classification rule tree. */
49:
50: void classification_setup ()
51: {
52: /* eval ... */
53: default_classification_rules = (struct executable_statement *)0;
54: if (!executable_statement_allocate (&default_classification_rules,
55: MDL))
56: log_fatal ("Can't allocate check of default collection");
57: default_classification_rules -> op = eval_statement;
58:
59: /* check-collection "default" */
60: if (!expression_allocate (&default_classification_rules -> data.eval,
61: MDL))
62: log_fatal ("Can't allocate default check expression");
63: default_classification_rules -> data.eval -> op = expr_check;
64: default_classification_rules -> data.eval -> data.check =
65: &default_collection;
66: }
67:
68: void classify_client (packet)
69: struct packet *packet;
70: {
71: execute_statements ((struct binding_value **)0, packet,
72: (struct lease *)0, (struct client_state *)0,
73: packet -> options, (struct option_state *)0,
74: &global_scope, default_classification_rules);
75: }
76:
77: int check_collection (packet, lease, collection)
78: struct packet *packet;
79: struct lease *lease;
80: struct collection *collection;
81: {
82: struct class *class, *nc;
83: struct data_string data;
84: int matched = 0;
85: int status;
86: int ignorep;
87:
88: for (class = collection -> classes; class; class = class -> nic) {
89: #if defined (DEBUG_CLASS_MATCHING)
90: log_info ("checking against class %s...", class -> name);
91: #endif
92: memset (&data, 0, sizeof data);
93:
94: /* If there is a "match if" expression, check it. If
95: we get a match, and there's no subclass expression,
96: it's a match. If we get a match and there is a subclass
97: expression, then we check the submatch. If it's not a
98: match, that's final - we don't check the submatch. */
99:
100: if (class -> expr) {
101: status = (evaluate_boolean_expression_result
102: (&ignorep, packet, lease,
103: (struct client_state *)0,
104: packet -> options, (struct option_state *)0,
105: lease ? &lease -> scope : &global_scope,
106: class -> expr));
107: if (status) {
108: if (!class -> submatch) {
109: matched = 1;
110: #if defined (DEBUG_CLASS_MATCHING)
111: log_info ("matches class.");
112: #endif
113: classify (packet, class);
114: continue;
115: }
116: } else
117: continue;
118: }
119:
120: /* Check to see if the client matches an existing subclass.
121: If it doesn't, and this is a spawning class, spawn a new
122: subclass and put the client in it. */
123: if (class -> submatch) {
124: status = (evaluate_data_expression
125: (&data, packet, lease,
126: (struct client_state *)0,
127: packet -> options, (struct option_state *)0,
128: lease ? &lease -> scope : &global_scope,
129: class -> submatch, MDL));
130: if (status && data.len) {
131: nc = (struct class *)0;
132: if (class_hash_lookup (&nc, class -> hash,
133: (const char *)data.data,
134: data.len, MDL)) {
135: #if defined (DEBUG_CLASS_MATCHING)
136: log_info ("matches subclass %s.",
137: print_hex_1 (data.len,
138: data.data, 60));
139: #endif
140: data_string_forget (&data, MDL);
141: classify (packet, nc);
142: matched = 1;
143: class_dereference (&nc, MDL);
144: continue;
145: }
146: if (!class -> spawning) {
147: data_string_forget (&data, MDL);
148: continue;
149: }
150: /* XXX Write out the spawned class? */
151: #if defined (DEBUG_CLASS_MATCHING)
152: log_info ("spawning subclass %s.",
153: print_hex_1 (data.len, data.data, 60));
154: #endif
155: status = class_allocate (&nc, MDL);
156: group_reference (&nc -> group,
157: class -> group, MDL);
158: class_reference (&nc -> superclass,
159: class, MDL);
160: nc -> lease_limit = class -> lease_limit;
161: nc -> dirty = 1;
162: if (nc -> lease_limit) {
163: nc -> billed_leases =
164: (dmalloc
165: (nc -> lease_limit *
166: sizeof (struct lease *),
167: MDL));
168: if (!nc -> billed_leases) {
169: log_error ("no memory for%s",
170: " billing");
171: data_string_forget
172: (&nc -> hash_string,
173: MDL);
174: class_dereference (&nc, MDL);
175: data_string_forget (&data,
176: MDL);
177: continue;
178: }
179: memset (nc -> billed_leases, 0,
180: (nc -> lease_limit *
181: sizeof nc -> billed_leases));
182: }
183: data_string_copy (&nc -> hash_string, &data,
184: MDL);
185: data_string_forget (&data, MDL);
186: if (!class -> hash)
187: class_new_hash(&class->hash,
188: SCLASS_HASH_SIZE, MDL);
189: class_hash_add (class -> hash,
190: (const char *)
191: nc -> hash_string.data,
192: nc -> hash_string.len,
193: nc, MDL);
194: classify (packet, nc);
195: class_dereference (&nc, MDL);
196: }
197: }
198: }
199: return matched;
200: }
201:
202: void classify (packet, class)
203: struct packet *packet;
204: struct class *class;
205: {
206: if (packet -> class_count < PACKET_MAX_CLASSES)
207: class_reference (&packet -> classes [packet -> class_count++],
208: class, MDL);
209: else
210: log_error ("too many classes match %s",
211: print_hw_addr (packet -> raw -> htype,
212: packet -> raw -> hlen,
213: packet -> raw -> chaddr));
214: }
215:
216:
217: isc_result_t unlink_class(struct class **class) {
218: struct collection *lp;
219: struct class *cp, *pp;
220:
221: for (lp = collections; lp; lp = lp -> next) {
222: for (pp = 0, cp = lp -> classes; cp; pp = cp, cp = cp -> nic)
223: if (cp == *class) {
224: if (pp == 0) {
225: lp->classes = cp->nic;
226: } else {
227: pp->nic = cp->nic;
228: }
229: cp->nic = 0;
230: class_dereference(class, MDL);
231:
232: return ISC_R_SUCCESS;
233: }
234: }
235: return ISC_R_NOTFOUND;
236: }
237:
238:
239: isc_result_t find_class (struct class **class, const char *name,
240: const char *file, int line)
241: {
242: struct collection *lp;
243: struct class *cp;
244:
245: for (lp = collections; lp; lp = lp -> next) {
246: for (cp = lp -> classes; cp; cp = cp -> nic)
247: if (cp -> name && !strcmp (name, cp -> name)) {
248: return class_reference (class, cp, file, line);
249: }
250: }
251: return ISC_R_NOTFOUND;
252: }
253:
254: int unbill_class (lease, class)
255: struct lease *lease;
256: struct class *class;
257: {
258: int i;
259:
260: for (i = 0; i < class -> lease_limit; i++)
261: if (class -> billed_leases [i] == lease)
262: break;
263: if (i == class -> lease_limit) {
264: log_error ("lease %s unbilled with no billing arrangement.",
265: piaddr (lease -> ip_addr));
266: return 0;
267: }
268: class_dereference (&lease -> billing_class, MDL);
269: lease_dereference (&class -> billed_leases [i], MDL);
270: class -> leases_consumed--;
271: return 1;
272: }
273:
274: int bill_class (lease, class)
275: struct lease *lease;
276: struct class *class;
277: {
278: int i;
279:
280: if (lease -> billing_class) {
281: log_error ("lease billed with existing billing arrangement.");
282: unbill_class (lease, lease -> billing_class);
283: }
284:
285: if (class -> leases_consumed == class -> lease_limit)
286: return 0;
287:
288: for (i = 0; i < class -> lease_limit; i++)
289: if (!class -> billed_leases [i])
290: break;
291:
292: if (i == class -> lease_limit) {
293: log_error ("class billing consumption disagrees with leases.");
294: return 0;
295: }
296:
297: lease_reference (&class -> billed_leases [i], lease, MDL);
298: class_reference (&lease -> billing_class, class, MDL);
299: class -> leases_consumed++;
300: return 1;
301: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>