The branch, master has been updated
       via  6a24ccc s3:smbd: only process fsctl_network_iface_info if multi 
channel is enabled
       via  e8a051f s3:smbd: implement fsctl_network_iface_info
       via  99d3dbe docs:smb.conf: document new extra syntax for interfaces.
       via  9fcf874 s4:lib:socket: skip extra data in interpret_interface()
       via  8284b34 s3:lib: extend interpret_interface() to optionally read 
speed, caps, and index from config
       via  3785be8 s3:lib: remove an unmotivated comment from 
interpret_interface()
       via  e569ffd s3:lib: copy speed, cap, and index in add_interface()
       via  9f9d6ac smb.h: add linkspeed, capability, and if_index to interface 
struct
       via  549a9ab lib:socket: detect link speed with ethtool ioctl in 
get_interfaces (on linux)
       via  1862aa6 build: detect support for ethtool
       via  64be8e7 lib:socket: set defaults for linkspeed and capability in 
get_interfaces()
       via  235f37b lib:socket: get interface index from kernel
       via  d392e0a lib:socket: add linkspeed, capability and if_index to 
iface_struct
       via  bc9e1fc librpc:idl: define FSCTL_NET_IFACE_NONE_CAPABLE in ioctl.idl
      from  a2894cf s3:lib: add braces around if-block in my_sam_name()

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 6a24cccd804eb8b89023fa0265d548fd722d909f
Author: Michael Adam <[email protected]>
Date:   Mon Jan 25 12:01:44 2016 +0100

    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 <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>
    
    Autobuild-User(master): Michael Adam <[email protected]>
    Autobuild-Date(master): Tue Jan 26 10:40:44 CET 2016 on sn-devel-144

commit e8a051f58a8f785ba8df66d263a1c632603f3650
Author: Stefan Metzmacher <[email protected]>
Date:   Fri Jun 13 17:42:00 2014 +0200

    s3:smbd: implement fsctl_network_iface_info
    
    The ioctl used for detecting interfaces for multi-channel.
    
    Pair-Programmed-With: Michael Adam <[email protected]>
    
    Signed-off-by: Stefan Metzmacher <[email protected]>
    Signed-off-by: Michael Adam <[email protected]>

commit 99d3dbee9952d2947e64a68380686b12c6a1e7f5
Author: Michael Adam <[email protected]>
Date:   Mon Jan 25 16:35:12 2016 +0100

    docs:smb.conf: document new extra syntax for interfaces.
    
    Signed-off-by: Michael Adam <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 9fcf87419f3f68429bb365ffb605be3eacc97e15
Author: Michael Adam <[email protected]>
Date:   Mon Jan 25 16:22:57 2016 +0100

    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 <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 8284b34f95639ad7c2e3a97b514529201c20e2ed
Author: Michael Adam <[email protected]>
Date:   Mon Jan 25 03:38:54 2016 +0100

    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 <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 3785be8d4e66f1bf01ec1b64a8e2325e4de08196
Author: Michael Adam <[email protected]>
Date:   Sun Jan 24 13:26:35 2016 +0100

    s3:lib: remove an unmotivated comment from interpret_interface()
    
    This seems to be a left-over from historic code.
    
    Signed-off-by: Michael Adam <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit e569ffd83138952454ba9b9fb38ee7d852293697
Author: Michael Adam <[email protected]>
Date:   Mon Jan 25 14:09:37 2016 +0100

    s3:lib: copy speed, cap, and index in add_interface()
    
    Signed-off-by: Michael Adam <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 9f9d6ac8c1594f0c090a176d189c99fba3c31966
Author: Michael Adam <[email protected]>
Date:   Mon Jan 25 03:38:16 2016 +0100

    smb.h: add linkspeed, capability, and if_index to interface struct
    
    Pair-Programmed-With: Anoop C S <[email protected]>
    
    Signed-off-by: Michael Adam <[email protected]>
    Signed-off-by: Anoop C S <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 549a9abc7e037442dd8955b52caaaf11a1e4bc02
Author: Anoop C S <[email protected]>
Date:   Fri Jan 22 20:51:55 2016 +0530

    lib:socket: detect link speed with ethtool ioctl in get_interfaces (on 
linux)
    
    Pair-Programmed-With: Michael Adam <[email protected]>
    
    Signed-off-by: Anoop C S <[email protected]>
    Signed-off-by: Michael Adam <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 1862aa6c259ebe6de86b220208e315a22515b453
