/** * Check the server name to find port info first * return 1 when found, else 0 * Warning: connect_info-> & login-> are all modified when needed */ static int parse_server_name_for_port(TDSCONNECTINFO * connect_info, TDSLOGIN * login) { char *pSep, *pEnd; char *server; /* seek the ':' in login server_name */ server = tds_dstr_cstr(&login->server_name); pEnd = server + strlen(server); for (pSep = server; pSep < pEnd; pSep++) if (*pSep == ':') break; if ((pSep < pEnd) && (pSep != server)) { /* yes, i found it! */ if (!tds_dstr_copyn(&connect_info->server_name, server, pSep - server)) /* end the server_name before the ':' */ return 0; /* FALSE */ /* modify connect_info-> && login->server_name & ->port */ login->port = connect_info->port = atoi(pSep + 1); *pSep = 0; /* connect_info->ip_addr needed */ { char tmp[256]; tds_lookup_host(tds_dstr_cstr(&connect_info->server_name), tmp); if (!tds_dstr_copy(&connect_info->ip_addr, tmp)) return 0; /* FALSE */ } return 1; /* TRUE */ } else return 0; /* FALSE */ }
static int get_default_instance_port(const char hostname[]) { char ip[24] = {'\0'}; tds_lookup_host(hostname, ip); if (!*ip) return 0; return tds7_get_instance_port(ip, "MSSQLSERVER"); }
TDSRET tds_lookup_host_set(const char *servername, struct addrinfo **addr) { struct addrinfo *newaddr; assert(servername != NULL && addr != NULL); if ((newaddr = tds_lookup_host(servername)) != NULL) { if (*addr != NULL) freeaddrinfo(*addr); *addr = newaddr; return TDS_SUCCESS; } return TDS_FAIL; }
/* TDSHOST env var, [email protected] 01/21/02 */ static void tds_config_env_tdshost(TDSCONNECTINFO * connect_info) { char *tdshost; char tmp[256]; if ((tdshost = getenv("TDSHOST"))) { tds_lookup_host(tdshost, tmp); tds_dstr_copy(&connect_info->ip_addr, tmp); tdsdump_log(TDS_DBG_INFO1, "%L Setting 'ip_addr' to %s (%s) from $TDSHOST.\n", tmp, tdshost); } return; }
static int get_default_instance_port(const char hostname[]) { int port; struct addrinfo *addr; if ((addr = tds_lookup_host(hostname)) == NULL) return 0; port = tds7_get_instance_port(addr, "MSSQLSERVER"); freeaddrinfo(addr); return port; }
/** * Try to find the IP number and port for a (possibly) logical server name. * * @note This function uses only the interfaces file and is deprecated. * * =========================================================================== */ static void tds_read_interfaces(const char *server, TDSCONNECTINFO * connect_info) { int founded = 0; /* read $SYBASE/interfaces */ if (!server || strlen(server) == 0) { server = getenv("TDSQUERY"); if (!server || strlen(server) == 0) { server = "SYBASE"; } tdsdump_log(TDS_DBG_INFO1, "%L Setting server to %s from $TDSQUERY.\n", server); } tdsdump_log(TDS_DBG_INFO1, "%L Looking for server %s....\n", server); /* * Look for the server in the interf_file iff interf_file has been set. */ if (interf_file) { tdsdump_log(TDS_DBG_INFO1, "%L Looking for server in file %s.\n", interf_file); founded = search_interface_file(connect_info, "", interf_file, server); } /* * if we haven't found the server yet then look for a $HOME/.interfaces file */ if (!founded) { char *path = tds_get_home_file(".interfaces"); if (path) { tdsdump_log(TDS_DBG_INFO1, "%L Looking for server in %s.\n", path); founded = search_interface_file(connect_info, "", path, server); free(path); } } /* * if we haven't found the server yet then look in $SYBBASE/interfaces file */ if (!founded) { const char *sybase = getenv("SYBASE"); if (!sybase || !sybase[0]) sybase = "/etc/freetds"; tdsdump_log(TDS_DBG_INFO1, "%L Looking for server in %s/interfaces.\n", sybase); founded = search_interface_file(connect_info, sybase, "interfaces", server); } /* * If we still don't have the server and port then assume the user * typed an actual server name. */ if (!founded) { char ip_addr[255]; int ip_port; const char *env_port; /* * Make a guess about the port number */ #ifdef TDS50 ip_port = 4000; #else ip_port = 1433; #endif if ((env_port = getenv("TDSPORT")) != NULL) { ip_port = tds_lookup_port(env_port); tdsdump_log(TDS_DBG_INFO1, "%L Setting 'ip_port' to %s from $TDSPORT.\n", env_port); } else tdsdump_log(TDS_DBG_INFO1, "%L Setting 'ip_port' to %d as a guess.\n", ip_port); /* * lookup the host */ tds_lookup_host(server, ip_addr); if (ip_addr[0]) tds_dstr_copy(&connect_info->ip_addr, ip_addr); if (ip_port) connect_info->port = ip_port; } }
/* ========================= search_interface_file() ========================= * * Def: Open and read the file 'file' searching for a logical server * by the name of 'host'. If one is found then lookup * the IP address and port number and store them in 'ip_addr', and * 'ip_port'. * * Ret: void * * =========================================================================== */ static int search_interface_file(TDSCONNECTINFO * connect_info, const char *dir, /* (I) Name of base directory for interface file */ const char *file, /* (I) Name of the interface file */ const char *host /* (I) Logical host to search for */ ) { char *pathname; char line[255]; char tmp_ip[sizeof(line)]; char tmp_port[sizeof(line)]; char tmp_ver[sizeof(line)]; FILE *in; char *field; int found = 0; int server_found = 0; char *lasts; line[0] = '\0'; tmp_ip[0] = '\0'; tmp_port[0] = '\0'; tmp_ver[0] = '\0'; tdsdump_log(TDS_DBG_INFO1, "%L Searching interfaces file %s/%s.\n", dir, file); pathname = (char *) malloc(strlen(dir) + strlen(file) + 10); if (!pathname) return 0; /* * * create the full pathname to the interface file */ if (file[0] == '\0') { pathname[0] = '\0'; } else { if (dir[0] == '\0') { pathname[0] = '\0'; } else { strcpy(pathname, dir); strcat(pathname, "/"); } strcat(pathname, file); } /* * * parse the interfaces file and find the server and port */ if ((in = fopen(pathname, "r")) == NULL) { tdsdump_log(TDS_DBG_INFO1, "%L Couldn't open %s.\n", pathname); free(pathname); return 0; } tdsdump_log(TDS_DBG_INFO1, "%L Interfaces file %s opened.\n", pathname); while (fgets(line, sizeof(line) - 1, in)) { if (line[0] == '#') continue; /* comment */ if (!TDS_ISSPACE(line[0])) { field = strtok_r(line, "\n\t ", &lasts); if (!strcmp(field, host)) { found = 1; tdsdump_log(TDS_DBG_INFO1, "%L Found matching entry for host %s.\n", host); } else found = 0; } else if (found && TDS_ISSPACE(line[0])) { field = strtok_r(line, "\n\t ", &lasts); if (field != NULL && !strcmp(field, "query")) { field = strtok_r(NULL, "\n\t ", &lasts); /* tcp or tli */ if (!strcmp(field, "tli")) { tdsdump_log(TDS_DBG_INFO1, "%L TLI service.\n"); field = strtok_r(NULL, "\n\t ", &lasts); /* tcp */ field = strtok_r(NULL, "\n\t ", &lasts); /* device */ field = strtok_r(NULL, "\n\t ", &lasts); /* host/port */ if (strlen(field) >= 18) { sprintf(tmp_port, "%d", hex2num(&field[6]) * 256 + hex2num(&field[8])); sprintf(tmp_ip, "%d.%d.%d.%d", hex2num(&field[10]), hex2num(&field[12]), hex2num(&field[14]), hex2num(&field[16])); tdsdump_log(TDS_DBG_INFO1, "%L tmp_port = %d.mtp_ip = %s.\n", tmp_port, tmp_ip); } } else { field = strtok_r(NULL, "\n\t ", &lasts); /* ether */ strcpy(tmp_ver, field); field = strtok_r(NULL, "\n\t ", &lasts); /* host */ strcpy(tmp_ip, field); tdsdump_log(TDS_DBG_INFO1, "%L host field %s.\n", tmp_ip); field = strtok_r(NULL, "\n\t ", &lasts); /* port */ strcpy(tmp_port, field); } /* else */ server_found = 1; } /* if */ } /* else if */ } /* while */ fclose(in); free(pathname); /* * Look up the host and service */ if (server_found) { tds_lookup_host(tmp_ip, line); tdsdump_log(TDS_DBG_INFO1, "%L Resolved IP as '%s'.\n", line); tds_dstr_copy(&connect_info->ip_addr, line); if (tmp_port[0]) connect_info->port = tds_lookup_port(tmp_port); if (tmp_ver[0]) tds_config_verstr(tmp_ver, connect_info); } return server_found; } /* search_interface_file() */
static void tds_parse_conf_section(const char *option, const char *value, void *param) { TDSCONNECTINFO *connect_info = (TDSCONNECTINFO *) param; char tmp[256]; tdsdump_log(TDS_DBG_INFO1, "%L option = '%s' value = '%s'.\n", option, value); if (!strcmp(option, TDS_STR_VERSION)) { tds_config_verstr(value, connect_info); } else if (!strcmp(option, TDS_STR_BLKSZ)) { if (atoi(value)) connect_info->block_size = atoi(value); } else if (!strcmp(option, TDS_STR_SWAPDT)) { connect_info->broken_dates = tds_config_boolean(value); } else if (!strcmp(option, TDS_STR_SWAPMNY)) { connect_info->broken_money = tds_config_boolean(value); } else if (!strcmp(option, TDS_STR_TRYSVR)) { connect_info->try_server_login = tds_config_boolean(value); } else if (!strcmp(option, TDS_STR_TRYDOM)) { connect_info->try_domain_login = tds_config_boolean(value); } else if (!strcmp(option, TDS_STR_DOMAIN)) { tds_dstr_copy(&connect_info->default_domain, value); } else if (!strcmp(option, TDS_STR_XDOMAUTH)) { connect_info->xdomain_auth = tds_config_boolean(value); } else if (!strcmp(option, TDS_STR_DUMPFILE)) { tds_dstr_copy(&connect_info->dump_file, value); } else if (!strcmp(option, TDS_STR_DEBUGLVL)) { if (atoi(value)) connect_info->debug_level = atoi(value); } else if (!strcmp(option, TDS_STR_TIMEOUT)) { if (atoi(value)) connect_info->timeout = atoi(value); } else if (!strcmp(option, TDS_STR_CONNTMOUT)) { if (atoi(value)) connect_info->connect_timeout = atoi(value); } else if (!strcmp(option, TDS_STR_HOST)) { tdsdump_log(TDS_DBG_INFO1, "%L Found host entry %s.\n", value); tds_lookup_host(value, tmp); tds_dstr_copy(&connect_info->ip_addr, tmp); tdsdump_log(TDS_DBG_INFO1, "%L IP addr is %s.\n", connect_info->ip_addr); } else if (!strcmp(option, TDS_STR_PORT)) { if (atoi(value)) connect_info->port = atoi(value); } else if (!strcmp(option, TDS_STR_EMUL_LE)) { connect_info->emul_little_endian = tds_config_boolean(value); } else if (!strcmp(option, TDS_STR_TEXTSZ)) { if (atoi(value)) connect_info->text_size = atoi(value); } else if (!strcmp(option, TDS_STR_CHARSET)) { tds_dstr_copy(&connect_info->server_charset, value); tdsdump_log(TDS_DBG_INFO1, "%L %s is %s.\n", option, connect_info->server_charset); } else if (!strcmp(option, TDS_STR_CLCHARSET)) { tds_dstr_copy(&connect_info->client_charset, value); tdsdump_log(TDS_DBG_INFO1, "%L tds_config_login:%d: %s is %s.\n", __LINE__, option, connect_info->client_charset); } else if (!strcmp(option, TDS_STR_LANGUAGE)) { tds_dstr_copy(&connect_info->language, value); } else if (!strcmp(option, TDS_STR_APPENDMODE)) { tds_g_append_mode = tds_config_boolean(value); } else { tdsdump_log(TDS_DBG_INFO1, "UNRECOGNIZED option '%s'...ignoring.\n", option); fprintf(stderr, "FreeTDS: %s:%d: ignoring unrecognized option '%s'\n", __FILE__, __LINE__, option); } }
/** * Parse connection string and fill connect_info according * @param connect_string connect string * @param connect_string_end connect string end (pointer to char past last) * @param connect_info where to store connection info * @return 1 if success 0 otherwhise */ int odbc_parse_connect_string(const char *connect_string, const char *connect_string_end, TDSCONNECTINFO * connect_info) { const char *p, *end; DSTR *dest_s, value; int reparse = 0; /* flag for indicate second parse of string */ char option[16]; char tmp[256]; tds_dstr_init(&value); for (p = connect_string; p && *p;) { dest_s = NULL; /* parse option */ end = (const char *) memchr(p, '=', connect_string_end - p); if (!end) break; /* account for spaces between ;'s. */ while (p < end && *p == ' ') ++p; if ((end - p) >= (int) sizeof(option)) option[0] = 0; else { memcpy(option, p, end - p); option[end - p] = 0; } /* parse value */ p = end + 1; if (*p == '{') { ++p; /* search "};" */ end = p; while ((end = (const char *) memchr(end, '}', connect_string_end - end)) != NULL) { if ((end + 1) != connect_string_end && end[1] == ';') break; ++end; } } else { end = (const char *) memchr(p, ';', connect_string_end - p); } if (!end) end = connect_string_end; if (!tds_dstr_copyn(&value, p, end - p)) return 0; if (strcasecmp(option, "SERVER") == 0) { /* ignore if servername specified */ if (!reparse) { dest_s = &connect_info->server_name; tds_lookup_host(tds_dstr_cstr(&value), tmp); if (!tds_dstr_copy(&connect_info->ip_addr, tmp)) { tds_dstr_free(&value); return 0; } } } else if (strcasecmp(option, "SERVERNAME") == 0) { if (!reparse) { tds_read_conf_file(connect_info, tds_dstr_cstr(&value)); reparse = 1; p = connect_string; continue; } } else if (strcasecmp(option, "DSN") == 0) { if (!reparse) { odbc_get_dsn_info(tds_dstr_cstr(&value), connect_info); reparse = 1; p = connect_string; continue; } } else if (strcasecmp(option, "DATABASE") == 0) { dest_s = &connect_info->database; } else if (strcasecmp(option, "UID") == 0) { dest_s = &connect_info->user_name; } else if (strcasecmp(option, "PWD") == 0) { dest_s = &connect_info->password; } else if (strcasecmp(option, "APP") == 0) { dest_s = &connect_info->app_name; } else if (strcasecmp(option, "WSID") == 0) { dest_s = &connect_info->host_name; } else if (strcasecmp(option, "LANGUAGE") == 0) { dest_s = &connect_info->language; } else if (strcasecmp(option, "Port") == 0) { connect_info->port = atoi(tds_dstr_cstr(&value)); } else if (strcasecmp(option, "TDS_Version") == 0) { tds_config_verstr(tds_dstr_cstr(&value), connect_info); } else if (strcasecmp(option, "Domain") == 0) { dest_s = &connect_info->default_domain; } else if (strcasecmp(option, "TextSize") == 0) { connect_info->text_size = atoi(tds_dstr_cstr(&value)); } else if (strcasecmp(option, "PacketSize") == 0) { connect_info->block_size = atoi(tds_dstr_cstr(&value)); /* TODO "Address" field */ } /* copy to destination */ if (dest_s) { tds_dstr_set(dest_s, tds_dstr_cstr(&value)); tds_dstr_init(&value); } p = end; /* handle "" ";.." "};.." cases */ if (p >= connect_string_end) break; if (*p == '}') ++p; ++p; } tds_dstr_free(&value); return p != NULL; }
/** * Read connection information from given DSN * @param DSN DSN name * @param connect_info where to store connection info * @return 1 if success 0 otherwhise */ int odbc_get_dsn_info(const char *DSN, TDSCONNECTINFO * connect_info) { char tmp[FILENAME_MAX]; int freetds_conf_less = 1; int address_specified = 0; /* use old servername */ tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Servername", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { freetds_conf_less = 0; tds_read_conf_file(connect_info, tmp); } /* search for server (compatible with ms one) */ if (freetds_conf_less) { tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Address", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { address_specified = 1; /* TODO parse like MS */ tds_lookup_host(tmp, tmp); tds_dstr_copy(&connect_info->ip_addr, tmp); } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Server", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { tds_dstr_copy(&connect_info->server_name, tmp); if (!address_specified) { tds_lookup_host(tds_dstr_cstr(&connect_info->server_name), tmp); tds_dstr_copy(&connect_info->ip_addr, tmp); } } } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Port", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { connect_info->port = atoi(tmp); } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "TDS_Version", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { tds_config_verstr(tmp, connect_info); } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Language", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { tds_dstr_copy(&connect_info->language, tmp); } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Database", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { tds_dstr_copy(&connect_info->database, tmp); } #if 0 tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Authentication", "Server", tmp, FILENAME_MAX, "odbc.ini") > 0) { if (!strcasecmp(tmp, "Server")) { connect_info->try_domain_login = 0; connect_info->try_server_login = 1; } else if (!strcasecmp(tmp, "Domain")) { connect_info->try_domain_login = 1; connect_info->try_server_login = 0; } else if (!strcasecmp(tmp, "Both")) { connect_info->try_server_login = 1; connect_info->try_domain_login = 1; } else { /* default to server authentication */ connect_info->try_domain_login = 0; connect_info->try_server_login = 1; } } #endif tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "Domain", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { tds_dstr_copy(&connect_info->default_domain, tmp); } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "TextSize", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { connect_info->text_size = atoi(tmp); } tmp[0] = '\0'; if (SQLGetPrivateProfileString(DSN, "PacketSize", "", tmp, FILENAME_MAX, "odbc.ini") > 0) { connect_info->block_size = atoi(tmp); } return 1; }