[BACK]Return to class.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / mpl / dhcp / dist / server

Annotation of src/external/mpl/dhcp/dist/server/class.c, Revision 1.3

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

CVSweb <webmaster@jp.NetBSD.org>