* getipbyhostname.c
- #include
/* gethostbyname */ - #include
/* time_t, localtime */ - #include
/* errno */ - #include
/* struct in_addr */ - #include
/* inet_ntoa */ - #include
/* strncpy */ - #include
/* va_start, va_end */ - #include
-
- #define E_FAIL -1
- #define E_OK 0
-
- #define _FL_ __FILE__,__LINE__
-
- #define E_MESSAGE 10000
- #define E_ALLOC 10300
- #define E_SOCKFD_SEND 10359
- #define E_SOCKFD_RECV 10360
- #define E_OSCALL 10201 /* 系统函数(%s)调用出错 */
- #define E_FUNCALL 10202 /* 平台函数(%s)调用出错 */
-
- #ifndef pid_t
- typedef int pid_t;
- #endif
- extern pid_t getpid(void);
-
- int bclerrlog(int appcode, char *file, long line, const char *fmt, ...)
- {
- time_t now_time;
- struct tm *info;
- char dt_buf[64];
- char appmsg[512];
- va_list ap;
-
- va_start(ap, fmt);
- /* bclerreg(appcode, file, line, fmt, ap); */
- vsnprintf(appmsg, 512, fmt, ap);
-
- time( &now_time );
- info = localtime( &now_time );
- strftime(dt_buf, 80, "%Y-%m-%d %H:%M:%S", info);
- fprintf(stderr, "---- %s ----\n", dt_buf);
-
- fprintf(stderr, "PID: %d\tFile: %s\tLine: %ld\n", getpid(), file, line);
- fprintf(stderr, "App Error: %d - %s\n", appcode, appmsg);
- fprintf(stderr, "System Error: %d - %s\n", errno, strerror(errno));
- va_end(ap);
- }
-
- #if 0
- typedef union {
- unsigned char a[4];
- unsigned int m;
- } IPAddr_t;
- #endif
-
- int main(int argc, char *argv[])
- {
- char host_name[256];
- struct hostent *host_entry;
- char *IPbuffer;
- struct in_addr addr;
-
- /* strncpy(host_name, "p3-sign.douyinpic.com", 256); */
- if (argc < 2) {
- fprintf(stdout, "Usage: %s xx.xx.com", argv[0]);
- return E_OK;
- }
- strncpy(host_name, argv[1], 256);
- printf("Hostname: [%s]\n", host_name);
-
- /* To retrieve host information */
- host_entry = gethostbyname(host_name);
- if (host_entry == NULL) {
- bclerrlog(E_OSCALL, _FL_, "gethostbyname()");
- return E_FAIL;
- }
- /* To convert an Internet network address into ASCII string */
- for (int i = 0; i < host_entry->h_length; i++) {
- IPbuffer = inet_ntoa(*((struct in_addr*)host_entry->h_addr_list[i]));
- memcpy(&addr, host_entry->h_addr_list[i], sizeof(struct in_addr));
- printf("Host IP#%d: %s\t%08x\n", i, IPbuffer, addr.s_addr);
- }
-
- return E_OK;
- }
$ cc -g getipbyhostname.c -o getipbyhostname
$ ./getipbyhostname p3-sign.douyinpic.com
Hostname: [p3-sign.douyinpic.com]
Host IP#0: 221.231.92.240 f05ce7dd
Host IP#1: 180.101.197.251 fbc565b4
Host IP#2: 116.207.144.248 f890cf74
Host IP#3: 58.215.47.228 e42fd73a
windows版:
需要引入头文件
- #include
/* WSADATA */ - #include
/* getaddrinfo */ - /* link with Ws2_32.lib */
- #pragma comment (lib, "Ws2_32.lib")
typedef int (*IpHandler_t)(const char* ip);
int getipv4byhostname(const char* hostname, IpHandler_t ipHandler);
- int getipv4byhostname(const char* hostname, IpHandler_t ipHandler) {
- //-----------------------------------------
- // Declare and initialize variables
- WSADATA wsaData;
- int iResult;
-
- struct addrinfo* result = NULL;
- struct addrinfo* ptr = NULL;
- struct addrinfo hints;
-
- // Initialize Winsock
- iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
- if (iResult != 0) {
- printf("WSAStartup failed: %d\n", iResult);
- return 1;
- }
- //--------------------------------
- // Setup the hints address info structure
- // which is passed to the getaddrinfo() function
- ZeroMemory(&hints, sizeof(hints));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
-
- int dwRetval = getaddrinfo(hostname, "0", &hints, &result);
- if (dwRetval != 0) {
- printf("getaddrinfo failed with error: %d\n", dwRetval);
- WSACleanup();
- return 1;
- }
-
- struct in_addr sockaddr_ipv4;
- char ipv4[INET_ADDRSTRLEN];
- const char* ip;
- // Retrieve each address and print out the hex bytes
- for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
- sockaddr_ipv4 = ((struct sockaddr_in*)ptr->ai_addr)->sin_addr;
- ip = inet_ntop(AF_INET, &sockaddr_ipv4, ipv4, sizeof(ipv4));
- ipHandler(ip);
- }
- return 0;
- }
处理函数:
- int ipHandler(const char *ip) {
- printf("IP=[%s]\n", ip);
- return 0;
- }
调用:
- char hostname[64];
- strncpy(hostname, "tcbox.baidu.com", 64);
- printf("host=[%s]\n", hostname);
-
- getipv4byhostname(hostname, ipHandler);
121.228.183.55
main.c
- #include "bcl_udp.h"
-
- int main() {
- char hostname[32] = {'\0'};
- struct ipv4head ipv4List;
- struct ipv4_entry *n1;
-
- strcpy(hostname, "qq.com"); /* octipus.net, www.google.co.il */
- bcl_dns_query(&ipv4List, hostname, "192.168.64.1"); /* Query gateway(DNS) */
- while(!TAILQ_EMPTY(&ipv4List)) {
- n1 = TAILQ_FIRST(&ipv4List);
- TAILQ_REMOVE(&ipv4List, n1, entries);
- printf("n1->data=%s\n", n1->data);
- free(n1);
- }
- return 0;
- }
* bcl_udp.h
- #ifndef ERRLOG_BCL_UDP_H
- #define ERRLOG_BCL_UDP_H
-
- #include
-
-
- struct ipv4_entry {
- char data[16];
- TAILQ_ENTRY(ipv4_entry) entries;
- };
- TAILQ_HEAD(ipv4head, ipv4_entry);
-
- int bcl_dns_query(struct ipv4head *head, char *host_name, const char *dns_ip);
-
- #endif //ERRLOG_BCL_UDP_H
* bcl_udp.c
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- #include
/* bzero */ - #include
/* inet_addr */ - #include
/* close */ - #include
/* strcat, memset */ - #include
/* getenv(), rand() */ -
- #include "bcl_udp.h"
- #include "arclog.h"
- #include "bcl_socket.h"
-
- #define PRIVATE static
-
- typedef union {
- unsigned char c[4];
- in_addr_t addr; /* unsigned int */
- } IPv4_t;
-
- in_addr_t ip2int(const char *ip) {
- IPv4_t un;
- int i, j;
- un.c[0] = un.c[1] = un.c[2] = un.c[3] = 0;
- for (i = 0, j = 0; i < 16 && ip[i] != '\0'; i++) {
- if (0x30 <= ip[i] && ip[i] < 0x3a) { /* '0','9' */
- un.c[j] *= 10;
- un.c[j] += ip[i] - 0x30;
- } else if (ip[i] == 0x2e) { /* '.' */
- j += 1;
- }
- }
- return un.addr;
- }
-
- int bcl_udp_datetime(char buf[]) {
- int sockfd;
- ssize_t n;
- /* sockfd = socket(PF_INET, SOCK_DGRAM, 0); */
- sockfd = bcl_tcp_connector(ip2int("129.6.15.32"), 13);
- if (sockfd < 0) {
- bclerrend();
- return E_FAIL;
- }
- /* n = sendto(sockfd, buf, 2, 0, (struct sockaddr *)&serv, sizeof(serv)); */
- bcl_send_nbytes(sockfd, buf, 2);
- /* n = recvfrom(sockfd, buf, 150, 0, (struct sockaddr *)0, (socklen_t *)0); */
- bzero(buf, 150);
- n = bcl_recv_nbytes(sockfd, buf, 150, 5);
- if (n < 2) {
- bclerrlog(E_OSCALL, _FL_, "recv from error");
- return E_FAIL;
- }
- buf[n - 2] = 0;
- /* bcl_debug("datetime from 129.6.15.32: %s", buf); */
- close(sockfd);
- return E_OK;
- }
-
- typedef struct {
- u_short transId; /* 0xb6f6 */
- u_short flags; /* 0x0100 Standard query */
- u_short questions; /* 0x0001 */
- u_char rss[6]; /* 00 00 00 00 00 00 */
- } DnsHdr_t;
-
- #define HOST_LEN 64
-
- typedef struct {
- u_char name[2]; /* ptr */
- u_short type; /* 0x0005 alias */
- u_short in; /* 0x0001 */
- u_int32_t ttl; /* 81, 1min21s */
- u_short dataLen; /* 0x0017, 23 */
- char cname[HOST_LEN]; /* 3www31633com8163jiasu3com */
- } __attribute__((packed)) DnsAnswer_t;
-
- /**
- * @ref: https://www.linuxquestions.org/questions/linux-networking-3/dns-packet-structure-289886/
- * @param name "p3-sign.douyinpic.com"
- * @param entry "7p3-sign9douyinpic3com"
- * @return
- */
- PRIVATE char *dns_entry(char *entry, const char *name) {
- const char *p = name;
- char *q = entry;
- int8_t len;
-
- while ('\0' != *p) {
- len = 0;
- for (; *p && *p != '.'; p++) {
- len += 1;
- }
- *q++ = len;
- memcpy(q, p - len, len);
- q += len;
- p++;
- }
- return q;
- }
-
- #define SWAP(a, b, type) do { type _t = a; a = b; b = _t;} while(0);
-
- #define REVERSE(a, b, type) do { \
- type *p = a, *q = b; \
- type t; \
- if (p > q) { SWAP(p, q, type *);} \
- for (; p < q; p++, q--) { \
- t = *p; \
- *p = *q; \
- *q = t; \
- } \
- } while (0);
-
- void IPv4_toString(char *s, IPv4_t ipv4) {
- int i;
- char *t;
- #ifdef __ORDER_LITTLE_ENDIAN__
- for (i = 0; i < 4; i++) {
- #else
- for (i = 3; 0 <= i; i--) {
- #endif
- t = s;
- while (ipv4.c[i]) {
- *s++ = ipv4.c[i] % 10 + 0x30;
- ipv4.c[i] /= 10;
- }
- REVERSE(s-1, t, char);
- *s++ = '.';
- }
- *(s-1) = '\0';
- }
-
- int bcl_dns_query(struct ipv4head *head, char *host_name, const char *dns_ip) {
- int sockfd;
- char buf[1024] = {'\0'};
- struct sockaddr_in dest_addr;
- DnsHdr_t header;
- char *p = NULL;
- off_t queryLen;
- DnsAnswer_t ans;
- IPv4_t ipv4;
- struct ipv4_entry *n1 = NULL;
-
- sockfd = socket(AF_INET, SOCK_DGRAM, 0);
- if (sockfd < 0) {
- bclerreg(E_OSCALL, _FL_, "socket() UDP");
- return E_FAIL;
- }
- /* DNS address */
- memset(&dest_addr, 0, sizeof(struct sockaddr_in));
- dest_addr.sin_family = AF_INET;
- dest_addr.sin_addr.s_addr = ip2int(dns_ip);
- dest_addr.sin_port = htons(53); /* DNS port 53 */
- if (connect(sockfd, (const struct sockaddr *) &dest_addr, sizeof(dest_addr)) < 0) {
- bclerreg(E_OSCALL, _FL_, "connect()");
- return E_FAIL;
- }
- /* DNS query packet */
- header.transId = (u_short) rand();
- header.flags = htons(0x0100);
- header.questions = htons(0x0001);
- memset(header.rss, 0, sizeof(header.rss));
-
- memcpy(buf, &header, sizeof(header));
- p = buf + sizeof(header);
- /* queries: p3-sign.douyinpic.com */
- p = dns_entry(p, host_name);
- *p++ = '\0';
- /* type A, class IN */
- *p++ = 0x00; *p++ = 0x01;
- *p++ = 0x00; *p++ = 0x01;
-
- queryLen = p - buf;
- if (send(sockfd, buf, queryLen, 0) < 0) {
- bclerreg(E_OSCALL, _FL_, "send()");
- return E_FAIL;
- }
- memset(buf, 0, 1024);
- if (recv(sockfd, buf, 1024, 0) < 1) {
- bclerreg(E_OSCALL, _FL_, "recv()");
- return E_FAIL;
- }
- p = buf + queryLen;
- /* Answers: buf + queryLen */
- TAILQ_INIT(head);
- while (*p != 0x00) {
- /* bcl_xxd(p, 0xa0); */
- if (*(u_char *)p == 0xc0) {
- /* c0 0c, c0 14 */
- ans.dataLen = ntohs(((DnsAnswer_t *)p)->dataLen);
- }
- printf("dataLen=%d\n", ans.dataLen);
- bcl_xxd(((DnsAnswer_t *)p)->cname, ans.dataLen);
- if (4 == ans.dataLen) { /* IPv4 */
- memcpy(&ipv4, &((DnsAnswer_t *)p)->cname, 4);
- n1 = (struct ipv4_entry *)malloc(sizeof(struct ipv4_entry));
- IPv4_toString(n1->data, ipv4);
- TAILQ_INSERT_TAIL(head, n1, entries);
- }
- p += sizeof(DnsAnswer_t) - HOST_LEN + ans.dataLen;
- }
- return E_OK;
- }
-
- #ifdef __cplusplus
- };
- #endif
调试用 bcl_xxd实现, 错误日志
- #ifndef byte
- typedef unsigned char byte;
- #endif
- #ifndef uint8_t
- typedef unsigned char uint8_t;
- #endif
- #ifndef uint16_t
- typedef unsigned short uint16_t;
- #endif
-
- uint8_t arc_xxd(byte *s, uint8_t len, void *param);
-
- void bcl_xxd(const void *s, size_t len)
- {
- uint16_t line = 0;
- byte *t = (byte *)s;
- uint8_t b;
- size_t left = len;
-
- for (; ;) {
- if (left > 16) {
- b = arc_xxd(t, 16, &line);
- } else {
- b = arc_xxd(t, left, &line);
- }
- if (b < 1) {break;}
- left -= b;
- if (left <= 0) {break;}
- t += b;
- }
- }
-
- uint8_t arc_xxd(byte *s, uint8_t len, void *param)
- {
- uint8_t i;
- uint16_t *line = (uint16_t *)param;
- fprintf(stdout, "%08x:", *line << 4);
- for (i = 0; i+2 < len; i+=2) {
- fprintf(stdout, " %02x%02x", s[i], s[i+1]);
- }
- if (i
fprintf(stdout, " %02x", s[i]); i+= 1;} - if (i
fprintf(stdout, "%02x", s[i]); i+=1;} - if (i < 16 && 0x00 != (i & 0x01)) { fputs(" ", stdout); i+=1;}
- for (; i <16; i+= 2) {
- fputs(" ", stdout); /* space * 5 */
- }
- fputs(" ", stdout);
- for (i = 0; i
- if (s[i] <0x20 || s[i] > 0x7e) {
- fputc('.', stdout);
- } else {
- fputc(s[i], stdout);
- }
- }
- fputs("\r\n", stdout);
- *line += 1;
- return i;
- }
运行输出:
dataLen=4
00000000: 7b96 4cda {.L.
dataLen=4
00000000: 716c 51bd qlQ.
n1->data=123.150.76.218
n1->data=113.108.81.189
qq.com的2个ip地址为 123,150.76.218, 113.108.81.189
用wireshark查看:

