Print this page
NEX-16824 SMB client connection setup rework
NEX-17232 SMB client reconnect failures
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (improve debug)


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.

  24  */
  25 
  26 /*
  27  * Functions to get list of addresses (TCP and/or NetBIOS)
  28  */
  29 
  30 #include <errno.h>
  31 #include <stdio.h>
  32 #include <stdlib.h>
  33 #include <string.h>
  34 #include <strings.h>
  35 #include <unistd.h>
  36 #include <netdb.h>
  37 #include <libintl.h>
  38 #include <xti.h>
  39 #include <assert.h>
  40 
  41 #include <sys/types.h>
  42 #include <sys/time.h>
  43 #include <sys/byteorder.h>
  44 #include <sys/socket.h>
  45 #include <sys/fcntl.h>
  46 
  47 #include <netinet/in.h>
  48 #include <netinet/tcp.h>
  49 #include <arpa/inet.h>
  50 
  51 #include <netsmb/smb.h>
  52 #include <netsmb/smb_lib.h>
  53 #include <netsmb/netbios.h>
  54 #include <netsmb/nb_lib.h>
  55 #include <netsmb/smb_dev.h>
  56 
  57 #include "charsets.h"
  58 #include "private.h"
  59 


  60 void
  61 dump_addrinfo(struct addrinfo *ai)
  62 {
  63         int i;
  64 
  65         if (ai == NULL) {
  66                 printf("ai==NULL\n");
  67                 return;
  68         }
  69 
  70         for (i = 0; ai; i++, ai = ai->ai_next) {
  71                 printf("ai[%d]: af=%d, len=%d", i,
  72                     ai->ai_family, ai->ai_addrlen);
  73                 dump_sockaddr(ai->ai_addr);
  74                 if (ai->ai_canonname) {
  75                         printf("ai[%d]: cname=\"%s\"\n",
  76                             i, ai->ai_canonname);
  77                 }
  78         }
  79 }


 101                     paddrbuf, sizeof (paddrbuf));
 102                 break;
 103         default:
 104                 ip = "?";
 105                 break;
 106         }
 107         printf(" IP=%s\n", ip);
 108 }
 109 
 110 
 111 /*
 112  * SMB client name resolution - normal, and/or NetBIOS.
 113  * Returns an EAI_xxx error number like getaddrinfo(3)
 114  */
 115 int
 116 smb_ctx_getaddr(struct smb_ctx *ctx)
 117 {
 118         struct nb_ctx   *nbc = ctx->ct_nb;
 119         struct addrinfo hints, *res;
 120         char *srvaddr_str;
 121         int gaierr, gaierr2;
 122 
 123         if (ctx->ct_fullserver == NULL || ctx->ct_fullserver[0] == '\0')
 124                 return (EAI_NONAME);
 125 
 126         if (ctx->ct_addrinfo != NULL) {
 127                 freeaddrinfo(ctx->ct_addrinfo);
 128                 ctx->ct_addrinfo = NULL;
 129         }
 130 
 131         /*
 132          * If the user specified an address, use it,
 133          * and don't do NetBIOS lookup.
 134          */
 135         if (ctx->ct_srvaddr_s) {
 136                 srvaddr_str = ctx->ct_srvaddr_s;
 137                 nbc->nb_flags &= ~NBCF_NS_ENABLE;
 138         } else
 139                 srvaddr_str = ctx->ct_fullserver;
 140 
 141         /*
 142          * Default the server name we'll use in the
 143          * protocol (i.e. NTLM, tree connect).
 144          */
 145         strlcpy(ctx->ct_srvname, ctx->ct_fullserver,
 146             sizeof (ctx->ct_srvname));
 147 
 148         /*
 149          * Try to lookup the host address using the
 150          * normal name-to-IP address mechanisms.
 151          * If that fails, we MAY try NetBIOS.
 152          */
 153         memset(&hints, 0, sizeof (hints));
 154         hints.ai_flags = AI_CANONNAME;
 155         hints.ai_family = PF_UNSPEC;
 156         hints.ai_socktype = SOCK_STREAM;
 157         gaierr = getaddrinfo(srvaddr_str, NULL, &hints, &res);
 158         if (gaierr == 0) {
 159                 ctx->ct_addrinfo = res;
 160                 return (0);
 161         }
 162 
 163         /*







 164          * If regular IP name lookup failed, try NetBIOS,
 165          * but only if given a valid NetBIOS name and if
 166          * NetBIOS name lookup is enabled.
 167          */
 168         if (nbc->nb_flags & NBCF_NS_ENABLE) {
 169                 gaierr2 = nbns_getaddrinfo(ctx->ct_fullserver, nbc, &res);
 170                 if (gaierr2 == 0) {
 171                         if (res->ai_canonname)
 172                                 strlcpy(ctx->ct_srvname,
 173                                     res->ai_canonname,
 174                                     sizeof (ctx->ct_srvname));
 175                         ctx->ct_addrinfo = res;
 176                         return (0);
 177                 }
 178         }

 179 
 180         /*
 181          * Return the original error from getaddrinfo
 182          */
 183         if (smb_verbose) {
 184                 smb_error(dgettext(TEXT_DOMAIN,
 185                     "getaddrinfo: %s: %s"), 0,
 186                     ctx->ct_fullserver,
 187                     gai_strerror(gaierr));
 188         }
 189         return (gaierr);
 190 }


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 
  27 /*
  28  * Functions to get list of addresses (TCP and/or NetBIOS)
  29  */
  30 
  31 #include <errno.h>
  32 #include <stdio.h>
  33 #include <stdlib.h>
  34 #include <string.h>
  35 #include <strings.h>
  36 #include <unistd.h>
  37 #include <netdb.h>
  38 #include <libintl.h>
  39 #include <xti.h>
  40 #include <assert.h>
  41 
  42 #include <sys/types.h>
  43 #include <sys/time.h>
  44 #include <sys/byteorder.h>
  45 #include <sys/socket.h>
  46 #include <sys/fcntl.h>
  47 
  48 #include <netinet/in.h>
  49 #include <netinet/tcp.h>
  50 #include <arpa/inet.h>
  51 
  52 #include <netsmb/smb.h>
  53 #include <netsmb/smb_lib.h>
  54 #include <netsmb/netbios.h>
  55 #include <netsmb/nb_lib.h>
  56 #include <netsmb/smb_dev.h>
  57 
  58 #include "charsets.h"
  59 #include "private.h"
  60 
  61 static char smb_port[16] = "445";
  62 
  63 void
  64 dump_addrinfo(struct addrinfo *ai)
  65 {
  66         int i;
  67 
  68         if (ai == NULL) {
  69                 printf("ai==NULL\n");
  70                 return;
  71         }
  72 
  73         for (i = 0; ai; i++, ai = ai->ai_next) {
  74                 printf("ai[%d]: af=%d, len=%d", i,
  75                     ai->ai_family, ai->ai_addrlen);
  76                 dump_sockaddr(ai->ai_addr);
  77                 if (ai->ai_canonname) {
  78                         printf("ai[%d]: cname=\"%s\"\n",
  79                             i, ai->ai_canonname);
  80                 }
  81         }
  82 }


 104                     paddrbuf, sizeof (paddrbuf));
 105                 break;
 106         default:
 107                 ip = "?";
 108                 break;
 109         }
 110         printf(" IP=%s\n", ip);
 111 }
 112 
 113 
 114 /*
 115  * SMB client name resolution - normal, and/or NetBIOS.
 116  * Returns an EAI_xxx error number like getaddrinfo(3)
 117  */
 118 int
 119 smb_ctx_getaddr(struct smb_ctx *ctx)
 120 {
 121         struct nb_ctx   *nbc = ctx->ct_nb;
 122         struct addrinfo hints, *res;
 123         char *srvaddr_str;
 124         int gaierr;
 125 
 126         if (ctx->ct_fullserver == NULL || ctx->ct_fullserver[0] == '\0')
 127                 return (EAI_NONAME);
 128 
 129         if (ctx->ct_addrinfo != NULL) {
 130                 freeaddrinfo(ctx->ct_addrinfo);
 131                 ctx->ct_addrinfo = NULL;
 132         }
 133 
 134         /*
 135          * If the user specified an address, use it,
 136          * and don't do NetBIOS lookup.
 137          */
 138         if (ctx->ct_srvaddr_s) {
 139                 srvaddr_str = ctx->ct_srvaddr_s;
 140                 nbc->nb_flags &= ~NBCF_NS_ENABLE;
 141         } else
 142                 srvaddr_str = ctx->ct_fullserver;
 143 
 144         /*
 145          * Default the server name we'll use in the
 146          * protocol (i.e. NTLM, tree connect).
 147          */
 148         strlcpy(ctx->ct_srvname, ctx->ct_fullserver,
 149             sizeof (ctx->ct_srvname));
 150 
 151         /*
 152          * Try to lookup the host address using the
 153          * normal name-to-IP address mechanisms.
 154          * If that fails, we MAY try NetBIOS.
 155          */
 156         memset(&hints, 0, sizeof (hints));
 157         hints.ai_flags = AI_CANONNAME;
 158         hints.ai_family = PF_UNSPEC;
 159         hints.ai_socktype = SOCK_STREAM;
 160         gaierr = getaddrinfo(srvaddr_str, smb_port, &hints, &res);
 161         if (gaierr == 0) {
 162                 ctx->ct_addrinfo = res;
 163                 return (0);
 164         }
 165 
 166         /*
 167          * If we really want to support NetBIOS, we should add
 168          * an AF_NETBIOS entry to the address list here.
 169          * For now, let's just skip NetBIOS.
 170          * (Can we just kill NetBIOS?  Please? :)
 171          */
 172 #if 0   /* XXX Just kill NetBIOS? */
 173         /*
 174          * If regular IP name lookup failed, try NetBIOS,
 175          * but only if given a valid NetBIOS name and if
 176          * NetBIOS name lookup is enabled.
 177          */
 178         if (nbc->nb_flags & NBCF_NS_ENABLE) {
 179                 int gaierr2 = nbns_getaddrinfo(ctx->ct_fullserver, nbc, &res);
 180                 if (gaierr2 == 0) {
 181                         if (res->ai_canonname)
 182                                 strlcpy(ctx->ct_srvname,
 183                                     res->ai_canonname,
 184                                     sizeof (ctx->ct_srvname));
 185                         ctx->ct_addrinfo = res;
 186                         return (0);
 187                 }
 188         }
 189 #endif
 190 
 191         /*
 192          * Return the original error from getaddrinfo
 193          */
 194         if (smb_verbose) {
 195                 smb_error(dgettext(TEXT_DOMAIN,
 196                     "getaddrinfo: %s: %s"), 0,
 197                     ctx->ct_fullserver,
 198                     gai_strerror(gaierr));
 199         }
 200         return (gaierr);
 201 }