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>