Annotation of embedaddon/dhcp/server/class.c, revision 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>