Author: Michael Adam <[email protected]>
Date:   Mon Jan 25 03:30:39 2016 +0100

    build: detect support for ethtool
    
    Pair-Programmed-With: Anoop C S <[email protected]>
    
    Signed-off-by: Michael Adam <[email protected]>
    Signed-off-by: Anoop C S <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 64be8e73ff73bfb546d4753b58937d53898412cb
Author: Michael Adam <[email protected]>
Date:   Mon Jan 25 03:38:31 2016 +0100

    lib:socket: set defaults for linkspeed and capability in get_interfaces()
    
    Signed-off-by: Michael Adam <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit 235f37baa7df03ef44f71aea50d72603297a611d
Author: Michael Adam <[email protected]>
Date:   Mon Jan 25 12:23:40 2016 +0100

    lib:socket: get interface index from kernel
    
    Signed-off-by: Michael Adam <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit d392e0a66d941eb66c1973cfa3e54653f5e7d240
Author: Michael Adam <[email protected]>
Date:   Mon Jan 25 03:38:05 2016 +0100

    lib:socket: add linkspeed, capability and if_index to iface_struct
    
    Pair-Programmed-With: Anoop C S <[email protected]>
    
    Signed-off-by: Michael Adam <[email protected]>
    Signed-off-by: Anoop C S <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

commit bc9e1fc70cda0dffd8a4959db4d51bc0bc136206
Author: Michael Adam <[email protected]>
Date:   Mon Jan 25 03:37:38 2016 +0100

    librpc:idl: define FSCTL_NET_IFACE_NONE_CAPABLE in ioctl.idl
    
    Signed-off-by: Michael Adam <[email protected]>
    Reviewed-by: Stefan Metzmacher <[email protected]>

-----------------------------------------------------------------------

Summary of changes:
 docs-xml/smbdotconf/base/interfaces.xml |  23 +++++-
 lib/socket/interfaces.c                 |  60 ++++++++++++++
 lib/socket/interfaces.h                 |   3 +
 lib/socket/wscript                      |   7 ++
 librpc/idl/ioctl.idl                    |   1 +
 source3/include/smb.h                   |   3 +
 source3/lib/interface.c                 | 109 ++++++++++++++++++++++++-
 source3/smbd/smb2_ioctl_network_fs.c    | 136 ++++++++++++++++++++++++++++++++
 source4/lib/socket/interface.c          |   9 +++
 wscript                                 |   1 +
 10 files changed, 350 insertions(+), 2 deletions(-)
 create mode 100644 lib/socket/wscript


Changeset truncated at 500 lines:

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. 
diff --git a/lib/socket/interfaces.c b/lib/socket/interfaces.c
index e62da3c..98341e2 100644
--- a/lib/socket/interfaces.c
+++ b/lib/socket/interfaces.c
@@ -24,6 +24,12 @@
 #include "system/network.h"
 #include "interfaces.h"
 #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.
@@ -119,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.
@@ -137,6 +184,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;
@@ -214,6 +262,18 @@ 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));
+               }
+
+#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;
+
                if (strlcpy(ifaces[total].name, ifptr->ifa_name,
                        sizeof(ifaces[total].name)) >=
                                sizeof(ifaces[total].name)) {
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;
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/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;
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
diff --git a/source3/lib/interface.c b/source3/lib/interface.c
index adf8b42..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;
@@ -333,6 +334,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);
 
@@ -347,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.
 
@@ -357,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)
@@ -370,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++) {
@@ -382,7 +445,24 @@ static void interpret_interface(char *token)
                return;
        }
 
-       /* maybe it is a DNS name */
+       /*
+        * 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)) {
@@ -395,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;
                        }
@@ -464,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;
@@ -486,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);
 }
 
diff --git a/source3/smbd/smb2_ioctl_network_fs.c 
b/source3/smbd/smb2_ioctl_network_fs.c
index 01798ac..d8590de 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,29 @@ struct tevent_req *smb2_ioctl_network_fs(uint32_t ctl_code,
                                        req);
                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);


-- 
Samba Shared Repository

Reply via email to