Add netmasks support to initiator-portal option.
MFC after: 2 weeks
This commit is contained in:
parent
56e397023c
commit
073edb1c91
@ -27,7 +27,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 20, 2014
|
||||
.Dd July 28, 2014
|
||||
.Dt CTL.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -119,7 +119,7 @@ name.
|
||||
Otherwise, only initiators with names matching one of defined
|
||||
ones will be allowed to connect.
|
||||
.It Ic initiator-portal Ao Ar address Ac
|
||||
Specifies iSCSI initiator portal - IPv4 or IPv6 address.
|
||||
Specifies iSCSI initiator portal - IPv4 or IPv6 address or network.
|
||||
If not defined, there will be no restrictions based on initiator
|
||||
address.
|
||||
Otherwise, only initiators with addresses matching one of defined
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
@ -319,14 +320,56 @@ const struct auth_portal *
|
||||
auth_portal_new(struct auth_group *ag, const char *portal)
|
||||
{
|
||||
struct auth_portal *ap;
|
||||
char *net, *mask, *str, *tmp;
|
||||
int len, dm, m;
|
||||
|
||||
ap = calloc(1, sizeof(*ap));
|
||||
if (ap == NULL)
|
||||
log_err(1, "calloc");
|
||||
ap->ap_auth_group = ag;
|
||||
ap->ap_initator_portal = checked_strdup(portal);
|
||||
mask = str = checked_strdup(portal);
|
||||
net = strsep(&mask, "/");
|
||||
if (net[0] == '[')
|
||||
net++;
|
||||
len = strlen(net);
|
||||
if (len == 0)
|
||||
goto error;
|
||||
if (net[len - 1] == ']')
|
||||
net[len - 1] = 0;
|
||||
if (strchr(net, ':') != NULL) {
|
||||
struct sockaddr_in6 *sin6 =
|
||||
(struct sockaddr_in6 *)&ap->ap_sa;
|
||||
|
||||
sin6->sin6_len = sizeof(*sin6);
|
||||
sin6->sin6_family = AF_INET6;
|
||||
if (inet_pton(AF_INET6, net, &sin6->sin6_addr) <= 0)
|
||||
goto error;
|
||||
dm = 128;
|
||||
} else {
|
||||
struct sockaddr_in *sin =
|
||||
(struct sockaddr_in *)&ap->ap_sa;
|
||||
|
||||
sin->sin_len = sizeof(*sin);
|
||||
sin->sin_family = AF_INET;
|
||||
if (inet_pton(AF_INET, net, &sin->sin_addr) <= 0)
|
||||
goto error;
|
||||
dm = 32;
|
||||
}
|
||||
if (mask != NULL) {
|
||||
m = strtol(mask, &tmp, 0);
|
||||
if (m < 0 || m > dm || tmp[0] != 0)
|
||||
goto error;
|
||||
} else
|
||||
m = dm;
|
||||
ap->ap_mask = m;
|
||||
free(str);
|
||||
TAILQ_INSERT_TAIL(&ag->ag_portals, ap, ap_next);
|
||||
return (ap);
|
||||
|
||||
error:
|
||||
log_errx(1, "Incorrect initiator portal '%s'", portal);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -347,13 +390,34 @@ auth_portal_defined(const struct auth_group *ag)
|
||||
}
|
||||
|
||||
const struct auth_portal *
|
||||
auth_portal_find(const struct auth_group *ag, const char *portal)
|
||||
auth_portal_find(const struct auth_group *ag, const struct sockaddr_storage *ss)
|
||||
{
|
||||
const struct auth_portal *auth_portal;
|
||||
const struct auth_portal *ap;
|
||||
uint8_t *a, *b, bmask;
|
||||
int i;
|
||||
|
||||
TAILQ_FOREACH(auth_portal, &ag->ag_portals, ap_next) {
|
||||
if (strcmp(auth_portal->ap_initator_portal, portal) == 0)
|
||||
return (auth_portal);
|
||||
TAILQ_FOREACH(ap, &ag->ag_portals, ap_next) {
|
||||
if (ap->ap_sa.ss_family != ss->ss_family)
|
||||
continue;
|
||||
if (ss->ss_family == AF_INET) {
|
||||
a = (uint8_t *)&((struct sockaddr_in *)ss)->sin_addr;
|
||||
b = (uint8_t *)&((struct sockaddr_in *)&ap->ap_sa)->sin_addr;
|
||||
} else {
|
||||
a = (uint8_t *)&((struct sockaddr_in6 *)ss)->sin6_addr;
|
||||
b = (uint8_t *)&((struct sockaddr_in6 *)&ap->ap_sa)->sin6_addr;
|
||||
}
|
||||
for (i = 0; i < ap->ap_mask / 8; i++) {
|
||||
if (a[i] != b[i])
|
||||
goto next;
|
||||
}
|
||||
if (ap->ap_mask % 8) {
|
||||
bmask = 0xff << (8 - (ap->ap_mask % 8));
|
||||
if ((a[i] & bmask) != (b[i] & bmask))
|
||||
goto next;
|
||||
}
|
||||
return (ap);
|
||||
next:
|
||||
;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
@ -950,7 +1014,8 @@ lun_option_set(struct lun_option *lo, const char *value)
|
||||
}
|
||||
|
||||
static struct connection *
|
||||
connection_new(struct portal *portal, int fd, const char *host)
|
||||
connection_new(struct portal *portal, int fd, const char *host,
|
||||
const struct sockaddr *client_sa)
|
||||
{
|
||||
struct connection *conn;
|
||||
|
||||
@ -960,6 +1025,7 @@ connection_new(struct portal *portal, int fd, const char *host)
|
||||
conn->conn_portal = portal;
|
||||
conn->conn_socket = fd;
|
||||
conn->conn_initiator_addr = checked_strdup(host);
|
||||
memcpy(&conn->conn_initiator_sa, client_sa, client_sa->sa_len);
|
||||
|
||||
/*
|
||||
* Default values, from RFC 3720, section 12.
|
||||
@ -1586,7 +1652,7 @@ wait_for_children(bool block)
|
||||
|
||||
static void
|
||||
handle_connection(struct portal *portal, int fd,
|
||||
const struct sockaddr *client_sa, socklen_t client_salen, bool dont_fork)
|
||||
const struct sockaddr *client_sa, bool dont_fork)
|
||||
{
|
||||
struct connection *conn;
|
||||
int error;
|
||||
@ -1621,7 +1687,7 @@ handle_connection(struct portal *portal, int fd,
|
||||
}
|
||||
pidfile_close(conf->conf_pidfh);
|
||||
|
||||
error = getnameinfo(client_sa, client_salen,
|
||||
error = getnameinfo(client_sa, client_sa->sa_len,
|
||||
host, sizeof(host), NULL, 0, NI_NUMERICHOST);
|
||||
if (error != 0)
|
||||
log_errx(1, "getnameinfo: %s", gai_strerror(error));
|
||||
@ -1631,7 +1697,7 @@ handle_connection(struct portal *portal, int fd,
|
||||
log_set_peer_addr(host);
|
||||
setproctitle("%s", host);
|
||||
|
||||
conn = connection_new(portal, fd, host);
|
||||
conn = connection_new(portal, fd, host, client_sa);
|
||||
set_timeout(conf);
|
||||
kernel_capsicate();
|
||||
login(conn);
|
||||
@ -1687,6 +1753,9 @@ main_loop(struct conf *conf, bool dont_fork)
|
||||
client_salen = sizeof(client_sa);
|
||||
kernel_accept(&connection_id, &portal_id,
|
||||
(struct sockaddr *)&client_sa, &client_salen);
|
||||
if (client_salen < client_sa.ss_len)
|
||||
log_errx(1, "salen %u < %u",
|
||||
client_salen, client_sa.ss_len);
|
||||
|
||||
log_debugx("incoming connection, id %d, portal id %d",
|
||||
connection_id, portal_id);
|
||||
@ -1703,8 +1772,7 @@ main_loop(struct conf *conf, bool dont_fork)
|
||||
|
||||
found:
|
||||
handle_connection(portal, connection_id,
|
||||
(struct sockaddr *)&client_sa, client_salen,
|
||||
dont_fork);
|
||||
(struct sockaddr *)&client_sa, dont_fork);
|
||||
} else {
|
||||
#endif
|
||||
assert(proxy_mode == false);
|
||||
@ -1731,9 +1799,13 @@ main_loop(struct conf *conf, bool dont_fork)
|
||||
&client_salen);
|
||||
if (client_fd < 0)
|
||||
log_err(1, "accept");
|
||||
if (client_salen < client_sa.ss_len)
|
||||
log_errx(1, "salen %u < %u",
|
||||
client_salen,
|
||||
client_sa.ss_len);
|
||||
handle_connection(portal, client_fd,
|
||||
(struct sockaddr *)&client_sa,
|
||||
client_salen, dont_fork);
|
||||
dont_fork);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -35,8 +35,8 @@
|
||||
#include <sys/queue.h>
|
||||
#ifdef ICL_KERNEL_PROXY
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <sys/socket.h>
|
||||
#include <stdbool.h>
|
||||
#include <libutil.h>
|
||||
|
||||
@ -67,6 +67,8 @@ struct auth_portal {
|
||||
TAILQ_ENTRY(auth_portal) ap_next;
|
||||
struct auth_group *ap_auth_group;
|
||||
char *ap_initator_portal;
|
||||
struct sockaddr_storage ap_sa;
|
||||
int ap_mask;
|
||||
};
|
||||
|
||||
#define AG_TYPE_UNKNOWN 0
|
||||
@ -179,6 +181,7 @@ struct connection {
|
||||
char *conn_initiator_addr;
|
||||
char *conn_initiator_alias;
|
||||
uint8_t conn_initiator_isid[6];
|
||||
struct sockaddr_storage conn_initiator_sa;
|
||||
uint32_t conn_cmdsn;
|
||||
uint32_t conn_statsn;
|
||||
size_t conn_max_data_segment_length;
|
||||
@ -235,7 +238,7 @@ const struct auth_portal *auth_portal_new(struct auth_group *ag,
|
||||
const char *initiator_portal);
|
||||
bool auth_portal_defined(const struct auth_group *ag);
|
||||
const struct auth_portal *auth_portal_find(const struct auth_group *ag,
|
||||
const char *initiator_portal);
|
||||
const struct sockaddr_storage *sa);
|
||||
|
||||
struct portal_group *portal_group_new(struct conf *conf, const char *name);
|
||||
void portal_group_delete(struct portal_group *pg);
|
||||
|
@ -954,7 +954,7 @@ login(struct connection *conn)
|
||||
}
|
||||
|
||||
if (auth_portal_defined(ag)) {
|
||||
if (auth_portal_find(ag, conn->conn_initiator_addr) == NULL) {
|
||||
if (auth_portal_find(ag, &conn->conn_initiator_sa) == NULL) {
|
||||
login_send_error(request, 0x02, 0x02);
|
||||
log_errx(1, "initiator does not match allowed "
|
||||
"initiator portals");
|
||||
|
Loading…
Reference in New Issue
Block a user