[PATCHES] multi-channel: implement network interface info ioctl

Michael Adam obnox at samba.org
Mon Jan 25 15:56:57 UTC 2016


Updated patchset (I guess final one) attached,
after some off-list review/rework with Metze.

Changes:
- fix a few issues (as reported here)
- detect link presence on interface with ethtool ioctl
- skip interfaces without link / linkspeed = 0 from the fsctl
- add support for if_index in interfaces loadparm option
- map all interfaces without if_index from kernel or config
  to index UINT32_MAX
- skip new loadparm syntax in s4-interfaces code
  (this really needs to be reconsiled one day)
- document new interfaces syntax in manpage

Cheers - Michael

On 2016-01-25 at 14:02 +0100, Michael Adam wrote:
> On 2016-01-25 at 18:29 +0530, Anoop C S wrote:
> > On Mon, 2016-01-25 at 13:09 +0100, Michael Adam wrote:
> > > Updated complete patchset attached:
> > > 
> > > - correctly (according to current samba) translate NOT_SUPPORTED
> > >   into NT_STATUS_FS_DRIVER_REQUIRED or
> > >   NT_STATUS_INVALID_DEVICE_REQUEST
> > > 
> > > - get if_index from the kernel
> > > - make it possible to override from the config
> > > - fall back to calculation 0x80000000 + count as suggested
> > >   if neither in kernel nor in config
> > > 
> > 
> > Correct me if I am wrong in understanding the modified patch (v3).
> > 
> > Assuming 'interfaces = ' parameter line is not specified in smb.conf,
> > consider the case where we failed to retrieve interface index via the
> > following lines of code:
> > 
> > +	ifaces[total].if_index = if_nametoindex(ifptr->ifa_name);
> > +	if (ifaces[total].if_index == 0) {
> > +		DBG_ERR("Failed to retrieve interface index for '%s':
> > "
> > +			"%s\n", ifptr->ifa_name, strerror(errno));
> > +		}
> > +
> > 
> > Will we keep if_index as 0 itself? If not we have to fill if_index with
> > a compiled in (non-colliding) default value as we did inside
> > interpret_interface().
> 
> Yeah, doing exactly this currently... :-)


-------------- next part --------------
From eccc3fea932db1475393cb4b85144cdef699d25a Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 25 Jan 2016 03:37:38 +0100
Subject: [PATCH 01/14] librpc:idl: define FSCTL_NET_IFACE_NONE_CAPABLE in
 ioctl.idl

Signed-off-by: Michael Adam <obnox at samba.org>
---
 librpc/idl/ioctl.idl | 1 +
 1 file changed, 1 insertion(+)

diff --git a/librpc/idl/ioctl.idl b/librpc/idl/ioctl.idl
index 5c3ee6d..dbeef14 100644
--- a/librpc/idl/ioctl.idl
+++ b/librpc/idl/ioctl.idl
@@ -111,6 +111,7 @@ interface compression
 interface netinterface
 {
 	typedef [bitmap32bit] bitmap {
+		FSCTL_NET_IFACE_NONE_CAPABLE = 0x00000000,
 		FSCTL_NET_IFACE_RSS_CAPABLE = 0x00000001,
 		FSCTL_NET_IFACE_RDMA_CAPABLE = 0x00000002
 	} fsctl_net_iface_capability;
-- 
2.5.0


From 52621063b6de554b9481c958ad9f25837c5046a6 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 25 Jan 2016 03:38:05 +0100
Subject: [PATCH 02/14] lib:socket: add linkspeed, capability and if_index to
 iface_struct

Pair-Programmed-With: Anoop C S <anoopcs at redhat.com>

Signed-off-by: Michael Adam <obnox at samba.org>
Signed-off-by: Anoop C S <anoopcs at redhat.com>
---
 lib/socket/interfaces.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/socket/interfaces.h b/lib/socket/interfaces.h
index b4e113d..0876f09 100644
--- a/lib/socket/interfaces.h
+++ b/lib/socket/interfaces.h
@@ -27,6 +27,9 @@ struct iface_struct {
 	struct sockaddr_storage ip;
 	struct sockaddr_storage netmask;
 	struct sockaddr_storage bcast;
+	uint32_t if_index;
+	uint64_t linkspeed;
+	uint32_t capability;
 };
 
 struct interface;
-- 
2.5.0


From aa1e714ad15ca202caa9758ba016a0e1a538859b Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 25 Jan 2016 12:23:40 +0100
Subject: [PATCH 03/14] lib:socket: get interface index from kernel

Signed-off-by: Michael Adam <obnox at samba.org>
---
 lib/socket/interfaces.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/lib/socket/interfaces.c b/lib/socket/interfaces.c
index e62da3c..3b15615 100644
--- a/lib/socket/interfaces.c
+++ b/lib/socket/interfaces.c
@@ -214,6 +214,12 @@ static int _get_interfaces(TALLOC_CTX *mem_ctx, struct iface_struct **pifaces)
 			continue;
 		}
 
