xref: /onnv-gate/usr/src/lib/libdhcpagent/common/dhcp_hostconf.c (revision 3431:9f2d277dcffa)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*3431Scarlsonj  * Common Development and Distribution License (the "License").
6*3431Scarlsonj  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*3431Scarlsonj  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <stdio.h>
290Sstevel@tonic-gate #include <stdlib.h>
300Sstevel@tonic-gate #include <unistd.h>
310Sstevel@tonic-gate #include <sys/socket.h>
320Sstevel@tonic-gate #include <netinet/in.h>
330Sstevel@tonic-gate #include <net/if.h>
340Sstevel@tonic-gate #include <netinet/dhcp.h>
350Sstevel@tonic-gate #include <sys/types.h>
360Sstevel@tonic-gate #include <sys/stat.h>
370Sstevel@tonic-gate #include <time.h>
380Sstevel@tonic-gate #include <string.h>			/* memcpy */
390Sstevel@tonic-gate #include <fcntl.h>
400Sstevel@tonic-gate #include <limits.h>
410Sstevel@tonic-gate 
420Sstevel@tonic-gate #include "dhcp_hostconf.h"
430Sstevel@tonic-gate 
440Sstevel@tonic-gate static void		relativize_time(DHCP_OPT *, time_t, time_t);
45*3431Scarlsonj static void		relativize_v6(uint32_t *, time_t, time_t);
460Sstevel@tonic-gate 
470Sstevel@tonic-gate /*
480Sstevel@tonic-gate  * ifname_to_hostconf(): converts an interface name into a hostconf file for
490Sstevel@tonic-gate  *			 that interface
500Sstevel@tonic-gate  *
510Sstevel@tonic-gate  *   input: const char *: the interface name
52*3431Scarlsonj  *	    boolean_t: B_TRUE if using DHCPv6
530Sstevel@tonic-gate  *  output: char *: the hostconf filename
540Sstevel@tonic-gate  *    note: uses an internal static buffer (not threadsafe)
550Sstevel@tonic-gate  */
560Sstevel@tonic-gate 
570Sstevel@tonic-gate char *
ifname_to_hostconf(const char * ifname,boolean_t isv6)58*3431Scarlsonj ifname_to_hostconf(const char *ifname, boolean_t isv6)
590Sstevel@tonic-gate {
60*3431Scarlsonj 	static char filename[sizeof (DHCP_HOSTCONF_TMPL6) + LIFNAMSIZ];
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	(void) snprintf(filename, sizeof (filename), "%s%s%s",
63*3431Scarlsonj 	    DHCP_HOSTCONF_PREFIX, ifname,
64*3431Scarlsonj 	    isv6 ? DHCP_HOSTCONF_SUFFIX6 : DHCP_HOSTCONF_SUFFIX);
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 	return (filename);
670Sstevel@tonic-gate }
680Sstevel@tonic-gate 
690Sstevel@tonic-gate /*
700Sstevel@tonic-gate  * remove_hostconf(): removes an interface.dhc file
710Sstevel@tonic-gate  *
720Sstevel@tonic-gate  *   input: const char *: the interface name
73*3431Scarlsonj  *	    boolean_t: B_TRUE if using DHCPv6
740Sstevel@tonic-gate  *  output: int: 0 if the file is removed, -1 if it can't be removed
750Sstevel@tonic-gate  *          (errno is set)
760Sstevel@tonic-gate  */
770Sstevel@tonic-gate 
780Sstevel@tonic-gate int
remove_hostconf(const char * ifname,boolean_t isv6)79*3431Scarlsonj remove_hostconf(const char *ifname, boolean_t isv6)
800Sstevel@tonic-gate {
81*3431Scarlsonj 	return (unlink(ifname_to_hostconf(ifname, isv6)));
820Sstevel@tonic-gate }
830Sstevel@tonic-gate 
840Sstevel@tonic-gate /*
850Sstevel@tonic-gate  * read_hostconf(): reads the contents of an <if>.dhc file into a PKT_LIST
860Sstevel@tonic-gate  *
870Sstevel@tonic-gate  *   input: const char *: the interface name
880Sstevel@tonic-gate  *	    PKT_LIST **: a pointer to a PKT_LIST * to store the info in
890Sstevel@tonic-gate  *	    uint_t: the length of the list of PKT_LISTs
90*3431Scarlsonj  *	    boolean_t: B_TRUE if using DHCPv6
91*3431Scarlsonj  *  output: int: >0 if the file is read and loaded into the PKT_LIST *
920Sstevel@tonic-gate  *	    successfully, -1 otherwise (errno is set)
930Sstevel@tonic-gate  *    note: the PKT and PKT_LISTs are dynamically allocated here
940Sstevel@tonic-gate  */
950Sstevel@tonic-gate 
960Sstevel@tonic-gate int
read_hostconf(const char * ifname,PKT_LIST ** plpp,uint_t plplen,boolean_t isv6)97*3431Scarlsonj read_hostconf(const char *ifname, PKT_LIST **plpp, uint_t plplen,
98*3431Scarlsonj     boolean_t isv6)
990Sstevel@tonic-gate {
1000Sstevel@tonic-gate 	PKT_LIST	*plp = NULL;
1010Sstevel@tonic-gate 	PKT		*pkt = NULL;
1020Sstevel@tonic-gate 	int		fd;
1030Sstevel@tonic-gate 	time_t		orig_time, current_time = time(NULL);
1040Sstevel@tonic-gate 	uint32_t	lease;
1050Sstevel@tonic-gate 	uint32_t	magic;
1060Sstevel@tonic-gate 	int		pcnt = 0;
1070Sstevel@tonic-gate 	int		retval;
1080Sstevel@tonic-gate 
109*3431Scarlsonj 	fd = open(ifname_to_hostconf(ifname, isv6), O_RDONLY);
1100Sstevel@tonic-gate 	if (fd == -1)
1110Sstevel@tonic-gate 		return (-1);
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 	if (read(fd, &magic, sizeof (magic)) != sizeof (magic))
1140Sstevel@tonic-gate 		goto failure;
1150Sstevel@tonic-gate 
116*3431Scarlsonj 	if (magic != (isv6 ? DHCP_HOSTCONF_MAGIC6 : DHCP_HOSTCONF_MAGIC))
1170Sstevel@tonic-gate 		goto failure;
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	if (read(fd, &orig_time, sizeof (orig_time)) != sizeof (orig_time))
1200Sstevel@tonic-gate 		goto failure;
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate 	/*
123*3431Scarlsonj 	 * read the packet back in from disk, and for v4, run it through
124*3431Scarlsonj 	 * dhcp_options_scan(). note that we use calloc() because
125*3431Scarlsonj 	 * dhcp_options_scan() relies on the structure being zeroed.
1260Sstevel@tonic-gate 	 */
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 	for (pcnt = 0; pcnt < plplen; pcnt++) {
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 		plp = NULL;
1310Sstevel@tonic-gate 		pkt = NULL;
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 		if ((plp = calloc(1, sizeof (PKT_LIST))) == NULL)
1340Sstevel@tonic-gate 			goto failure;
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 		retval = read(fd, &plp->len, sizeof (plp->len));
1370Sstevel@tonic-gate 		if (retval == 0 && pcnt != 0) {
1380Sstevel@tonic-gate 			/*
1390Sstevel@tonic-gate 			 * Reached end of file on a boundary, but after
1400Sstevel@tonic-gate 			 * we've read at least one packet, so we consider
1410Sstevel@tonic-gate 			 * this successful, allowing us to use files from
1420Sstevel@tonic-gate 			 * older versions of the agent happily.
1430Sstevel@tonic-gate 			 */
1440Sstevel@tonic-gate 			free(plp);
1450Sstevel@tonic-gate 			break;
1460Sstevel@tonic-gate 		} else if (retval != sizeof (plp->len))
1470Sstevel@tonic-gate 			goto failure;
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 		if ((pkt = malloc(plp->len)) == NULL)
1500Sstevel@tonic-gate 			goto failure;
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 		if (read(fd, pkt, plp->len) != plp->len)
1530Sstevel@tonic-gate 			goto failure;
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 		plp->pkt = pkt;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 		plpp[pcnt] = plp;
1580Sstevel@tonic-gate 
159*3431Scarlsonj 		if (!isv6 && dhcp_options_scan(plp, B_TRUE) != 0)
1600Sstevel@tonic-gate 			goto failure;
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 		/*
1630Sstevel@tonic-gate 		 * First packet used to validate that we're interested,
1640Sstevel@tonic-gate 		 * the rest are presumed to be historical reference and
1650Sstevel@tonic-gate 		 * are not relativized
1660Sstevel@tonic-gate 		 */
1670Sstevel@tonic-gate 		if (pcnt == 0)
1680Sstevel@tonic-gate 			continue;
1690Sstevel@tonic-gate 
170*3431Scarlsonj 		if (isv6) {
171*3431Scarlsonj 			dhcpv6_option_t	d6o;
172*3431Scarlsonj 			dhcpv6_ia_na_t	d6in;
173*3431Scarlsonj 			dhcpv6_iaaddr_t	d6ia;
174*3431Scarlsonj 			uchar_t		*opts, *optmax, *subomax;
175*3431Scarlsonj 
176*3431Scarlsonj 			/*
177*3431Scarlsonj 			 * Loop over contents of the packet to find the address
178*3431Scarlsonj 			 * options.
179*3431Scarlsonj 			 */
180*3431Scarlsonj 			opts = (uchar_t *)pkt + sizeof (dhcpv6_message_t);
181*3431Scarlsonj 			optmax = (uchar_t *)pkt + plp->len;
182*3431Scarlsonj 			while (opts + sizeof (d6o) <= optmax) {
183*3431Scarlsonj 
184*3431Scarlsonj 				/*
185*3431Scarlsonj 				 * Extract option header and make sure option
186*3431Scarlsonj 				 * is intact.
187*3431Scarlsonj 				 */
188*3431Scarlsonj 				(void) memcpy(&d6o, opts, sizeof (d6o));
189*3431Scarlsonj 				d6o.d6o_code = ntohs(d6o.d6o_code);
190*3431Scarlsonj 				d6o.d6o_len = ntohs(d6o.d6o_len);
191*3431Scarlsonj 				subomax = opts + sizeof (d6o) + d6o.d6o_len;
192*3431Scarlsonj 				if (subomax > optmax)
193*3431Scarlsonj 					break;
1940Sstevel@tonic-gate 
195*3431Scarlsonj 				/*
196*3431Scarlsonj 				 * If this isn't an option that contains
197*3431Scarlsonj 				 * address or prefix leases, then skip over it.
198*3431Scarlsonj 				 */
199*3431Scarlsonj 				if (d6o.d6o_code != DHCPV6_OPT_IA_NA &&
200*3431Scarlsonj 				    d6o.d6o_code != DHCPV6_OPT_IA_TA &&
201*3431Scarlsonj 				    d6o.d6o_code != DHCPV6_OPT_IA_PD) {
202*3431Scarlsonj 					opts = subomax;
203*3431Scarlsonj 					continue;
204*3431Scarlsonj 				}
2050Sstevel@tonic-gate 
206*3431Scarlsonj 				/*
207*3431Scarlsonj 				 * Handle the option first.
208*3431Scarlsonj 				 */
209*3431Scarlsonj 				if (d6o.d6o_code == DHCPV6_OPT_IA_TA) {
210*3431Scarlsonj 					/* no timers in this structure */
211*3431Scarlsonj 					opts += sizeof (dhcpv6_ia_ta_t);
212*3431Scarlsonj 				} else {
213*3431Scarlsonj 					/* both na and pd */
214*3431Scarlsonj 					if (opts + sizeof (d6in) > subomax) {
215*3431Scarlsonj 						opts = subomax;
216*3431Scarlsonj 						continue;
217*3431Scarlsonj 					}
218*3431Scarlsonj 					(void) memcpy(&d6in, opts,
219*3431Scarlsonj 					    sizeof (d6in));
220*3431Scarlsonj 					relativize_v6(&d6in.d6in_t1, orig_time,
221*3431Scarlsonj 					    current_time);
222*3431Scarlsonj 					relativize_v6(&d6in.d6in_t2, orig_time,
223*3431Scarlsonj 					    current_time);
224*3431Scarlsonj 					(void) memcpy(opts, &d6in,
225*3431Scarlsonj 					    sizeof (d6in));
226*3431Scarlsonj 					opts += sizeof (d6in);
227*3431Scarlsonj 				}
2280Sstevel@tonic-gate 
229*3431Scarlsonj 				/*
230*3431Scarlsonj 				 * Now handle each suboption (address) inside.
231*3431Scarlsonj 				 */
232*3431Scarlsonj 				while (opts + sizeof (d6o) <= subomax) {
233*3431Scarlsonj 					/*
234*3431Scarlsonj 					 * Verify the suboption header first.
235*3431Scarlsonj 					 */
236*3431Scarlsonj 					(void) memcpy(&d6o, opts,
237*3431Scarlsonj 					    sizeof (d6o));
238*3431Scarlsonj 					d6o.d6o_code = ntohs(d6o.d6o_code);
239*3431Scarlsonj 					d6o.d6o_len = ntohs(d6o.d6o_len);
240*3431Scarlsonj 					if (opts + sizeof (d6o) + d6o.d6o_len >
241*3431Scarlsonj 					    subomax)
242*3431Scarlsonj 						break;
243*3431Scarlsonj 					if (d6o.d6o_code != DHCPV6_OPT_IAADDR) {
244*3431Scarlsonj 						opts += sizeof (d6o) +
245*3431Scarlsonj 						    d6o.d6o_len;
246*3431Scarlsonj 						continue;
247*3431Scarlsonj 					}
248*3431Scarlsonj 
249*3431Scarlsonj 					/*
250*3431Scarlsonj 					 * Now process the contents.
251*3431Scarlsonj 					 */
252*3431Scarlsonj 					if (opts + sizeof (d6ia) > subomax)
253*3431Scarlsonj 						break;
254*3431Scarlsonj 					(void) memcpy(&d6ia, opts,
255*3431Scarlsonj 					    sizeof (d6ia));
256*3431Scarlsonj 					relativize_v6(&d6ia.d6ia_preflife,
257*3431Scarlsonj 					    orig_time, current_time);
258*3431Scarlsonj 					relativize_v6(&d6ia.d6ia_vallife,
259*3431Scarlsonj 					    orig_time, current_time);
260*3431Scarlsonj 					(void) memcpy(opts, &d6ia,
261*3431Scarlsonj 					    sizeof (d6ia));
262*3431Scarlsonj 					opts += sizeof (d6o) + d6o.d6o_len;
263*3431Scarlsonj 				}
264*3431Scarlsonj 				opts = subomax;
265*3431Scarlsonj 			}
266*3431Scarlsonj 		} else {
267*3431Scarlsonj 
268*3431Scarlsonj 			/*
269*3431Scarlsonj 			 * make sure the IPv4 DHCP lease is still valid.
270*3431Scarlsonj 			 */
271*3431Scarlsonj 
272*3431Scarlsonj 			if (plp->opts[CD_LEASE_TIME] != NULL &&
273*3431Scarlsonj 			    plp->opts[CD_LEASE_TIME]->len ==
274*3431Scarlsonj 			    sizeof (lease_t)) {
275*3431Scarlsonj 
276*3431Scarlsonj 				(void) memcpy(&lease,
277*3431Scarlsonj 				    plp->opts[CD_LEASE_TIME]->value,
278*3431Scarlsonj 				    sizeof (lease_t));
279*3431Scarlsonj 
280*3431Scarlsonj 				lease = ntohl(lease);
281*3431Scarlsonj 				if ((lease != DHCP_PERM) &&
282*3431Scarlsonj 				    (orig_time + lease) <= current_time)
283*3431Scarlsonj 					goto failure;
284*3431Scarlsonj 			}
285*3431Scarlsonj 
286*3431Scarlsonj 			relativize_time(plp->opts[CD_T1_TIME], orig_time,
287*3431Scarlsonj 			    current_time);
288*3431Scarlsonj 			relativize_time(plp->opts[CD_T2_TIME], orig_time,
289*3431Scarlsonj 			    current_time);
290*3431Scarlsonj 			relativize_time(plp->opts[CD_LEASE_TIME], orig_time,
291*3431Scarlsonj 			    current_time);
2920Sstevel@tonic-gate 		}
2930Sstevel@tonic-gate 	}
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	(void) close(fd);
2960Sstevel@tonic-gate 	return (pcnt);
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate failure:
2990Sstevel@tonic-gate 	free(pkt);
3000Sstevel@tonic-gate 	free(plp);
3010Sstevel@tonic-gate 	while (pcnt-- > 0) {
3020Sstevel@tonic-gate 		free(plpp[pcnt]->pkt);
3030Sstevel@tonic-gate 		free(plpp[pcnt]);
3040Sstevel@tonic-gate 	}
3050Sstevel@tonic-gate 	(void) close(fd);
3060Sstevel@tonic-gate 	return (-1);
3070Sstevel@tonic-gate }
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate /*
3100Sstevel@tonic-gate  * write_hostconf(): writes the contents of a PKT_LIST into an <if>.dhc file
3110Sstevel@tonic-gate  *
3120Sstevel@tonic-gate  *   input: const char *: the interface name
3130Sstevel@tonic-gate  *	    PKT_LIST **: a list of pointers to PKT_LIST to write
314*3431Scarlsonj  *	    uint_t: length of the list of PKT_LIST pointers
3150Sstevel@tonic-gate  *	    time_t: a starting time to treat the relative lease times
3160Sstevel@tonic-gate  *		    in the first packet as relative to
317*3431Scarlsonj  *	    boolean_t: B_TRUE if using DHCPv6
3180Sstevel@tonic-gate  *  output: int: 0 if the file is written successfully, -1 otherwise
3190Sstevel@tonic-gate  *	    (errno is set)
3200Sstevel@tonic-gate  */
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate int
write_hostconf(const char * ifname,PKT_LIST * pl[],uint_t pllen,time_t relative_to,boolean_t isv6)3230Sstevel@tonic-gate write_hostconf(
3240Sstevel@tonic-gate     const char *ifname,
3250Sstevel@tonic-gate     PKT_LIST *pl[],
3260Sstevel@tonic-gate     uint_t pllen,
327*3431Scarlsonj     time_t relative_to,
328*3431Scarlsonj     boolean_t isv6)
3290Sstevel@tonic-gate {
3300Sstevel@tonic-gate 	int		fd;
3310Sstevel@tonic-gate 	struct iovec	iov[IOV_MAX];
3320Sstevel@tonic-gate 	int		retval;
333*3431Scarlsonj 	uint32_t	magic;
3340Sstevel@tonic-gate 	ssize_t		explen = 0; /* Expected length of write */
3350Sstevel@tonic-gate 	int		i, iovlen = 0;
3360Sstevel@tonic-gate 
337*3431Scarlsonj 	fd = open(ifname_to_hostconf(ifname, isv6), O_WRONLY|O_CREAT|O_TRUNC,
338*3431Scarlsonj 	    0600);
3390Sstevel@tonic-gate 	if (fd == -1)
3400Sstevel@tonic-gate 		return (-1);
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 	/*
3430Sstevel@tonic-gate 	 * first write our magic number, then the relative time of the
3440Sstevel@tonic-gate 	 * leases, then for each packet we write the length of the packet
3450Sstevel@tonic-gate 	 * followed by the packet.  we will then use the relative time in
3460Sstevel@tonic-gate 	 * read_hostconf() to recalculate the lease times for the first packet.
3470Sstevel@tonic-gate 	 */
3480Sstevel@tonic-gate 
349*3431Scarlsonj 	magic = isv6 ? DHCP_HOSTCONF_MAGIC6 : DHCP_HOSTCONF_MAGIC;
3500Sstevel@tonic-gate 	iov[iovlen].iov_base = (caddr_t)&magic;
3510Sstevel@tonic-gate 	explen += iov[iovlen++].iov_len  = sizeof (magic);
3520Sstevel@tonic-gate 	iov[iovlen].iov_base = (caddr_t)&relative_to;
3530Sstevel@tonic-gate 	explen += iov[iovlen++].iov_len  = sizeof (relative_to);
3540Sstevel@tonic-gate 	for (i = 0; i < pllen && iovlen < (IOV_MAX - 1); i++) {
3550Sstevel@tonic-gate 		iov[iovlen].iov_base = (caddr_t)&pl[i]->len;
3560Sstevel@tonic-gate 		explen += iov[iovlen++].iov_len  = sizeof (pl[i]->len);
3570Sstevel@tonic-gate 		iov[iovlen].iov_base = (caddr_t)pl[i]->pkt;
3580Sstevel@tonic-gate 		explen += iov[iovlen++].iov_len  = pl[i]->len;
3590Sstevel@tonic-gate 	}
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	retval = writev(fd, iov, iovlen);
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 	(void) close(fd);
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	if (retval != explen)
3660Sstevel@tonic-gate 		return (-1);
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 	return (0);
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate /*
3720Sstevel@tonic-gate  * relativize_time(): re-relativizes a time in a DHCP option
3730Sstevel@tonic-gate  *
3740Sstevel@tonic-gate  *   input: DHCP_OPT *: the DHCP option parameter to convert
3750Sstevel@tonic-gate  *	    time_t: the time the leases in the packet are currently relative to
3760Sstevel@tonic-gate  *	    time_t: the current time which leases will become relative to
3770Sstevel@tonic-gate  *  output: void
3780Sstevel@tonic-gate  */
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate static void
relativize_time(DHCP_OPT * option,time_t orig_time,time_t current_time)3810Sstevel@tonic-gate relativize_time(DHCP_OPT *option, time_t orig_time, time_t current_time)
3820Sstevel@tonic-gate {
3830Sstevel@tonic-gate 	uint32_t	pkt_time;
3840Sstevel@tonic-gate 	time_t		time_diff = current_time - orig_time;
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 	if (option == NULL || option->len != sizeof (lease_t))
3870Sstevel@tonic-gate 		return;
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 	(void) memcpy(&pkt_time, option->value, option->len);
3900Sstevel@tonic-gate 	if (ntohl(pkt_time) != DHCP_PERM)
3910Sstevel@tonic-gate 		pkt_time = htonl(ntohl(pkt_time) - time_diff);
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 	(void) memcpy(option->value, &pkt_time, option->len);
3940Sstevel@tonic-gate }
395*3431Scarlsonj 
396*3431Scarlsonj /*
397*3431Scarlsonj  * relativize_v6(): re-relativizes a time in a DHCPv6 option
398*3431Scarlsonj  *
399*3431Scarlsonj  *   input: uint32_t *: the time value to convert
400*3431Scarlsonj  *	    time_t: the time the leases in the packet are currently relative to
401*3431Scarlsonj  *	    time_t: the current time which leases will become relative to
402*3431Scarlsonj  *  output: void
403*3431Scarlsonj  */
404*3431Scarlsonj 
405*3431Scarlsonj static void
relativize_v6(uint32_t * val,time_t orig_time,time_t current_time)406*3431Scarlsonj relativize_v6(uint32_t *val, time_t orig_time, time_t current_time)
407*3431Scarlsonj {
408*3431Scarlsonj 	uint32_t	hval;
409*3431Scarlsonj 	time_t		time_diff = current_time - orig_time;
410*3431Scarlsonj 
411*3431Scarlsonj 	hval = ntohl(*val);
412*3431Scarlsonj 	if (hval != DHCPV6_INFTIME) {
413*3431Scarlsonj 		if (hval < time_diff)
414*3431Scarlsonj 			*val = 0;
415*3431Scarlsonj 		else
416*3431Scarlsonj 			*val = htonl(hval - time_diff);
417*3431Scarlsonj 	}
418*3431Scarlsonj }
419