dhcp_hostconf.c (7c478bd9) | dhcp_hostconf.c (d04ccbb3) |
---|---|
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the | 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. | 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance 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/* | 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* |
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. | 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. |
24 * Use is subject to license terms. 25 */ 26 27#pragma ident "%Z%%M% %I% %E% SMI" 28 29#include <stdio.h> 30#include <stdlib.h> 31#include <unistd.h> --- 6 unchanged lines hidden (view full) --- 38#include <time.h> 39#include <string.h> /* memcpy */ 40#include <fcntl.h> 41#include <limits.h> 42 43#include "dhcp_hostconf.h" 44 45static void relativize_time(DHCP_OPT *, time_t, time_t); | 23 * Use is subject to license terms. 24 */ 25 26#pragma ident "%Z%%M% %I% %E% SMI" 27 28#include <stdio.h> 29#include <stdlib.h> 30#include <unistd.h> --- 6 unchanged lines hidden (view full) --- 37#include <time.h> 38#include <string.h> /* memcpy */ 39#include <fcntl.h> 40#include <limits.h> 41 42#include "dhcp_hostconf.h" 43 44static void relativize_time(DHCP_OPT *, time_t, time_t); |
45static void relativize_v6(uint32_t *, time_t, time_t); |
|
46 47/* 48 * ifname_to_hostconf(): converts an interface name into a hostconf file for 49 * that interface 50 * 51 * input: const char *: the interface name | 46 47/* 48 * ifname_to_hostconf(): converts an interface name into a hostconf file for 49 * that interface 50 * 51 * input: const char *: the interface name |
52 * boolean_t: B_TRUE if using DHCPv6 |
|
52 * output: char *: the hostconf filename 53 * note: uses an internal static buffer (not threadsafe) 54 */ 55 56char * | 53 * output: char *: the hostconf filename 54 * note: uses an internal static buffer (not threadsafe) 55 */ 56 57char * |
57ifname_to_hostconf(const char *ifname) | 58ifname_to_hostconf(const char *ifname, boolean_t isv6) |
58{ | 59{ |
59 static char filename[sizeof (DHCP_HOSTCONF_TMPL) + IFNAMSIZ]; | 60 static char filename[sizeof (DHCP_HOSTCONF_TMPL6) + LIFNAMSIZ]; |
60 61 (void) snprintf(filename, sizeof (filename), "%s%s%s", | 61 62 (void) snprintf(filename, sizeof (filename), "%s%s%s", |
62 DHCP_HOSTCONF_PREFIX, ifname, DHCP_HOSTCONF_SUFFIX); | 63 DHCP_HOSTCONF_PREFIX, ifname, 64 isv6 ? DHCP_HOSTCONF_SUFFIX6 : DHCP_HOSTCONF_SUFFIX); |
63 64 return (filename); 65} 66 67/* 68 * remove_hostconf(): removes an interface.dhc file 69 * 70 * input: const char *: the interface name | 65 66 return (filename); 67} 68 69/* 70 * remove_hostconf(): removes an interface.dhc file 71 * 72 * input: const char *: the interface name |
73 * boolean_t: B_TRUE if using DHCPv6 |
|
71 * output: int: 0 if the file is removed, -1 if it can't be removed 72 * (errno is set) 73 */ 74 75int | 74 * output: int: 0 if the file is removed, -1 if it can't be removed 75 * (errno is set) 76 */ 77 78int |
76remove_hostconf(const char *ifname) | 79remove_hostconf(const char *ifname, boolean_t isv6) |
77{ | 80{ |
78 return (unlink(ifname_to_hostconf(ifname))); | 81 return (unlink(ifname_to_hostconf(ifname, isv6))); |
79} 80 81/* 82 * read_hostconf(): reads the contents of an <if>.dhc file into a PKT_LIST 83 * 84 * input: const char *: the interface name 85 * PKT_LIST **: a pointer to a PKT_LIST * to store the info in 86 * uint_t: the length of the list of PKT_LISTs | 82} 83 84/* 85 * read_hostconf(): reads the contents of an <if>.dhc file into a PKT_LIST 86 * 87 * input: const char *: the interface name 88 * PKT_LIST **: a pointer to a PKT_LIST * to store the info in 89 * uint_t: the length of the list of PKT_LISTs |
87 * output: int: 0 if the file is read and loaded into the PKT_LIST * | 90 * boolean_t: B_TRUE if using DHCPv6 91 * output: int: >0 if the file is read and loaded into the PKT_LIST * |
88 * successfully, -1 otherwise (errno is set) 89 * note: the PKT and PKT_LISTs are dynamically allocated here 90 */ 91 92int | 92 * successfully, -1 otherwise (errno is set) 93 * note: the PKT and PKT_LISTs are dynamically allocated here 94 */ 95 96int |
93read_hostconf(const char *ifname, PKT_LIST **plpp, uint_t plplen) | 97read_hostconf(const char *ifname, PKT_LIST **plpp, uint_t plplen, 98 boolean_t isv6) |
94{ 95 PKT_LIST *plp = NULL; 96 PKT *pkt = NULL; 97 int fd; 98 time_t orig_time, current_time = time(NULL); 99 uint32_t lease; 100 uint32_t magic; 101 int pcnt = 0; 102 int retval; 103 | 99{ 100 PKT_LIST *plp = NULL; 101 PKT *pkt = NULL; 102 int fd; 103 time_t orig_time, current_time = time(NULL); 104 uint32_t lease; 105 uint32_t magic; 106 int pcnt = 0; 107 int retval; 108 |
104 fd = open(ifname_to_hostconf(ifname), O_RDONLY); | 109 fd = open(ifname_to_hostconf(ifname, isv6), O_RDONLY); |
105 if (fd == -1) 106 return (-1); 107 108 if (read(fd, &magic, sizeof (magic)) != sizeof (magic)) 109 goto failure; 110 | 110 if (fd == -1) 111 return (-1); 112 113 if (read(fd, &magic, sizeof (magic)) != sizeof (magic)) 114 goto failure; 115 |
111 if (magic != DHCP_HOSTCONF_MAGIC) | 116 if (magic != (isv6 ? DHCP_HOSTCONF_MAGIC6 : DHCP_HOSTCONF_MAGIC)) |
112 goto failure; 113 114 if (read(fd, &orig_time, sizeof (orig_time)) != sizeof (orig_time)) 115 goto failure; 116 117 /* | 117 goto failure; 118 119 if (read(fd, &orig_time, sizeof (orig_time)) != sizeof (orig_time)) 120 goto failure; 121 122 /* |
118 * read the packet back in from disk, and run it through 119 * dhcp_options_scan(). note that we use calloc() since 120 * dhcp_options_scan() relies on the packet being zeroed. | 123 * read the packet back in from disk, and for v4, run it through 124 * dhcp_options_scan(). note that we use calloc() because 125 * dhcp_options_scan() relies on the structure being zeroed. |
121 */ 122 123 for (pcnt = 0; pcnt < plplen; pcnt++) { 124 125 plp = NULL; 126 pkt = NULL; 127 128 if ((plp = calloc(1, sizeof (PKT_LIST))) == NULL) --- 17 unchanged lines hidden (view full) --- 146 147 if (read(fd, pkt, plp->len) != plp->len) 148 goto failure; 149 150 plp->pkt = pkt; 151 152 plpp[pcnt] = plp; 153 | 126 */ 127 128 for (pcnt = 0; pcnt < plplen; pcnt++) { 129 130 plp = NULL; 131 pkt = NULL; 132 133 if ((plp = calloc(1, sizeof (PKT_LIST))) == NULL) --- 17 unchanged lines hidden (view full) --- 151 152 if (read(fd, pkt, plp->len) != plp->len) 153 goto failure; 154 155 plp->pkt = pkt; 156 157 plpp[pcnt] = plp; 158 |
154 if (dhcp_options_scan(plp, B_TRUE) != 0) | 159 if (!isv6 && dhcp_options_scan(plp, B_TRUE) != 0) |
155 goto failure; 156 157 /* 158 * First packet used to validate that we're interested, 159 * the rest are presumed to be historical reference and 160 * are not relativized 161 */ 162 if (pcnt == 0) 163 continue; 164 | 160 goto failure; 161 162 /* 163 * First packet used to validate that we're interested, 164 * the rest are presumed to be historical reference and 165 * are not relativized 166 */ 167 if (pcnt == 0) 168 continue; 169 |
165 /* 166 * make sure the lease is still valid. 167 */ | 170 if (isv6) { 171 dhcpv6_option_t d6o; 172 dhcpv6_ia_na_t d6in; 173 dhcpv6_iaaddr_t d6ia; 174 uchar_t *opts, *optmax, *subomax; |
168 | 175 |
169 if (plp->opts[CD_LEASE_TIME] != NULL && 170 plp->opts[CD_LEASE_TIME]->len == sizeof (lease_t)) { | 176 /* 177 * Loop over contents of the packet to find the address 178 * options. 179 */ 180 opts = (uchar_t *)pkt + sizeof (dhcpv6_message_t); 181 optmax = (uchar_t *)pkt + plp->len; 182 while (opts + sizeof (d6o) <= optmax) { |
171 | 183 |
172 (void) memcpy(&lease, plp->opts[CD_LEASE_TIME]->value, 173 sizeof (lease_t)); | 184 /* 185 * Extract option header and make sure option 186 * is intact. 187 */ 188 (void) memcpy(&d6o, opts, sizeof (d6o)); 189 d6o.d6o_code = ntohs(d6o.d6o_code); 190 d6o.d6o_len = ntohs(d6o.d6o_len); 191 subomax = opts + sizeof (d6o) + d6o.d6o_len; 192 if (subomax > optmax) 193 break; |
174 | 194 |
175 lease = ntohl(lease); 176 if ((lease != DHCP_PERM) && 177 (orig_time + lease) <= current_time) 178 goto failure; 179 } | 195 /* 196 * If this isn't an option that contains 197 * address or prefix leases, then skip over it. 198 */ 199 if (d6o.d6o_code != DHCPV6_OPT_IA_NA && 200 d6o.d6o_code != DHCPV6_OPT_IA_TA && 201 d6o.d6o_code != DHCPV6_OPT_IA_PD) { 202 opts = subomax; 203 continue; 204 } |
180 | 205 |
181 relativize_time(plp->opts[CD_T1_TIME], orig_time, current_time); 182 relativize_time(plp->opts[CD_T2_TIME], orig_time, current_time); 183 relativize_time(plp->opts[CD_LEASE_TIME], orig_time, 184 current_time); | 206 /* 207 * Handle the option first. 208 */ 209 if (d6o.d6o_code == DHCPV6_OPT_IA_TA) { 210 /* no timers in this structure */ 211 opts += sizeof (dhcpv6_ia_ta_t); 212 } else { 213 /* both na and pd */ 214 if (opts + sizeof (d6in) > subomax) { 215 opts = subomax; 216 continue; 217 } 218 (void) memcpy(&d6in, opts, 219 sizeof (d6in)); 220 relativize_v6(&d6in.d6in_t1, orig_time, 221 current_time); 222 relativize_v6(&d6in.d6in_t2, orig_time, 223 current_time); 224 (void) memcpy(opts, &d6in, 225 sizeof (d6in)); 226 opts += sizeof (d6in); 227 } 228 229 /* 230 * Now handle each suboption (address) inside. 231 */ 232 while (opts + sizeof (d6o) <= subomax) { 233 /* 234 * Verify the suboption header first. 235 */ 236 (void) memcpy(&d6o, opts, 237 sizeof (d6o)); 238 d6o.d6o_code = ntohs(d6o.d6o_code); 239 d6o.d6o_len = ntohs(d6o.d6o_len); 240 if (opts + sizeof (d6o) + d6o.d6o_len > 241 subomax) 242 break; 243 if (d6o.d6o_code != DHCPV6_OPT_IAADDR) { 244 opts += sizeof (d6o) + 245 d6o.d6o_len; 246 continue; 247 } 248 249 /* 250 * Now process the contents. 251 */ 252 if (opts + sizeof (d6ia) > subomax) 253 break; 254 (void) memcpy(&d6ia, opts, 255 sizeof (d6ia)); 256 relativize_v6(&d6ia.d6ia_preflife, 257 orig_time, current_time); 258 relativize_v6(&d6ia.d6ia_vallife, 259 orig_time, current_time); 260 (void) memcpy(opts, &d6ia, 261 sizeof (d6ia)); 262 opts += sizeof (d6o) + d6o.d6o_len; 263 } 264 opts = subomax; 265 } 266 } else { 267 268 /* 269 * make sure the IPv4 DHCP lease is still valid. 270 */ 271 272 if (plp->opts[CD_LEASE_TIME] != NULL && 273 plp->opts[CD_LEASE_TIME]->len == 274 sizeof (lease_t)) { 275 276 (void) memcpy(&lease, 277 plp->opts[CD_LEASE_TIME]->value, 278 sizeof (lease_t)); 279 280 lease = ntohl(lease); 281 if ((lease != DHCP_PERM) && 282 (orig_time + lease) <= current_time) 283 goto failure; 284 } 285 286 relativize_time(plp->opts[CD_T1_TIME], orig_time, 287 current_time); 288 relativize_time(plp->opts[CD_T2_TIME], orig_time, 289 current_time); 290 relativize_time(plp->opts[CD_LEASE_TIME], orig_time, 291 current_time); 292 } |
185 } 186 187 (void) close(fd); 188 return (pcnt); 189 190failure: 191 free(pkt); 192 free(plp); --- 5 unchanged lines hidden (view full) --- 198 return (-1); 199} 200 201/* 202 * write_hostconf(): writes the contents of a PKT_LIST into an <if>.dhc file 203 * 204 * input: const char *: the interface name 205 * PKT_LIST **: a list of pointers to PKT_LIST to write | 293 } 294 295 (void) close(fd); 296 return (pcnt); 297 298failure: 299 free(pkt); 300 free(plp); --- 5 unchanged lines hidden (view full) --- 306 return (-1); 307} 308 309/* 310 * write_hostconf(): writes the contents of a PKT_LIST into an <if>.dhc file 311 * 312 * input: const char *: the interface name 313 * PKT_LIST **: a list of pointers to PKT_LIST to write |
206 * int: length of the list of PKT_LIST pointers | 314 * uint_t: length of the list of PKT_LIST pointers |
207 * time_t: a starting time to treat the relative lease times 208 * in the first packet as relative to | 315 * time_t: a starting time to treat the relative lease times 316 * in the first packet as relative to |
317 * boolean_t: B_TRUE if using DHCPv6 |
|
209 * output: int: 0 if the file is written successfully, -1 otherwise 210 * (errno is set) 211 */ 212 213int 214write_hostconf( 215 const char *ifname, 216 PKT_LIST *pl[], 217 uint_t pllen, | 318 * output: int: 0 if the file is written successfully, -1 otherwise 319 * (errno is set) 320 */ 321 322int 323write_hostconf( 324 const char *ifname, 325 PKT_LIST *pl[], 326 uint_t pllen, |
218 time_t relative_to) | 327 time_t relative_to, 328 boolean_t isv6) |
219{ 220 int fd; 221 struct iovec iov[IOV_MAX]; 222 int retval; | 329{ 330 int fd; 331 struct iovec iov[IOV_MAX]; 332 int retval; |
223 uint32_t magic = DHCP_HOSTCONF_MAGIC; | 333 uint32_t magic; |
224 ssize_t explen = 0; /* Expected length of write */ 225 int i, iovlen = 0; 226 | 334 ssize_t explen = 0; /* Expected length of write */ 335 int i, iovlen = 0; 336 |
227 fd = open(ifname_to_hostconf(ifname), O_WRONLY|O_CREAT|O_TRUNC, 0600); | 337 fd = open(ifname_to_hostconf(ifname, isv6), O_WRONLY|O_CREAT|O_TRUNC, 338 0600); |
228 if (fd == -1) 229 return (-1); 230 231 /* 232 * first write our magic number, then the relative time of the 233 * leases, then for each packet we write the length of the packet 234 * followed by the packet. we will then use the relative time in 235 * read_hostconf() to recalculate the lease times for the first packet. 236 */ 237 | 339 if (fd == -1) 340 return (-1); 341 342 /* 343 * first write our magic number, then the relative time of the 344 * leases, then for each packet we write the length of the packet 345 * followed by the packet. we will then use the relative time in 346 * read_hostconf() to recalculate the lease times for the first packet. 347 */ 348 |
349 magic = isv6 ? DHCP_HOSTCONF_MAGIC6 : DHCP_HOSTCONF_MAGIC; |
|
238 iov[iovlen].iov_base = (caddr_t)&magic; 239 explen += iov[iovlen++].iov_len = sizeof (magic); 240 iov[iovlen].iov_base = (caddr_t)&relative_to; 241 explen += iov[iovlen++].iov_len = sizeof (relative_to); 242 for (i = 0; i < pllen && iovlen < (IOV_MAX - 1); i++) { 243 iov[iovlen].iov_base = (caddr_t)&pl[i]->len; 244 explen += iov[iovlen++].iov_len = sizeof (pl[i]->len); 245 iov[iovlen].iov_base = (caddr_t)pl[i]->pkt; --- 29 unchanged lines hidden (view full) --- 275 return; 276 277 (void) memcpy(&pkt_time, option->value, option->len); 278 if (ntohl(pkt_time) != DHCP_PERM) 279 pkt_time = htonl(ntohl(pkt_time) - time_diff); 280 281 (void) memcpy(option->value, &pkt_time, option->len); 282} | 350 iov[iovlen].iov_base = (caddr_t)&magic; 351 explen += iov[iovlen++].iov_len = sizeof (magic); 352 iov[iovlen].iov_base = (caddr_t)&relative_to; 353 explen += iov[iovlen++].iov_len = sizeof (relative_to); 354 for (i = 0; i < pllen && iovlen < (IOV_MAX - 1); i++) { 355 iov[iovlen].iov_base = (caddr_t)&pl[i]->len; 356 explen += iov[iovlen++].iov_len = sizeof (pl[i]->len); 357 iov[iovlen].iov_base = (caddr_t)pl[i]->pkt; --- 29 unchanged lines hidden (view full) --- 387 return; 388 389 (void) memcpy(&pkt_time, option->value, option->len); 390 if (ntohl(pkt_time) != DHCP_PERM) 391 pkt_time = htonl(ntohl(pkt_time) - time_diff); 392 393 (void) memcpy(option->value, &pkt_time, option->len); 394} |
395 396/* 397 * relativize_v6(): re-relativizes a time in a DHCPv6 option 398 * 399 * input: uint32_t *: the time value to convert 400 * time_t: the time the leases in the packet are currently relative to 401 * time_t: the current time which leases will become relative to 402 * output: void 403 */ 404 405static void 406relativize_v6(uint32_t *val, time_t orig_time, time_t current_time) 407{ 408 uint32_t hval; 409 time_t time_diff = current_time - orig_time; 410 411 hval = ntohl(*val); 412 if (hval != DHCPV6_INFTIME) { 413 if (hval < time_diff) 414 *val = 0; 415 else 416 *val = htonl(hval - time_diff); 417 } 418} |
|