+		ifaces[total].if_index = if_nametoindex(ifptr->ifa_name);
+		if (ifaces[total].if_index == 0) {
+			DBG_ERR("Failed to retrieve interface index for '%s': "
+				"%s\n", ifptr->ifa_name, strerror(errno));
+		}
+
 		if (strlcpy(ifaces[total].name, ifptr->ifa_name,
 			sizeof(ifaces[total].name)) >=
 				sizeof(ifaces[total].name)) {
-- 
2.5.0


From eb45406e0690c9509d0e188664240474535cc9f0 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 25 Jan 2016 03:38:31 +0100
Subject: [PATCH 04/14] lib:socket: set defaults for linkspeed and capability
 in get_interfaces()

Signed-off-by: Michael Adam <obnox at samba.org>
---
 lib/socket/interfaces.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lib/socket/interfaces.c b/lib/socket/interfaces.c
index 3b15615..e18fb07 100644
--- a/lib/socket/interfaces.c
+++ b/lib/socket/interfaces.c
@@ -24,6 +24,7 @@
 #include "system/network.h"
 #include "interfaces.h"
 #include "lib/util/tsort.h"
+#include "librpc/gen_ndr/ioctl.h"
 
 /****************************************************************************
  Create a struct sockaddr_storage with the netmask bits set to 1.
@@ -137,6 +138,7 @@ static int _get_interfaces(TALLOC_CTX *mem_ctx, struct iface_struct **pifaces)
 	int count;
 	int total = 0;
 	size_t copy_size;
+	uint64_t if_speed = 1000 * 1000 * 1000; /* 1GBit */
 
 	if (getifaddrs(&iflist) < 0) {
 		return -1;
@@ -220,6 +222,9 @@ static int _get_interfaces(TALLOC_CTX *mem_ctx, struct iface_struct **pifaces)
 				"%s\n", ifptr->ifa_name, strerror(errno));
 		}
 
