163783933SJohn Baldwin /*- 263783933SJohn Baldwin * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 363783933SJohn Baldwin * 463783933SJohn Baldwin * Copyright (c) 2012 The FreeBSD Foundation 563783933SJohn Baldwin * 663783933SJohn Baldwin * This software was developed by Edward Tomasz Napierala under sponsorship 763783933SJohn Baldwin * from the FreeBSD Foundation. 863783933SJohn Baldwin * 963783933SJohn Baldwin * Redistribution and use in source and binary forms, with or without 1063783933SJohn Baldwin * modification, are permitted provided that the following conditions 1163783933SJohn Baldwin * are met: 1263783933SJohn Baldwin * 1. Redistributions of source code must retain the above copyright 1363783933SJohn Baldwin * notice, this list of conditions and the following disclaimer. 1463783933SJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright 1563783933SJohn Baldwin * notice, this list of conditions and the following disclaimer in the 1663783933SJohn Baldwin * documentation and/or other materials provided with the distribution. 1763783933SJohn Baldwin * 1863783933SJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1963783933SJohn Baldwin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2063783933SJohn Baldwin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2163783933SJohn Baldwin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2263783933SJohn Baldwin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2363783933SJohn Baldwin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2463783933SJohn Baldwin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2563783933SJohn Baldwin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2663783933SJohn Baldwin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2763783933SJohn Baldwin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2863783933SJohn Baldwin * SUCH DAMAGE. 2963783933SJohn Baldwin */ 3063783933SJohn Baldwin 3163783933SJohn Baldwin #include <assert.h> 3263783933SJohn Baldwin #include <stdio.h> 3363783933SJohn Baldwin #include <stdlib.h> 3463783933SJohn Baldwin #include <string.h> 3563783933SJohn Baldwin 3663783933SJohn Baldwin #include "libiscsiutil.h" 3763783933SJohn Baldwin 3863783933SJohn Baldwin struct keys * 3963783933SJohn Baldwin keys_new(void) 4063783933SJohn Baldwin { 4163783933SJohn Baldwin struct keys *keys; 4263783933SJohn Baldwin 4363783933SJohn Baldwin keys = calloc(1, sizeof(*keys)); 4463783933SJohn Baldwin if (keys == NULL) 4563783933SJohn Baldwin log_err(1, "calloc"); 4663783933SJohn Baldwin 4763783933SJohn Baldwin return (keys); 4863783933SJohn Baldwin } 4963783933SJohn Baldwin 5063783933SJohn Baldwin void 5163783933SJohn Baldwin keys_delete(struct keys *keys) 5263783933SJohn Baldwin { 5363783933SJohn Baldwin 54fd99905bSJohn Baldwin for (int i = 0; i < KEYS_MAX; i++) { 55fd99905bSJohn Baldwin free(keys->keys_names[i]); 56fd99905bSJohn Baldwin free(keys->keys_values[i]); 57fd99905bSJohn Baldwin } 5863783933SJohn Baldwin free(keys); 5963783933SJohn Baldwin } 6063783933SJohn Baldwin 6163783933SJohn Baldwin void 6225700db3SJohn Baldwin keys_load(struct keys *keys, const char *data, size_t len) 6363783933SJohn Baldwin { 6463783933SJohn Baldwin int i; 65fd99905bSJohn Baldwin char *keys_data, *name, *pair, *value; 6663783933SJohn Baldwin size_t pair_len; 6763783933SJohn Baldwin 6825700db3SJohn Baldwin if (len == 0) 6963783933SJohn Baldwin return; 7063783933SJohn Baldwin 7125700db3SJohn Baldwin if (data[len - 1] != '\0') 7263783933SJohn Baldwin log_errx(1, "protocol error: key not NULL-terminated\n"); 7363783933SJohn Baldwin 7425700db3SJohn Baldwin keys_data = malloc(len); 75fd99905bSJohn Baldwin if (keys_data == NULL) 7663783933SJohn Baldwin log_err(1, "malloc"); 7725700db3SJohn Baldwin memcpy(keys_data, data, len); 7863783933SJohn Baldwin 7963783933SJohn Baldwin /* 8063783933SJohn Baldwin * XXX: Review this carefully. 8163783933SJohn Baldwin */ 82fd99905bSJohn Baldwin pair = keys_data; 8363783933SJohn Baldwin for (i = 0;; i++) { 8463783933SJohn Baldwin if (i >= KEYS_MAX) 8563783933SJohn Baldwin log_errx(1, "too many keys received"); 8663783933SJohn Baldwin 8763783933SJohn Baldwin pair_len = strlen(pair); 8863783933SJohn Baldwin 89fd99905bSJohn Baldwin value = pair; 90fd99905bSJohn Baldwin name = strsep(&value, "="); 91fd99905bSJohn Baldwin if (name == NULL || value == NULL) 9263783933SJohn Baldwin log_errx(1, "malformed keys"); 93fd99905bSJohn Baldwin keys->keys_names[i] = checked_strdup(name); 94fd99905bSJohn Baldwin keys->keys_values[i] = checked_strdup(value); 9563783933SJohn Baldwin log_debugx("key received: \"%s=%s\"", 9663783933SJohn Baldwin keys->keys_names[i], keys->keys_values[i]); 9763783933SJohn Baldwin 9863783933SJohn Baldwin pair += pair_len + 1; /* +1 to skip the terminating '\0'. */ 9925700db3SJohn Baldwin if (pair == keys_data + len) 10063783933SJohn Baldwin break; 10125700db3SJohn Baldwin assert(pair < keys_data + len); 10263783933SJohn Baldwin } 103fd99905bSJohn Baldwin free(keys_data); 10463783933SJohn Baldwin } 10563783933SJohn Baldwin 10663783933SJohn Baldwin void 10725700db3SJohn Baldwin keys_save(struct keys *keys, char **datap, size_t *lenp) 10863783933SJohn Baldwin { 1092ccb8fdeSJohn Baldwin FILE *fp; 11063783933SJohn Baldwin char *data; 11163783933SJohn Baldwin size_t len; 11263783933SJohn Baldwin int i; 11363783933SJohn Baldwin 1142ccb8fdeSJohn Baldwin fp = open_memstream(&data, &len); 1152ccb8fdeSJohn Baldwin if (fp == NULL) 1162ccb8fdeSJohn Baldwin log_err(1, "open_memstream"); 11763783933SJohn Baldwin for (i = 0; i < KEYS_MAX; i++) { 11863783933SJohn Baldwin if (keys->keys_names[i] == NULL) 11963783933SJohn Baldwin break; 1202ccb8fdeSJohn Baldwin 1212ccb8fdeSJohn Baldwin fprintf(fp, "%s=%s", keys->keys_names[i], keys->keys_values[i]); 1222ccb8fdeSJohn Baldwin 1232ccb8fdeSJohn Baldwin /* Append a '\0' after each key pair. */ 1242ccb8fdeSJohn Baldwin fputc('\0', fp); 12563783933SJohn Baldwin } 1262ccb8fdeSJohn Baldwin if (fclose(fp) != 0) 1272ccb8fdeSJohn Baldwin log_err(1, "fclose"); 12863783933SJohn Baldwin 1292ccb8fdeSJohn Baldwin if (len == 0) { 1302ccb8fdeSJohn Baldwin free(data); 1312ccb8fdeSJohn Baldwin data = NULL; 1322ccb8fdeSJohn Baldwin } 13363783933SJohn Baldwin 13425700db3SJohn Baldwin *datap = data; 13525700db3SJohn Baldwin *lenp = len; 13663783933SJohn Baldwin } 13763783933SJohn Baldwin 13863783933SJohn Baldwin const char * 13963783933SJohn Baldwin keys_find(struct keys *keys, const char *name) 14063783933SJohn Baldwin { 14163783933SJohn Baldwin int i; 14263783933SJohn Baldwin 14363783933SJohn Baldwin /* 14463783933SJohn Baldwin * Note that we don't handle duplicated key names here, 14563783933SJohn Baldwin * as they are not supposed to happen in requests, and if they do, 14663783933SJohn Baldwin * it's an initiator error. 14763783933SJohn Baldwin */ 14863783933SJohn Baldwin for (i = 0; i < KEYS_MAX; i++) { 14963783933SJohn Baldwin if (keys->keys_names[i] == NULL) 15063783933SJohn Baldwin return (NULL); 15163783933SJohn Baldwin if (strcmp(keys->keys_names[i], name) == 0) 15263783933SJohn Baldwin return (keys->keys_values[i]); 15363783933SJohn Baldwin } 15463783933SJohn Baldwin return (NULL); 15563783933SJohn Baldwin } 15663783933SJohn Baldwin 15763783933SJohn Baldwin void 15863783933SJohn Baldwin keys_add(struct keys *keys, const char *name, const char *value) 15963783933SJohn Baldwin { 16063783933SJohn Baldwin int i; 16163783933SJohn Baldwin 16263783933SJohn Baldwin log_debugx("key to send: \"%s=%s\"", name, value); 16363783933SJohn Baldwin 16463783933SJohn Baldwin /* 16563783933SJohn Baldwin * Note that we don't check for duplicates here, as they are perfectly 166*29b36af9SGordon Bergling * fine in responses, e.g. the "TargetName" keys in discovery session 16763783933SJohn Baldwin * response. 16863783933SJohn Baldwin */ 16963783933SJohn Baldwin for (i = 0; i < KEYS_MAX; i++) { 17063783933SJohn Baldwin if (keys->keys_names[i] == NULL) { 17163783933SJohn Baldwin keys->keys_names[i] = checked_strdup(name); 17263783933SJohn Baldwin keys->keys_values[i] = checked_strdup(value); 17363783933SJohn Baldwin return; 17463783933SJohn Baldwin } 17563783933SJohn Baldwin } 17663783933SJohn Baldwin log_errx(1, "too many keys"); 17763783933SJohn Baldwin } 17863783933SJohn Baldwin 17963783933SJohn Baldwin void 18063783933SJohn Baldwin keys_add_int(struct keys *keys, const char *name, int value) 18163783933SJohn Baldwin { 18263783933SJohn Baldwin char *str; 18363783933SJohn Baldwin int ret; 18463783933SJohn Baldwin 18563783933SJohn Baldwin ret = asprintf(&str, "%d", value); 18663783933SJohn Baldwin if (ret <= 0) 18763783933SJohn Baldwin log_err(1, "asprintf"); 18863783933SJohn Baldwin 18963783933SJohn Baldwin keys_add(keys, name, str); 19063783933SJohn Baldwin free(str); 19163783933SJohn Baldwin } 192