xref: /freebsd/lib/libiscsiutil/keys.c (revision 4d846d260e2b9a3d4d0a701462568268cbfe7a5b)
163783933SJohn Baldwin /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
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 *
keys_new(void)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
keys_delete(struct keys * keys)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
keys_load(struct keys * keys,const char * data,size_t len)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
keys_save(struct keys * keys,char ** datap,size_t * lenp)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 *
keys_find(struct keys * keys,const char * name)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
keys_add(struct keys * keys,const char * name,const char * value)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
16629b36af9SGordon 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
keys_add_int(struct keys * keys,const char * name,int value)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