+		ifaces[total].linkspeed = if_speed;
+		ifaces[total].capability = FSCTL_NET_IFACE_NONE_CAPABLE;
+
 		if (strlcpy(ifaces[total].name, ifptr->ifa_name,
 			sizeof(ifaces[total].name)) >=
 				sizeof(ifaces[total].name)) {
-- 
2.5.0


From 6761979b4f88a843927af6749cdec5598aa02222 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 25 Jan 2016 03:30:39 +0100
Subject: [PATCH 05/14] build: detect support for ethtool

Pair-Programmed-With: Anoop C S <anoopcs at redhat.com>a

Signed-off-by: Michael Adam <obnox at samba.org>
---
 lib/socket/wscript | 7 +++++++
 wscript            | 1 +
 2 files changed, 8 insertions(+)
 create mode 100644 lib/socket/wscript

diff --git a/lib/socket/wscript b/lib/socket/wscript
new file mode 100644
index 0000000..d8c269a
--- /dev/null
+++ b/lib/socket/wscript
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+def configure(conf):
+    conf.CHECK_HEADERS('linux/sockios.h linux/ethtool.h')
+    if (conf.CONFIG_SET('HAVE_LINUX_SOCKIOS_H') and \
+                    conf.CONFIG_SET('HAVE_LINUX_ETHTOOL_H')):
+        conf.DEFINE('HAVE_ETHTOOL', 1)
diff --git a/wscript b/wscript
index c3c3cfd..41ed5da 100644
--- a/wscript
+++ b/wscript
@@ -180,6 +180,7 @@ def configure(conf):
     conf.RECURSE('lib/texpect')
     if conf.env.with_ctdb:
         conf.RECURSE('ctdb')
+    conf.RECURSE('lib/socket')
 
     conf.SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS()
 
-- 
2.5.0


From 16e07ab92c30d0541b7be0be8290bad5f8f7c566 Mon Sep 17 00:00:00 2001
From: Anoop C S <anoopcs at redhat.com>
Date: Fri, 22 Jan 2016 20:51:55 +0530
Subject: [PATCH 06/14] lib:socket: detect link speed with ethtool ioctl in
 get_interfaces (on linux)

Pair-Programmed-With: Michael Adam <obnox at samba.org>

Signed-off-by: Anoop C S <anoopcs at redhat.com>
Signed-off-by: Michael Adam <obnox at samba.org>
---
 lib/socket/interfaces.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/lib/socket/interfaces.c b/lib/socket/interfaces.c
index e18fb07..98341e2 100644
--- a/lib/socket/interfaces.c
+++ b/lib/socket/interfaces.c
@@ -26,6 +26,11 @@
 #include "lib/util/tsort.h"
 #include "librpc/gen_ndr/ioctl.h"
 
+#ifdef HAVE_ETHTOOL
+#include "linux/sockios.h"
+#include "linux/ethtool.h"
+#endif
+
 /****************************************************************************
  Create a struct sockaddr_storage with the netmask bits set to 1.
 ****************************************************************************/
@@ -120,6 +125,47 @@ void make_net(struct sockaddr_storage *pss_out,
 	make_bcast_or_net(pss_out, pss_in, nmask, false);
 }
 
+#ifdef HAVE_ETHTOOL
+static void query_iface_speed_from_name(const char *name, uint64_t *speed)
+{
+	int ret = 0;
+	struct ethtool_cmd ecmd;
+	struct ethtool_value edata;
+	struct ifreq ifr;
+	int fd;
+
+	fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+	if (fd == -1) {
+		DBG_ERR("Failed to open socket.");
+		return;
+	}
+
+	strncpy(ifr.ifr_name, name, IF_NAMESIZE);
+
+	ifr.ifr_data = (void *)&edata;
+	edata.cmd = ETHTOOL_GLINK;
+	ret = ioctl(fd, SIOCETHTOOL, &ifr);
+	if (ret == -1) {
+		goto done;
+	}
+	if (edata.data == 0) {
+		/* no link detected */
+		*speed = 0;
+		goto done;
+	}
+
+	ifr.ifr_data = (void *)&ecmd;
+	ecmd.cmd = ETHTOOL_GSET;
+	ret = ioctl(fd, SIOCETHTOOL, &ifr);
+	if (ret == -1) {
+		goto done;
+	}
+	*speed = (ethtool_cmd_speed(&ecmd)) * 1000 * 1000;
+
+done:
+	(void)close(fd);
+}
+#endif
 
 /****************************************************************************
  Try the "standard" getifaddrs/freeifaddrs interfaces.
@@ -222,6 +268,9 @@ static int _get_interfaces(TALLOC_CTX *mem_ctx, struct iface_struct **pifaces)
 				"%s\n", ifptr->ifa_name, strerror(errno));
 		}
 
+#ifdef HAVE_ETHTOOL
+		query_iface_speed_from_name(ifptr->ifa_name, &if_speed);
+#endif
 		ifaces[total].linkspeed = if_speed;
 		ifaces[total].capability = FSCTL_NET_IFACE_NONE_CAPABLE;
 
-- 
2.5.0


From b371af425c8f4fc007a2530e05b6754c970529d9 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 25 Jan 2016 03:38:16 +0100
Subject: [PATCH 07/14] smb.h: add linkspeed, capability, and if_index to
 interface struct

Pair-Programmed-With: Anoop C S <anoopcs at redhat.com>

Signed-off-by: Michael Adam <obnox at samba.org>
Signed-off-by: Anoop C S <anoopcs at redhat.com>
---
 source3/include/smb.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/source3/include/smb.h b/source3/include/smb.h
index 94a0e8a..7eeef88 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -181,6 +181,9 @@ struct interface {
 	struct sockaddr_storage ip;
 	struct sockaddr_storage netmask;
 	struct sockaddr_storage bcast;
+	uint32_t if_index;
+	uint64_t linkspeed;
+	uint32_t capability;
 };
 
 #define SHARE_MODE_FLAG_POSIX_OPEN	0x1
-- 
2.5.0


From c9db60c211d0266385dc065c76f65a06628855d4 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 25 Jan 2016 14:09:37 +0100
Subject: [PATCH 08/14] s3:lib: copy speed, cap, and index in add_interface()

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/lib/interface.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/source3/lib/interface.c b/source3/lib/interface.c
index adf8b42..2e4bf0a 100644
--- a/source3/lib/interface.c
+++ b/source3/lib/interface.c
@@ -333,6 +333,9 @@ static void add_interface(const struct iface_struct *ifs)
 	iface->ip = ifs->ip;
 	iface->netmask = ifs->netmask;
 	iface->bcast = ifs->bcast;
+	iface->linkspeed = ifs->linkspeed;
+	iface->capability = ifs->capability;
+	iface->if_index = ifs->if_index;
 
 	DLIST_ADD(local_interfaces, iface);
 
-- 
2.5.0


From de3e2d634854185ee89e925fb2c6d4525ac5bd8d Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Sun, 24 Jan 2016 13:26:35 +0100
Subject: [PATCH 09/14] s3:lib: remove an unmotivated comment from
 interpret_interface()

This seems to be a left-over from historic code.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/lib/interface.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/source3/lib/interface.c b/source3/lib/interface.c
index 2e4bf0a..69b1041 100644
--- a/source3/lib/interface.c
+++ b/source3/lib/interface.c
@@ -385,7 +385,6 @@ static void interpret_interface(char *token)
 		return;
 	}
 
-	/* maybe it is a DNS name */
 	p = strchr_m(token,'/');
 	if (p == NULL) {
 		if (!interpret_string_addr(&ss, token, 0)) {
-- 
2.5.0


From 209c032f9c3ccdc3a32e28d239c6ca2c4ee04eeb Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 25 Jan 2016 03:38:54 +0100
Subject: [PATCH 10/14] s3:lib: extend interpret_interface() to optionally read
 speed, caps, and index from config

New syntax for interfaces parameter:

  interfaces = address[;key=value[,key=value[,...]]]

- keys can be 'speed', 'capability', and 'if_index'.

- speed is in bits per second.

- capability can be RSS and RDMA.

- if_index should be used with care, because
  these indexes should not conicide with indexes
  the kernel sets...

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/lib/interface.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 105 insertions(+)

diff --git a/source3/lib/interface.c b/source3/lib/interface.c
index 69b1041..a3bc5d2 100644
--- a/source3/lib/interface.c
+++ b/source3/lib/interface.c
@@ -20,6 +20,7 @@
 
 #include "includes.h"
 #include "lib/socket/interfaces.h"
+#include "librpc/gen_ndr/ioctl.h"
 
 static struct iface_struct *probed_ifaces;
 static int total_probed;
@@ -350,6 +351,45 @@ static void add_interface(const struct iface_struct *ifs)
 			&iface->netmask) ));
 }
 
