2
* target.c - ietd target handling
4
* Copyright (C) 2002-2003 Ardis Technolgies <roman at ardistech dot com>
5
* Copyright (C) 2004-2010 VMware, Inc. All Rights Reserved.
6
* Copyright (C) 2007-2010 Ross Walker <rswwalker at gmail dot com>
8
* This file is part of iSCSI Enterprise Target software.
10
* Released under the terms of the GNU GPL v2.0.
12
* This program is free software; you can redistribute it and/or
13
* modify it under the terms of the GNU General Public License as
14
* published by the Free Software Foundation; either version 2 of the
15
* License, or (at your option) any later version.
17
* This program is distributed in the hope that it will be useful, but
18
* WITHOUT ANY WARRANTY; without even the implied warranty of
19
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
* General Public License for more details.
22
* You should have received a copy of the GNU General Public License
23
* along with this program; if not, write to the Free Software
24
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
36
#include <arpa/inet.h>
37
#include <netinet/in.h>
39
#include <sys/socket.h>
41
#include <sys/types.h>
45
struct __qelem targets_list = LIST_HEAD_INIT(targets_list);
47
extern struct pollfd poll_array[POLL_MAX];
49
static int is_addr_loopback(char *addr)
54
if (inet_pton(AF_INET, addr, &ia) == 1)
55
return !strncmp(addr, "127.", 4);
57
if (inet_pton(AF_INET6, addr, &ia6) == 1)
58
return IN6_IS_ADDR_LOOPBACK(&ia6);
63
static int is_addr_unspecified(char *addr)
68
if (inet_pton(AF_INET, addr, &ia) == 1)
69
return (ia.s_addr == 0);
71
if (inet_pton(AF_INET6, addr, &ia6) == 1)
72
return IN6_IS_ADDR_UNSPECIFIED(&ia6);
77
static void target_print_addr(struct connection *conn, char *addr, int family)
79
char taddr[NI_MAXHOST + NI_MAXSERV + 5];
81
snprintf(taddr, sizeof(taddr),
82
(family == AF_INET) ? "%s:%d,1" : "[%s]:%d,1",
85
text_key_add(conn, "TargetAddress", taddr);
88
void target_list_build_ifaddrs(struct connection *conn, u32 tid, char *addr,
91
struct ifaddrs *ifaddr, *ifa;
92
char if_addr[NI_MAXHOST];
96
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
100
int sa_family = ifa->ifa_addr->sa_family;
102
if (sa_family == family) {
103
if (getnameinfo(ifa->ifa_addr, (family == AF_INET) ?
104
sizeof(struct sockaddr_in) :
105
sizeof(struct sockaddr_in6),
106
if_addr, sizeof(if_addr),
107
NULL, 0, NI_NUMERICHOST))
110
if (strcmp(addr, if_addr) && !is_addr_loopback(if_addr)
111
&& cops->target_allow(tid, ifa->ifa_addr))
112
target_print_addr(conn, if_addr, family);
119
void target_list_build(struct connection *conn, char *name)
121
struct target *target;
122
struct sockaddr_storage ss1, ss2;
123
socklen_t slen = sizeof(struct sockaddr_storage);
124
char addr1[NI_MAXHOST], addr2[NI_MAXHOST];
127
if (getsockname(conn->fd, (struct sockaddr *) &ss1, &slen)) {
128
log_error("getsockname failed: %m");
132
ret = getnameinfo((struct sockaddr *) &ss1, slen, addr1,
133
sizeof(addr1), NULL, 0, NI_NUMERICHOST);
135
log_error("getnameinfo failed: %s",
136
(ret == EAI_SYSTEM) ? strerror(errno) :
141
family = ss1.ss_family;
143
list_for_each_entry(target, &targets_list, tlist) {
144
if (name && strcmp(target->name, name))
147
if (!isns_scn_allow(target->tid, conn->initiator)
148
|| !cops->initiator_allow(target->tid, conn->fd,
150
|| !cops->target_allow(target->tid,
151
(struct sockaddr *) &ss1))
154
text_key_add(conn, "TargetName", target->name);
156
target_print_addr(conn, addr1, family);
158
for (i = 0; i < LISTEN_MAX && poll_array[i].fd; i++) {
159
slen = sizeof(struct sockaddr_storage);
161
if (getsockname(poll_array[i].fd,
162
(struct sockaddr *) &ss2, &slen))
165
if (getnameinfo((struct sockaddr *) &ss2, slen, addr2,
166
sizeof(addr2), NULL, 0, NI_NUMERICHOST))
169
if (ss2.ss_family != family)
172
if (is_addr_unspecified(addr2))
173
target_list_build_ifaddrs(conn, target->tid,
175
else if (strcmp(addr1, addr2)
176
&& !is_addr_loopback(addr2)
177
&& cops->target_allow(target->tid,
178
(struct sockaddr *) &ss2))
179
target_print_addr(conn, addr2, family);
184
struct target* target_find_by_name(const char *name)
186
struct target *target;
188
list_for_each_entry(target, &targets_list, tlist) {
189
if (!strcasecmp(target->name, name))
196
struct target* target_find_by_id(u32 tid)
198
struct target *target;
200
list_for_each_entry(target, &targets_list, tlist) {
201
if (target->tid == tid)
208
static void all_accounts_del(u32 tid, int dir)
210
char name[ISCSI_NAME_LEN], pass[ISCSI_NAME_LEN];
212
memset(name, 0, sizeof(name));
214
for (;cops->account_query(tid, dir, name, pass) != -ENOENT;
215
memset(name, 0, sizeof(name))) {
216
cops->account_del(tid, dir, name);
221
int target_del(u32 tid)
223
struct target *target = target_find_by_id(tid);
229
if (!list_empty(&target->sessions_list)) {
230
log_warning("%s: target %u still has sessions\n", __FUNCTION__,
235
err = ki->target_destroy(tid);
237
log_error("unable to delete target %u: %d", tid, errno);
241
remque(&target->tlist);
243
all_accounts_del(tid, AUTH_DIR_INCOMING);
244
all_accounts_del(tid, AUTH_DIR_OUTGOING);
246
isns_target_deregister(target->name);
252
int target_add(u32 *tid, char *name)
254
struct target *target;
260
if (!(target = malloc(sizeof(*target))))
263
memset(target, 0, sizeof(*target));
264
memcpy(target->name, name, sizeof(target->name) - 1);
266
err = ki->target_create(tid, name);
268
log_warning("unable create target %u: %d\n", *tid, errno);
272
INIT_LIST_HEAD(&target->tlist);
273
INIT_LIST_HEAD(&target->sessions_list);
274
INIT_LIST_HEAD(&target->isns_head);
276
insque(&target->tlist, &targets_list);
278
isns_target_register(name);
280
log_debug(1, "created target %s", name);
288
int target_redirected(struct target *target, struct connection *conn, struct sockaddr *sa)
290
char tmp[NI_MAXHOST + 1];
291
char addr[NI_MAXHOST + 3];
292
char redirect[NI_MAXHOST + NI_MAXSERV + 4];
295
if (!strlen(target->redirect.addr))
298
if (getnameinfo(sa, (sa->sa_family == AF_INET) ?
299
sizeof(struct sockaddr_in) :
300
sizeof(struct sockaddr_in6),
301
tmp, sizeof(tmp), NULL, 0,
305
if ((p = strrchr(tmp, '%')))
308
if (sa->sa_family == AF_INET6)
309
snprintf(addr, sizeof(addr), "[%s]", tmp);
311
snprintf(addr, sizeof(addr), "%s", tmp);
313
snprintf(redirect, sizeof(redirect), "%s:%s", target->redirect.addr,
314
strlen(target->redirect.port) ? target->redirect.port : "3260");
316
if (strcmp(target->redirect.addr, addr)) {
317
text_key_add(conn, "TargetAddress", redirect);