17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*d04ccbb3Scarlsonj * Common Development and Distribution License (the "License").
6*d04ccbb3Scarlsonj * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*d04ccbb3Scarlsonj * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <stdio.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <unistd.h>
297c478bd9Sstevel@tonic-gate #include <sys/socket.h>
307c478bd9Sstevel@tonic-gate #include <netinet/in.h>
317c478bd9Sstevel@tonic-gate #include <net/if.h>
327c478bd9Sstevel@tonic-gate #include <netinet/dhcp.h>
337c478bd9Sstevel@tonic-gate #include <sys/types.h>
347c478bd9Sstevel@tonic-gate #include <sys/stat.h>
357c478bd9Sstevel@tonic-gate #include <time.h>
367c478bd9Sstevel@tonic-gate #include <string.h> /* memcpy */
377c478bd9Sstevel@tonic-gate #include <fcntl.h>
387c478bd9Sstevel@tonic-gate #include <limits.h>
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate #include "dhcp_hostconf.h"
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate static void relativize_time(DHCP_OPT *, time_t, time_t);
43*d04ccbb3Scarlsonj static void relativize_v6(uint32_t *, time_t, time_t);
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate /*
467c478bd9Sstevel@tonic-gate * ifname_to_hostconf(): converts an interface name into a hostconf file for
477c478bd9Sstevel@tonic-gate * that interface
487c478bd9Sstevel@tonic-gate *
497c478bd9Sstevel@tonic-gate * input: const char *: the interface name
50*d04ccbb3Scarlsonj * boolean_t: B_TRUE if using DHCPv6
517c478bd9Sstevel@tonic-gate * output: char *: the hostconf filename
527c478bd9Sstevel@tonic-gate * note: uses an internal static buffer (not threadsafe)
537c478bd9Sstevel@tonic-gate */
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate char *
ifname_to_hostconf(const char * ifname,boolean_t isv6)56*d04ccbb3Scarlsonj ifname_to_hostconf(const char *ifname, boolean_t isv6)
577c478bd9Sstevel@tonic-gate {
58*d04ccbb3Scarlsonj static char filename[sizeof (DHCP_HOSTCONF_TMPL6) + LIFNAMSIZ];
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate (void) snprintf(filename, sizeof (filename), "%s%s%s",
61*d04ccbb3Scarlsonj DHCP_HOSTCONF_PREFIX, ifname,
62*d04ccbb3Scarlsonj isv6 ? DHCP_HOSTCONF_SUFFIX6 : DHCP_HOSTCONF_SUFFIX);
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate return (filename);
657c478bd9Sstevel@tonic-gate }
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate /*
687c478bd9Sstevel@tonic-gate * remove_hostconf(): removes an interface.dhc file
697c478bd9Sstevel@tonic-gate *
707c478bd9Sstevel@tonic-gate * input: const char *: the interface name
71*d04ccbb3Scarlsonj * boolean_t: B_TRUE if using DHCPv6
727c478bd9Sstevel@tonic-gate * output: int: 0 if the file is removed, -1 if it can't be removed
737c478bd9Sstevel@tonic-gate * (errno is set)
747c478bd9Sstevel@tonic-gate */
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate int
remove_hostconf(const char * ifname,boolean_t isv6)77*d04ccbb3Scarlsonj remove_hostconf(const char *ifname, boolean_t isv6)
787c478bd9Sstevel@tonic-gate {
79*d04ccbb3Scarlsonj return (unlink(ifname_to_hostconf(ifname, isv6)));
807c478bd9Sstevel@tonic-gate }
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate /*
837c478bd9Sstevel@tonic-gate * read_hostconf(): reads the contents of an <if>.dhc file into a PKT_LIST
847c478bd9Sstevel@tonic-gate *
857c478bd9Sstevel@tonic-gate * input: const char *: the interface name
867c478bd9Sstevel@tonic-gate * PKT_LIST **: a pointer to a PKT_LIST * to store the info in
877c478bd9Sstevel@tonic-gate * uint_t: the length of the list of PKT_LISTs
88*d04ccbb3Scarlsonj * boolean_t: B_TRUE if using DHCPv6
89*d04ccbb3Scarlsonj * output: int: >0 if the file is read and loaded into the PKT_LIST *
907c478bd9Sstevel@tonic-gate * successfully, -1 otherwise (errno is set)
917c478bd9Sstevel@tonic-gate * note: the PKT and PKT_LISTs are dynamically allocated here
927c478bd9Sstevel@tonic-gate */
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate int
read_hostconf(const char * ifname,PKT_LIST ** plpp,uint_t plplen,boolean_t isv6)95*d04ccbb3Scarlsonj read_hostconf(const char *ifname, PKT_LIST **plpp, uint_t plplen,
96*d04ccbb3Scarlsonj boolean_t isv6)
977c478bd9Sstevel@tonic-gate {
987c478bd9Sstevel@tonic-gate PKT_LIST *plp = NULL;
997c478bd9Sstevel@tonic-gate PKT *pkt = NULL;
1007c478bd9Sstevel@tonic-gate int fd;
1017c478bd9Sstevel@tonic-gate time_t orig_time, current_time = time(NULL);
1027c478bd9Sstevel@tonic-gate uint32_t lease;
1037c478bd9Sstevel@tonic-gate uint32_t magic;
1047c478bd9Sstevel@tonic-gate int pcnt = 0;
1057c478bd9Sstevel@tonic-gate int retval;
1067c478bd9Sstevel@tonic-gate
107*d04ccbb3Scarlsonj fd = open(ifname_to_hostconf(ifname, isv6), O_RDONLY);
1087c478bd9Sstevel@tonic-gate if (fd == -1)
1097c478bd9Sstevel@tonic-gate return (-1);
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate if (read(fd, &magic, sizeof (magic)) != sizeof (magic))
1127c478bd9Sstevel@tonic-gate goto failure;
1137c478bd9Sstevel@tonic-gate
114*d04ccbb3Scarlsonj if (magic != (isv6 ? DHCP_HOSTCONF_MAGIC6 : DHCP_HOSTCONF_MAGIC))
1157c478bd9Sstevel@tonic-gate goto failure;
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate if (read(fd, &orig_time, sizeof (orig_time)) != sizeof (orig_time))
1187c478bd9Sstevel@tonic-gate goto failure;
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate /*
121*d04ccbb3Scarlsonj * read the packet back in from disk, and for v4, run it through
122*d04ccbb3Scarlsonj * dhcp_options_scan(). note that we use calloc() because
123*d04ccbb3Scarlsonj * dhcp_options_scan() relies on the structure being zeroed.
1247c478bd9Sstevel@tonic-gate */
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate for (pcnt = 0; pcnt < plplen; pcnt++) {
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate plp = NULL;
1297c478bd9Sstevel@tonic-gate pkt = NULL;
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate if ((plp = calloc(1, sizeof (PKT_LIST))) == NULL)
1327c478bd9Sstevel@tonic-gate goto failure;
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate retval = read(fd, &plp->len, sizeof (plp->len));
1357c478bd9Sstevel@tonic-gate if (retval == 0 && pcnt != 0) {
1367c478bd9Sstevel@tonic-gate /*
1377c478bd9Sstevel@tonic-gate * Reached end of file on a boundary, but after
1387c478bd9Sstevel@tonic-gate * we've read at least one packet, so we consider
1397c478bd9Sstevel@tonic-gate * this successful, allowing us to use files from
1407c478bd9Sstevel@tonic-gate * older versions of the agent happily.
1417c478bd9Sstevel@tonic-gate */
1427c478bd9Sstevel@tonic-gate free(plp);
1437c478bd9Sstevel@tonic-gate break;
1447c478bd9Sstevel@tonic-gate } else if (retval != sizeof (plp->len))
1457c478bd9Sstevel@tonic-gate goto failure;
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate if ((pkt = malloc(plp->len)) == NULL)
1487c478bd9Sstevel@tonic-gate goto failure;
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate if (read(fd, pkt, plp->len) != plp->len)
1517c478bd9Sstevel@tonic-gate goto failure;
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate plp->pkt = pkt;
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate plpp[pcnt] = plp;
1567c478bd9Sstevel@tonic-gate
157*d04ccbb3Scarlsonj if (!isv6 && dhcp_options_scan(plp, B_TRUE) != 0)
1587c478bd9Sstevel@tonic-gate goto failure;
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate /*
1617c478bd9Sstevel@tonic-gate * First packet used to validate that we're interested,
1627c478bd9Sstevel@tonic-gate * the rest are presumed to be historical reference and
1637c478bd9Sstevel@tonic-gate * are not relativized
1647c478bd9Sstevel@tonic-gate */
1657c478bd9Sstevel@tonic-gate if (pcnt == 0)
1667c478bd9Sstevel@tonic-gate continue;
1677c478bd9Sstevel@tonic-gate
168*d04ccbb3Scarlsonj if (isv6) {
169*d04ccbb3Scarlsonj dhcpv6_option_t d6o;
170*d04ccbb3Scarlsonj dhcpv6_ia_na_t d6in;
171*d04ccbb3Scarlsonj dhcpv6_iaaddr_t d6ia;
172*d04ccbb3Scarlsonj uchar_t *opts, *optmax, *subomax;
1737c478bd9Sstevel@tonic-gate
174*d04ccbb3Scarlsonj /*
175*d04ccbb3Scarlsonj * Loop over contents of the packet to find the address
176*d04ccbb3Scarlsonj * options.
177*d04ccbb3Scarlsonj */
178*d04ccbb3Scarlsonj opts = (uchar_t *)pkt + sizeof (dhcpv6_message_t);
179*d04ccbb3Scarlsonj optmax = (uchar_t *)pkt + plp->len;
180*d04ccbb3Scarlsonj while (opts + sizeof (d6o) <= optmax) {
181*d04ccbb3Scarlsonj
182*d04ccbb3Scarlsonj /*
183*d04ccbb3Scarlsonj * Extract option header and make sure option
184*d04ccbb3Scarlsonj * is intact.
185*d04ccbb3Scarlsonj */
186*d04ccbb3Scarlsonj (void) memcpy(&d6o, opts, sizeof (d6o));
187*d04ccbb3Scarlsonj d6o.d6o_code = ntohs(d6o.d6o_code);
188*d04ccbb3Scarlsonj d6o.d6o_len = ntohs(d6o.d6o_len);
189*d04ccbb3Scarlsonj subomax = opts + sizeof (d6o) + d6o.d6o_len;
190*d04ccbb3Scarlsonj if (subomax > optmax)
191*d04ccbb3Scarlsonj break;
192*d04ccbb3Scarlsonj
193*d04ccbb3Scarlsonj /*
194*d04ccbb3Scarlsonj * If this isn't an option that contains
195*d04ccbb3Scarlsonj * address or prefix leases, then skip over it.
196*d04ccbb3Scarlsonj */
197*d04ccbb3Scarlsonj if (d6o.d6o_code != DHCPV6_OPT_IA_NA &&
198*d04ccbb3Scarlsonj d6o.d6o_code != DHCPV6_OPT_IA_TA &&
199*d04ccbb3Scarlsonj d6o.d6o_code != DHCPV6_OPT_IA_PD) {
200*d04ccbb3Scarlsonj opts = subomax;
201*d04ccbb3Scarlsonj continue;
202*d04ccbb3Scarlsonj }
203*d04ccbb3Scarlsonj
204*d04ccbb3Scarlsonj /*
205*d04ccbb3Scarlsonj * Handle the option first.
206*d04ccbb3Scarlsonj */
207*d04ccbb3Scarlsonj if (d6o.d6o_code == DHCPV6_OPT_IA_TA) {
208*d04ccbb3Scarlsonj /* no timers in this structure */
209*d04ccbb3Scarlsonj opts += sizeof (dhcpv6_ia_ta_t);
210*d04ccbb3Scarlsonj } else {
211*d04ccbb3Scarlsonj /* both na and pd */
212*d04ccbb3Scarlsonj if (opts + sizeof (d6in) > subomax) {
213*d04ccbb3Scarlsonj opts = subomax;
214*d04ccbb3Scarlsonj continue;
215*d04ccbb3Scarlsonj }
216*d04ccbb3Scarlsonj (void) memcpy(&d6in, opts,
217*d04ccbb3Scarlsonj sizeof (d6in));
218*d04ccbb3Scarlsonj relativize_v6(&d6in.d6in_t1, orig_time,
219*d04ccbb3Scarlsonj current_time);
220*d04ccbb3Scarlsonj relativize_v6(&d6in.d6in_t2, orig_time,
221*d04ccbb3Scarlsonj current_time);
222*d04ccbb3Scarlsonj (void) memcpy(opts, &d6in,
223*d04ccbb3Scarlsonj sizeof (d6in));
224*d04ccbb3Scarlsonj opts += sizeof (d6in);
225*d04ccbb3Scarlsonj }
226*d04ccbb3Scarlsonj
227*d04ccbb3Scarlsonj /*
228*d04ccbb3Scarlsonj * Now handle each suboption (address) inside.
229*d04ccbb3Scarlsonj */
230*d04ccbb3Scarlsonj while (opts + sizeof (d6o) <= subomax) {
231*d04ccbb3Scarlsonj /*
232*d04ccbb3Scarlsonj * Verify the suboption header first.
233*d04ccbb3Scarlsonj */
234*d04ccbb3Scarlsonj (void) memcpy(&d6o, opts,
235*d04ccbb3Scarlsonj sizeof (d6o));
236*d04ccbb3Scarlsonj d6o.d6o_code = ntohs(d6o.d6o_code);
237*d04ccbb3Scarlsonj d6o.d6o_len = ntohs(d6o.d6o_len);
238*d04ccbb3Scarlsonj if (opts + sizeof (d6o) + d6o.d6o_len >
239*d04ccbb3Scarlsonj subomax)
240*d04ccbb3Scarlsonj break;
241*d04ccbb3Scarlsonj if (d6o.d6o_code != DHCPV6_OPT_IAADDR) {
242*d04ccbb3Scarlsonj opts += sizeof (d6o) +
243*d04ccbb3Scarlsonj d6o.d6o_len;
244*d04ccbb3Scarlsonj continue;
245*d04ccbb3Scarlsonj }
246*d04ccbb3Scarlsonj
247*d04ccbb3Scarlsonj /*
248*d04ccbb3Scarlsonj * Now process the contents.
249*d04ccbb3Scarlsonj */
250*d04ccbb3Scarlsonj if (opts + sizeof (d6ia) > subomax)
251*d04ccbb3Scarlsonj break;
252*d04ccbb3Scarlsonj (void) memcpy(&d6ia, opts,
253*d04ccbb3Scarlsonj sizeof (d6ia));
254*d04ccbb3Scarlsonj relativize_v6(&d6ia.d6ia_preflife,
255*d04ccbb3Scarlsonj orig_time, current_time);
256*d04ccbb3Scarlsonj relativize_v6(&d6ia.d6ia_vallife,
257*d04ccbb3Scarlsonj orig_time, current_time);
258*d04ccbb3Scarlsonj (void) memcpy(opts, &d6ia,
259*d04ccbb3Scarlsonj sizeof (d6ia));
260*d04ccbb3Scarlsonj opts += sizeof (d6o) + d6o.d6o_len;
261*d04ccbb3Scarlsonj }
262*d04ccbb3Scarlsonj opts = subomax;
263*d04ccbb3Scarlsonj }
264*d04ccbb3Scarlsonj } else {
2657c478bd9Sstevel@tonic-gate
266*d04ccbb3Scarlsonj /*
267*d04ccbb3Scarlsonj * make sure the IPv4 DHCP lease is still valid.
268*d04ccbb3Scarlsonj */
2697c478bd9Sstevel@tonic-gate
270*d04ccbb3Scarlsonj if (plp->opts[CD_LEASE_TIME] != NULL &&
271*d04ccbb3Scarlsonj plp->opts[CD_LEASE_TIME]->len ==
272*d04ccbb3Scarlsonj sizeof (lease_t)) {
273*d04ccbb3Scarlsonj
274*d04ccbb3Scarlsonj (void) memcpy(&lease,
275*d04ccbb3Scarlsonj plp->opts[CD_LEASE_TIME]->value,
276*d04ccbb3Scarlsonj sizeof (lease_t));
277*d04ccbb3Scarlsonj
278*d04ccbb3Scarlsonj lease = ntohl(lease);
279*d04ccbb3Scarlsonj if ((lease != DHCP_PERM) &&
280*d04ccbb3Scarlsonj (orig_time + lease) <= current_time)
281*d04ccbb3Scarlsonj goto failure;
282*d04ccbb3Scarlsonj }
283*d04ccbb3Scarlsonj
284*d04ccbb3Scarlsonj relativize_time(plp->opts[CD_T1_TIME], orig_time,
285*d04ccbb3Scarlsonj current_time);
286*d04ccbb3Scarlsonj relativize_time(plp->opts[CD_T2_TIME], orig_time,
287*d04ccbb3Scarlsonj current_time);
288*d04ccbb3Scarlsonj relativize_time(plp->opts[CD_LEASE_TIME], orig_time,
289*d04ccbb3Scarlsonj current_time);
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate (void) close(fd);
2947c478bd9Sstevel@tonic-gate return (pcnt);
2957c478bd9Sstevel@tonic-gate
2967c478bd9Sstevel@tonic-gate failure:
2977c478bd9Sstevel@tonic-gate free(pkt);
2987c478bd9Sstevel@tonic-gate free(plp);
2997c478bd9Sstevel@tonic-gate while (pcnt-- > 0) {
3007c478bd9Sstevel@tonic-gate free(plpp[pcnt]->pkt);
3017c478bd9Sstevel@tonic-gate free(plpp[pcnt]);
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate (void) close(fd);
3047c478bd9Sstevel@tonic-gate return (-1);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /*
3087c478bd9Sstevel@tonic-gate * write_hostconf(): writes the contents of a PKT_LIST into an <if>.dhc file
3097c478bd9Sstevel@tonic-gate *
3107c478bd9Sstevel@tonic-gate * input: const char *: the interface name
3117c478bd9Sstevel@tonic-gate * PKT_LIST **: a list of pointers to PKT_LIST to write
312*d04ccbb3Scarlsonj * uint_t: length of the list of PKT_LIST pointers
3137c478bd9Sstevel@tonic-gate * time_t: a starting time to treat the relative lease times
3147c478bd9Sstevel@tonic-gate * in the first packet as relative to
315*d04ccbb3Scarlsonj * boolean_t: B_TRUE if using DHCPv6
3167c478bd9Sstevel@tonic-gate * output: int: 0 if the file is written successfully, -1 otherwise
3177c478bd9Sstevel@tonic-gate * (errno is set)
3187c478bd9Sstevel@tonic-gate */
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate int
write_hostconf(const char * ifname,PKT_LIST * pl[],uint_t pllen,time_t relative_to,boolean_t isv6)3217c478bd9Sstevel@tonic-gate write_hostconf(
3227c478bd9Sstevel@tonic-gate const char *ifname,
3237c478bd9Sstevel@tonic-gate PKT_LIST *pl[],
3247c478bd9Sstevel@tonic-gate uint_t pllen,
325*d04ccbb3Scarlsonj time_t relative_to,
326*d04ccbb3Scarlsonj boolean_t isv6)
3277c478bd9Sstevel@tonic-gate {
3287c478bd9Sstevel@tonic-gate int fd;
3297c478bd9Sstevel@tonic-gate struct iovec iov[IOV_MAX];
3307c478bd9Sstevel@tonic-gate int retval;
331*d04ccbb3Scarlsonj uint32_t magic;
3327c478bd9Sstevel@tonic-gate ssize_t explen = 0; /* Expected length of write */
3337c478bd9Sstevel@tonic-gate int i, iovlen = 0;
3347c478bd9Sstevel@tonic-gate
335*d04ccbb3Scarlsonj fd = open(ifname_to_hostconf(ifname, isv6), O_WRONLY|O_CREAT|O_TRUNC,
336*d04ccbb3Scarlsonj 0600);
3377c478bd9Sstevel@tonic-gate if (fd == -1)
3387c478bd9Sstevel@tonic-gate return (-1);
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate /*
3417c478bd9Sstevel@tonic-gate * first write our magic number, then the relative time of the
3427c478bd9Sstevel@tonic-gate * leases, then for each packet we write the length of the packet
3437c478bd9Sstevel@tonic-gate * followed by the packet. we will then use the relative time in
3447c478bd9Sstevel@tonic-gate * read_hostconf() to recalculate the lease times for the first packet.
3457c478bd9Sstevel@tonic-gate */
3467c478bd9Sstevel@tonic-gate
347*d04ccbb3Scarlsonj magic = isv6 ? DHCP_HOSTCONF_MAGIC6 : DHCP_HOSTCONF_MAGIC;
3487c478bd9Sstevel@tonic-gate iov[iovlen].iov_base = (caddr_t)&magic;
3497c478bd9Sstevel@tonic-gate explen += iov[iovlen++].iov_len = sizeof (magic);
3507c478bd9Sstevel@tonic-gate iov[iovlen].iov_base = (caddr_t)&relative_to;
3517c478bd9Sstevel@tonic-gate explen += iov[iovlen++].iov_len = sizeof (relative_to);
3527c478bd9Sstevel@tonic-gate for (i = 0; i < pllen && iovlen < (IOV_MAX - 1); i++) {
3537c478bd9Sstevel@tonic-gate iov[iovlen].iov_base = (caddr_t)&pl[i]->len;
3547c478bd9Sstevel@tonic-gate explen += iov[iovlen++].iov_len = sizeof (pl[i]->len);
3557c478bd9Sstevel@tonic-gate iov[iovlen].iov_base = (caddr_t)pl[i]->pkt;
3567c478bd9Sstevel@tonic-gate explen += iov[iovlen++].iov_len = pl[i]->len;
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate retval = writev(fd, iov, iovlen);
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gate (void) close(fd);
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate if (retval != explen)
3647c478bd9Sstevel@tonic-gate return (-1);
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate return (0);
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate /*
3707c478bd9Sstevel@tonic-gate * relativize_time(): re-relativizes a time in a DHCP option
3717c478bd9Sstevel@tonic-gate *
3727c478bd9Sstevel@tonic-gate * input: DHCP_OPT *: the DHCP option parameter to convert
3737c478bd9Sstevel@tonic-gate * time_t: the time the leases in the packet are currently relative to
3747c478bd9Sstevel@tonic-gate * time_t: the current time which leases will become relative to
3757c478bd9Sstevel@tonic-gate * output: void
3767c478bd9Sstevel@tonic-gate */
3777c478bd9Sstevel@tonic-gate
3787c478bd9Sstevel@tonic-gate static void
relativize_time(DHCP_OPT * option,time_t orig_time,time_t current_time)3797c478bd9Sstevel@tonic-gate relativize_time(DHCP_OPT *option, time_t orig_time, time_t current_time)
3807c478bd9Sstevel@tonic-gate {
3817c478bd9Sstevel@tonic-gate uint32_t pkt_time;
3827c478bd9Sstevel@tonic-gate time_t time_diff = current_time - orig_time;
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate if (option == NULL || option->len != sizeof (lease_t))
3857c478bd9Sstevel@tonic-gate return;
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate (void) memcpy(&pkt_time, option->value, option->len);
3887c478bd9Sstevel@tonic-gate if (ntohl(pkt_time) != DHCP_PERM)
3897c478bd9Sstevel@tonic-gate pkt_time = htonl(ntohl(pkt_time) - time_diff);
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate (void) memcpy(option->value, &pkt_time, option->len);
3927c478bd9Sstevel@tonic-gate }
393*d04ccbb3Scarlsonj
394*d04ccbb3Scarlsonj /*
395*d04ccbb3Scarlsonj * relativize_v6(): re-relativizes a time in a DHCPv6 option
396*d04ccbb3Scarlsonj *
397*d04ccbb3Scarlsonj * input: uint32_t *: the time value to convert
398*d04ccbb3Scarlsonj * time_t: the time the leases in the packet are currently relative to
399*d04ccbb3Scarlsonj * time_t: the current time which leases will become relative to
400*d04ccbb3Scarlsonj * output: void
401*d04ccbb3Scarlsonj */
402*d04ccbb3Scarlsonj
403*d04ccbb3Scarlsonj static void
relativize_v6(uint32_t * val,time_t orig_time,time_t current_time)404*d04ccbb3Scarlsonj relativize_v6(uint32_t *val, time_t orig_time, time_t current_time)
405*d04ccbb3Scarlsonj {
406*d04ccbb3Scarlsonj uint32_t hval;
407*d04ccbb3Scarlsonj time_t time_diff = current_time - orig_time;
408*d04ccbb3Scarlsonj
409*d04ccbb3Scarlsonj hval = ntohl(*val);
410*d04ccbb3Scarlsonj if (hval != DHCPV6_INFTIME) {
411*d04ccbb3Scarlsonj if (hval < time_diff)
412*d04ccbb3Scarlsonj *val = 0;
413*d04ccbb3Scarlsonj else
414*d04ccbb3Scarlsonj *val = htonl(hval - time_diff);
415*d04ccbb3Scarlsonj }
416*d04ccbb3Scarlsonj }
417