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