1*613a2f6bSGordon Ross /* 2*613a2f6bSGordon Ross * CDDL HEADER START 3*613a2f6bSGordon Ross * 4*613a2f6bSGordon Ross * The contents of this file are subject to the terms of the 5*613a2f6bSGordon Ross * Common Development and Distribution License (the "License"). 6*613a2f6bSGordon Ross * You may not use this file except in compliance with the License. 7*613a2f6bSGordon Ross * 8*613a2f6bSGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*613a2f6bSGordon Ross * or http://www.opensolaris.org/os/licensing. 10*613a2f6bSGordon Ross * See the License for the specific language governing permissions 11*613a2f6bSGordon Ross * and limitations under the License. 12*613a2f6bSGordon Ross * 13*613a2f6bSGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 14*613a2f6bSGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*613a2f6bSGordon Ross * If applicable, add the following below this CDDL HEADER, with the 16*613a2f6bSGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 17*613a2f6bSGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 18*613a2f6bSGordon Ross * 19*613a2f6bSGordon Ross * CDDL HEADER END 20*613a2f6bSGordon Ross */ 21*613a2f6bSGordon Ross 22*613a2f6bSGordon Ross /* 23*613a2f6bSGordon Ross * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*613a2f6bSGordon Ross * Use is subject to license terms. 25*613a2f6bSGordon Ross */ 26*613a2f6bSGordon Ross 27*613a2f6bSGordon Ross /* 28*613a2f6bSGordon Ross * Functions to get list of addresses (TCP and/or NetBIOS) 29*613a2f6bSGordon Ross */ 30*613a2f6bSGordon Ross 31*613a2f6bSGordon Ross #include <errno.h> 32*613a2f6bSGordon Ross #include <stdio.h> 33*613a2f6bSGordon Ross #include <stdlib.h> 34*613a2f6bSGordon Ross #include <string.h> 35*613a2f6bSGordon Ross #include <strings.h> 36*613a2f6bSGordon Ross #include <unistd.h> 37*613a2f6bSGordon Ross #include <netdb.h> 38*613a2f6bSGordon Ross #include <libintl.h> 39*613a2f6bSGordon Ross #include <xti.h> 40*613a2f6bSGordon Ross #include <assert.h> 41*613a2f6bSGordon Ross 42*613a2f6bSGordon Ross #include <sys/types.h> 43*613a2f6bSGordon Ross #include <sys/time.h> 44*613a2f6bSGordon Ross #include <sys/byteorder.h> 45*613a2f6bSGordon Ross #include <sys/socket.h> 46*613a2f6bSGordon Ross #include <sys/fcntl.h> 47*613a2f6bSGordon Ross 48*613a2f6bSGordon Ross #include <netinet/in.h> 49*613a2f6bSGordon Ross #include <netinet/tcp.h> 50*613a2f6bSGordon Ross #include <arpa/inet.h> 51*613a2f6bSGordon Ross 52*613a2f6bSGordon Ross #include <netsmb/smb.h> 53*613a2f6bSGordon Ross #include <netsmb/smb_lib.h> 54*613a2f6bSGordon Ross #include <netsmb/netbios.h> 55*613a2f6bSGordon Ross #include <netsmb/nb_lib.h> 56*613a2f6bSGordon Ross #include <netsmb/smb_dev.h> 57*613a2f6bSGordon Ross 58*613a2f6bSGordon Ross #include "charsets.h" 59*613a2f6bSGordon Ross #include "private.h" 60*613a2f6bSGordon Ross 61*613a2f6bSGordon Ross void 62*613a2f6bSGordon Ross dump_addrinfo(struct addrinfo *ai) 63*613a2f6bSGordon Ross { 64*613a2f6bSGordon Ross int i; 65*613a2f6bSGordon Ross 66*613a2f6bSGordon Ross if (ai == NULL) { 67*613a2f6bSGordon Ross printf("ai==NULL\n"); 68*613a2f6bSGordon Ross return; 69*613a2f6bSGordon Ross } 70*613a2f6bSGordon Ross 71*613a2f6bSGordon Ross for (i = 0; ai; i++, ai = ai->ai_next) { 72*613a2f6bSGordon Ross printf("ai[%d]: af=%d, len=%d", i, 73*613a2f6bSGordon Ross ai->ai_family, ai->ai_addrlen); 74*613a2f6bSGordon Ross dump_sockaddr(ai->ai_addr); 75*613a2f6bSGordon Ross if (ai->ai_canonname) { 76*613a2f6bSGordon Ross printf("ai[%d]: cname=\"%s\"\n", 77*613a2f6bSGordon Ross i, ai->ai_canonname); 78*613a2f6bSGordon Ross } 79*613a2f6bSGordon Ross } 80*613a2f6bSGordon Ross } 81*613a2f6bSGordon Ross 82*613a2f6bSGordon Ross void 83*613a2f6bSGordon Ross dump_sockaddr(struct sockaddr *sa) 84*613a2f6bSGordon Ross { 85*613a2f6bSGordon Ross char paddrbuf[INET6_ADDRSTRLEN]; 86*613a2f6bSGordon Ross struct sockaddr_in *sin; 87*613a2f6bSGordon Ross struct sockaddr_in6 *sin6; 88*613a2f6bSGordon Ross int af = sa->sa_family; 89*613a2f6bSGordon Ross const char *ip; 90*613a2f6bSGordon Ross 91*613a2f6bSGordon Ross printf(" saf=%d,", af); 92*613a2f6bSGordon Ross switch (af) { 93*613a2f6bSGordon Ross case AF_NETBIOS: /* see nbns_rq.c */ 94*613a2f6bSGordon Ross case AF_INET: 95*613a2f6bSGordon Ross sin = (void *)sa; 96*613a2f6bSGordon Ross ip = inet_ntop(AF_INET, &sin->sin_addr, 97*613a2f6bSGordon Ross paddrbuf, sizeof (paddrbuf)); 98*613a2f6bSGordon Ross break; 99*613a2f6bSGordon Ross case AF_INET6: 100*613a2f6bSGordon Ross sin6 = (void *)sa; 101*613a2f6bSGordon Ross ip = inet_ntop(AF_INET6, &sin6->sin6_addr, 102*613a2f6bSGordon Ross paddrbuf, sizeof (paddrbuf)); 103*613a2f6bSGordon Ross break; 104*613a2f6bSGordon Ross default: 105*613a2f6bSGordon Ross ip = "?"; 106*613a2f6bSGordon Ross break; 107*613a2f6bSGordon Ross } 108*613a2f6bSGordon Ross printf(" IP=%s\n", ip); 109*613a2f6bSGordon Ross } 110*613a2f6bSGordon Ross 111*613a2f6bSGordon Ross 112*613a2f6bSGordon Ross /* 113*613a2f6bSGordon Ross * SMB client name resolution - normal, and/or NetBIOS. 114*613a2f6bSGordon Ross * Returns an EAI_xxx error number like getaddrinfo(3) 115*613a2f6bSGordon Ross */ 116*613a2f6bSGordon Ross int 117*613a2f6bSGordon Ross smb_ctx_getaddr(struct smb_ctx *ctx) 118*613a2f6bSGordon Ross { 119*613a2f6bSGordon Ross struct nb_ctx *nbc = ctx->ct_nb; 120*613a2f6bSGordon Ross struct addrinfo hints, *res; 121*613a2f6bSGordon Ross char *srvaddr_str; 122*613a2f6bSGordon Ross int gaierr, gaierr2; 123*613a2f6bSGordon Ross 124*613a2f6bSGordon Ross if (ctx->ct_fullserver == NULL || ctx->ct_fullserver[0] == '\0') 125*613a2f6bSGordon Ross return (EAI_NONAME); 126*613a2f6bSGordon Ross 127*613a2f6bSGordon Ross if (ctx->ct_addrinfo != NULL) { 128*613a2f6bSGordon Ross freeaddrinfo(ctx->ct_addrinfo); 129*613a2f6bSGordon Ross ctx->ct_addrinfo = NULL; 130*613a2f6bSGordon Ross } 131*613a2f6bSGordon Ross 132*613a2f6bSGordon Ross /* 133*613a2f6bSGordon Ross * If the user specified an address, use it, 134*613a2f6bSGordon Ross * and don't do NetBIOS lookup. 135*613a2f6bSGordon Ross */ 136*613a2f6bSGordon Ross if (ctx->ct_srvaddr_s) { 137*613a2f6bSGordon Ross srvaddr_str = ctx->ct_srvaddr_s; 138*613a2f6bSGordon Ross nbc->nb_flags &= ~NBCF_NS_ENABLE; 139*613a2f6bSGordon Ross } else 140*613a2f6bSGordon Ross srvaddr_str = ctx->ct_fullserver; 141*613a2f6bSGordon Ross 142*613a2f6bSGordon Ross /* 143*613a2f6bSGordon Ross * Default the server name we'll use in the 144*613a2f6bSGordon Ross * protocol (i.e. NTLM, tree connect). 145*613a2f6bSGordon Ross * If we get a canonical name, we'll 146*613a2f6bSGordon Ross * overwrite this below. 147*613a2f6bSGordon Ross */ 148*613a2f6bSGordon Ross strlcpy(ctx->ct_srvname, ctx->ct_fullserver, 149*613a2f6bSGordon Ross sizeof (ctx->ct_srvname)); 150*613a2f6bSGordon Ross 151*613a2f6bSGordon Ross /* 152*613a2f6bSGordon Ross * Try to lookup the host address using the 153*613a2f6bSGordon Ross * normal name-to-IP address mechanisms. 154*613a2f6bSGordon Ross * If that fails, we MAY try NetBIOS. 155*613a2f6bSGordon Ross */ 156*613a2f6bSGordon Ross memset(&hints, 0, sizeof (hints)); 157*613a2f6bSGordon Ross hints.ai_flags = AI_CANONNAME; 158*613a2f6bSGordon Ross hints.ai_family = PF_UNSPEC; 159*613a2f6bSGordon Ross hints.ai_socktype = SOCK_STREAM; 160*613a2f6bSGordon Ross gaierr = getaddrinfo(srvaddr_str, NULL, &hints, &res); 161*613a2f6bSGordon Ross if (gaierr == 0) { 162*613a2f6bSGordon Ross #if 1 163*613a2f6bSGordon Ross /* 164*613a2f6bSGordon Ross * XXX Temporarily work-around CR 6831339: 165*613a2f6bSGordon Ross * getaddrinfo() sets ai_canonname incorrectly 166*613a2f6bSGordon Ross */ 167*613a2f6bSGordon Ross char tmphost[256]; 168*613a2f6bSGordon Ross gaierr2 = getnameinfo(res->ai_addr, res->ai_addrlen, 169*613a2f6bSGordon Ross tmphost, sizeof (tmphost), 170*613a2f6bSGordon Ross NULL, 0, NI_NAMEREQD); 171*613a2f6bSGordon Ross if (gaierr2 == 0) { 172*613a2f6bSGordon Ross DPRINT("cname: %s", tmphost); 173*613a2f6bSGordon Ross strlcpy(ctx->ct_srvname, tmphost, 174*613a2f6bSGordon Ross sizeof (ctx->ct_srvname)); 175*613a2f6bSGordon Ross } 176*613a2f6bSGordon Ross #else 177*613a2f6bSGordon Ross if (res->ai_canonname) 178*613a2f6bSGordon Ross strlcpy(ctx->ct_srvname, res->ai_canonname, 179*613a2f6bSGordon Ross sizeof (ctx->ct_srvname)); 180*613a2f6bSGordon Ross #endif 181*613a2f6bSGordon Ross ctx->ct_addrinfo = res; 182*613a2f6bSGordon Ross return (0); 183*613a2f6bSGordon Ross } 184*613a2f6bSGordon Ross 185*613a2f6bSGordon Ross /* 186*613a2f6bSGordon Ross * If regular IP name lookup failed, try NetBIOS, 187*613a2f6bSGordon Ross * but only if given a valid NetBIOS name and if 188*613a2f6bSGordon Ross * NetBIOS name lookup is enabled. 189*613a2f6bSGordon Ross * 190*613a2f6bSGordon Ross * Note: we only have ssn_srvname if the full name 191*613a2f6bSGordon Ross * was also a valid NetBIOS name. 192*613a2f6bSGordon Ross */ 193*613a2f6bSGordon Ross if (nbc->nb_flags & NBCF_NS_ENABLE) { 194*613a2f6bSGordon Ross gaierr2 = nbns_getaddrinfo(ctx->ct_fullserver, nbc, &res); 195*613a2f6bSGordon Ross if (gaierr2 == 0) { 196*613a2f6bSGordon Ross if (res->ai_canonname) 197*613a2f6bSGordon Ross strlcpy(ctx->ct_srvname, 198*613a2f6bSGordon Ross res->ai_canonname, 199*613a2f6bSGordon Ross sizeof (ctx->ct_srvname)); 200*613a2f6bSGordon Ross ctx->ct_addrinfo = res; 201*613a2f6bSGordon Ross return (0); 202*613a2f6bSGordon Ross } 203*613a2f6bSGordon Ross } 204*613a2f6bSGordon Ross 205*613a2f6bSGordon Ross /* 206*613a2f6bSGordon Ross * Return the original error from getaddrinfo 207*613a2f6bSGordon Ross */ 208*613a2f6bSGordon Ross if (smb_verbose) { 209*613a2f6bSGordon Ross smb_error(dgettext(TEXT_DOMAIN, 210*613a2f6bSGordon Ross "getaddrinfo: %s: %s"), 0, 211*613a2f6bSGordon Ross ctx->ct_fullserver, 212*613a2f6bSGordon Ross gai_strerror(gaierr)); 213*613a2f6bSGordon Ross } 214*613a2f6bSGordon Ross return (gaierr); 215*613a2f6bSGordon Ross } 216