close

 

To retrieve internet ip address from host which is behind a router in C

 

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 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
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
 * Compile:
 *
 * 	$ gcc -o get_wan_ipaddr get_wan_ipaddr.c -Wall
 *
 * WAN IP Detection methods:
 *	$ dig +short -p 8253 @ipcast1.dynupdate.no-ip.com wan.ip
 *	$ curl http://ip1.dynupdate.no-ip.com
 *	$ external_ip=`lynx -dump "http://checkip.dyndns.org" | awk -F":" '{print $2}'` && echo $external_ip
 *	$ external_ip=`html2text http://checkip.dyndns.org | awk -F"Current IP Address:" '{print $2}'` && echo $external_ip
 *
 *
 * References:
 *
 *	http://www.readynas.com/forum/viewtopic.php?t=61297&p=343930
 * 	http://souptonuts.sourceforge.net/code/http_get.c.html
 * 	http://tools.ietf.org/html/rfc2202
 *	http://wiki.mikrotik.com/wiki/Dynamic_DNS_Update_Script_for_No-IP_DNS
 *	https://github.com/AntonioCS/no-ip.com-bash-updater
 *	http://www.os-cms.net/blog/view/21/NO-IP-client-written-in-PHP
 *	http://wiki.dreamhost.com/Dynamic_DNS
 *	http://patinya-tuk.blogspot.tw/2009/09/ddnshowtoopenwrt.html
 *	http://man7.org/linux/man-pages/man3/inet_pton.3.html
 *	http://beej.us/guide/bgnet/output/html/multipage/inet_ntopman.html
 *
 */

#include <arpa/inet.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netdb.h>
#include <unistd.h>

#define USER_AGENT		"Linux Update Client/0.01 VERSION/1.00 jackie.cpluspluc@gmail.com"
#define WANIP_QUERY_SERVER	"ip1.dynupdate.no-ip.com"
#define WANIP_QUERY_SVR		"myip.dnsomatic.com"
#define SA			struct sockaddr
#define MAXLINE			16384
#define MAXSUB			16384
#define LISTENQ			1024
#define HTTP_PORT		80
#define IP_LENGTH		128
//#define __DEBUG__
#ifdef __DEBUG__
#define LOG_MSG			printf
#else
#define LOG_MSG(...)
#endif

extern int h_errno;

int tcp_connect(int *sock, const char* host, const char *port)
{
	int i;
	char str[50];
	char **pptr, *inet;
	struct hostent *hptr;
	struct sockaddr_in servaddr;

	if ((hptr = gethostbyname(host)) == NULL) {
		fprintf(stderr, " Server down error for host: %s: %s",
				host, hstrerror(h_errno));
		return -1;
	}
	LOG_MSG("hostname: %s \n", hptr->h_name);
	if (hptr->h_addrtype == AF_INET
		&& (pptr = hptr->h_addr_list) != NULL) {
		inet = inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str));
		LOG_MSG("address: %s\n", inet);
	} else {
		fprintf(stderr, "Error call inet_ntop \n");
	}

	*sock = socket(AF_INET, SOCK_STREAM, 0);
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(HTTP_PORT);
	inet_pton(AF_INET, str, &servaddr.sin_addr);

	i = connect(*sock, (SA *) & servaddr, sizeof(servaddr));
	if (i < 0)  {
		close(*sock);
		return i;
	}
	else
		return 0;
	return -1;
}

int file_read(int fh, char *recvline, int len) {
	int n;
	if (!fh)
		return -1;
	while ((n = read(fh, recvline, MAXLINE)) > 0) {
		recvline[n] = '\0';
		//LOG_MSG("%s", recvline);  // <-- this
	}
	return n;
}

int file_write(int fh, const char* sendline, int len) {
	if (!fh)
		return -1;
	if (write(fh, sendline, len) != len) {
		return -1;
	}
	return 0;
}

int http_session(int sock, const char *buf)
{
#ifdef __DEBUG__
	char	*p, *q;
	p = buf;
	while ((q = strchr(p, '\n'))) {
		*q = 0;
		fprintf(stderr, "> %s\n", p);
		*q++ = '\n';
		p = q;
	}
	if (*p)
		fprintf(stderr, "> %s\n", p);
#endif
	if (file_write(sock, buf, strlen(buf)) < 0) {
		close(sock);
		return -1;
	}
	if (file_read(sock, buf, MAXLINE) < 0) {
		close(sock);
		return -1;
	}

#ifdef __DEBUG__
	LOG_MSG("\n\n");
	p = buf;
	while ((q = strchr(p, '\n'))) {
		*q = 0;
		fprintf(stderr, "< %s\n", p);
		*q++ = '\n';
		p = q;
	}
	if (*p)
		fprintf(stderr, "< %s\n", p);
#endif
	return 0;
}

bool isValidIPAddress(char *ipAddress)
{
	struct sockaddr_in sa;
	int result = inet_pton(AF_INET, ipAddress, &(sa.sin_addr));
	return result != 0;
}

int detecte_wan_ipaddr(char *wan_ip)
{
	int socket_fd = 0;
	char buffer[MAXLINE];
	char *p = NULL;

	memset(buffer, 0, sizeof(buffer));

	snprintf(buffer, MAXSUB,
			"GET / HTTP/1.1\r\n"
			"Host: %s\r\n"
			"User-Agent: %s\r\n\r\n"
			, WANIP_QUERY_SVR, USER_AGENT);

	if (tcp_connect(&socket_fd, WANIP_QUERY_SVR, HTTP_PORT) < 0)
		return -1;

	if (http_session(socket_fd, buffer) < 0)
		return -1;
	close(socket_fd);
	if ((p = strrchr(buffer, '\n'))){
		strcpy(wan_ip, ++p);
		if (isValidIPAddress(wan_ip) == false)
			return -1;
	}
	return 0;
}

int main(int argc, char **argv)
{
	char wan_ip[IP_LENGTH];
	memset(wan_ip, 0, sizeof(wan_ip));
	if (detecte_wan_ipaddr(wan_ip) == 0)
		printf("%s\n", wan_ip);
	else
		return -1;
	return 0;
}

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 Bluelove1968 的頭像
    Bluelove1968

    藍色情懷

    Bluelove1968 發表在 痞客邦 留言(0) 人氣()