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 #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <stdio.h> 297c478bd9Sstevel@tonic-gate #include <stdlib.h> 307c478bd9Sstevel@tonic-gate #include <unistd.h> 317c478bd9Sstevel@tonic-gate #include <sys/socket.h> 327c478bd9Sstevel@tonic-gate #include <netinet/in.h> 337c478bd9Sstevel@tonic-gate #include <net/if.h> 347c478bd9Sstevel@tonic-gate #include <netinet/dhcp.h> 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 367c478bd9Sstevel@tonic-gate #include <sys/stat.h> 377c478bd9Sstevel@tonic-gate #include <time.h> 387c478bd9Sstevel@tonic-gate #include <string.h> /* memcpy */ 397c478bd9Sstevel@tonic-gate #include <fcntl.h> 407c478bd9Sstevel@tonic-gate #include <limits.h> 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #include "dhcp_hostconf.h" 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate static void relativize_time(DHCP_OPT *, time_t, time_t); 45*d04ccbb3Scarlsonj static void relativize_v6(uint32_t *, time_t, time_t); 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate /* 487c478bd9Sstevel@tonic-gate * ifname_to_hostconf(): converts an interface name into a hostconf file for 497c478bd9Sstevel@tonic-gate * that interface 507c478bd9Sstevel@tonic-gate * 517c478bd9Sstevel@tonic-gate * input: const char *: the interface name 52*d04ccbb3Scarlsonj * boolean_t: B_TRUE if using DHCPv6 537c478bd9Sstevel@tonic-gate * output: char *: the hostconf filename 547c478bd9Sstevel@tonic-gate * note: uses an internal static buffer (not threadsafe) 557c478bd9Sstevel@tonic-gate */ 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate char * 58*d04ccbb3Scarlsonj ifname_to_hostconf(const char *ifname, boolean_t isv6) 597c478bd9Sstevel@tonic-gate { 60*d04ccbb3Scarlsonj static char filename[sizeof (DHCP_HOSTCONF_TMPL6) + LIFNAMSIZ]; 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate (void) snprintf(filename, sizeof (filename), "%s%s%s", 63*d04ccbb3Scarlsonj DHCP_HOSTCONF_PREFIX, ifname, 64*d04ccbb3Scarlsonj isv6 ? DHCP_HOSTCONF_SUFFIX6 : DHCP_HOSTCONF_SUFFIX); 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate return (filename); 677c478bd9Sstevel@tonic-gate } 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate /* 707c478bd9Sstevel@tonic-gate * remove_hostconf(): removes an interface.dhc file 717c478bd9Sstevel@tonic-gate * 727c478bd9Sstevel@tonic-gate * input: const char *: the interface name 73*d04ccbb3Scarlsonj * boolean_t: B_TRUE if using DHCPv6 747c478bd9Sstevel@tonic-gate * output: int: 0 if the file is removed, -1 if it can't be removed 757c478bd9Sstevel@tonic-gate * (errno is set) 767c478bd9Sstevel@tonic-gate */ 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate int 79*d04ccbb3Scarlsonj remove_hostconf(const char *ifname, boolean_t isv6) 807c478bd9Sstevel@tonic-gate { 81*d04ccbb3Scarlsonj return (unlink(ifname_to_hostconf(ifname, isv6))); 827c478bd9Sstevel@tonic-gate } 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* 857c478bd9Sstevel@tonic-gate * read_hostconf(): reads the contents of an <if>.dhc file into a PKT_LIST 867c478bd9Sstevel@tonic-gate * 877c478bd9Sstevel@tonic-gate * input: const char *: the interface name 887c478bd9Sstevel@tonic-gate * PKT_LIST **: a pointer to a PKT_LIST * to store the info in 897c478bd9Sstevel@tonic-gate * uint_t: the length of the list of PKT_LISTs 90*d04ccbb3Scarlsonj * boolean_t: B_TRUE if using DHCPv6 91*d04ccbb3Scarlsonj * output: int: >0 if the file is read and loaded into the PKT_LIST * 927c478bd9Sstevel@tonic-gate * successfully, -1 otherwise (errno is set) 937c478bd9Sstevel@tonic-gate * note: the PKT and PKT_LISTs are dynamically allocated here 947c478bd9Sstevel@tonic-gate */ 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate int 97*d04ccbb3Scarlsonj read_hostconf(const char *ifname, PKT_LIST **plpp, uint_t plplen, 98*d04ccbb3Scarlsonj boolean_t isv6) 997c478bd9Sstevel@tonic-gate { 1007c478bd9Sstevel@tonic-gate PKT_LIST *plp = NULL; 1017c478bd9Sstevel@tonic-gate PKT *pkt = NULL; 1027c478bd9Sstevel@tonic-gate int fd; 1037c478bd9Sstevel@tonic-gate time_t orig_time, current_time = time(NULL); 1047c478bd9Sstevel@tonic-gate uint32_t lease; 1057c478bd9Sstevel@tonic-gate uint32_t magic; 1067c478bd9Sstevel@tonic-gate int pcnt = 0; 1077c478bd9Sstevel@tonic-gate int retval; 1087c478bd9Sstevel@tonic-gate 109*d04ccbb3Scarlsonj fd = open(ifname_to_hostconf(ifname, isv6), O_RDONLY); 1107c478bd9Sstevel@tonic-gate if (fd == -1) 1117c478bd9Sstevel@tonic-gate return (-1); 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate if (read(fd, &magic, sizeof (magic)) != sizeof (magic)) 1147c478bd9Sstevel@tonic-gate goto failure; 1157c478bd9Sstevel@tonic-gate 116*d04ccbb3Scarlsonj if (magic != (isv6 ? DHCP_HOSTCONF_MAGIC6 : DHCP_HOSTCONF_MAGIC)) 1177c478bd9Sstevel@tonic-gate goto failure; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate if (read(fd, &orig_time, sizeof (orig_time)) != sizeof (orig_time)) 1207c478bd9Sstevel@tonic-gate goto failure; 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate /* 123*d04ccbb3Scarlsonj * read the packet back in from disk, and for v4, run it through 124*d04ccbb3Scarlsonj * dhcp_options_scan(). note that we use calloc() because 125*d04ccbb3Scarlsonj * dhcp_options_scan() relies on the structure being zeroed. 1267c478bd9Sstevel@tonic-gate */ 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate for (pcnt = 0; pcnt < plplen; pcnt++) { 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate plp = NULL; 1317c478bd9Sstevel@tonic-gate pkt = NULL; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate if ((plp = calloc(1, sizeof (PKT_LIST))) == NULL) 1347c478bd9Sstevel@tonic-gate goto failure; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate retval = read(fd, &plp->len, sizeof (plp->len)); 1377c478bd9Sstevel@tonic-gate if (retval == 0 && pcnt != 0) { 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * Reached end of file on a boundary, but after 1407c478bd9Sstevel@tonic-gate * we've read at least one packet, so we consider 1417c478bd9Sstevel@tonic-gate * this successful, allowing us to use files from 1427c478bd9Sstevel@tonic-gate * older versions of the agent happily. 1437c478bd9Sstevel@tonic-gate */ 1447c478bd9Sstevel@tonic-gate free(plp); 1457c478bd9Sstevel@tonic-gate break; 1467c478bd9Sstevel@tonic-gate } else if (retval != sizeof (plp->len)) 1477c478bd9Sstevel@tonic-gate goto failure; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate if ((pkt = malloc(plp->len)) == NULL) 1507c478bd9Sstevel@tonic-gate goto failure; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate if (read(fd, pkt, plp->len) != plp->len) 1537c478bd9Sstevel@tonic-gate goto failure; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate plp->pkt = pkt; 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate plpp[pcnt] = plp; 1587c478bd9Sstevel@tonic-gate 159*d04ccbb3Scarlsonj if (!isv6 && dhcp_options_scan(plp, B_TRUE) != 0) 1607c478bd9Sstevel@tonic-gate goto failure; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate /* 1637c478bd9Sstevel@tonic-gate * First packet used to validate that we're interested, 1647c478bd9Sstevel@tonic-gate * the rest are presumed to be historical reference and 1657c478bd9Sstevel@tonic-gate * are not relativized 1667c478bd9Sstevel@tonic-gate */ 1677c478bd9Sstevel@tonic-gate if (pcnt == 0) 1687c478bd9Sstevel@tonic-gate continue; 1697c478bd9Sstevel@tonic-gate 170*d04ccbb3Scarlsonj if (isv6) { 171*d04ccbb3Scarlsonj dhcpv6_option_t d6o; 172*d04ccbb3Scarlsonj dhcpv6_ia_na_t d6in; 173*d04ccbb3Scarlsonj dhcpv6_iaaddr_t d6ia; 174*d04ccbb3Scarlsonj uchar_t *opts, *optmax, *subomax; 1757c478bd9Sstevel@tonic-gate 176*d04ccbb3Scarlsonj /* 177*d04ccbb3Scarlsonj * Loop over contents of the packet to find the address 178*d04ccbb3Scarlsonj * options. 179*d04ccbb3Scarlsonj */ 180*d04ccbb3Scarlsonj opts = (uchar_t *)pkt + sizeof (dhcpv6_message_t); 181*d04ccbb3Scarlsonj optmax = (uchar_t *)pkt + plp->len; 182*d04ccbb3Scarlsonj while (opts + sizeof (d6o) <= optmax) { 183*d04ccbb3Scarlsonj 184*d04ccbb3Scarlsonj /* 185*d04ccbb3Scarlsonj * Extract option header and make sure option 186*d04ccbb3Scarlsonj * is intact. 187*d04ccbb3Scarlsonj */ 188*d04ccbb3Scarlsonj (void) memcpy(&d6o, opts, sizeof (d6o)); 189*d04ccbb3Scarlsonj d6o.d6o_code = ntohs(d6o.d6o_code); 190*d04ccbb3Scarlsonj d6o.d6o_len = ntohs(d6o.d6o_len); 191*d04ccbb3Scarlsonj subomax = opts + sizeof (d6o) + d6o.d6o_len; 192*d04ccbb3Scarlsonj if (subomax > optmax) 193*d04ccbb3Scarlsonj break; 194*d04ccbb3Scarlsonj 195*d04ccbb3Scarlsonj /* 196*d04ccbb3Scarlsonj * If this isn't an option that contains 197*d04ccbb3Scarlsonj * address or prefix leases, then skip over it. 198*d04ccbb3Scarlsonj */ 199*d04ccbb3Scarlsonj if (d6o.d6o_code != DHCPV6_OPT_IA_NA && 200*d04ccbb3Scarlsonj d6o.d6o_code != DHCPV6_OPT_IA_TA && 201*d04ccbb3Scarlsonj d6o.d6o_code != DHCPV6_OPT_IA_PD) { 202*d04ccbb3Scarlsonj opts = subomax; 203*d04ccbb3Scarlsonj continue; 204*d04ccbb3Scarlsonj } 205*d04ccbb3Scarlsonj 206*d04ccbb3Scarlsonj /* 207*d04ccbb3Scarlsonj * Handle the option first. 208*d04ccbb3Scarlsonj */ 209*d04ccbb3Scarlsonj if (d6o.d6o_code == DHCPV6_OPT_IA_TA) { 210*d04ccbb3Scarlsonj /* no timers in this structure */ 211*d04ccbb3Scarlsonj opts += sizeof (dhcpv6_ia_ta_t); 212*d04ccbb3Scarlsonj } else { 213*d04ccbb3Scarlsonj /* both na and pd */ 214*d04ccbb3Scarlsonj if (opts + sizeof (d6in) > subomax) { 215*d04ccbb3Scarlsonj opts = subomax; 216*d04ccbb3Scarlsonj continue; 217*d04ccbb3Scarlsonj } 218*d04ccbb3Scarlsonj (void) memcpy(&d6in, opts, 219*d04ccbb3Scarlsonj sizeof (d6in)); 220*d04ccbb3Scarlsonj relativize_v6(&d6in.d6in_t1, orig_time, 221*d04ccbb3Scarlsonj current_time); 222*d04ccbb3Scarlsonj relativize_v6(&d6in.d6in_t2, orig_time, 223*d04ccbb3Scarlsonj current_time); 224*d04ccbb3Scarlsonj (void) memcpy(opts, &d6in, 225*d04ccbb3Scarlsonj sizeof (d6in)); 226*d04ccbb3Scarlsonj opts += sizeof (d6in); 227*d04ccbb3Scarlsonj } 228*d04ccbb3Scarlsonj 229*d04ccbb3Scarlsonj /* 230*d04ccbb3Scarlsonj * Now handle each suboption (address) inside. 231*d04ccbb3Scarlsonj */ 232*d04ccbb3Scarlsonj while (opts + sizeof (d6o) <= subomax) { 233*d04ccbb3Scarlsonj /* 234*d04ccbb3Scarlsonj * Verify the suboption header first. 235*d04ccbb3Scarlsonj */ 236*d04ccbb3Scarlsonj (void) memcpy(&d6o, opts, 237*d04ccbb3Scarlsonj sizeof (d6o)); 238*d04ccbb3Scarlsonj d6o.d6o_code = ntohs(d6o.d6o_code); 239*d04ccbb3Scarlsonj d6o.d6o_len = ntohs(d6o.d6o_len); 240*d04ccbb3Scarlsonj if (opts + sizeof (d6o) + d6o.d6o_len > 241*d04ccbb3Scarlsonj subomax) 242*d04ccbb3Scarlsonj break; 243*d04ccbb3Scarlsonj if (d6o.d6o_code != DHCPV6_OPT_IAADDR) { 244*d04ccbb3Scarlsonj opts += sizeof (d6o) + 245*d04ccbb3Scarlsonj d6o.d6o_len; 246*d04ccbb3Scarlsonj continue; 247*d04ccbb3Scarlsonj } 248*d04ccbb3Scarlsonj 249*d04ccbb3Scarlsonj /* 250*d04ccbb3Scarlsonj * Now process the contents. 251*d04ccbb3Scarlsonj */ 252*d04ccbb3Scarlsonj if (opts + sizeof (d6ia) > subomax) 253*d04ccbb3Scarlsonj break; 254*d04ccbb3Scarlsonj (void) memcpy(&d6ia, opts, 255*d04ccbb3Scarlsonj sizeof (d6ia)); 256*d04ccbb3Scarlsonj relativize_v6(&d6ia.d6ia_preflife, 257*d04ccbb3Scarlsonj orig_time, current_time); 258*d04ccbb3Scarlsonj relativize_v6(&d6ia.d6ia_vallife, 259*d04ccbb3Scarlsonj orig_time, current_time); 260*d04ccbb3Scarlsonj (void) memcpy(opts, &d6ia, 261*d04ccbb3Scarlsonj sizeof (d6ia)); 262*d04ccbb3Scarlsonj opts += sizeof (d6o) + d6o.d6o_len; 263*d04ccbb3Scarlsonj } 264*d04ccbb3Scarlsonj opts = subomax; 265*d04ccbb3Scarlsonj } 266*d04ccbb3Scarlsonj } else { 2677c478bd9Sstevel@tonic-gate 268*d04ccbb3Scarlsonj /* 269*d04ccbb3Scarlsonj * make sure the IPv4 DHCP lease is still valid. 270*d04ccbb3Scarlsonj */ 2717c478bd9Sstevel@tonic-gate 272*d04ccbb3Scarlsonj if (plp->opts[CD_LEASE_TIME] != NULL && 273*d04ccbb3Scarlsonj plp->opts[CD_LEASE_TIME]->len == 274*d04ccbb3Scarlsonj sizeof (lease_t)) { 275*d04ccbb3Scarlsonj 276*d04ccbb3Scarlsonj (void) memcpy(&lease, 277*d04ccbb3Scarlsonj plp->opts[CD_LEASE_TIME]->value, 278*d04ccbb3Scarlsonj sizeof (lease_t)); 279*d04ccbb3Scarlsonj 280*d04ccbb3Scarlsonj lease = ntohl(lease); 281*d04ccbb3Scarlsonj if ((lease != DHCP_PERM) && 282*d04ccbb3Scarlsonj (orig_time + lease) <= current_time) 283*d04ccbb3Scarlsonj goto failure; 284*d04ccbb3Scarlsonj } 285*d04ccbb3Scarlsonj 286*d04ccbb3Scarlsonj relativize_time(plp->opts[CD_T1_TIME], orig_time, 287*d04ccbb3Scarlsonj current_time); 288*d04ccbb3Scarlsonj relativize_time(plp->opts[CD_T2_TIME], orig_time, 289*d04ccbb3Scarlsonj current_time); 290*d04ccbb3Scarlsonj relativize_time(plp->opts[CD_LEASE_TIME], orig_time, 291*d04ccbb3Scarlsonj current_time); 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate (void) close(fd); 2967c478bd9Sstevel@tonic-gate return (pcnt); 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate failure: 2997c478bd9Sstevel@tonic-gate free(pkt); 3007c478bd9Sstevel@tonic-gate free(plp); 3017c478bd9Sstevel@tonic-gate while (pcnt-- > 0) { 3027c478bd9Sstevel@tonic-gate free(plpp[pcnt]->pkt); 3037c478bd9Sstevel@tonic-gate free(plpp[pcnt]); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate (void) close(fd); 3067c478bd9Sstevel@tonic-gate return (-1); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * write_hostconf(): writes the contents of a PKT_LIST into an <if>.dhc file 3117c478bd9Sstevel@tonic-gate * 3127c478bd9Sstevel@tonic-gate * input: const char *: the interface name 3137c478bd9Sstevel@tonic-gate * PKT_LIST **: a list of pointers to PKT_LIST to write 314*d04ccbb3Scarlsonj * uint_t: length of the list of PKT_LIST pointers 3157c478bd9Sstevel@tonic-gate * time_t: a starting time to treat the relative lease times 3167c478bd9Sstevel@tonic-gate * in the first packet as relative to 317*d04ccbb3Scarlsonj * boolean_t: B_TRUE if using DHCPv6 3187c478bd9Sstevel@tonic-gate * output: int: 0 if the file is written successfully, -1 otherwise 3197c478bd9Sstevel@tonic-gate * (errno is set) 3207c478bd9Sstevel@tonic-gate */ 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate int 3237c478bd9Sstevel@tonic-gate write_hostconf( 3247c478bd9Sstevel@tonic-gate const char *ifname, 3257c478bd9Sstevel@tonic-gate PKT_LIST *pl[], 3267c478bd9Sstevel@tonic-gate uint_t pllen, 327*d04ccbb3Scarlsonj time_t relative_to, 328*d04ccbb3Scarlsonj boolean_t isv6) 3297c478bd9Sstevel@tonic-gate { 3307c478bd9Sstevel@tonic-gate int fd; 3317c478bd9Sstevel@tonic-gate struct iovec iov[IOV_MAX]; 3327c478bd9Sstevel@tonic-gate int retval; 333*d04ccbb3Scarlsonj uint32_t magic; 3347c478bd9Sstevel@tonic-gate ssize_t explen = 0; /* Expected length of write */ 3357c478bd9Sstevel@tonic-gate int i, iovlen = 0; 3367c478bd9Sstevel@tonic-gate 337*d04ccbb3Scarlsonj fd = open(ifname_to_hostconf(ifname, isv6), O_WRONLY|O_CREAT|O_TRUNC, 338*d04ccbb3Scarlsonj 0600); 3397c478bd9Sstevel@tonic-gate if (fd == -1) 3407c478bd9Sstevel@tonic-gate return (-1); 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* 3437c478bd9Sstevel@tonic-gate * first write our magic number, then the relative time of the 3447c478bd9Sstevel@tonic-gate * leases, then for each packet we write the length of the packet 3457c478bd9Sstevel@tonic-gate * followed by the packet. we will then use the relative time in 3467c478bd9Sstevel@tonic-gate * read_hostconf() to recalculate the lease times for the first packet. 3477c478bd9Sstevel@tonic-gate */ 3487c478bd9Sstevel@tonic-gate 349*d04ccbb3Scarlsonj magic = isv6 ? DHCP_HOSTCONF_MAGIC6 : DHCP_HOSTCONF_MAGIC; 3507c478bd9Sstevel@tonic-gate iov[iovlen].iov_base = (caddr_t)&magic; 3517c478bd9Sstevel@tonic-gate explen += iov[iovlen++].iov_len = sizeof (magic); 3527c478bd9Sstevel@tonic-gate iov[iovlen].iov_base = (caddr_t)&relative_to; 3537c478bd9Sstevel@tonic-gate explen += iov[iovlen++].iov_len = sizeof (relative_to); 3547c478bd9Sstevel@tonic-gate for (i = 0; i < pllen && iovlen < (IOV_MAX - 1); i++) { 3557c478bd9Sstevel@tonic-gate iov[iovlen].iov_base = (caddr_t)&pl[i]->len; 3567c478bd9Sstevel@tonic-gate explen += iov[iovlen++].iov_len = sizeof (pl[i]->len); 3577c478bd9Sstevel@tonic-gate iov[iovlen].iov_base = (caddr_t)pl[i]->pkt; 3587c478bd9Sstevel@tonic-gate explen += iov[iovlen++].iov_len = pl[i]->len; 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate retval = writev(fd, iov, iovlen); 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate (void) close(fd); 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate if (retval != explen) 3667c478bd9Sstevel@tonic-gate return (-1); 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate return (0); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate /* 3727c478bd9Sstevel@tonic-gate * relativize_time(): re-relativizes a time in a DHCP option 3737c478bd9Sstevel@tonic-gate * 3747c478bd9Sstevel@tonic-gate * input: DHCP_OPT *: the DHCP option parameter to convert 3757c478bd9Sstevel@tonic-gate * time_t: the time the leases in the packet are currently relative to 3767c478bd9Sstevel@tonic-gate * time_t: the current time which leases will become relative to 3777c478bd9Sstevel@tonic-gate * output: void 3787c478bd9Sstevel@tonic-gate */ 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate static void 3817c478bd9Sstevel@tonic-gate relativize_time(DHCP_OPT *option, time_t orig_time, time_t current_time) 3827c478bd9Sstevel@tonic-gate { 3837c478bd9Sstevel@tonic-gate uint32_t pkt_time; 3847c478bd9Sstevel@tonic-gate time_t time_diff = current_time - orig_time; 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate if (option == NULL || option->len != sizeof (lease_t)) 3877c478bd9Sstevel@tonic-gate return; 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate (void) memcpy(&pkt_time, option->value, option->len); 3907c478bd9Sstevel@tonic-gate if (ntohl(pkt_time) != DHCP_PERM) 3917c478bd9Sstevel@tonic-gate pkt_time = htonl(ntohl(pkt_time) - time_diff); 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate (void) memcpy(option->value, &pkt_time, option->len); 3947c478bd9Sstevel@tonic-gate } 395*d04ccbb3Scarlsonj 396*d04ccbb3Scarlsonj /* 397*d04ccbb3Scarlsonj * relativize_v6(): re-relativizes a time in a DHCPv6 option 398*d04ccbb3Scarlsonj * 399*d04ccbb3Scarlsonj * input: uint32_t *: the time value to convert 400*d04ccbb3Scarlsonj * time_t: the time the leases in the packet are currently relative to 401*d04ccbb3Scarlsonj * time_t: the current time which leases will become relative to 402*d04ccbb3Scarlsonj * output: void 403*d04ccbb3Scarlsonj */ 404*d04ccbb3Scarlsonj 405*d04ccbb3Scarlsonj static void 406*d04ccbb3Scarlsonj relativize_v6(uint32_t *val, time_t orig_time, time_t current_time) 407*d04ccbb3Scarlsonj { 408*d04ccbb3Scarlsonj uint32_t hval; 409*d04ccbb3Scarlsonj time_t time_diff = current_time - orig_time; 410*d04ccbb3Scarlsonj 411*d04ccbb3Scarlsonj hval = ntohl(*val); 412*d04ccbb3Scarlsonj if (hval != DHCPV6_INFTIME) { 413*d04ccbb3Scarlsonj if (hval < time_diff) 414*d04ccbb3Scarlsonj *val = 0; 415*d04ccbb3Scarlsonj else 416*d04ccbb3Scarlsonj *val = htonl(hval - time_diff); 417*d04ccbb3Scarlsonj } 418*d04ccbb3Scarlsonj } 419