summaryrefslogtreecommitdiffstats
path: root/rpc/rpc-lib/src/rpcsvc.c
diff options
context:
space:
mode:
Diffstat (limited to 'rpc/rpc-lib/src/rpcsvc.c')
-rw-r--r--rpc/rpc-lib/src/rpcsvc.c91
1 files changed, 89 insertions, 2 deletions
diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c
index 8be64c1..34ee6f2 100644
--- a/rpc/rpc-lib/src/rpcsvc.c
+++ b/rpc/rpc-lib/src/rpcsvc.c
@@ -59,6 +59,9 @@ int
rpcsvc_notify (rpc_transport_t *trans, void *mydata,
rpc_transport_event_t event, void *data, ...);
+static int
+match_subnet_v4 (const char *addrtok, const char *ipaddr);
+
rpcsvc_notify_wrapper_t *
rpcsvc_notify_wrapper_alloc (void)
{
@@ -2181,6 +2184,13 @@ rpcsvc_transport_peer_check_search (dict_t *options, char *pattern,
goto err;
}
+ /* Compare IPv4 subnetwork */
+ if (strchr (addrtok, '/')) {
+ ret = match_subnet_v4 (addrtok, ip);
+ if (ret == 0)
+ goto err;
+ }
+
addrtok = strtok_r (NULL, ",", &svptr);
}
@@ -2327,8 +2337,20 @@ rpcsvc_auth_check (rpcsvc_t *svc, char *volname,
ret = dict_get_str (options, srchstr, &reject_str);
GF_FREE (srchstr);
- if (reject_str == NULL && !strcmp ("*", allow_str))
- return RPCSVC_AUTH_ACCEPT;
+
+ /*
+ * If "reject_str" is being set as '*' (anonymous), then NFS-server
+ * would reject everything. If the "reject_str" is not set and
+ * "allow_str" is set as '*' (anonymous), then NFS-server would
+ * accept mount requests from all clients.
+ */
+ if (reject_str != NULL) {
+ if (!strcmp ("*", reject_str))
+ return RPCSVC_AUTH_REJECT;
+ } else {
+ if (!strcmp ("*", allow_str))
+ return RPCSVC_AUTH_ACCEPT;
+ }
/* Non-default rule, authenticate */
if (!get_host_name (client_ip, &ip))
@@ -2461,6 +2483,71 @@ out:
return addrstr;
}
+/*
+ * match_subnet_v4() takes subnetwork address pattern and checks
+ * if the target IPv4 address has the same network address with
+ * the help of network mask.
+ *
+ * Returns 0 for SUCCESS and -1 otherwise.
+ *
+ * NB: Validation of subnetwork address pattern is not required
+ * as it's already being done at the time of CLI SET.
+ */
+static int
+match_subnet_v4 (const char *addrtok, const char *ipaddr)
+{
+ char *slash = NULL;
+ char *netaddr = NULL;
+ long prefixlen = -1;
+ int ret = -1;
+ uint32_t shift = 0;
+ struct sockaddr_in sin1 = {0, };
+ struct sockaddr_in sin2 = {0, };
+ struct sockaddr_in mask = {0, };
+
+ /* Copy the input */
+ netaddr = gf_strdup (addrtok);
+ if (netaddr == NULL) /* ENOMEM */
+ goto out;
+
+ /* Find the network socket addr of target */
+ if (inet_pton (AF_INET, ipaddr, &sin1.sin_addr) == 0)
+ goto out;
+
+ /* Find the network socket addr of subnet pattern */
+ slash = strchr (netaddr, '/');
+ *slash = '\0';
+ if (inet_pton (AF_INET, netaddr, &sin2.sin_addr) == 0)
+ goto out;
+
+ /*
+ * Find the network mask in network byte order.
+ * NB: 32 : Max len of IPv4 address.
+ */
+ prefixlen = atoi (slash + 1);
+ shift = 32 - (uint32_t)prefixlen;
+ mask.sin_addr.s_addr = htonl ((uint32_t)~0 << shift);
+
+ /*
+ * Check if both have same network address.
+ * Extract the network address from the IP addr by applying the
+ * network mask. If they match, return SUCCESS. i.e.
+ *
+ * (x == y) <=> (x ^ y == 0)
+ * (x & y) ^ (x & z) <=> x & (y ^ z)
+ *
+ * ((ip1 & mask) == (ip2 & mask)) <=> ((mask & (ip1 ^ ip2)) == 0)
+ */
+ if (((mask.sin_addr.s_addr) &
+ (sin1.sin_addr.s_addr ^ sin2.sin_addr.s_addr)) != 0)
+ goto out;
+
+ ret = 0; /* SUCCESS */
+out:
+ GF_FREE (netaddr);
+ return ret;
+}
+
rpcsvc_actor_t gluster_dump_actors[] = {
[GF_DUMP_NULL] = {"NULL", GF_DUMP_NULL, NULL, NULL, 0, DRC_NA},