Module Name: src
Committed By: martin
Date: Mon Dec 18 14:12:35 UTC 2023
Modified Files:
src/sbin/iscsictl [netbsd-10]: iscsic_parse.c
src/sbin/iscsid [netbsd-10]: iscsid_driverif.c
Log Message:
Pull up following revision(s) (requested by mlelstv in ticket #504):
sbin/iscsictl/iscsic_parse.c: revision 1.5
sbin/iscsid/iscsid_driverif.c: revision 1.9
Parse IPv6 targets and handle IPv6 addresses.
To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.4.2.1 src/sbin/iscsictl/iscsic_parse.c
cvs rdiff -u -r1.8 -r1.8.26.1 src/sbin/iscsid/iscsid_driverif.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sbin/iscsictl/iscsic_parse.c
diff -u src/sbin/iscsictl/iscsic_parse.c:1.4 src/sbin/iscsictl/iscsic_parse.c:1.4.2.1
--- src/sbin/iscsictl/iscsic_parse.c:1.4 Fri Dec 3 13:27:38 2021
+++ src/sbin/iscsictl/iscsic_parse.c Mon Dec 18 14:12:35 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: iscsic_parse.c,v 1.4 2021/12/03 13:27:38 andvar Exp $ */
+/* $NetBSD: iscsic_parse.c,v 1.4.2.1 2023/12/18 14:12:35 martin Exp $ */
/*-
* Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc.
@@ -48,50 +48,62 @@
STATIC void
get_address(iscsi_portal_address_t * portal, char *str, char *arg)
{
- char *sp, *sp2;
+ char *sp;
int val;
if (!str || !*str)
arg_error(arg, "Address is missing");
- /* is there a port? don't check inside square brackets (IPv6 addr) */
- for (sp = str + 1, val = 0; *sp && (*sp != ':' || val); sp++) {
- if (*sp == '[')
- val = 1;
- else if (*sp == ']')
- val = 0;
- }
-
- /* */
- if (*sp) {
- for (sp2 = sp + 1; *sp2 && *sp2 != ':'; sp2++);
- /* if there's a second colon, assume it's an unbracketed IPv6 address */
- if (!*sp2) {
- /* truncate source, that's the address */
- *sp++ = '\0';
- if (sscanf(sp, "%d", &val) != 1)
- arg_error(arg, "Bad address format: Expected port number");
- if (val < 0 || val > 0xffff)
- arg_error(arg, "Bad address format: Port number out of range");
- portal->port = (uint16_t) val;
- }
- /* is there a group tag? */
- for (; isdigit((unsigned char)*sp); sp++);
- if (*sp && *sp != ',')
- arg_error(arg, "Bad address format: Extra character(s) '%c'", *sp);
- } else
- for (sp = str + 1; *sp && *sp != ','; sp++);
-
- if (*sp) {
+ /* Parse and strip trailing group tag */
+ sp = strrchr(str, ',');
+ if (sp != NULL) {
if (sscanf(sp + 1, "%d", &val) != 1)
arg_error(arg, "Bad address format: Expected group tag");
if (val < 0 || val > 0xffff)
arg_error(arg, "Bad address format: Group tag out of range");
portal->group_tag = (uint16_t) val;
- /* truncate source, that's the address */
*sp = '\0';
}
- /* only check length, don't verify correct format (too many possibilities) */
+
+ /* Skip over bracketed IPv6 address */
+ sp = strchr(str, ']');
+ if (sp != NULL)
+ sp++;
+ else
+ sp = str;
+
+ /* Parse and strip trailing port number */
+ sp = strchr(sp, ':');
+ if (sp != NULL) {
+ if (strchr(sp + 1, ':') != NULL) {
+ /*
+ * If there's a second colon, assume
+ * it's an unbracketed IPv6 address
+ */
+ portal->port = 0;
+ } else {
+ if (sscanf(sp + 1, "%d", &val) != 1)
+ arg_error(arg, "Bad address format: Expected port number");
+ if (val < 0 || val > 0xffff)
+ arg_error(arg, "Bad address format: Port number ut of range");
+ portal->port = (uint16_t) val;
+ *sp = '\0';
+ }
+ }
+
+ /* Remove brackets */
+ if (*str == '[') {
+ sp = strchr(str, ']');
+ if (sp != NULL && !*(sp+1)) {
+ str = str + 1;
+ *sp = '\0';
+ }
+ }
+
+ /*
+ * only check length, don't verify correct format
+ * (too many possibilities)
+ */
if (strlen(str) >= sizeof(portal->address))
arg_error(arg, "Bad address format: Address string too long");
Index: src/sbin/iscsid/iscsid_driverif.c
diff -u src/sbin/iscsid/iscsid_driverif.c:1.8 src/sbin/iscsid/iscsid_driverif.c:1.8.26.1
--- src/sbin/iscsid/iscsid_driverif.c:1.8 Sun May 29 13:35:45 2016
+++ src/sbin/iscsid/iscsid_driverif.c Mon Dec 18 14:12:35 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: iscsid_driverif.c,v 1.8 2016/05/29 13:35:45 mlelstv Exp $ */
+/* $NetBSD: iscsid_driverif.c,v 1.8.26.1 2023/12/18 14:12:35 martin Exp $ */
/*-
* Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc.
@@ -98,23 +98,29 @@ set_node_name(iscsid_set_node_name_req_t
static int
bind_socket(int sock, uint8_t * addr)
{
- struct sockaddr_in serverAddress;
- struct hostent *host;
+ struct addrinfo hints, *ai, *ai0;
+ int ret = FALSE;
DEB(8, ("Binding to <%s>", addr));
- (void) memset(&serverAddress, 0x0, sizeof(serverAddress));
- host = gethostbyname((char *)addr);
- if (host == NULL)
- return FALSE;
- if (host->h_length > (int)sizeof(serverAddress.sin_addr))
- return FALSE;
- serverAddress.sin_family = host->h_addrtype;
- serverAddress.sin_port = 0;
- serverAddress.sin_len = host->h_length;
- memcpy(&serverAddress.sin_addr, host->h_addr_list[0], host->h_length);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE;
+ if (getaddrinfo((char *)addr, NULL, &hints, &ai0))
+ return ret;
+
+ for (ai = ai0; ai; ai = ai->ai_next) {
+ if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0)
+ continue;
+
+ listen(sock, 5);
+ ret = TRUE;
+ break;
+ }
+ freeaddrinfo(ai0);
- return bind(sock, (struct sockaddr *)(void *)&serverAddress,
- (socklen_t)sizeof(serverAddress)) >= 0;
+ return ret;
}
@@ -183,14 +189,13 @@ make_connection(session_t * sess, iscsid
target_t *target;
portal_t *portal = NULL;
iscsi_portal_address_t *addr;
- struct sockaddr_in serverAddress;
- struct hostent *host;
+ struct addrinfo hints, *ai, *ai0;
+ char portnum[6];
initiator_t *init;
DEB(9, ("Make Connection sess=%p, req=%p, res=%p, stid=%p",
sess, req, res, stid));
(void) memset(&loginp, 0x0, sizeof(loginp));
- (void) memset(&serverAddress, 0x0, sizeof(serverAddress));
/* find the target portal */
if (stid != NULL) {
@@ -277,69 +282,72 @@ make_connection(session_t * sess, iscsid
/* translate target address */
DEB(8, ("Connecting to <%s>, port %d", addr->address, addr->port));
- host = gethostbyname((char *)addr->address);
- if (host == NULL) {
- switch (h_errno) {
- case HOST_NOT_FOUND:
- res->status = ISCSID_STATUS_HOST_NOT_FOUND;
- break;
- case TRY_AGAIN:
- res->status = ISCSID_STATUS_HOST_TRY_AGAIN;
- break;
- default:
- res->status = ISCSID_STATUS_HOST_ERROR;
- break;
- }
- return NULL;
- }
- if (host->h_length > (int)sizeof(serverAddress.sin_addr)) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ snprintf(portnum, sizeof(portnum), "%u", addr->port);
+ ret = getaddrinfo((char *)addr->address, portnum, &hints, &ai0);
+ switch (ret) {
+ case 0:
+ break;
+ case EAI_NODATA:
+ res->status = ISCSID_STATUS_HOST_NOT_FOUND;
+ break;
+ case EAI_AGAIN:
+ res->status = ISCSID_STATUS_HOST_TRY_AGAIN;
+ break;
+ default:
res->status = ISCSID_STATUS_HOST_ERROR;
- return NULL;
+ break;
}
- DEB(8, ("Gethostbyname OK, addrtype %d, len %d, addr %x",
- host->h_addrtype, host->h_length, *((int *) host->h_addr_list[0])));
- serverAddress.sin_family = host->h_addrtype;
- serverAddress.sin_port = htons((addr->port)
- ? addr->port : ISCSI_DEFAULT_PORT);
- serverAddress.sin_len = host->h_length;
- memcpy(&serverAddress.sin_addr, host->h_addr_list[0], host->h_length);
/* alloc the connection structure */
conn = calloc(1, sizeof(*conn));
if (conn == NULL) {
+ freeaddrinfo(ai0);
res->status = ISCSID_STATUS_NO_RESOURCES;
return NULL;
}
- /* create and connect the socket */
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock < 0) {
- free(conn);
- res->status = ISCSID_STATUS_SOCKET_ERROR;
- return NULL;
- }
- if (init) {
- if (!bind_socket(sock, init->address)) {
+ res->status = ISCSID_STATUS_HOST_ERROR;
+ sock = -1;
+ for (ai = ai0; ai; ai = ai->ai_next) {
+ /* create and connect the socket */
+ sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (sock < 0) {
+ res->status = ISCSID_STATUS_SOCKET_ERROR;
+ break;
+ }
+
+ if (init) {
+ if (!bind_socket(sock, init->address)) {
+ close(sock);
+ res->status = ISCSID_STATUS_INITIATOR_BIND_ERROR;
+ break;
+ }
+ }
+
+ DEB(8, ("Connecting socket"));
+ if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
close(sock);
- free(conn);
- res->status = ISCSID_STATUS_INITIATOR_BIND_ERROR;
- return NULL;
+ res->status = ISCSID_STATUS_CONNECT_ERROR;
+ continue;
}
+
+ res->status = ISCSID_STATUS_SUCCESS;
+ break;
}
+ freeaddrinfo(ai0);
- DEB(8, ("Connecting socket"));
- if (connect(sock, (struct sockaddr *)(void *)&serverAddress,
- (socklen_t)sizeof(serverAddress)) < 0) {
- close(sock);
+ if (sock < 0) {
free(conn);
- res->status = ISCSID_STATUS_CONNECT_ERROR;
DEB(1, ("Connecting to socket failed (error %d), returning %d",
errno, res->status));
return NULL;
}
+
/* speed up socket processing */
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &yes, (socklen_t)sizeof(yes));
-
/* setup login parameter structure */
loginp.socket = sock;
if (target->TargetName[0]) {
@@ -506,11 +514,10 @@ event_recover_connection(uint32_t sid, u
portal_t *portal;
initiator_t *init;
iscsi_portal_address_t *addr;
- struct sockaddr_in serverAddress;
- struct hostent *host;
+ struct addrinfo hints, *ai, *ai0;
+ char portnum[6];
DEB(1, ("Event_Recover_Connection sid=%d, cid=%d", sid, cid));
- (void) memset(&serverAddress, 0x0, sizeof(serverAddress));
LOCK_SESSIONS;
@@ -543,47 +550,53 @@ event_recover_connection(uint32_t sid, u
DEB(1, ("Event_Recover_Connection Connecting to <%s>, port %d",
addr->address, addr->port));
- if ((host = gethostbyname((char *)addr->address)) == NULL) {
- DEB(1, ("GetHostByName failed (error %d)", h_errno));
- return;
- }
- if (host->h_length > (int)sizeof(serverAddress.sin_addr)) {
- DEB(1, ("Host address length invalid (%d)", host->h_length));
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ snprintf(portnum, sizeof(portnum), "%u", addr->port);
+ ret = getaddrinfo((char *)addr->address, portnum, &hints, &ai0);
+ if (ret) {
+ DEB(1, ("getaddrinfo failed (%s)", gai_strerror(ret)));
return;
}
- serverAddress.sin_family = host->h_addrtype;
- serverAddress.sin_port = htons((addr->port)
- ? addr->port : ISCSI_DEFAULT_PORT);
- serverAddress.sin_len = host->h_length;
- memcpy(&serverAddress.sin_addr, host->h_addr_list[0], host->h_length);
+ sock = -1;
+ for (ai = ai0; ai; ai = ai->ai_next) {
- /* create and connect the socket */
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock < 0) {
- DEB(1, ("Creating socket failed (error %d)", errno));
- return;
- }
+ /* create and connect the socket */
+ sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (sock < 0) {
+ DEB(1, ("Creating socket failed (error %d)", errno));
+ break;
+ }
- DEB(1, ("recover_connection: Socket = %d", sock));
+ DEB(1, ("recover_connection: Socket = %d", sock));
- if (init) {
- if (!bind_socket(sock, init->address)) {
- DEB(1, ("Binding to interface failed (error %d)", errno));
+ if (init) {
+ if (!bind_socket(sock, init->address)) {
+ DEB(1, ("Binding to interface failed (error %d)", errno));
+ close(sock);
+ sock = -1;
+ continue;
+ }
+ }
+
+ if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
close(sock);
- return;
+ sock = -1;
+ DEB(1, ("Connecting to socket failed (error %d)", errno));
+ continue;
}
+
+ break;
}
+ freeaddrinfo(ai0);
- if (connect(sock, (struct sockaddr *)(void *)&serverAddress,
- (socklen_t)sizeof(serverAddress)) < 0) {
- DEB(1, ("Connecting to socket failed (error %d)", errno));
- close(sock);
+ if (sock < 0)
return;
- }
+
/* speed up socket processing */
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &yes, (socklen_t)sizeof(yes));
-
conn->loginp.socket = sock;
conn->loginp.status = 0;
ret = ioctl(driver, ISCSI_RESTORE_CONNECTION, &conn->loginp);
@@ -631,7 +644,6 @@ log_in(iscsid_login_req_t * req, iscsid_
UNLOCK_SESSIONS;
}
-
/*
* add_connection:
* Handle ADD_CONNECTION request: Log secondary connection into given portal.