1*63783933SJohn Baldwin /*- 2*63783933SJohn Baldwin * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*63783933SJohn Baldwin * 4*63783933SJohn Baldwin * Copyright (c) 2012 The FreeBSD Foundation 5*63783933SJohn Baldwin * 6*63783933SJohn Baldwin * This software was developed by Edward Tomasz Napierala under sponsorship 7*63783933SJohn Baldwin * from the FreeBSD Foundation. 8*63783933SJohn Baldwin * 9*63783933SJohn Baldwin * Redistribution and use in source and binary forms, with or without 10*63783933SJohn Baldwin * modification, are permitted provided that the following conditions 11*63783933SJohn Baldwin * are met: 12*63783933SJohn Baldwin * 1. Redistributions of source code must retain the above copyright 13*63783933SJohn Baldwin * notice, this list of conditions and the following disclaimer. 14*63783933SJohn Baldwin * 2. Redistributions in binary form must reproduce the above copyright 15*63783933SJohn Baldwin * notice, this list of conditions and the following disclaimer in the 16*63783933SJohn Baldwin * documentation and/or other materials provided with the distribution. 17*63783933SJohn Baldwin * 18*63783933SJohn Baldwin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19*63783933SJohn Baldwin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*63783933SJohn Baldwin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*63783933SJohn Baldwin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22*63783933SJohn Baldwin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23*63783933SJohn Baldwin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24*63783933SJohn Baldwin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25*63783933SJohn Baldwin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26*63783933SJohn Baldwin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27*63783933SJohn Baldwin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28*63783933SJohn Baldwin * SUCH DAMAGE. 29*63783933SJohn Baldwin */ 30*63783933SJohn Baldwin 31*63783933SJohn Baldwin #include <assert.h> 32*63783933SJohn Baldwin #include <stdio.h> 33*63783933SJohn Baldwin #include <stdlib.h> 34*63783933SJohn Baldwin #include <string.h> 35*63783933SJohn Baldwin 36*63783933SJohn Baldwin #include "libiscsiutil.h" 37*63783933SJohn Baldwin 38*63783933SJohn Baldwin struct keys * 39*63783933SJohn Baldwin keys_new(void) 40*63783933SJohn Baldwin { 41*63783933SJohn Baldwin struct keys *keys; 42*63783933SJohn Baldwin 43*63783933SJohn Baldwin keys = calloc(1, sizeof(*keys)); 44*63783933SJohn Baldwin if (keys == NULL) 45*63783933SJohn Baldwin log_err(1, "calloc"); 46*63783933SJohn Baldwin 47*63783933SJohn Baldwin return (keys); 48*63783933SJohn Baldwin } 49*63783933SJohn Baldwin 50*63783933SJohn Baldwin void 51*63783933SJohn Baldwin keys_delete(struct keys *keys) 52*63783933SJohn Baldwin { 53*63783933SJohn Baldwin 54*63783933SJohn Baldwin free(keys->keys_data); 55*63783933SJohn Baldwin free(keys); 56*63783933SJohn Baldwin } 57*63783933SJohn Baldwin 58*63783933SJohn Baldwin void 59*63783933SJohn Baldwin keys_load(struct keys *keys, const struct pdu *pdu) 60*63783933SJohn Baldwin { 61*63783933SJohn Baldwin int i; 62*63783933SJohn Baldwin char *pair; 63*63783933SJohn Baldwin size_t pair_len; 64*63783933SJohn Baldwin 65*63783933SJohn Baldwin if (pdu->pdu_data_len == 0) 66*63783933SJohn Baldwin return; 67*63783933SJohn Baldwin 68*63783933SJohn Baldwin if (pdu->pdu_data[pdu->pdu_data_len - 1] != '\0') 69*63783933SJohn Baldwin log_errx(1, "protocol error: key not NULL-terminated\n"); 70*63783933SJohn Baldwin 71*63783933SJohn Baldwin assert(keys->keys_data == NULL); 72*63783933SJohn Baldwin keys->keys_data_len = pdu->pdu_data_len; 73*63783933SJohn Baldwin keys->keys_data = malloc(keys->keys_data_len); 74*63783933SJohn Baldwin if (keys->keys_data == NULL) 75*63783933SJohn Baldwin log_err(1, "malloc"); 76*63783933SJohn Baldwin memcpy(keys->keys_data, pdu->pdu_data, keys->keys_data_len); 77*63783933SJohn Baldwin 78*63783933SJohn Baldwin /* 79*63783933SJohn Baldwin * XXX: Review this carefully. 80*63783933SJohn Baldwin */ 81*63783933SJohn Baldwin pair = keys->keys_data; 82*63783933SJohn Baldwin for (i = 0;; i++) { 83*63783933SJohn Baldwin if (i >= KEYS_MAX) 84*63783933SJohn Baldwin log_errx(1, "too many keys received"); 85*63783933SJohn Baldwin 86*63783933SJohn Baldwin pair_len = strlen(pair); 87*63783933SJohn Baldwin 88*63783933SJohn Baldwin keys->keys_values[i] = pair; 89*63783933SJohn Baldwin keys->keys_names[i] = strsep(&keys->keys_values[i], "="); 90*63783933SJohn Baldwin if (keys->keys_names[i] == NULL || keys->keys_values[i] == NULL) 91*63783933SJohn Baldwin log_errx(1, "malformed keys"); 92*63783933SJohn Baldwin log_debugx("key received: \"%s=%s\"", 93*63783933SJohn Baldwin keys->keys_names[i], keys->keys_values[i]); 94*63783933SJohn Baldwin 95*63783933SJohn Baldwin pair += pair_len + 1; /* +1 to skip the terminating '\0'. */ 96*63783933SJohn Baldwin if (pair == keys->keys_data + keys->keys_data_len) 97*63783933SJohn Baldwin break; 98*63783933SJohn Baldwin assert(pair < keys->keys_data + keys->keys_data_len); 99*63783933SJohn Baldwin } 100*63783933SJohn Baldwin } 101*63783933SJohn Baldwin 102*63783933SJohn Baldwin void 103*63783933SJohn Baldwin keys_save(struct keys *keys, struct pdu *pdu) 104*63783933SJohn Baldwin { 105*63783933SJohn Baldwin char *data; 106*63783933SJohn Baldwin size_t len; 107*63783933SJohn Baldwin int i; 108*63783933SJohn Baldwin 109*63783933SJohn Baldwin /* 110*63783933SJohn Baldwin * XXX: Not particularly efficient. 111*63783933SJohn Baldwin */ 112*63783933SJohn Baldwin len = 0; 113*63783933SJohn Baldwin for (i = 0; i < KEYS_MAX; i++) { 114*63783933SJohn Baldwin if (keys->keys_names[i] == NULL) 115*63783933SJohn Baldwin break; 116*63783933SJohn Baldwin /* 117*63783933SJohn Baldwin * +1 for '=', +1 for '\0'. 118*63783933SJohn Baldwin */ 119*63783933SJohn Baldwin len += strlen(keys->keys_names[i]) + 120*63783933SJohn Baldwin strlen(keys->keys_values[i]) + 2; 121*63783933SJohn Baldwin } 122*63783933SJohn Baldwin 123*63783933SJohn Baldwin if (len == 0) 124*63783933SJohn Baldwin return; 125*63783933SJohn Baldwin 126*63783933SJohn Baldwin data = malloc(len); 127*63783933SJohn Baldwin if (data == NULL) 128*63783933SJohn Baldwin log_err(1, "malloc"); 129*63783933SJohn Baldwin 130*63783933SJohn Baldwin pdu->pdu_data = data; 131*63783933SJohn Baldwin pdu->pdu_data_len = len; 132*63783933SJohn Baldwin 133*63783933SJohn Baldwin for (i = 0; i < KEYS_MAX; i++) { 134*63783933SJohn Baldwin if (keys->keys_names[i] == NULL) 135*63783933SJohn Baldwin break; 136*63783933SJohn Baldwin data += sprintf(data, "%s=%s", 137*63783933SJohn Baldwin keys->keys_names[i], keys->keys_values[i]); 138*63783933SJohn Baldwin data += 1; /* for '\0'. */ 139*63783933SJohn Baldwin } 140*63783933SJohn Baldwin } 141*63783933SJohn Baldwin 142*63783933SJohn Baldwin const char * 143*63783933SJohn Baldwin keys_find(struct keys *keys, const char *name) 144*63783933SJohn Baldwin { 145*63783933SJohn Baldwin int i; 146*63783933SJohn Baldwin 147*63783933SJohn Baldwin /* 148*63783933SJohn Baldwin * Note that we don't handle duplicated key names here, 149*63783933SJohn Baldwin * as they are not supposed to happen in requests, and if they do, 150*63783933SJohn Baldwin * it's an initiator error. 151*63783933SJohn Baldwin */ 152*63783933SJohn Baldwin for (i = 0; i < KEYS_MAX; i++) { 153*63783933SJohn Baldwin if (keys->keys_names[i] == NULL) 154*63783933SJohn Baldwin return (NULL); 155*63783933SJohn Baldwin if (strcmp(keys->keys_names[i], name) == 0) 156*63783933SJohn Baldwin return (keys->keys_values[i]); 157*63783933SJohn Baldwin } 158*63783933SJohn Baldwin return (NULL); 159*63783933SJohn Baldwin } 160*63783933SJohn Baldwin 161*63783933SJohn Baldwin void 162*63783933SJohn Baldwin keys_add(struct keys *keys, const char *name, const char *value) 163*63783933SJohn Baldwin { 164*63783933SJohn Baldwin int i; 165*63783933SJohn Baldwin 166*63783933SJohn Baldwin log_debugx("key to send: \"%s=%s\"", name, value); 167*63783933SJohn Baldwin 168*63783933SJohn Baldwin /* 169*63783933SJohn Baldwin * Note that we don't check for duplicates here, as they are perfectly 170*63783933SJohn Baldwin * fine in responses, e.g. the "TargetName" keys in discovery sesion 171*63783933SJohn Baldwin * response. 172*63783933SJohn Baldwin */ 173*63783933SJohn Baldwin for (i = 0; i < KEYS_MAX; i++) { 174*63783933SJohn Baldwin if (keys->keys_names[i] == NULL) { 175*63783933SJohn Baldwin keys->keys_names[i] = checked_strdup(name); 176*63783933SJohn Baldwin keys->keys_values[i] = checked_strdup(value); 177*63783933SJohn Baldwin return; 178*63783933SJohn Baldwin } 179*63783933SJohn Baldwin } 180*63783933SJohn Baldwin log_errx(1, "too many keys"); 181*63783933SJohn Baldwin } 182*63783933SJohn Baldwin 183*63783933SJohn Baldwin void 184*63783933SJohn Baldwin keys_add_int(struct keys *keys, const char *name, int value) 185*63783933SJohn Baldwin { 186*63783933SJohn Baldwin char *str; 187*63783933SJohn Baldwin int ret; 188*63783933SJohn Baldwin 189*63783933SJohn Baldwin ret = asprintf(&str, "%d", value); 190*63783933SJohn Baldwin if (ret <= 0) 191*63783933SJohn Baldwin log_err(1, "asprintf"); 192*63783933SJohn Baldwin 193*63783933SJohn Baldwin keys_add(keys, name, str); 194*63783933SJohn Baldwin free(str); 195*63783933SJohn Baldwin } 196