+
+static void parse_extra_info(char *key, uint64_t *speed, uint32_t *cap,
+			     uint32_t *if_index)
+{
+	while (key != NULL && *key != '\0') {
+		char *next_key;
+		char *val;
+
+		next_key = strchr_m(key, ',');
+		if (next_key != NULL) {
+			*next_key++ = 0;
+		}
+
+		val = strchr_m(key, '=');
+		if (val != NULL) {
+			*val++ = 0;
+
+			if (strequal_m(key, "speed")) {
+				*speed = (uint64_t)strtoull(val, NULL, 0);
+			} else if (strequal_m(key, "capability")) {
+				if (strequal_m(val, "RSS")) {
+					*cap |= FSCTL_NET_IFACE_RSS_CAPABLE;
+				} else if (strequal(val, "RDMA")) {
+					*cap |= FSCTL_NET_IFACE_RDMA_CAPABLE;
+				} else {
+					DBG_WARNING("Capability unknown: "
+						    "'%s'\n", val);
+				}
+			} else if (strequal_m(key, "if_index")) {
+				*if_index = (uint32_t)strtoul(val, NULL, 0);
+			} else {
+				DBG_DEBUG("Key unknown: '%s'\n", key);
+			}
+		}
+
+		key = next_key;
+	}
+}
+
 /****************************************************************************
  Interpret a single element from a interfaces= config line.
 
@@ -360,6 +400,20 @@ static void add_interface(const struct iface_struct *ifs)
  3) IP/masklen
  4) ip/mask
  5) bcast/mask
+
+ Additional information for an interface can be specified with
+ this extended syntax:
+
+    interface[;key1=value1[,key2=value2[...]]]
+
+ where
+ - keys known: 'speed', 'capability', 'if_index'
+ - speed is in bits per second
+ - capabilites known: 'RSS', 'RDMA'
+ - if_index should be used with care, because
+   these indexes should not conicide with indexes
+   the kernel sets...
+
 ****************************************************************************/
 
 static void interpret_interface(char *token)
