diff -ruN ../../dhcp-3.0.5.orig/includes/dhcpd.h ./includes/dhcpd.h --- ../../dhcp-3.0.5.orig/includes/dhcpd.h Wed May 17 22:16:59 2006 +++ dhcp-3.0.5/includes/dhcpd.h Tue Jan 22 21:28:24 2008 @@ -551,6 +551,7 @@ permit_class } type; struct class *class; + struct data_string hash_string; }; struct pool { diff -ruN ../../dhcp-3.0.5.orig/server/confpars.c ./server/confpars.c --- ../../dhcp-3.0.5.orig/server/confpars.c Thu Jul 20 18:02:52 2006 +++ dhcp-3.0.5/server/confpars.c Tue Jan 22 21:28:24 2008 @@ -1231,6 +1231,21 @@ } #endif /* defined (FAILOVER_PROTOCOL) */ + +/* Permit_same_class returns 1 if both permit structs contain + * the same class and the same hash_string aka subclass. */ + +int permit_same_class(struct permit *plp, struct permit *prp) +{ + if (plp -> class != prp -> class) + return 0; + if (plp -> hash_string.len == 0 || + plp -> hash_string.len != prp -> hash_string.len) + return 0; + return memcmp(plp -> hash_string.data, + prp -> hash_string.data, prp -> hash_string.len) == 0; +} + /* Permit_list_match returns 1 if every element of the permit list in lhs also appears in rhs. Note that this doesn't by itself mean that the two lists are equal - to check for equality, permit_list_match has to @@ -1250,7 +1265,7 @@ for (prp = rhs; prp; prp = prp -> next) { if (prp -> type == plp -> type && (prp -> type != permit_class || - prp -> class == plp -> class)) { + permit_same_class(prp, plp))) { matched = 1; break; } @@ -1275,6 +1290,7 @@ int declaration = 0; isc_result_t status; struct lease *lpchain = (struct lease *)0, *lp; + struct data_string *dp; pool = (struct pool *)0; status = pool_allocate (&pool, MDL); @@ -1440,10 +1456,39 @@ } permit -> type = permit_class; permit -> class = (struct class *)0; + find_class (&permit -> class, val, MDL); - if (!permit -> class) + if (!permit -> class) { parse_warn (cfile, "no such class: %s", val); + break; + } + + dp = &permit -> hash_string; + + token = peek_token (&val, (unsigned *)0, cfile); + if (token == STRING) { + token = next_token(&val, + &dp -> len, cfile); + dp -> buffer = (struct buffer *)0; + if (!buffer_allocate (&dp -> buffer, + dp -> len + 1, MDL)) { + free_permit(permit, MDL); + continue; + } + dp -> terminated = 1; + dp -> data = &dp -> buffer -> data [0]; + memcpy ((char *)dp -> buffer -> data, + val, dp -> len + 1); + } else if (token == NUMBER_OR_NAME || + token == NUMBER) { + memset (dp, 0, sizeof *dp); + if (!parse_cshl (dp, cfile)) { + free_permit(permit, MDL); + continue; + } + } + break; default: diff -ruN ../../dhcp-3.0.5.orig/server/dhcp.c ./server/dhcp.c --- ../../dhcp-3.0.5.orig/server/dhcp.c Tue Aug 22 19:15:56 2006 +++ dhcp-3.0.5/server/dhcp.c Tue Jan 22 21:28:24 2008 @@ -3807,12 +3807,28 @@ case permit_class: for (i = 0; i < packet -> class_count; i++) { - if (p -> class == packet -> classes [i]) - return 1; - if (packet -> classes [i] && - packet -> classes [i] -> superclass && - (packet -> classes [i] -> superclass == - p -> class)) + int r = 0; + struct class *pc = packet -> classes[i]; + + /* Does packet class or superclass match ? */ + if (!p -> class || !pc) + continue; + if (p -> class == pc) + r = 1; + if (p -> class == pc -> superclass) + r = 1; + + /* Does the subclass match as well ? */ + if (r && p -> hash_string.len) { + + if (p -> hash_string.len != + pc -> hash_string.len || + memcmp(p -> hash_string.data, + pc -> hash_string.data, + pc -> hash_string.len)) + r = 0; + } + if (r) return 1; } break; diff -ruN ../../dhcp-3.0.5.orig/server/salloc.c ./server/salloc.c --- ../../dhcp-3.0.5.orig/server/salloc.c Wed Feb 22 23:43:27 2006 +++ dhcp-3.0.5/server/salloc.c Tue Jan 22 21:28:24 2008 @@ -252,7 +252,10 @@ const char *file; int line; { - if (permit -> type == permit_class) + if (permit -> type == permit_class) { class_dereference (&permit -> class, MDL); + if (permit -> hash_string.buffer) + buffer_dereference(&permit -> hash_string.buffer, MDL); + } dfree (permit, file, line); }