1d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* 2d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * dhcpcd - DHCP client daemon 3d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Copyright (c) 2006-2015 Roy Marples <roy@marples.name> 4d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * All rights reserved 5d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 6d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Redistribution and use in source and binary forms, with or without 7d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * modification, are permitted provided that the following conditions 8d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * are met: 9d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 1. Redistributions of source code must retain the above copyright 10d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * notice, this list of conditions and the following disclaimer. 11d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 2. Redistributions in binary form must reproduce the above copyright 12d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * notice, this list of conditions and the following disclaimer in the 13d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * documentation and/or other materials provided with the distribution. 14d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 15d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * SUCH DAMAGE. 26d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan */ 27d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 28d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <sys/utsname.h> 29d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 30d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <ctype.h> 31d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <errno.h> 32d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <fcntl.h> 33d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <inttypes.h> 34d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stdlib.h> 35d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <string.h> 36d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <unistd.h> 37d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 38d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "config.h" 39d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 40d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "common.h" 41d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "dhcp-common.h" 42d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "dhcp.h" 43d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "if.h" 44d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "ipv6.h" 45d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 46d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid 47d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tandhcp_print_option_encoding(const struct dhcp_opt *opt, int cols) 48d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 49d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 50d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (cols < 40) { 51d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan putchar(' '); 52d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan cols++; 53d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 54d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan putchar('\t'); 55d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->type & EMBED) 56d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" embed"); 57d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->type & ENCAP) 58d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" encap"); 59d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->type & INDEX) 60d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" index"); 61d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->type & ARRAY) 62d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" array"); 63d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->type & UINT8) 64d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" byte"); 65d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (opt->type & UINT16) 66d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" uint16"); 67d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (opt->type & SINT16) 68d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" sint16"); 69d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (opt->type & UINT32) 70d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" uint32"); 71d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (opt->type & SINT32) 72d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" sint32"); 73d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (opt->type & ADDRIPV4) 74d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" ipaddress"); 75d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (opt->type & ADDRIPV6) 76d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" ip6address"); 77d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (opt->type & FLAG) 78d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" flag"); 79d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (opt->type & RFC3397) 80d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" domain"); 81d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (opt->type & DOMAIN) 82d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" dname"); 83d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (opt->type & ASCII) 84d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" ascii"); 85d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (opt->type & RAW) 86d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" raw"); 87d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (opt->type & BINHEX) 88d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" binhex"); 89d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (opt->type & STRING) 90d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" string"); 91d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->type & RFC3361) 92d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" rfc3361"); 93d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->type & RFC3442) 94d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" rfc3442"); 95d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->type & RFC5969) 96d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" rfc5969"); 97d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->type & REQUEST) 98d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" request"); 99d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->type & NOREQ) 100d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan printf(" norequest"); 101d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan putchar('\n'); 102d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 103d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 104d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstruct dhcp_opt * 105d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvivso_find(uint32_t iana_en, const void *arg) 106d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 107d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct interface *ifp; 108d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t i; 109d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_opt *opt; 110d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 111d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp = arg; 112d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (i = 0, opt = ifp->options->vivso_override; 113d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i < ifp->options->vivso_override_len; 114d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i++, opt++) 115d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->option == iana_en) 116d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return opt; 117d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (i = 0, opt = ifp->ctx->vivso; 118d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i < ifp->ctx->vivso_len; 119d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i++, opt++) 120d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->option == iana_en) 121d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return opt; 122d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return NULL; 123d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 124d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 125d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanssize_t 126d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tandhcp_vendor(char *str, size_t len) 127d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 128d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct utsname utn; 129d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *p; 130d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int l; 131d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 132d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (uname(&utn) != 0) 133d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return (ssize_t)snprintf(str, len, "%s-%s", 134d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan PACKAGE, VERSION); 135d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p = str; 136d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = snprintf(p, len, 137d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s-%s:%s-%s:%s", PACKAGE, VERSION, 138d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan utn.sysname, utn.release, utn.machine); 139d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (l == -1 || (size_t)(l + 1) > len) 140d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 141d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p += l; 142d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len -= (size_t)l; 143d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = if_machinearch(p, len); 144d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (l == -1 || (size_t)(l + 1) > len) 145d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 146d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p += l; 147d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return p - str; 148d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 149d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 150d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 151d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanmake_option_mask(const struct dhcp_opt *dopts, size_t dopts_len, 152d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct dhcp_opt *odopts, size_t odopts_len, 153d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint8_t *mask, const char *opts, int add) 154d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 155d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *token, *o, *p; 156d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct dhcp_opt *opt; 157d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int match, e; 158d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned int n; 159d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t i; 160d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 161d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opts == NULL) 162d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 163d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan o = p = strdup(opts); 164d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while ((token = strsep(&p, ", "))) { 165d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (*token == '\0') 166d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 167d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan match = 0; 168d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (i = 0, opt = odopts; i < odopts_len; i++, opt++) { 169d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (strcmp(opt->var, token) == 0) 170d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan match = 1; 171d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else { 172d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n = (unsigned int)strtou(token, NULL, 0, 173d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 0, UINT_MAX, &e); 174d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e == 0 && opt->option == n) 175d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan match = 1; 176d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 177d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (match) 178d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 179d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 180d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (match == 0) { 181d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (i = 0, opt = dopts; i < dopts_len; i++, opt++) { 182d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (strcmp(opt->var, token) == 0) 183d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan match = 1; 184d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else { 185d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n = (unsigned int)strtou(token, NULL, 0, 186d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 0, UINT_MAX, &e); 187d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (e == 0 && opt->option == n) 188d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan match = 1; 189d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 190d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (match) 191d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 192d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 193d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 194d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!match || !opt->option) { 195d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(o); 196d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOENT; 197d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 198d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 199d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (add == 2 && !(opt->type & ADDRIPV4)) { 200d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(o); 201d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EINVAL; 202d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 203d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 204d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (add == 1 || add == 2) 205d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan add_option_mask(mask, opt->option); 206d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 207d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan del_option_mask(mask, opt->option); 208d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 209d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(o); 210d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 211d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 212d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 213d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tansize_t 214d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanencode_rfc1035(const char *src, uint8_t *dst) 215d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 216d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint8_t *p; 217d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint8_t *lp; 218d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t len; 219d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint8_t has_dot; 220d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 221d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (src == NULL || *src == '\0') 222d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 223d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 224d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (dst) { 225d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p = dst; 226d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan lp = p++; 227d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 228d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Silence bogus GCC warnings */ 229d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 230d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p = lp = NULL; 231d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 232d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = 1; 233d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan has_dot = 0; 234d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (; *src; src++) { 235d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (*src == '\0') 236d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 237d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (*src == '.') { 238d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Skip the trailing . */ 239d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (src[1] == '\0') 240d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 241d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan has_dot = 1; 242d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (dst) { 243d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *lp = (uint8_t)(p - lp - 1); 244d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (*lp == '\0') 245d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return len; 246d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan lp = p++; 247d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 248d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (dst) 249d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *p++ = (uint8_t)*src; 250d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len++; 251d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 252d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 253d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (dst) { 254d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *lp = (uint8_t)(p - lp - 1); 255d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (has_dot) 256d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *p++ = '\0'; 257d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 258d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 259d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (has_dot) 260d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len++; 261d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 262d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return len; 263d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 264d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 265d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* Decode an RFC3397 DNS search order option into a space 266d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * separated string. Returns length of string (including 267d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * terminating zero) or zero on error. out may be NULL 268d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * to just determine output length. */ 269d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanssize_t 270d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tandecode_rfc3397(char *out, size_t len, const uint8_t *p, size_t pl) 271d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 272d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const char *start; 273d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t start_len, l, count; 274d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const uint8_t *r, *q = p, *e; 275d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int hops; 276d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint8_t ltype; 277d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 278d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan count = 0; 279d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan start = out; 280d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan start_len = len; 281d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan q = p; 282d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = p + pl; 283d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (q < e) { 284d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = NULL; 285d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan hops = 0; 286d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Check we are inside our length again in-case 287d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * the name isn't fully qualified (ie, not terminated) */ 288d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (q < e && (l = (size_t)*q++)) { 289d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ltype = l & 0xc0; 290d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ltype == 0x80 || ltype == 0x40) 291d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 292d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (ltype == 0xc0) { /* pointer */ 293d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (q == e) { 294d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ERANGE; 295d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 296d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 297d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = (l & 0x3f) << 8; 298d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l |= *q++; 299d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* save source of first jump. */ 300d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!r) 301d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = q; 302d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan hops++; 303d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (hops > 255) { 304d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ERANGE; 305d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 306d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 307d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan q = p + l; 308d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (q >= e) { 309d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ERANGE; 310d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 311d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 312d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 313d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* straightforward name segment, add with '.' */ 314d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (q + l > e) { 315d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ERANGE; 316d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 317d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 318d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan count += l + 1; 319d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (out) { 320d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (l + 1 > len) { 321d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOBUFS; 322d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 323d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 324d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(out, q, l); 325d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan out += l; 326d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *out++ = '.'; 327d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len -= l; 328d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len--; 329d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 330d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan q += l; 331d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 332d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 333d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* change last dot to space */ 334d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (out && out != start) 335d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *(out - 1) = ' '; 336d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (r) 337d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan q = r; 338d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 339d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 340d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* change last space to zero terminator */ 341d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (out) { 342d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (out != start) 343d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *(out - 1) = '\0'; 344d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (start_len > 0) 345d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *out = '\0'; 346d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 347d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 348d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (count) 349d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Don't count the trailing NUL */ 350d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan count--; 351d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return (ssize_t)count; 352d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 353d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 354d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* Check for a valid domain name as per RFC1123 with the exception of 355d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * allowing - and _ (but not at start or end) as they seem to be widely used. */ 356d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic int 357d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvalid_domainname(char *lbl, int type) 358d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 359d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *slbl, *lst; 360d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned char c; 361d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int start, len, errset; 362d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 363d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (lbl == NULL || *lbl == '\0') { 364d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EINVAL; 365d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 366d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 367d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 368d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan slbl = lbl; 369d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan lst = NULL; 370d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan start = 1; 371d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = errset = 0; 372d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (;;) { 373d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan c = (unsigned char)*lbl++; 374d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (c == '\0') 375d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 1; 376d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (c == ' ') { 377d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (lbl - 1 == slbl) /* No space at start */ 378d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 379d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!(type & ARRAY)) 380d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 381d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Skip to the next label */ 382d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!start) { 383d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan start = 1; 384d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan lst = lbl - 1; 385d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 386d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len) 387d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = 0; 388d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 389d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 390d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (c == '.') { 391d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (*lbl == '.') 392d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 393d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = 0; 394d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 395d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 396d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (((c == '-' || c == '_') && 397d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan !start && *lbl != ' ' && *lbl != '\0') || 398d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan isalnum(c)) 399d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 400d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (++len > 63) { 401d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ERANGE; 402d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errset = 1; 403d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 404d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 405d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 406d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 407d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (start) 408d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan start = 0; 409d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 410d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 411d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!errset) 412d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EINVAL; 413d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (lst) { 414d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* At least one valid domain, return it */ 415d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *lst = '\0'; 416d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 1; 417d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 418d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 419d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 420d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 421d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* 422d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Prints a chunk of data to a string. 423d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * PS_SHELL goes as it is these days, it's upto the target to validate it. 424d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * PS_SAFE has all non ascii and non printables changes to escaped octal. 425d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan */ 426d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic const char hexchrs[] = "0123456789abcdef"; 427d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanssize_t 428d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanprint_string(char *dst, size_t len, int type, const uint8_t *data, size_t dl) 429d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 430d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *odst; 431d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint8_t c; 432d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const uint8_t *e; 433d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t bytes; 434d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 435d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan odst = dst; 436d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes = 0; 437d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = data + dl; 438d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 439d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (data < e) { 440d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan c = *data++; 441d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type & BINHEX) { 442d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (dst) { 443d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len == 0 || len == 1) { 444d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOSPC; 445d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 446d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 447d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *dst++ = hexchrs[(c & 0xF0) >> 4]; 448d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *dst++ = hexchrs[(c & 0x0F)]; 449d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len -= 2; 450d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 451d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes += 2; 452d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 453d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 454d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type & ASCII && (!isascii(c))) { 455d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EINVAL; 456d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 457d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 458d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!(type & (ASCII | RAW | ESCSTRING | ESCFILE)) /* plain */ && 459d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (!isascii(c) && !isprint(c))) 460d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 461d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EINVAL; 462d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 463d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 464d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((type & (ESCSTRING | ESCFILE) && 465d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (c == '\\' || !isascii(c) || !isprint(c))) || 466d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (type & ESCFILE && (c == '/' || c == ' '))) 467d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 468d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EINVAL; 469d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (c == '\\') { 470d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (dst) { 471d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len == 0 || len == 1) { 472d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOSPC; 473d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 474d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 475d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *dst++ = '\\'; *dst++ = '\\'; 476d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len -= 2; 477d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 478d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes += 2; 479d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 480d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 481d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (dst) { 482d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len < 5) { 483d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOSPC; 484d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 485d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 486d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *dst++ = '\\'; 487d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *dst++ = (char)(((c >> 6) & 03) + '0'); 488d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *dst++ = (char)(((c >> 3) & 07) + '0'); 489d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *dst++ = (char)(( c & 07) + '0'); 490d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len -= 4; 491d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 492d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes += 4; 493d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 494d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (dst) { 495d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len == 0) { 496d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOSPC; 497d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 498d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 499d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *dst++ = (char)c; 500d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len--; 501d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 502d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes++; 503d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 504d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 505d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 506d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* NULL */ 507d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (dst) { 508d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len == 0) { 509d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOSPC; 510d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 511d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 512d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *dst = '\0'; 513d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 514d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Now we've printed it, validate the domain */ 515d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type & DOMAIN && !valid_domainname(odst, type)) { 516d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *odst = '\0'; 517d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 1; 518d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 519d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 520d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 521d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 522d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return (ssize_t)bytes; 523d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 524d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 525d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define ADDR6SZ 16 526d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic size_t 527d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tandhcp_optlen(const struct dhcp_opt *opt, size_t dl) 528d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 529d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t sz; 530d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 531ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan if (opt->type & ADDRIPV6) 532ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan sz = ADDR6SZ; 533ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan else if (opt->type & (UINT32 | ADDRIPV4)) 534ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan sz = sizeof(uint32_t); 535ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan else if (opt->type & UINT16) 536ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan sz = sizeof(uint16_t); 537ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan else if (opt->type & (UINT8 | BITFLAG)) 538ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan sz = sizeof(uint8_t); 539ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan else if (opt->type & FLAG) 540d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 541ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan else { 542ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan /* All other types are variable length */ 543d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->len) { 544ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan if ((size_t)opt->len > dl) { 545ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan errno = ENODATA; 546ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan return -1; 547ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan } 548ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan return (ssize_t)opt->len; 549d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 550ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan return (ssize_t)dl; 551d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 552ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan if (dl < sz) { 553ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan errno = ENODATA; 554ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan return -1; 555d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 556d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 557ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan /* Trim any extra data. 558ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan * Maybe we need a settng to reject DHCP options with extra data? */ 559ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan if (opt->type & ARRAY) 560ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan return (ssize_t)(dl - (dl % sz)); 561ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan return (ssize_t)sz; 562d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 563d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 564d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 565d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define PO_IFNAME 566d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 567d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define PO_IFNAME __unused 568d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 569d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 570d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanssize_t 571d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanprint_option(char *s, size_t len, int type, const uint8_t *data, size_t dl, 572d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan PO_IFNAME const char *ifname) 573d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 574d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const uint8_t *e, *t; 575d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint16_t u16; 576d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int16_t s16; 577d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint32_t u32; 578d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int32_t s32; 579d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct in_addr addr; 580d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ssize_t bytes = 0, sl; 581d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t l; 582d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *tmp; 583d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 584d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type & RFC3397) { 585d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = decode_rfc3397(NULL, 0, data, dl); 586d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sl == 0 || sl == -1) 587d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return sl; 588d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = (size_t)sl + 1; 589d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan tmp = malloc(l); 590d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (tmp == NULL) 591d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 592d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan decode_rfc3397(tmp, l, data, dl); 593d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = print_string(s, len, type, (uint8_t *)tmp, l - 1); 594d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(tmp); 595d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return sl; 596d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 597d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 598d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET 599d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type & RFC3361) { 600d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((tmp = decode_rfc3361(data, dl)) == NULL) 601d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 602d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = strlen(tmp); 603d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = print_string(s, len, type, (uint8_t *)tmp, l); 604d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(tmp); 605d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return sl; 606d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 607d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 608d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type & RFC3442) 609d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return decode_rfc3442(s, len, data, dl); 610d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 611d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type & RFC5969) 612d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return decode_rfc5969(s, len, data, dl); 613d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 614d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 615d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type & STRING) 616d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return print_string(s, len, type, data, dl); 617d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 618d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type & FLAG) { 619d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (s) { 620d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *s++ = '1'; 621d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *s = '\0'; 622d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 623d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 1; 624d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 625d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 626d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!s) { 627d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type & UINT8) 628d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = 3; 629d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (type & UINT16) { 630d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = 5; 631d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dl /= 2; 632d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (type & SINT16) { 633d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = 6; 634d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dl /= 2; 635d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (type & UINT32) { 636d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = 10; 637d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dl /= 4; 638d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (type & SINT32) { 639d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = 11; 640d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dl /= 4; 641d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (type & ADDRIPV4) { 642d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = 16; 643d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dl /= 4; 644d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 645d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 646d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (type & ADDRIPV6) { 647d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = data + dl; 648d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l = 0; 649d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (data < e) { 650d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (l) 651d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l++; /* space */ 652d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = ipv6_printaddr(NULL, 0, data, ifname); 653d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sl != -1) 654d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan l += (size_t)sl; 655d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan data += 16; 656d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 657d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return (ssize_t)l; 658d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 659d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 660d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else { 661d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = EINVAL; 662d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return -1; 663d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 664d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return (ssize_t)(l * dl); 665d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 666d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 667d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan t = data; 668d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = data + dl; 669d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while (data < e) { 670d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (data != t) { 671d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *s++ = ' '; 672d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes++; 673d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len--; 674d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 675d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (type & UINT8) { 676d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = snprintf(s, len, "%u", *data); 677d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan data++; 678d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (type & UINT16) { 679d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&u16, data, sizeof(u16)); 680d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan u16 = ntohs(u16); 681d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = snprintf(s, len, "%u", u16); 682d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan data += sizeof(u16); 683d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (type & SINT16) { 684d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&u16, data, sizeof(u16)); 685d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan s16 = (int16_t)ntohs(u16); 686d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = snprintf(s, len, "%d", s16); 687d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan data += sizeof(u16); 688d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (type & UINT32) { 689d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&u32, data, sizeof(u32)); 690d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan u32 = ntohl(u32); 691d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = snprintf(s, len, "%u", u32); 692d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan data += sizeof(u32); 693d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (type & SINT32) { 694d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&u32, data, sizeof(u32)); 695d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan s32 = (int32_t)ntohl(u32); 696d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = snprintf(s, len, "%d", s32); 697d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan data += sizeof(u32); 698d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else if (type & ADDRIPV4) { 699d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&addr.s_addr, data, sizeof(addr.s_addr)); 700d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = snprintf(s, len, "%s", inet_ntoa(addr)); 701d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan data += sizeof(addr.s_addr); 702d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 703d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef INET6 704d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else if (type & ADDRIPV6) { 705d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ssize_t r; 706d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 707d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan r = ipv6_printaddr(s, len, data, ifname); 708d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (r != -1) 709d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = r; 710d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 711d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = 0; 712d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan data += 16; 713d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 714d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 715d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 716d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sl = 0; 7179ae79b8946de6ac1e295417875f2ac7316dd0f80Samuel Tan if (len <= sl) { 7189ae79b8946de6ac1e295417875f2ac7316dd0f80Samuel Tan bytes += len; 7199ae79b8946de6ac1e295417875f2ac7316dd0f80Samuel Tan break; 7209ae79b8946de6ac1e295417875f2ac7316dd0f80Samuel Tan } 721d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len -= (size_t)sl; 722d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan bytes += sl; 723d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan s += sl; 724d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 725d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 726d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return bytes; 727d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 728d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 729e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan/* Lease file name is formatted according to the expectation of the ChromiumOS's 730e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan * connection manager (shill). */ 731d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanint 732d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tandhcp_set_leasefile(char *leasefile, size_t len, int family, 733d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct interface *ifp, const char *extra) 734d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 735d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char ssid[len]; 736d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 737d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp->name[0] == '\0') { 738d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan strlcpy(leasefile, ifp->ctx->pidfile, len); 739d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 740d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 741d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 742a3595821594453ea89ef8e6790927694b0a1adf1Samuel Tan if (strlen(ifp->lease_identifier) > 0) { 743e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan return snprintf(leasefile, len, 744e942e091ac1efb0ee1916add2b12f64fdfd59476Samuel Tan family == AF_INET ? LEASEFILE : LEASEFILE6, 74568df7cfd9156424667636ad3544d0fa9f337647dSamuel Tan ifp->lease_identifier, "", extra); 746d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 747d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return snprintf(leasefile, len, 7488e603a0d0354b88712f1a81cc48dbd9936244fd5Samuel Tan family == AF_INET ? LEASEFILE : LEASEFILE6, 74968df7cfd9156424667636ad3544d0fa9f337647dSamuel Tan ifp->name, "", extra); 750d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 751d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 752d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic size_t 753d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tandhcp_envoption1(struct dhcpcd_ctx *ctx, char **env, const char *prefix, 754d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct dhcp_opt *opt, int vname, const uint8_t *od, size_t ol, 755d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const char *ifname) 756d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 757d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ssize_t len; 758d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t e; 759d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *v, *val; 760d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 761ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan /* Ensure a valid length */ 762ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan ol = (size_t)dhcp_optlen(opt, ol); 763ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan if ((ssize_t)ol == -1) 764ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan return 0; 765ddbf02ae19016710a31fca4b2bc26f08a6fe191fSamuel Tan 766d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan len = print_option(NULL, 0, opt->type, od, ol, ifname); 767d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len < 0) 768d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 769d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (vname) 770d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = strlen(opt->var) + 1; 771d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 772d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = 0; 773d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (prefix) 774d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e += strlen(prefix); 775d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e += (size_t)len + 2; 776d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (env == NULL) 777d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return e; 778d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan v = val = *env = malloc(e); 779d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (v == NULL) { 780d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx, LOG_ERR, "%s: %m", __func__); 781d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 782d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 783d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (vname) 784d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan v += snprintf(val, e, "%s_%s=", prefix, opt->var); 785d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 786d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan v += snprintf(val, e, "%s=", prefix); 787d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (len != 0) 788d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan print_option(v, (size_t)len + 1, opt->type, od, ol, ifname); 789d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return e; 790d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 791d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 792d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tansize_t 793d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tandhcp_envoption(struct dhcpcd_ctx *ctx, char **env, const char *prefix, 794d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const char *ifname, struct dhcp_opt *opt, 795d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const uint8_t *(*dgetopt)(struct dhcpcd_ctx *, 796d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t *, unsigned int *, size_t *, 797d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const uint8_t *, size_t, struct dhcp_opt **), 798d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const uint8_t *od, size_t ol) 799d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 800d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t e, i, n, eos, eol; 801d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned int eoc; 802d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const uint8_t *eod; 803d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan int ov; 804d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_opt *eopt, *oopt; 805d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan char *pfx; 806d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 807d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* If no embedded or encapsulated options, it's easy */ 808d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->embopts_len == 0 && opt->encopts_len == 0) { 809d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (dhcp_envoption1(ctx, env == NULL ? NULL : &env[0], 810d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan prefix, opt, 1, od, ol, ifname)) 811d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 1; 812d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 813d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 814d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 815d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Create a new prefix based on the option */ 816d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (env) { 817d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->type & INDEX) { 818d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->index > 999) { 819d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan errno = ENOBUFS; 820d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx, LOG_ERR, "%s: %m", __func__); 821d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 822d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 823d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 824d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = strlen(prefix) + strlen(opt->var) + 2 + 825d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (opt->type & INDEX ? 3 : 0); 826d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan pfx = malloc(e); 827d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (pfx == NULL) { 828d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ctx, LOG_ERR, "%s: %m", __func__); 829d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return 0; 830d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 831d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->type & INDEX) 832d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan snprintf(pfx, e, "%s_%s%d", prefix, 833d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan opt->var, ++opt->index); 834d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 835d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan snprintf(pfx, e, "%s_%s", prefix, opt->var); 836d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 837d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan pfx = NULL; 838d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 839d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Embedded options are always processed first as that 840d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * is a fixed layout */ 841d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n = 0; 842d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (i = 0, eopt = opt->embopts; i < opt->embopts_len; i++, eopt++) { 843d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan e = dhcp_optlen(eopt, ol); 8440c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan if (e == 0) { 8450c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan /* An option was expected, but there is not enough 8460c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan * data for it. 8470c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan * This may not be an error as some options like 8480c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan * DHCP FQDN in RFC4702 have a string as the last 8490c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan * option which is optional. 8500c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan * FIXME: Add an flag to the options to indicate 8510c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan * wether this is allowable or not. */ 8520c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan if (ol != 0 || i + 1 < opt->embopts_len) 8530c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan logger(ctx, LOG_WARNING, 8540c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan "%s: %s: malformed option %d", 8550c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan ifname, __func__, opt->option); 8560c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan goto out; 8570c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tan } 858d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Use the option prefix if the embedded option 859d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * name is different. 860d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * This avoids new_fqdn_fqdn which would be silly. */ 861d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ov = strcmp(opt->var, eopt->var); 862d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (dhcp_envoption1(ctx, env == NULL ? NULL : &env[n], 863d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan pfx, eopt, ov, od, e, ifname)) 864d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n++; 865d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan od += e; 866d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ol -= e; 867d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 868d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 869d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Enumerate our encapsulated options */ 870d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (opt->encopts_len && ol > 0) { 871d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Zero any option indexes 872d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * We assume that referenced encapsulated options are NEVER 873d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * recursive as the index order could break. */ 874d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (i = 0, eopt = opt->encopts; 875d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i < opt->encopts_len; 876d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i++, eopt++) 877d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 878d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan eoc = opt->option; 879d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (eopt->type & OPTION) { 880d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dgetopt(ctx, NULL, &eoc, NULL, NULL, 0, &oopt); 881d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (oopt) 882d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan oopt->index = 0; 883d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 884d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 885d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 886d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan while ((eod = dgetopt(ctx, &eos, &eoc, &eol, od, ol, &oopt))) { 887d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (i = 0, eopt = opt->encopts; 888d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i < opt->encopts_len; 889d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan i++, eopt++) 890d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan { 891d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (eopt->option == eoc) { 892d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (eopt->type & OPTION) { 893d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (oopt == NULL) 894d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Report error? */ 895d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 896d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 897d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan n += dhcp_envoption(ctx, 898d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan env == NULL ? NULL : &env[n], pfx, 899d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifname, 900d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan eopt->type & OPTION ? oopt : eopt, 901d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dgetopt, eod, eol); 902d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 903d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 904d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 905d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan od += eos + eol; 906d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ol -= eos + eol; 907d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 908d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 909d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 9100c07e7a4a10f902911d93f37e01b8a0308d67e96Samuel Tanout: 911d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (env) 912d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(pfx); 913d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 914d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Return number of options found */ 915d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return n; 916d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 917d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 918d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid 919d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tandhcp_zero_index(struct dhcp_opt *opt) 920d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 921d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan size_t i; 922d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_opt *o; 923d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 924d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan opt->index = 0; 925d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (i = 0, o = opt->embopts; i < opt->embopts_len; i++, o++) 926d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcp_zero_index(o); 927d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (i = 0, o = opt->encopts; i < opt->encopts_len; i++, o++) 928d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcp_zero_index(o); 929d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 930