@@ -373,6 +427,12 @@ static void interpret_interface(char *token)
 	int i;
 	bool added=false;
 	bool goodaddr = false;
+	uint64_t speed = 0;
+	uint32_t cap = FSCTL_NET_IFACE_NONE_CAPABLE;
+	uint32_t if_index = 0;
+	bool speed_set = false;
+	bool cap_set = false;
+	bool if_index_set = false;
 
 	/* first check if it is an interface name */
 	for (i=0;i<total_probed;i++) {
@@ -385,6 +445,24 @@ static void interpret_interface(char *token)
 		return;
 	}
 
+	/*
+	 * extract speed / capability information if present
+	 */
+	p = strchr_m(token, ';');
+	if (p != NULL) {
+		*p++ = 0;
+		parse_extra_info(p, &speed, &cap, &if_index);
+		if (speed != 0) {
+			speed_set = true;
+		}
+		if (cap != FSCTL_NET_IFACE_NONE_CAPABLE) {
+			cap_set = true;
+		}
+		if (if_index != 0) {
+			if_index_set = true;
+		}
+	}
+
 	p = strchr_m(token,'/');
 	if (p == NULL) {
 		if (!interpret_string_addr(&ss, token, 0)) {
@@ -397,6 +475,15 @@ static void interpret_interface(char *token)
 			if (sockaddr_equal((struct sockaddr *)&ss,
 				(struct sockaddr *)&probed_ifaces[i].ip))
 			{
+				if (speed_set) {
+					probed_ifaces[i].linkspeed = speed;
+				}
+				if (cap_set) {
+					probed_ifaces[i].capability = cap;
+				}
+				if (if_index_set) {
+					probed_ifaces[i].if_index = if_index;
+				}
 				add_interface(&probed_ifaces[i]);
 				return;
 			}
@@ -466,6 +553,15 @@ static void interpret_interface(char *token)
 					"config file on interface %s\n",
 					p,
 					probed_ifaces[i].name));
