Skip to content

Commit 25edb8e

Browse files
Peter Deaconfreddy77
authored andcommitted
Add IPv6 support
Implement tds_getaddrinfo and family as replacements is getaddrinfo (is not present). Use them instead of classic IPv4 versions. Signed-off-by: Peter Deacon <peterd@iea-software.com> Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
1 parent 3932c10 commit 25edb8e

File tree

13 files changed

+331
-130
lines changed

13 files changed

+331
-130
lines changed

include/replacements.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,27 @@ char *strsep(char **stringp, const char *delim);
8888
size_t tds_strlcpy(char *dest, const char *src, size_t len);
8989
#endif
9090

91+
#if HAVE_GETADDRINFO
92+
#define tds_addrinfo addrinfo
93+
#define tds_getaddrinfo getaddrinfo
94+
#define tds_getnameinfo getnameinfo
95+
#define tds_freeaddrinfo freeaddrinfo
96+
#else
97+
typedef struct tds_addrinfo {
98+
int ai_flags;
99+
int ai_family;
100+
int ai_socktype;
101+
int ai_protocol;
102+
size_t ai_addrlen;
103+
struct sockaddr *ai_addr;
104+
struct tds_addrinfo *ai_next;
105+
} tds_addrinfo;
106+
107+
int tds_getaddrinfo(const char *node, const char *service, const struct tds_addrinfo *hints, struct tds_addrinfo **res);
108+
int tds_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);
109+
void tds_freeaddrinfo(struct tds_addrinfo *addr);
110+
#endif
111+
91112
#if HAVE_STRLCAT
92113
#define tds_strlcat(d,s,l) strlcat(d,s,l)
93114
#else

include/tds.h

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
#include <stddef.h>
3232
#endif
3333

34+
#if HAVE_NETDB_H
35+
#include <netdb.h>
36+
#endif /* HAVE_NETDB_H */
37+
3438
#if HAVE_NETINET_IN_H
3539
#include <netinet/in.h>
3640
#endif /* HAVE_NET_INET_IN_H */
@@ -48,6 +52,7 @@ typedef struct tds_column TDSCOLUMN;
4852
#include "tds_sysdep_public.h"
4953
#include "tds_sysdep_private.h"
5054
#include "tdsthread.h"
55+
#include "replacements.h"
5156

5257
#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__MINGW32__)
5358
#pragma GCC visibility push(hidden)
@@ -556,7 +561,8 @@ typedef struct tds_login
556561
DSTR client_charset;
557562
DSTR database;
558563

559-
DSTR ip_addr; /**< ip of server */
564+
struct tds_addrinfo *ip_addrs; /**< ip(s) of server */
565+
struct tds_addrinfo *connected_addr; /* ip of connected server */
560566
DSTR instance_name;
561567
DSTR dump_file;
562568
int debug_flags;
@@ -1174,7 +1180,10 @@ void tds_parse_conf_section(const char *option, const char *value, void *param);
11741180
TDSLOGIN *tds_read_config_info(TDSSOCKET * tds, TDSLOGIN * login, TDSLOCALE * locale);
11751181
void tds_fix_login(TDSLOGIN* login);
11761182
TDS_USMALLINT * tds_config_verstr(const char *tdsver, TDSLOGIN* login);
1177-
TDSRET tds_lookup_host(const char *servername, char *ip);
1183+
struct tds_addrinfo *tds_lookup_host(const char *servername);
1184+
TDSRET tds_lookup_host_set(const char *servername, struct tds_addrinfo **addr);
1185+
TDSRET tds_addrinfo2str(struct tds_addrinfo *addr, char *name, int namemax);
1186+
11781187
TDSRET tds_set_interfaces_file_loc(const char *interfloc);
11791188
extern const char STD_DATETIME_FMT[];
11801189
int tds_config_boolean(const char *value);
@@ -1383,10 +1392,10 @@ extern int tds_debug_flags;
13831392
extern int tds_g_append_mode;
13841393

