int cmd_lookup(int argc, char *argv[]) { struct nb_ctx *ctx; struct sockaddr *sap; char *hostname; int error, opt; if (argc < 2) lookup_usage(); error = nb_ctx_create(&ctx); if (error) { smb_error("unable to create nbcontext", error); exit(1); } if (smb_open_rcfile() == 0) { if (nb_ctx_readrcsection(smb_rc, ctx, "default", 0) != 0) exit(1); rc_close(smb_rc); } while ((opt = getopt(argc, argv, "w:")) != EOF) { switch(opt) { case 'w': nb_ctx_setns(ctx, optarg); break; default: lookup_usage(); /*NOTREACHED*/ } } if (optind >= argc) lookup_usage(); if (nb_ctx_resolve(ctx) != 0) exit(1); hostname = argv[argc - 1]; /* printf("Looking for %s...\n", hostname);*/ error = nbns_resolvename(hostname, ctx, &sap); if (error) { smb_error("unable to resolve %s", error, hostname); exit(1); } printf("Got response from %s\n", inet_ntoa(ctx->nb_lastns.sin_addr)); printf("IP address of %s: %s\n", hostname, inet_ntoa(((struct sockaddr_in*)sap)->sin_addr)); return 0; }
/* * Verify context before connect operation(s), * lookup specified server and try to fill all forgotten fields. */ int smb_ctx_resolve(struct smb_ctx *ctx) { struct smbioc_ossn *ssn = &ctx->ct_ssn; struct smbioc_oshare *sh = &ctx->ct_sh; struct nb_name nn; struct sockaddr *sap; struct sockaddr_nb *salocal, *saserver; char *cp; u_char cstbl[256]; u_int i; int error = 0; ctx->ct_flags &= ~SMBCF_RESOLVED; if (ssn->ioc_srvname[0] == 0) { smb_error("no server name specified", 0); return EINVAL; } if (ssn->ioc_user[0] == 0) { smb_error("no user name specified for server %s", 0, ssn->ioc_srvname); return EINVAL; } if (ctx->ct_minlevel >= SMBL_SHARE && sh->ioc_share[0] == 0) { smb_error("no share name specified for %s@%s", 0, ssn->ioc_user, ssn->ioc_srvname); return EINVAL; } error = nb_ctx_resolve(ctx->ct_nb); if (error) return error; if (ssn->ioc_localcs[0] == 0) strcpy(ssn->ioc_localcs, "default"); /* XXX: locale name ? */ error = smb_addiconvtbl("tolower", ssn->ioc_localcs, nls_lower); if (error) return error; error = smb_addiconvtbl("toupper", ssn->ioc_localcs, nls_upper); if (error) return error; if (ssn->ioc_servercs[0] != 0) { for(i = 0; i < sizeof(cstbl); i++) cstbl[i] = i; nls_mem_toext(cstbl, cstbl, sizeof(cstbl)); error = smb_addiconvtbl(ssn->ioc_servercs, ssn->ioc_localcs, cstbl); if (error) return error; for(i = 0; i < sizeof(cstbl); i++) cstbl[i] = i; nls_mem_toloc(cstbl, cstbl, sizeof(cstbl)); error = smb_addiconvtbl(ssn->ioc_localcs, ssn->ioc_servercs, cstbl); if (error) return error; } if (ctx->ct_srvaddr) { error = nb_resolvehost_in(ctx->ct_srvaddr, &sap); } else { error = nbns_resolvename(ssn->ioc_srvname, ctx->ct_nb, &sap); } if (error) { smb_error("can't get server address", error); return error; } nn.nn_scope = ctx->ct_nb->nb_scope; nn.nn_type = NBT_SERVER; strcpy(nn.nn_name, ssn->ioc_srvname); error = nb_sockaddr(sap, &nn, &saserver); nb_snbfree(sap); if (error) { smb_error("can't allocate server address", error); return error; } ssn->ioc_server = (struct sockaddr*)saserver; if (ctx->ct_locname[0] == 0) { error = nb_getlocalname(ctx->ct_locname); if (error) { smb_error("can't get local name", error); return error; } nls_str_upper(ctx->ct_locname, ctx->ct_locname); } strcpy(nn.nn_name, ctx->ct_locname); nn.nn_type = NBT_WKSTA; nn.nn_scope = ctx->ct_nb->nb_scope; error = nb_sockaddr(NULL, &nn, &salocal); if (error) { nb_snbfree((struct sockaddr*)saserver); smb_error("can't allocate local address", error); return error; } ssn->ioc_local = (struct sockaddr*)salocal; ssn->ioc_lolen = salocal->snb_len; ssn->ioc_svlen = saserver->snb_len; if (ssn->ioc_password[0] == 0 && (ctx->ct_flags & SMBCF_NOPWD) == 0) { cp = getpass("Password:"); error = smb_ctx_setpassword(ctx, cp); if (error) return error; } ctx->ct_flags |= SMBCF_RESOLVED; return 0; }
/* Find all address associated with the NetBIOS name */ struct sockaddr_storage * SMBResolveNetBIOSNameEx(const char *hostName, uint8_t nodeType, const char *winServer, uint32_t timeout, struct sockaddr_storage *respAddr, int32_t *outCount) { struct sockaddr_storage *outAddr = NULL, *listAddr; char *netbios_name = NULL; struct nb_ctx ctx; CFMutableArrayRef addressArray = NULL; CFMutableDataRef addressData; struct connectAddress *conn; CFIndex ii; int error = 0; struct smb_prefs prefs; bzero(&ctx, sizeof(struct nb_ctx)); /* Read the preference files */ readPreferences(&prefs, NULL, NULL, FALSE, TRUE); /* They gave us a wins server use it */ if (winServer) { setWINSAddress(&prefs, winServer, 1); } /* They gave us a timeout value use it */ if ((int32_t)timeout > 0) { prefs.NetBIOSResolverTimeout = timeout; } /* * We uppercase and convert the server name given in the URL to Windows Code * Page. */ netbios_name = convert_utf8_to_wincs(hostName, prefs.WinCodePage, TRUE); if (netbios_name == NULL) { error = ENOMEM; goto done; } /* Only returns IPv4 address */ error = nbns_resolvename(&ctx, &prefs, netbios_name, nodeType, &addressArray, SMB_TCP_PORT_445, TRUE, FALSE, NULL); if (error) { goto done; } if (respAddr) { memcpy(respAddr, &ctx.nb_sender, sizeof(ctx.nb_sender)); } listAddr = outAddr = malloc(CFArrayGetCount(addressArray) * sizeof(struct sockaddr_storage)); if (outAddr == NULL) { error = ENOMEM; goto done; } for (ii=0; ii < CFArrayGetCount(addressArray); ii++) { addressData = (CFMutableDataRef)CFArrayGetValueAtIndex(addressArray, ii); if (addressData) { conn = (struct connectAddress *)(void *)CFDataGetMutableBytePtr(addressData); if (conn) { *outCount += 1; *listAddr++ = conn->storage; } } } if (*outCount == 0) { free(outAddr); outAddr = NULL; /* Didn't really find any */ error = EHOSTUNREACH; } done: if (addressArray) CFRelease(addressArray); if (netbios_name) { free(netbios_name); } releasePreferenceInfo(&prefs); errno = error; return outAddr; }
/* * Call NetBIOS name lookup and return a result in the * same form as getaddrinfo(3) returns. Return code is * zero or one of the EAI_xxx codes like getaddrinfo. */ int nbns_getaddrinfo(const char *name, struct nb_ctx *nbc, struct addrinfo **res) { struct addrinfo *nai = NULL; struct sockaddr *sap = NULL; char *ucname = NULL; int err; /* * Try NetBIOS name lookup. */ if (strlen(name) >= NB_NAMELEN) { err = EAI_OVERFLOW; goto out; } ucname = utf8_str_toupper(name); if (ucname == NULL) goto nomem; /* Note: this returns an NBERROR value. */ err = nbns_resolvename(ucname, nbc, &sap); if (err) { if (smb_verbose) smb_error(dgettext(TEXT_DOMAIN, "nbns_resolvename: %s"), err, name); err = EAI_NODATA; goto out; } /* Note: sap allocated */ /* * Build the addrinfo struct to return. */ nai = malloc(sizeof (*nai)); if (nai == NULL) goto nomem; bzero(nai, sizeof (*nai)); nai->ai_flags = AI_CANONNAME; nai->ai_family = sap->sa_family; nai->ai_socktype = SOCK_STREAM; nai->ai_canonname = ucname; ucname = NULL; /* * The type of this is really sockaddr_in, * but is returned in the generic form. * See nbns_resolvename. */ nai->ai_addrlen = sizeof (struct sockaddr_in); nai->ai_addr = sap; *res = nai; return (0); nomem: err = EAI_MEMORY; out: if (nai != NULL) free(nai); if (sap) free(sap); if (ucname) free(ucname); *res = NULL; return (err); }