1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 #pragma ident "%Z%%M% %I% %E% SMI" 23 24 /* 25 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <stdarg.h> 33 #include <sys/types.h> 34 #include <errno.h> 35 #include <assert.h> 36 #include <string.h> 37 #include <sys/syslog.h> 38 #include <sys/socket.h> 39 #include <netinet/in.h> 40 #include <arpa/inet.h> 41 #include <netinet/dhcp.h> 42 #include "hash.h" 43 #include "dhcpd.h" 44 #include "per_dnet.h" 45 46 /* 47 * This file contains the code which creates, manipulates, and frees encode 48 * structures. 49 */ 50 51 /* 52 * Free an individual encode structure, including data. 53 */ 54 void 55 free_encode(ENCODE *ecp) 56 { 57 if (ecp != NULL) { 58 if (ecp->data) 59 free(ecp->data); 60 free(ecp); 61 } 62 } 63 64 /* 65 * Dump an entire encode list, including data. 66 */ 67 void 68 free_encode_list(ENCODE *ecp) 69 { 70 ENCODE *tmp; 71 72 while (ecp != NULL) { 73 tmp = ecp; 74 ecp = ecp->next; 75 free_encode(tmp); 76 } 77 } 78 79 /* 80 * Allocate an ENCODE structure, and fill it in with the passed data. 81 * 82 * Doesn't copy data if copy_flag is not set. 83 * 84 * Returns: ptr for success. Doesn't return if a failure occurs. 85 */ 86 ENCODE * 87 make_encode(uchar_t cat, ushort_t code, uchar_t len, void *data, 88 int copy_flag) 89 { 90 ENCODE *ecp; 91 92 ecp = (ENCODE *)smalloc(sizeof (ENCODE)); 93 94 ecp->category = cat; 95 ecp->code = code; 96 ecp->len = len; 97 98 if (data != NULL && len != 0) { 99 if (copy_flag == ENC_COPY) { 100 ecp->data = (uchar_t *)smalloc(len); 101 (void) memcpy(ecp->data, data, len); 102 } else 103 ecp->data = data; 104 } 105 return (ecp); 106 } 107 108 /* 109 * Find a specific code in the ENCODE list. Doesn't consider class. 110 * 111 * Returns: ptr if successful, NULL otherwise. 112 */ 113 ENCODE * 114 find_encode(ENCODE *eclp, uchar_t cat, ushort_t code) 115 { 116 for (; eclp != NULL; eclp = eclp->next) { 117 if (eclp->category == cat && eclp->code == code) 118 return (eclp); 119 } 120 return (NULL); 121 } 122 123 /* 124 * Duplicate the passed encode structure. 125 */ 126 ENCODE * 127 dup_encode(ENCODE *ecp) 128 { 129 assert(ecp != NULL); 130 return (make_encode(ecp->category, ecp->code, ecp->len, ecp->data, 131 ENC_COPY)); 132 } 133 134 /* 135 * Duplicate an encode list. May be called with NULL as a convenience. 136 */ 137 ENCODE * 138 dup_encode_list(ENCODE *ecp) 139 { 140 ENCODE *pp, *np, *headp; 141 142 if (ecp == NULL) 143 return (NULL); 144 145 /* 146 * Note: pp/np are used as placeholders in parallel list. 147 */ 148 pp = headp = NULL; 149 for (; ecp != NULL; ecp = ecp->next) { 150 np = dup_encode(ecp); 151 if (pp == NULL) { 152 headp = np; 153 np->prev = NULL; 154 } else { 155 pp->next = np; 156 np->prev = pp; 157 } 158 pp = np; 159 } 160 return (headp); 161 } 162 163 /* 164 * Given two ENCODE lists, produce NEW ENCODE list by "OR"ing the first 165 * encode list with the second. Note that the settings in the second encode 166 * list override any identical code settings in the first encode list. 167 * 168 * The primary list is copied if flags argument is ENC_COPY. Class is not 169 * considered. 170 * 171 * Returns a ptr to the merged list for success, NULL ptr otherwise. 172 */ 173 ENCODE * 174 combine_encodes(ENCODE *first_ecp, ENCODE *second_ecp, int flags) 175 { 176 ENCODE *ep; 177 178 if (first_ecp != NULL) { 179 if (flags == ENC_COPY) 180 first_ecp = dup_encode_list(first_ecp); 181 182 for (ep = second_ecp; ep != NULL; ep = ep->next) 183 replace_encode(&first_ecp, ep, ENC_COPY); 184 } else { 185 first_ecp = dup_encode_list(second_ecp); 186 } 187 return (first_ecp); 188 } 189 190 /* 191 * Replace/add the encode matching the code value of the second ENCODE 192 * parameter in the list represented by the first ENCODE parameter. 193 */ 194 void 195 replace_encode(ENCODE **elistpp, ENCODE *rp, int flags) 196 { 197 ENCODE *wp; 198 199 assert(elistpp != NULL && rp != NULL); 200 201 if (flags == ENC_COPY) 202 rp = dup_encode(rp); 203 204 if (*elistpp == NULL) { 205 *elistpp = rp; 206 return; 207 } 208 wp = find_encode(*elistpp, rp->category, rp->code); 209 210 if (wp == NULL) { 211 rp->next = *elistpp; 212 rp->next->prev = rp; 213 *elistpp = rp; 214 rp->prev = NULL; 215 } else { 216 if (wp->prev == NULL) { 217 rp->next = wp->next; 218 *elistpp = rp; 219 rp->prev = NULL; 220 } else { 221 rp->next = wp->next; 222 rp->prev = wp->prev; 223 wp->prev->next = rp; 224 } 225 if (wp->next != NULL) 226 wp->next->prev = rp; 227 free_encode(wp); 228 } 229 } 230 231 /* 232 * Given a MACRO and a class name, return the ENCODE list for 233 * that class name, or null if a ENCODE list by that class doesn't exist. 234 */ 235 ENCODE * 236 vendor_encodes(MACRO *mp, char *class) 237 { 238 VNDLIST **tvpp; 239 int i; 240 241 assert(mp != NULL && class != NULL); 242 243 for (tvpp = mp->list, i = 0; tvpp != NULL && i < mp->classes; i++) { 244 if (strcmp(tvpp[i]->class, class) == 0) 245 return (tvpp[i]->head); 246 } 247 return (NULL); 248 }