13851394
/* net.c */
1386-
TDSERRNO tds_open_socket(TDSSOCKET * tds, const char *ip_addr, unsigned int port, int timeout, int *p_oserr);
1395+
TDSERRNO tds_open_socket(TDSSOCKET * tds, struct tds_addrinfo *ipaddr, unsigned int port, int timeout, int *p_oserr);
13871396
void tds_close_socket(TDSSOCKET * tds);
1388-
int tds7_get_instance_ports(FILE *output, const char *ip_addr);
1389-
int tds7_get_instance_port(const char *ip_addr, const char *instance);
1397+
int tds7_get_instance_ports(FILE *output, struct tds_addrinfo *addr);
1398+
int tds7_get_instance_port(struct tds_addrinfo *addr, const char *instance);
13901399
TDSRET tds_ssl_init(TDSSOCKET *tds);
13911400
void tds_ssl_deinit(TDSCONNECTION *conn);
13921401
const char *tds_prwsaerror(int erc);

include/tds_sysdep_private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ typedef int pid_t;
7070

7171
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64)
7272
#include <winsock2.h>
73+
#include <ws2tcpip.h>
74+
#include <wspiapi.h>
7375
#include <windows.h>
7476
#define READSOCKET(a,b,c) recv((a), (char *) (b), (c), TDS_NOSIGNAL)
7577
#define WRITESOCKET(a,b,c) send((a), (const char *) (b), (c), TDS_NOSIGNAL)

src/apps/tsql.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -395,14 +395,17 @@ get_opt_flags(char *s, int *opt_flags)
395395
static int
396396
get_default_instance_port(const char hostname[])
397397
{
398-
char ip[24] = {'\0'};
398+
int port;
399+
struct tds_addrinfo *addr;
399400

400-
tds_lookup_host(hostname, ip);
401-
402-
if (!*ip)
401+
if ((addr = tds_lookup_host(hostname)) == NULL)
403402
return 0;
403+
404+
port = tds7_get_instance_port(addr, "MSSQLSERVER");
405+
406+
tds_freeaddrinfo(addr);
404407

405-
return tds7_get_instance_port(ip, "MSSQLSERVER");
408+
return port;
406409
}
407410

408411
#if !defined(LC_ALL)
@@ -519,7 +522,7 @@ populate_login(TDSLOGIN * login, int argc, char **argv)
519522

520523
if ((global_opt_flags & OPT_INSTANCES) && hostname) {
521524
static const char template[] = "%s.instances";
522-
char ip[24] = {'\0'};
525+
struct tds_addrinfo *addr;
523526
char *filename = getenv("TDSDUMP");
524527

525528
if (filename) {
@@ -529,8 +532,10 @@ populate_login(TDSLOGIN * login, int argc, char **argv)
529532
tdsdump_open(filename);
530533
free(filename);
531534
}
532-
tds_lookup_host(hostname, ip);
533-
tds7_get_instance_ports(stderr, ip);
535+
if ((addr = tds_lookup_host(hostname)) != NULL) {
536+
tds7_get_instance_ports(stderr, addr);
537+
tds_freeaddrinfo(addr);
538+
}
534539
tdsdump_close();
535540
exit(0);
536541
}

src/odbc/connectparams.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ static int SQLGetPrivateProfileString(LPCSTR pszSection, LPCSTR pszEntry, LPCSTR
108108
static int
109109
parse_server(TDS_ERRS *errs, char *server, TDSLOGIN * login)
110110
{
111-
char ip[64];
112111
char *p = (char *) strchr(server, '\\');
113112

114113
if (p) {
@@ -125,14 +124,9 @@ parse_server(TDS_ERRS *errs, char *server, TDSLOGIN * login)
125124
}
126125
}
127126

128-
if (TDS_SUCCEED(tds_lookup_host(server, ip)))
127+
if (TDS_SUCCEED(tds_lookup_host_set(server, &login->ip_addrs)))
129128
tds_dstr_copy(&login->server_host_name, server);
130129

131-
if (!tds_dstr_copy(&login->ip_addr, ip)) {
132-
odbc_errs_add(errs, "HY001", NULL);
133-
return 0;
134-
}
135-
136130
return 1;
137131
}
138132

