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 54*fd99905bSJohn Baldwin for (int i = 0; i < KEYS_MAX; i++) { 55*fd99905bSJohn Baldwin free(keys->keys_names[i]); 56*fd99905bSJohn Baldwin free(keys->keys_values[i]); 57*fd99905bSJohn Baldwin } 5863783933SJohn Baldwin free(keys); 5963783933SJohn Baldwin } 6063783933SJohn Baldwin 6163783933SJohn Baldwin void 6263783933SJohn Baldwin keys_load(struct keys *keys, const struct pdu *pdu) 6363783933SJohn Baldwin { 6463783933SJohn Baldwin int i; 65*fd99905bSJohn Baldwin char *keys_data, *name, *pair, *value; 6663783933SJohn Baldwin size_t pair_len; 6763783933SJohn Baldwin 6863783933SJohn Baldwin if (pdu->pdu_data_len == 0) 6963783933SJohn Baldwin return; 7063783933SJohn Baldwin 7163783933SJohn Baldwin if (pdu->pdu_data[pdu->pdu_data_len - 1] != '\0') 7263783933SJohn Baldwin log_errx(1, "protocol error: key not NULL-terminated\n"); 7363783933SJohn Baldwin 74*fd99905bSJohn Baldwin keys_data = malloc(pdu->pdu_data_len); 75*fd99905bSJohn Baldwin if (keys_data == NULL) 7663783933SJohn Baldwin log_err(1, "malloc"); 77*fd99905bSJohn Baldwin memcpy(keys_data, pdu->pdu_data, pdu->pdu_data_len); 7863783933SJohn Baldwin 7963783933SJohn Baldwin /* 8063783933SJohn Baldwin * XXX: Review this carefully. 8163783933SJohn Baldwin */ 82*fd99905bSJohn 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 89*fd99905bSJohn Baldwin value = pair; 90*fd99905bSJohn Baldwin name = strsep(&value, "="); 91*fd99905bSJohn Baldwin if (name == NULL || value == NULL) 9263783933SJohn Baldwin log_errx(1, "malformed keys"); 93*fd99905bSJohn Baldwin keys->keys_names[i] = checked_strdup(name); 94*fd99905bSJohn 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'. */ 99*fd99905bSJohn Baldwin if (pair == keys_data + pdu->pdu_data_len) 10063783933SJohn Baldwin break; 101*fd99905bSJohn Baldwin assert(pair < keys_data + pdu->pdu_data_len); 10263783933SJohn Baldwin } 103*fd99905bSJohn Baldwin free(keys_data); 10463783933SJohn Baldwin } 10563783933SJohn Baldwin 10663783933SJohn Baldwin void 10763783933SJohn Baldwin keys_save(struct keys *keys, struct pdu *pdu) 10863783933SJohn Baldwin { 10963783933SJohn Baldwin char *data; 11063783933SJohn Baldwin size_t len; 11163783933SJohn Baldwin int i; 11263783933SJohn Baldwin 11363783933SJohn Baldwin /* 11463783933SJohn Baldwin * XXX: Not particularly efficient. 11563783933SJohn Baldwin */ 11663783933SJohn Baldwin len = 0; 11763783933SJohn Baldwin for (i = 0; i < KEYS_MAX; i++) { 11863783933SJohn Baldwin if (keys->keys_names[i] == NULL) 11963783933SJohn Baldwin break; 12063783933SJohn Baldwin /* 12163783933SJohn Baldwin * +1 for '=', +1 for '\0'. 12263783933SJohn Baldwin */ 12363783933SJohn Baldwin len += strlen(keys->keys_names[i]) + 12463783933SJohn Baldwin strlen(keys->keys_values[i]) + 2; 12563783933SJohn Baldwin } 12663783933SJohn Baldwin 12763783933SJohn Baldwin if (len == 0) 12863783933SJohn Baldwin return; 12963783933SJohn Baldwin 13063783933SJohn Baldwin data = malloc(len); 13163783933SJohn Baldwin if (data == NULL) 13263783933SJohn Baldwin log_err(1, "malloc"); 13363783933SJohn Baldwin 13463783933SJohn Baldwin pdu->pdu_data = data; 13563783933SJohn Baldwin pdu->pdu_data_len = len; 13663783933SJohn Baldwin 13763783933SJohn Baldwin for (i = 0; i < KEYS_MAX; i++) { 13863783933SJohn Baldwin if (keys->keys_names[i] == NULL) 13963783933SJohn Baldwin break; 14063783933SJohn Baldwin data += sprintf(data, "%s=%s", 14163783933SJohn Baldwin keys->keys_names[i], keys->keys_values[i]); 14263783933SJohn Baldwin data += 1; /* for '\0'. */ 14363783933SJohn Baldwin } 14463783933SJohn Baldwin } 14563783933SJohn Baldwin 14663783933SJohn Baldwin const char * 14763783933SJohn Baldwin keys_find(struct keys *keys, const char *name) 14863783933SJohn Baldwin { 14963783933SJohn Baldwin int i; 15063783933SJohn Baldwin 15163783933SJohn Baldwin /* 15263783933SJohn Baldwin * Note that we don't handle duplicated key names here, 15363783933SJohn Baldwin * as they are not supposed to happen in requests, and if they do, 15463783933SJohn Baldwin * it's an initiator error. 15563783933SJohn Baldwin */ 15663783933SJohn Baldwin for (i = 0; i < KEYS_MAX; i++) { 15763783933SJohn Baldwin if (keys->keys_names[i] == NULL) 15863783933SJohn Baldwin return (NULL); 15963783933SJohn Baldwin if (strcmp(keys->keys_names[i], name) == 0) 16063783933SJohn Baldwin return (keys->keys_values[i]); 16163783933SJohn Baldwin } 16263783933SJohn Baldwin return (NULL); 16363783933SJohn Baldwin } 16463783933SJohn Baldwin 16563783933SJohn Baldwin void 16663783933SJohn Baldwin keys_add(struct keys *keys, const char *name, const char *value) 16763783933SJohn Baldwin { 16863783933SJohn Baldwin int i; 16963783933SJohn Baldwin 17063783933SJohn Baldwin log_debugx("key to send: \"%s=%s\"", name, value); 17163783933SJohn Baldwin 17263783933SJohn Baldwin /* 17363783933SJohn Baldwin * Note that we don't check for duplicates here, as they are perfectly 17463783933SJohn Baldwin * fine in responses, e.g. the "TargetName" keys in discovery sesion 17563783933SJohn Baldwin * response. 17663783933SJohn Baldwin */ 17763783933SJohn Baldwin for (i = 0; i < KEYS_MAX; i++) { 17863783933SJohn Baldwin if (keys->keys_names[i] == NULL) { 17963783933SJohn Baldwin keys->keys_names[i] = checked_strdup(name); 18063783933SJohn Baldwin keys->keys_values[i] = checked_strdup(value); 18163783933SJohn Baldwin return; 18263783933SJohn Baldwin } 18363783933SJohn Baldwin } 18463783933SJohn Baldwin log_errx(1, "too many keys"); 18563783933SJohn Baldwin } 18663783933SJohn Baldwin 18763783933SJohn Baldwin void 18863783933SJohn Baldwin keys_add_int(struct keys *keys, const char *name, int value) 18963783933SJohn Baldwin { 19063783933SJohn Baldwin char *str; 19163783933SJohn Baldwin int ret; 19263783933SJohn Baldwin 19363783933SJohn Baldwin ret = asprintf(&str, "%d", value); 19463783933SJohn Baldwin if (ret <= 0) 19563783933SJohn Baldwin log_err(1, "asprintf"); 19663783933SJohn Baldwin 19763783933SJohn Baldwin keys_add(keys, name, str); 19863783933SJohn Baldwin free(str); 19963783933SJohn Baldwin } 200