+				if (speed_set) {
+					probed_ifaces[i].linkspeed = speed;
+				}
+				if (cap_set) {
+					probed_ifaces[i].capability = cap;
+				}
+				if (if_index_set) {
+					probed_ifaces[i].if_index = if_index;
+				}
 				add_interface(&probed_ifaces[i]);
 				probed_ifaces[i].netmask = saved_mask;
 				return;
@@ -488,6 +584,15 @@ static void interpret_interface(char *token)
 	ifs.ip = ss;
 	ifs.netmask = ss_mask;
 	ifs.bcast = ss_bcast;
+	if (if_index_set) {
+		probed_ifaces[i].if_index = if_index;
+	}
+	if (speed_set) {
+		ifs.linkspeed = speed;
+	} else {
+		ifs.linkspeed = 1000 * 1000 * 1000;
+	}
+	ifs.capability = cap;
 	add_interface(&ifs);
 }
 
-- 
2.5.0


From 547fda62a32a0d9665f0bfcdb9e59efdd6e903e0 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 25 Jan 2016 16:22:57 +0100
Subject: [PATCH 11/14] s4:lib:socket: skip extra data in interpret_interface()

This is currently smbd-specific.
No need to duplicate the extended parsing
while these functions have not been merged yet.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source4/lib/socket/interface.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/source4/lib/socket/interface.c b/source4/lib/socket/interface.c
index 504a727..9b0d00e 100644
--- a/source4/lib/socket/interface.c
+++ b/source4/lib/socket/interface.c
@@ -178,6 +178,15 @@ static void interpret_interface(TALLOC_CTX *mem_ctx,
 		return;
 	}
 