@@ -177,8 +171,8 @@ odbc_get_dsn_info(TDS_ERRS *errs, const char *DSN, TDSLOGIN * login)
177171
if (myGetPrivateProfileString(DSN, odbc_param_Address, tmp) > 0) {
178172
address_specified = 1;
179173
/* TODO parse like MS */
180-
tds_lookup_host(tmp, tmp);
181-
tds_dstr_copy(&login->ip_addr, tmp);
174+
175+
tds_lookup_host_set(tmp, &login->ip_addrs);
182176
}
183177
if (myGetPrivateProfileString(DSN, odbc_param_Server, tmp) > 0) {
184178
tds_dstr_copy(&login->server_name, tmp);

src/replacements/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ EXTRA_DIST= asprintf.c \
1111
getopt.c \
1212
readpassphrase.c \
1313
strlcat.c \
14+
getaddrinfo.c \
1415
strlcpy.c \
1516
strtok_r.c \
1617
strsep.c \

src/replacements/getaddrinfo.c

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2+
* Copyright (C) 2013 Peter Deacon
3+
* Copyright (C) 2013 Ziglio Frediano
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Library General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 2 of the License, or (at your option) any later version.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Library General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Library General Public
16+
* License along with this library; if not, write to the
17+
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18+
* Boston, MA 02111-1307, USA.
19+
*/
20+
21+
#include <config.h>
22+
23+
#if !defined(HAVE_GETADDRINFO)
24+
#include <assert.h>
25+
26+
#include "tds.h"
27+
#include "tds_sysdep_private.h"
28+
#include "replacements.h"
29+
30+
/* Incomplete implementation, single ipv4 addr, service does not work, hints do not work */
31+
int
32+
tds_getaddrinfo(const char *node, const char *service, const struct tds_addrinfo *hints, struct tds_addrinfo **res)
33+
{
34+
int retcode = 0;
35+
struct tds_addrinfo *addr;
36+
struct sockaddr_in *sin, *s;
37+
struct hostent *host = NULL;
38+
unsigned int ipaddr;
39+
char buffer[4096];
40+
struct hostent result;
41+
int h_errnop;
42+
43+
assert(node != NULL);
44+
45+
if ((addr = (tds_addrinfo *) malloc(sizeof(struct tds_addrinfo))) != NULL)
46+
memset(addr, '\0', sizeof(struct tds_addrinfo));
47+
else
48+
retcode = -1;
49+
50+
if ((sin = (struct sockaddr_in *) malloc(sizeof(struct sockaddr_in))) != NULL)
51+
memset(sin, '\0', sizeof(struct sockaddr_in));
52+
else
53+
retcode = -1;
54+
55+
if (retcode == 0) {
56+
addr->ai_addr = (struct sockaddr *) sin;
57+
addr->ai_addrlen = sizeof(struct sockaddr_in);
58+
addr->ai_family = AF_INET;
59+
sin = NULL;
60+
61+
if ((ipaddr = inet_addr(node)) == INADDR_NONE) {
62+
if ((host = tds_gethostbyname_r(node, &result, buffer, sizeof(buffer), &h_errnop)) != NULL)
63+
ipaddr = *(unsigned int *) host->h_addr;
64+
else
65+
retcode = -1;
66+
}
67+
} else
68+
retcode = -1;
69+
70+
if (retcode == 0) {
71+
s = (struct sockaddr_in *) addr->ai_addr;
72+
s->sin_family = AF_INET;
73+
s->sin_addr.s_addr = ipaddr;
74+
s->sin_port = htons(atoi(service));
75+
76+
*res = addr;
77+
addr = NULL;
78+
}
79+
80+
if (addr != NULL)
81+
tds_freeaddrinfo(addr);
82+
83+
if (sin != NULL)
84+
free(sin);
85+
86+
return retcode;
87+
}
88+
89+
/* Incomplete implementation, ipv4 only, port does not work, flags do not work */
90+
int
91+
tds_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
92+
{
93+
int retcode = 0;
94+
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
95+
96+
if (host != NULL)
97+
tds_inet_ntoa_r(sin->sin_addr, host, hostlen);
98+
99+
return retcode;
100+
}
101+
102+
void
103+
tds_freeaddrinfo(struct tds_addrinfo *addr)
104+
{
105+
assert(addr != NULL);
106+
if (addr->ai_addr != NULL)
107+
free(addr->ai_addr);
108+
free(addr);
109+
}
110+
111+
#endif

0 commit comments

Comments
 (0)