• 根据域名找到IP地址 getipbyhostname.c


    * getipbyhostname.c

    1. #include /* gethostbyname */
    2. #include /* time_t, localtime */
    3. #include /* errno */
    4. #include /* struct in_addr */
    5. #include /* inet_ntoa */
    6. #include /* strncpy */
    7. #include /* va_start, va_end */
    8. #include
    9. #define E_FAIL -1
    10. #define E_OK 0
    11. #define _FL_ __FILE__,__LINE__
    12. #define E_MESSAGE 10000
    13. #define E_ALLOC 10300
    14. #define E_SOCKFD_SEND 10359
    15. #define E_SOCKFD_RECV 10360
    16. #define E_OSCALL 10201 /* 系统函数(%s)调用出错 */
    17. #define E_FUNCALL 10202 /* 平台函数(%s)调用出错 */
    18. #ifndef pid_t
    19. typedef int pid_t;
    20. #endif
    21. extern pid_t getpid(void);
    22. int bclerrlog(int appcode, char *file, long line, const char *fmt, ...)
    23. {
    24. time_t now_time;
    25. struct tm *info;
    26. char dt_buf[64];
    27. char appmsg[512];
    28. va_list ap;
    29. va_start(ap, fmt);
    30. /* bclerreg(appcode, file, line, fmt, ap); */
    31. vsnprintf(appmsg, 512, fmt, ap);
    32. time( &now_time );
    33. info = localtime( &now_time );
    34. strftime(dt_buf, 80, "%Y-%m-%d %H:%M:%S", info);
    35. fprintf(stderr, "---- %s ----\n", dt_buf);
    36. fprintf(stderr, "PID: %d\tFile: %s\tLine: %ld\n", getpid(), file, line);
    37. fprintf(stderr, "App Error: %d - %s\n", appcode, appmsg);
    38. fprintf(stderr, "System Error: %d - %s\n", errno, strerror(errno));
    39. va_end(ap);
    40. }
    41. #if 0
    42. typedef union {
    43. unsigned char a[4];
    44. unsigned int m;
    45. } IPAddr_t;
    46. #endif
    47. int main(int argc, char *argv[])
    48. {
    49. char host_name[256];
    50. struct hostent *host_entry;
    51. char *IPbuffer;
    52. struct in_addr addr;
    53. /* strncpy(host_name, "p3-sign.douyinpic.com", 256); */
    54. if (argc < 2) {
    55. fprintf(stdout, "Usage: %s xx.xx.com", argv[0]);
    56. return E_OK;
    57. }
    58. strncpy(host_name, argv[1], 256);
    59. printf("Hostname: [%s]\n", host_name);
    60. /* To retrieve host information */
    61. host_entry = gethostbyname(host_name);
    62. if (host_entry == NULL) {
    63. bclerrlog(E_OSCALL, _FL_, "gethostbyname()");
    64. return E_FAIL;
    65. }
    66. /* To convert an Internet network address into ASCII string */
    67. for (int i = 0; i < host_entry->h_length; i++) {
    68. IPbuffer = inet_ntoa(*((struct in_addr*)host_entry->h_addr_list[i]));
    69. memcpy(&addr, host_entry->h_addr_list[i], sizeof(struct in_addr));
    70. printf("Host IP#%d: %s\t%08x\n", i, IPbuffer, addr.s_addr);
    71. }
    72. return E_OK;
    73. }

    $ 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版:

    需要引入头文件

    1. #include /* WSADATA */
    2. #include /* getaddrinfo */
    3. /* link with Ws2_32.lib */
    4. #pragma comment (lib, "Ws2_32.lib")

    typedef int (*IpHandler_t)(const char* ip);

    int getipv4byhostname(const char* hostname, IpHandler_t ipHandler);

    1. int getipv4byhostname(const char* hostname, IpHandler_t ipHandler) {
    2. //-----------------------------------------
    3. // Declare and initialize variables
    4. WSADATA wsaData;
    5. int iResult;
    6. struct addrinfo* result = NULL;
    7. struct addrinfo* ptr = NULL;
    8. struct addrinfo hints;
    9. // Initialize Winsock
    10. iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    11. if (iResult != 0) {
    12. printf("WSAStartup failed: %d\n", iResult);
    13. return 1;
    14. }
    15. //--------------------------------
    16. // Setup the hints address info structure
    17. // which is passed to the getaddrinfo() function
    18. ZeroMemory(&hints, sizeof(hints));
    19. hints.ai_family = AF_UNSPEC;
    20. hints.ai_socktype = SOCK_STREAM;
    21. hints.ai_protocol = IPPROTO_TCP;
    22. int dwRetval = getaddrinfo(hostname, "0", &hints, &result);
    23. if (dwRetval != 0) {
    24. printf("getaddrinfo failed with error: %d\n", dwRetval);
    25. WSACleanup();
    26. return 1;
    27. }
    28. struct in_addr sockaddr_ipv4;
    29. char ipv4[INET_ADDRSTRLEN];
    30. const char* ip;
    31. // Retrieve each address and print out the hex bytes
    32. for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
    33. sockaddr_ipv4 = ((struct sockaddr_in*)ptr->ai_addr)->sin_addr;
    34. ip = inet_ntop(AF_INET, &sockaddr_ipv4, ipv4, sizeof(ipv4));
    35. ipHandler(ip);
    36. }
    37. return 0;
    38. }

      处理函数:

    1. int ipHandler(const char *ip) {
    2.     printf("IP=[%s]\n", ip);
    3.     return 0;
    4. }

    调用:

    1.     char hostname[64];
    2.     strncpy(hostname, "tcbox.baidu.com", 64);
    3.     printf("host=[%s]\n", hostname);
    4.     getipv4byhostname(hostname, ipHandler);

    121.228.183.55

    查询DNS 参照RFC1035

    main.c

    1. #include "bcl_udp.h"
    2. int main() {
    3. char hostname[32] = {'\0'};
    4. struct ipv4head ipv4List;
    5. struct ipv4_entry *n1;
    6. strcpy(hostname, "qq.com"); /* octipus.net, www.google.co.il */
    7. bcl_dns_query(&ipv4List, hostname, "192.168.64.1"); /* Query gateway(DNS) */
    8. while(!TAILQ_EMPTY(&ipv4List)) {
    9. n1 = TAILQ_FIRST(&ipv4List);
    10. TAILQ_REMOVE(&ipv4List, n1, entries);
    11. printf("n1->data=%s\n", n1->data);
    12. free(n1);
    13. }
    14. return 0;
    15. }

    * bcl_udp.h

    1. #ifndef ERRLOG_BCL_UDP_H
    2. #define ERRLOG_BCL_UDP_H
    3. #include
    4. struct ipv4_entry {
    5. char data[16];
    6. TAILQ_ENTRY(ipv4_entry) entries;
    7. };
    8. TAILQ_HEAD(ipv4head, ipv4_entry);
    9. int bcl_dns_query(struct ipv4head *head, char *host_name, const char *dns_ip);
    10. #endif //ERRLOG_BCL_UDP_H

    * bcl_udp.c

    dns-packet-structure

    1. #ifdef __cplusplus
    2. extern "C" {
    3. #endif
    4. #include /* bzero */
    5. #include /* inet_addr */
    6. #include /* close */
    7. #include /* strcat, memset */
    8. #include /* getenv(), rand() */
    9. #include "bcl_udp.h"
    10. #include "arclog.h"
    11. #include "bcl_socket.h"
    12. #define PRIVATE static
    13. typedef union {
    14. unsigned char c[4];
    15. in_addr_t addr; /* unsigned int */
    16. } IPv4_t;
    17. in_addr_t ip2int(const char *ip) {
    18. IPv4_t un;
    19. int i, j;
    20. un.c[0] = un.c[1] = un.c[2] = un.c[3] = 0;
    21. for (i = 0, j = 0; i < 16 && ip[i] != '\0'; i++) {
    22. if (0x30 <= ip[i] && ip[i] < 0x3a) { /* '0','9' */
    23. un.c[j] *= 10;
    24. un.c[j] += ip[i] - 0x30;
    25. } else if (ip[i] == 0x2e) { /* '.' */
    26. j += 1;
    27. }
    28. }
    29. return un.addr;
    30. }
    31. int bcl_udp_datetime(char buf[]) {
    32. int sockfd;
    33. ssize_t n;
    34. /* sockfd = socket(PF_INET, SOCK_DGRAM, 0); */
    35. sockfd = bcl_tcp_connector(ip2int("129.6.15.32"), 13);
    36. if (sockfd < 0) {
    37. bclerrend();
    38. return E_FAIL;
    39. }
    40. /* n = sendto(sockfd, buf, 2, 0, (struct sockaddr *)&serv, sizeof(serv)); */
    41. bcl_send_nbytes(sockfd, buf, 2);
    42. /* n = recvfrom(sockfd, buf, 150, 0, (struct sockaddr *)0, (socklen_t *)0); */
    43. bzero(buf, 150);
    44. n = bcl_recv_nbytes(sockfd, buf, 150, 5);
    45. if (n < 2) {
    46. bclerrlog(E_OSCALL, _FL_, "recv from error");
    47. return E_FAIL;
    48. }
    49. buf[n - 2] = 0;
    50. /* bcl_debug("datetime from 129.6.15.32: %s", buf); */
    51. close(sockfd);
    52. return E_OK;
    53. }
    54. typedef struct {
    55. u_short transId; /* 0xb6f6 */
    56. u_short flags; /* 0x0100 Standard query */
    57. u_short questions; /* 0x0001 */
    58. u_char rss[6]; /* 00 00 00 00 00 00 */
    59. } DnsHdr_t;
    60. #define HOST_LEN 64
    61. typedef struct {
    62. u_char name[2]; /* ptr */
    63. u_short type; /* 0x0005 alias */
    64. u_short in; /* 0x0001 */
    65. u_int32_t ttl; /* 81, 1min21s */
    66. u_short dataLen; /* 0x0017, 23 */
    67. char cname[HOST_LEN]; /* 3www31633com8163jiasu3com */
    68. } __attribute__((packed)) DnsAnswer_t;
    69. /**
    70. * @ref: https://www.linuxquestions.org/questions/linux-networking-3/dns-packet-structure-289886/
    71. * @param name "p3-sign.douyinpic.com"
    72. * @param entry "7p3-sign9douyinpic3com"
    73. * @return
    74. */
    75. PRIVATE char *dns_entry(char *entry, const char *name) {
    76. const char *p = name;
    77. char *q = entry;
    78. int8_t len;
    79. while ('\0' != *p) {
    80. len = 0;
    81. for (; *p && *p != '.'; p++) {
    82. len += 1;
    83. }
    84. *q++ = len;
    85. memcpy(q, p - len, len);
    86. q += len;
    87. p++;
    88. }
    89. return q;
    90. }
    91. #define SWAP(a, b, type) do { type _t = a; a = b; b = _t;} while(0);
    92. #define REVERSE(a, b, type) do { \
    93. type *p = a, *q = b; \
    94. type t; \
    95. if (p > q) { SWAP(p, q, type *);} \
    96. for (; p < q; p++, q--) { \
    97. t = *p; \
    98. *p = *q; \
    99. *q = t; \
    100. } \
    101. } while (0);
    102. void IPv4_toString(char *s, IPv4_t ipv4) {
    103. int i;
    104. char *t;
    105. #ifdef __ORDER_LITTLE_ENDIAN__
    106. for (i = 0; i < 4; i++) {
    107. #else
    108. for (i = 3; 0 <= i; i--) {
    109. #endif
    110. t = s;
    111. while (ipv4.c[i]) {
    112. *s++ = ipv4.c[i] % 10 + 0x30;
    113. ipv4.c[i] /= 10;
    114. }
    115. REVERSE(s-1, t, char);
    116. *s++ = '.';
    117. }
    118. *(s-1) = '\0';
    119. }
    120. int bcl_dns_query(struct ipv4head *head, char *host_name, const char *dns_ip) {
    121. int sockfd;
    122. char buf[1024] = {'\0'};
    123. struct sockaddr_in dest_addr;
    124. DnsHdr_t header;
    125. char *p = NULL;
    126. off_t queryLen;
    127. DnsAnswer_t ans;
    128. IPv4_t ipv4;
    129. struct ipv4_entry *n1 = NULL;
    130. sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    131. if (sockfd < 0) {
    132. bclerreg(E_OSCALL, _FL_, "socket() UDP");
    133. return E_FAIL;
    134. }
    135. /* DNS address */
    136. memset(&dest_addr, 0, sizeof(struct sockaddr_in));
    137. dest_addr.sin_family = AF_INET;
    138. dest_addr.sin_addr.s_addr = ip2int(dns_ip);
    139. dest_addr.sin_port = htons(53); /* DNS port 53 */
    140. if (connect(sockfd, (const struct sockaddr *) &dest_addr, sizeof(dest_addr)) < 0) {
    141. bclerreg(E_OSCALL, _FL_, "connect()");
    142. return E_FAIL;
    143. }
    144. /* DNS query packet */
    145. header.transId = (u_short) rand();
    146. header.flags = htons(0x0100);
    147. header.questions = htons(0x0001);
    148. memset(header.rss, 0, sizeof(header.rss));
    149. memcpy(buf, &header, sizeof(header));
    150. p = buf + sizeof(header);
    151. /* queries: p3-sign.douyinpic.com */
    152. p = dns_entry(p, host_name);
    153. *p++ = '\0';
    154. /* type A, class IN */
    155. *p++ = 0x00; *p++ = 0x01;
    156. *p++ = 0x00; *p++ = 0x01;
    157. queryLen = p - buf;
    158. if (send(sockfd, buf, queryLen, 0) < 0) {
    159. bclerreg(E_OSCALL, _FL_, "send()");
    160. return E_FAIL;
    161. }
    162. memset(buf, 0, 1024);
    163. if (recv(sockfd, buf, 1024, 0) < 1) {
    164. bclerreg(E_OSCALL, _FL_, "recv()");
    165. return E_FAIL;
    166. }
    167. p = buf + queryLen;
    168. /* Answers: buf + queryLen */
    169. TAILQ_INIT(head);
    170. while (*p != 0x00) {
    171. /* bcl_xxd(p, 0xa0); */
    172. if (*(u_char *)p == 0xc0) {
    173. /* c0 0c, c0 14 */
    174. ans.dataLen = ntohs(((DnsAnswer_t *)p)->dataLen);
    175. }
    176. printf("dataLen=%d\n", ans.dataLen);
    177. bcl_xxd(((DnsAnswer_t *)p)->cname, ans.dataLen);
    178. if (4 == ans.dataLen) { /* IPv4 */
    179. memcpy(&ipv4, &((DnsAnswer_t *)p)->cname, 4);
    180. n1 = (struct ipv4_entry *)malloc(sizeof(struct ipv4_entry));
    181. IPv4_toString(n1->data, ipv4);
    182. TAILQ_INSERT_TAIL(head, n1, entries);
    183. }
    184. p += sizeof(DnsAnswer_t) - HOST_LEN + ans.dataLen;
    185. }
    186. return E_OK;
    187. }
    188. #ifdef __cplusplus
    189. };
    190. #endif

    调试用 bcl_xxd实现, 错误日志

    1. #ifndef byte
    2. typedef unsigned char byte;
    3. #endif
    4. #ifndef uint8_t
    5. typedef unsigned char uint8_t;
    6. #endif
    7. #ifndef uint16_t
    8. typedef unsigned short uint16_t;
    9. #endif
    10. uint8_t arc_xxd(byte *s, uint8_t len, void *param);
    11. void bcl_xxd(const void *s, size_t len)
    12. {
    13. uint16_t line = 0;
    14. byte *t = (byte *)s;
    15. uint8_t b;
    16. size_t left = len;
    17. for (; ;) {
    18. if (left > 16) {
    19. b = arc_xxd(t, 16, &line);
    20. } else {
    21. b = arc_xxd(t, left, &line);
    22. }
    23. if (b < 1) {break;}
    24. left -= b;
    25. if (left <= 0) {break;}
    26. t += b;
    27. }
    28. }
    29. uint8_t arc_xxd(byte *s, uint8_t len, void *param)
    30. {
    31. uint8_t i;
    32. uint16_t *line = (uint16_t *)param;
    33. fprintf(stdout, "%08x:", *line << 4);
    34. for (i = 0; i+2 < len; i+=2) {
    35. fprintf(stdout, " %02x%02x", s[i], s[i+1]);
    36. }
    37. if (i fprintf(stdout, " %02x", s[i]); i+= 1;}
    38. if (i fprintf(stdout, "%02x", s[i]); i+=1;}
    39. if (i < 16 && 0x00 != (i & 0x01)) { fputs(" ", stdout); i+=1;}
    40. for (; i <16; i+= 2) {
    41. fputs(" ", stdout); /* space * 5 */
    42. }
    43. fputs(" ", stdout);
    44. for (i = 0; i
    45. if (s[i] <0x20 || s[i] > 0x7e) {
    46. fputc('.', stdout);
    47. } else {
    48. fputc(s[i], stdout);
    49. }
    50. }
    51. fputs("\r\n", stdout);
    52. *line += 1;
    53. return i;
    54. }

    运行输出:

    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查看:

     

  • 相关阅读:
    Spring——AOP(Aspect Oriented Programming)
    独立站FP收款黑科技来啦!再也不用担心账户被封了~
    词法作用域&改变词法作用域
    Android C++系列:Linux文件IO操作(一)
    BUG:ERROR: Could not find a version that satisfies the requirement cython
    记录一次关于Rank()排序函数问题
    Centos环境使用Docker安装Kafka
    vivo鄢楠:基于OceanBase 的降本增效实践
    基于.NetCore开发博客项目 StarBlog - (16) 一些新功能 (监控/统计/配置/初始化)
    《Python+Kivy(App开发)从入门到实践》自学笔记:高级UX部件——FileChooser文件选择器
  • 原文地址:https://blog.csdn.net/fareast_mzh/article/details/132948360