1/*- 2 * Copyright (c) 2012 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Edward Tomasz Napierala under sponsorship 6 * from the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 15 unchanged lines hidden (view full) --- 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 */ 30 31#include <sys/cdefs.h> |
32__FBSDID("$FreeBSD: stable/10/usr.sbin/ctld/discovery.c 279006 2015-02-19 14:52:01Z mav $"); |
33 34#include <assert.h> 35#include <stdint.h> 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <netinet/in.h> 40#include <netdb.h> --- 116 unchanged lines hidden (view full) --- 157 bhslr2->bhslr_maxcmdsn = htonl(conn->conn_cmdsn); 158 159 return (response); 160} 161 162static void 163discovery_add_target(struct keys *response_keys, const struct target *targ) 164{ |
165 struct port *port; |
166 struct portal *portal; 167 char *buf; 168 char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 169 struct addrinfo *ai; 170 int ret; 171 172 keys_add(response_keys, "TargetName", targ->t_name); |
173 TAILQ_FOREACH(port, &targ->t_ports, p_ts) { 174 if (port->p_portal_group == NULL) 175 continue; 176 TAILQ_FOREACH(portal, &port->p_portal_group->pg_portals, p_next) { |
177 ai = portal->p_ai; 178 ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, 179 hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), 180 NI_NUMERICHOST | NI_NUMERICSERV); 181 if (ret != 0) { 182 log_warnx("getnameinfo: %s", gai_strerror(ret)); 183 continue; 184 } 185 switch (ai->ai_addr->sa_family) { 186 case AF_INET: 187 if (strcmp(hbuf, "0.0.0.0") == 0) 188 continue; 189 ret = asprintf(&buf, "%s:%s,%d", hbuf, sbuf, |
190 port->p_portal_group->pg_tag); |
191 break; 192 case AF_INET6: 193 if (strcmp(hbuf, "::") == 0) 194 continue; 195 ret = asprintf(&buf, "[%s]:%s,%d", hbuf, sbuf, |
196 port->p_portal_group->pg_tag); |
197 break; 198 default: 199 continue; 200 } 201 if (ret <= 0) 202 log_err(1, "asprintf"); 203 keys_add(response_keys, "TargetAddress", buf); 204 free(buf); |
205 } |
206 } 207} 208 209static bool 210discovery_target_filtered_out(const struct connection *conn, |
211 const struct port *port) |
212{ 213 const struct auth_group *ag; 214 const struct portal_group *pg; |
215 const struct target *targ; |
216 const struct auth *auth; 217 int error; 218 |
219 targ = port->p_target; 220 ag = port->p_auth_group; 221 if (ag == NULL) 222 ag = targ->t_auth_group; |
223 pg = conn->conn_portal->p_portal_group; 224 225 assert(pg->pg_discovery_auth_group != PG_FILTER_UNKNOWN); 226 227 if (pg->pg_discovery_filter >= PG_FILTER_PORTAL && 228 auth_portal_check(ag, &conn->conn_initiator_sa) != 0) { 229 log_debugx("initiator does not match initiator portals " 230 "allowed for target \"%s\"; skipping", targ->t_name); --- 38 unchanged lines hidden (view full) --- 269 return (false); 270} 271 272void 273discovery(struct connection *conn) 274{ 275 struct pdu *request, *response; 276 struct keys *request_keys, *response_keys; |
277 const struct port *port; |
278 const struct portal_group *pg; |
279 const char *send_targets; 280 281 pg = conn->conn_portal->p_portal_group; 282 283 log_debugx("beginning discovery session; waiting for Text PDU"); 284 request = text_receive(conn); 285 request_keys = keys_new(); 286 keys_load(request_keys, request); 287 288 send_targets = keys_find(request_keys, "SendTargets"); 289 if (send_targets == NULL) 290 log_errx(1, "received Text PDU without SendTargets"); 291 292 response = text_new_response(request); 293 response_keys = keys_new(); 294 295 if (strcmp(send_targets, "All") == 0) { |
296 TAILQ_FOREACH(port, &pg->pg_ports, p_pgs) { 297 if (discovery_target_filtered_out(conn, port)) { |
298 /* Ignore this target. */ 299 continue; 300 } |
301 discovery_add_target(response_keys, port->p_target); |
302 } 303 } else { |
304 port = port_find_in_pg(pg, send_targets); 305 if (port == NULL) { |
306 log_debugx("initiator requested information on unknown " 307 "target \"%s\"; returning nothing", send_targets); 308 } else { |
309 if (discovery_target_filtered_out(conn, port)) { |
310 /* Ignore this target. */ 311 } else { |
312 discovery_add_target(response_keys, port->p_target); |
313 } 314 } 315 } 316 keys_save(response_keys, response); 317 318 pdu_send(response); 319 pdu_delete(response); 320 keys_delete(response_keys); --- 13 unchanged lines hidden --- |