+	p = strchr_m(token, ';');
+	if (p != NULL) {
+		/*
+		 * skip smbd-specific extra data:
+		 * link speed, capabilities, and interface index
+		 */
+		*p = 0;
+	}
+
 	/* maybe it is a DNS name */
 	p = strchr_m(token,'/');
 	if (p == NULL) {
-- 
2.5.0


From 65ae3d08d3a9a6665895e79cdb3159bc58559141 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 25 Jan 2016 16:35:12 +0100
Subject: [PATCH 12/14] docs:smb.conf: document new extra syntax for
 interfaces.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 docs-xml/smbdotconf/base/interfaces.xml | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/docs-xml/smbdotconf/base/interfaces.xml b/docs-xml/smbdotconf/base/interfaces.xml
index db12fa1..b804e64 100644
--- a/docs-xml/smbdotconf/base/interfaces.xml
+++ b/docs-xml/smbdotconf/base/interfaces.xml
@@ -38,7 +38,28 @@
 	By default Samba enables all active interfaces that are broadcast capable
 	except the loopback adaptor (IP address 127.0.0.1).
 	</para>
-	
+
+	<para>
+	In order to support SMB3 multi-channel configurations, smbd understands
+	some extra data that can be appended after the actual interface with
+	this extended syntax:
+	</para>
+
+	<para>
+	interface[;key1=value1[,key2=value2[...]]]
+	</para>
+
+	<para>
+	Known keys are speed, capability, and if_index. Speed is specified in
+	bits per second. Known capabilities are RSS and RDMA. The
+	if_index should be used with care: the values must not coincide with
+	indexes used by the kernel.
+	Note that these options are mainly intended for testing and
+	development rather than for production use. At least on Linux systems,
+	these values should be auto-detected, but the settings can serve
+	as last a resort when autodetection is not working or is not available.
+	</para>
+
 	<para>
 	The example below configures three network interfaces corresponding 
 	to the eth0 device and IP addresses 192.168.2.10 and 192.168.3.10. 
-- 
2.5.0


From 8e2d073fae413ab19876cc3f7b849ab9e39501e3 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 13 Jun 2014 17:42:00 +0200
Subject: [PATCH 13/14] s3:smbd: implement fsctl_network_iface_info

The ioctl used for detecting interfaces for multi-channel.

Pair-Programmed-With: Michael Adam <obnox at samba.org>

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/smbd/smb2_ioctl_network_fs.c | 124 +++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/source3/smbd/smb2_ioctl_network_fs.c b/source3/smbd/smb2_ioctl_network_fs.c
index 01798ac..844e322 100644
--- a/source3/smbd/smb2_ioctl_network_fs.c
+++ b/source3/smbd/smb2_ioctl_network_fs.c
@@ -29,6 +29,7 @@
 #include "../librpc/ndr/libndr.h"
 #include "librpc/gen_ndr/ndr_ioctl.h"
 #include "smb2_ioctl_private.h"
+#include "../lib/tsocket/tsocket.h"
 
 #define COPYCHUNK_MAX_CHUNKS	256		/* 2k8r2 & win8 = 256 */
 #define COPYCHUNK_MAX_CHUNK_LEN	1048576		/* 2k8r2 & win8 = 1048576 */
@@ -379,6 +380,118 @@ static NTSTATUS fsctl_srv_copychunk_recv(struct tevent_req *req,
 	return status;
 }
 
+static NTSTATUS fsctl_network_iface_info(TALLOC_CTX *mem_ctx,
+					 struct tevent_context *ev,
+					 struct smbXsrv_connection *xconn,
+					 DATA_BLOB *in_input,
+					 uint32_t in_max_output,
+					 DATA_BLOB *out_output)
+{
+	struct fsctl_net_iface_info *array = NULL;
+	struct fsctl_net_iface_info *first = NULL;
+	struct fsctl_net_iface_info *last = NULL;
+	size_t i;
+	size_t num_ifaces = iface_count();
+	enum ndr_err_code ndr_err;
+
+	if (in_input->length != 0) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
+
+	*out_output = data_blob_null;
+
+	array = talloc_zero_array(mem_ctx,
+				  struct fsctl_net_iface_info,
+				  num_ifaces);
+	if (array == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	for (i=0; i < num_ifaces; i++) {
+		struct fsctl_net_iface_info *cur = &array[i];
+		const struct interface *iface = get_interface(i);
+		const struct sockaddr_storage *ifss = &iface->ip;
+		const void *ifptr = ifss;
+		const struct sockaddr *ifsa = (const struct sockaddr *)ifptr;
+		struct tsocket_address *a = NULL;
+		char *addr;
+		bool ok;
+		int ret;
+
+		ret = tsocket_address_bsd_from_sockaddr(array,
+					ifsa, sizeof(struct sockaddr_storage),
+					&a);
+		if (ret != 0) {
+			return map_nt_error_from_unix_common(errno);
+		}
+
+		ok = tsocket_address_is_inet(a, "ip");
+		if (!ok) {
+			continue;
+		}
+
+		addr = tsocket_address_inet_addr_string(a, array);
+		if (addr == NULL) {
+			TALLOC_FREE(array);
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		cur->ifindex = iface->if_index;
+		if (cur->ifindex == 0) {
+			/*
+			 * Did not get interface index from kernel,
+			 * nor from the config. ==> Apply a common
+			 * default value for these cases.
+			 */
+			cur->ifindex = UINT32_MAX;
+		}
+		cur->capability = iface->capability;
+		cur->linkspeed = iface->linkspeed;
+		if (cur->linkspeed == 0) {
+			DBG_DEBUG("Link speed 0 on interface [%s] - skipping "
+				  "address [%s].\n", iface->name, addr);
+			continue;
+		}
+
+		ok = tsocket_address_is_inet(a, "ipv4");
+		if (ok) {
+			cur->sockaddr.family = FSCTL_NET_IFACE_AF_INET;
+			cur->sockaddr.saddr.saddr_in.ipv4 = addr;
+		}
+		ok = tsocket_address_is_inet(a, "ipv6");
+		if (ok) {
+			cur->sockaddr.family = FSCTL_NET_IFACE_AF_INET6;
+			cur->sockaddr.saddr.saddr_in6.ipv6 = addr;
+		}
+
+		if (first == NULL) {
+			first = cur;
+		}
+		if (last != NULL) {
+			last->next = cur;
+		}
+		last = cur;
+	}
+
+	if (first == NULL) {
+		TALLOC_FREE(array);
+		return NT_STATUS_OK;
+	}
+
+	if (DEBUGLEVEL >= 10) {
+		NDR_PRINT_DEBUG(fsctl_net_iface_info, first);
+	}
+
+	ndr_err = ndr_push_struct_blob(out_output, mem_ctx, first,
+			(ndr_push_flags_fn_t)ndr_push_fsctl_net_iface_info);
+	TALLOC_FREE(array);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		return ndr_map_error2ntstatus(ndr_err);
+	}
+
+	return NT_STATUS_OK;
+}
+
 static NTSTATUS fsctl_validate_neg_info(TALLOC_CTX *mem_ctx,
 				        struct tevent_context *ev,
 				        struct smbXsrv_connection *conn,
@@ -541,6 +654,17 @@ struct tevent_req *smb2_ioctl_network_fs(uint32_t ctl_code,
 					req);
 		return req;
 		break;
+	case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
+		status = fsctl_network_iface_info(state, ev,
+						  state->smbreq->xconn,
+						  &state->in_input,
+						  state->in_max_output,
+						  &state->out_output);
+		if (!tevent_req_nterror(req, status)) {
+			tevent_req_done(req);
+		}
+		return tevent_req_post(req, ev);
+		break;
 	case FSCTL_VALIDATE_NEGOTIATE_INFO:
 		status = fsctl_validate_neg_info(state, ev,
 						 state->smbreq->xconn,
-- 
2.5.0


From d4f9ce5a0782ed9c49396314936ddc9647ba5cb5 Mon Sep 17 00:00:00 2001
From: Michael Adam <obnox at samba.org>
Date: Mon, 25 Jan 2016 12:01:44 +0100
Subject: [PATCH 14/14] s3:smbd: only process fsctl_network_iface_info if multi
 channel is enabled

This effectively disables it for now.
Ultimately, we may want to remove this restriction.
Hence a separate patch.

Signed-off-by: Michael Adam <obnox at samba.org>
---
 source3/smbd/smb2_ioctl_network_fs.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/source3/smbd/smb2_ioctl_network_fs.c b/source3/smbd/smb2_ioctl_network_fs.c
index 844e322..d8590de 100644
--- a/source3/smbd/smb2_ioctl_network_fs.c
+++ b/source3/smbd/smb2_ioctl_network_fs.c
@@ -655,6 +655,18 @@ struct tevent_req *smb2_ioctl_network_fs(uint32_t ctl_code,
 		return req;
 		break;
 	case FSCTL_QUERY_NETWORK_INTERFACE_INFO:
+		if (!state->smbreq->xconn->client->server_multi_channel_enabled)
+		{
+			if (IS_IPC(state->smbreq->conn)) {
+				status = NT_STATUS_FS_DRIVER_REQUIRED;
+			} else {
+				status = NT_STATUS_INVALID_DEVICE_REQUEST;
+			}
+
+			tevent_req_nterror(req, status);
+			return tevent_req_post(req, ev);
+		}
+
 		status = fsctl_network_iface_info(state, ev,
 						  state->smbreq->xconn,
 						  &state->in_input,
-- 
2.5.0

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20160125/d9da3e79/signature.sig>


More information about the samba-technical mailing list