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