1 /* 2 * CDDL HEADER START 3 * 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 } 83 84 void 85 dump_sockaddr(struct sockaddr *sa) 86 { 87 char paddrbuf[INET6_ADDRSTRLEN]; 88 struct sockaddr_in *sin; 89 struct sockaddr_in6 *sin6; 90 int af = sa->sa_family; 91 const char *ip; 92 93 printf(" saf=%d,", af); 94 switch (af) { 95 case AF_NETBIOS: /* see nbns_rq.c */ 96 case AF_INET: 97 sin = (void *)sa; 98 ip = inet_ntop(AF_INET, &sin->sin_addr, 99 paddrbuf, sizeof (paddrbuf)); 100 break; 101 case AF_INET6: 102 sin6 = (void *)sa; 103 ip = inet_ntop(AF_INET6, &sin6->sin6_addr, 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 } 202