netwrap.c 4.71 KB
Newer Older
1
2
3
4
5
6
/* Network related wrapper functions */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
7
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 *																			*
 * This library is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU Lesser General Public License		*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU Lesser General Public License for more details: lgpl.txt or	*
 * http://www.fsf.org/copyleft/lesser.html									*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

22
#include "sockwrap.h"
23
24
25
26
27
28
29
30
31
#include "genwrap.h"	/* truncsp */
#include "netwrap.h"	/* verify prototypes */

#include <stdlib.h>		/* malloc() */

#if defined(_WIN32)
	#include <iphlpapi.h>	/* GetNetworkParams */
#endif

Rob Swindell's avatar
Rob Swindell committed
32
str_list_t getNameServerList(void)
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
{
#ifdef __unix__	/* Look up DNS server address */
	FILE*	fp;
	char*	p;
	char	str[128];
	str_list_t	list;

	if((list=strListInit())==NULL)
		return(NULL);
	if((fp=fopen("/etc/resolv.conf","r"))!=NULL) {
		while(!feof(fp)) {
			if(fgets(str,sizeof(str),fp)==NULL)
				break;
			truncsp(str);
			p=str;
			SKIP_WHITESPACE(p);
			if(strnicmp(p,"nameserver",10)!=0) /* no match */
				continue;
			FIND_WHITESPACE(p);	/* skip "nameserver" */
			SKIP_WHITESPACE(p);	/* skip more white-space */
			strListPush(&list,p);
		}
		fclose(fp);
	}
	return(list);

#elif defined(_WIN32)
	FIXED_INFO* FixedInfo=NULL;
	ULONG    	FixedInfoLen=0;
	IP_ADDR_STRING* ip;
	str_list_t	list;

	if((list=strListInit())==NULL)
		return(NULL);
	if(GetNetworkParams(FixedInfo,&FixedInfoLen) == ERROR_BUFFER_OVERFLOW) {
        FixedInfo=(FIXED_INFO*)malloc(FixedInfoLen);
		if(GetNetworkParams(FixedInfo,&FixedInfoLen) == ERROR_SUCCESS) {
			ip=&FixedInfo->DnsServerList;
			for(; ip!=NULL; ip=ip->Next)
				strListPush(&list,ip->IpAddress.String);
		}
        if(FixedInfo!=NULL)
            free(FixedInfo);
    }
	return(list);
#else
	#error "Need a get_nameserver() implementation for this platform"
#endif
}

Rob Swindell's avatar
Rob Swindell committed
83
const char* getHostNameByAddr(const char* str)
84
85
86
87
88
89
90
91
{
	HOSTENT*	h;
	uint32_t	ip;

#ifdef _WIN32
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
92
93
	if(str==NULL)
		return NULL;
94
	if((ip=parseIPv4Address(str)) == INADDR_NONE)
95
96
97
98
		return str;
	if((h=gethostbyaddr((char *)&ip,sizeof(ip),AF_INET))==NULL)
		return NULL;

99
#ifdef _WIN32
100
	WSACleanup();
101
#endif
102
103
104
105

	return h->h_name;
}

106
/* In case we want to DLL-export getNameServerList in the future */
Rob Swindell's avatar
Rob Swindell committed
107
void freeNameServerList(str_list_t list)
108
109
110
111
{
	strListFree(&list);
}

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// If the input is invalid, INADDR_NONE (usually -1) is returned
uint32_t parseIPv4Address(const char* value)
{
	uint32_t result = 0;

	if(strchr(value,'.') == NULL)
		return strtol(value, NULL, 10);

#if defined(__BORLANDC__) || defined(__MINGW32__)
	result = inet_addr(value); // deprecated function call
#else
	if(inet_pton(AF_INET, value, &result) != 1)
		result = INADDR_NONE;
#endif
	return ntohl(result);
}

struct in6_addr parseIPv6Address(const char* value)
{
	struct addrinfo hints = {0};
	struct addrinfo *res, *cur;
	struct in6_addr ret = {{{0}}};

	hints.ai_flags = AI_NUMERICHOST|AI_PASSIVE;
	if(getaddrinfo(value, NULL, &hints, &res))
		return ret;

	for(cur = res; cur; cur++) {
		if(cur->ai_addr->sa_family == AF_INET6)
			break;
	}
	if(!cur) {
		freeaddrinfo(res);
		return ret;
	}
	memcpy(&ret, &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr, sizeof(ret));
	freeaddrinfo(res);
	return ret;
}

const char* IPv4AddressToStr(uint32_t addr, char* dest, size_t size)
{
154
155
156
157
158
159
160
161
#if defined _WIN32
	int result;
	WSADATA wsaData;
	SOCKADDR_IN sockaddr = {0};
	sockaddr.sin_family = AF_INET;
	sockaddr.sin_addr.s_addr = htonl(addr);

	if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
162
		return NULL;
163
164
165
166
167
	result = getnameinfo((SOCKADDR*)&sockaddr, sizeof(sockaddr), dest, size, NULL, 0, NI_NUMERICHOST);
	WSACleanup();
	if(result != 0)
		return NULL;
	return dest;
168
#else
169
170
171
	struct in_addr in_addr;
	in_addr.s_addr = htonl(addr);
	return inet_ntop(AF_INET, &in_addr, dest, size);
172
173
174
#endif
}

175
#if NETWRAP_TEST
176
int main(int argc, char** argv)
177
178
179
180
181
182
183
184
185
186
{
	size_t		i;
	str_list_t	list;

	if((list=getNameServerList())!=NULL) {
		for(i=0;list[i]!=NULL;i++)
			printf("%s\n",list[i]);
		freeNameServerList(list);
	}

187
188
	if(argc>1)
		printf("%s\n", getHostNameByAddr(argv[1]));
189

190
191
192
193
	return 0;
}
#endif