busybox無法ping域名的解決辦法 ping: sendto: Network is unreachable


$ ping www.google.com

ping : bad address 'www.google.com

現在各個版本的busybox都一樣, 網上有人講需要libnss_dns* ...文件, 拷貝過去還是不能用,

手編2.6.21內核+手編1.5.1busybox+一堆deb包解壓縮出gcc, 一個自定義的linux基本完成了,就差這麼一個東西, hack源代碼... 

最終發現getaddrinfo這個函數調用失敗,解決思路就是模擬dns協議把域名發給dns服務器,把域名轉化爲ip,然後再調用getaddrinfo,試驗成功。

1. 把下面這段代碼加入libbb/xconnect.c 的開頭。
2. 把xconnect.c的str2sockaddr函數中getaddrinfo改爲hgetaddrinfo。

  1. #include <arpa/inet.h>  
  2. #include <netdb.h>  
  3. #include <stdio.h>  
  4. #include <stdlib.h>  
  5. #include <string.h>  
  6. #define oops(msg) { perror(msg); exit(1);}  
  7. #include<ctype.h>  
  8.   
  9.   
  10.   
  11. void fillip(char* buffer, const char* ip);  
  12. char* name2ip(const char* name);  
  13. /** 
  14.  *  * head len: 12 
  15.  *   * query: ? + 4 
  16.  *    * total: strlen(query.buffer) + 16 
  17.  *     */  
  18. typedef struct{  
  19.         u_short txid;  
  20.         u_short flag;  
  21.         u_short question;  
  22.         u_short answer;  
  23.         u_short authority;  
  24.         u_short additional;  
  25.         char buffer[256];  
  26.         struct {  
  27.                 u_short type;  
  28.                 u_short cls;  
  29.         }query;  
  30. }dns_req;  
  31. /** length of resp: 12 */  
  32. typedef struct{  
  33.         u_short txid;  
  34.         u_short flag;  
  35.         u_short question;  
  36.         u_short answer;  
  37.         u_short authority;  
  38.         u_short addtional;  
  39.         char buffer[1024];  
  40.         struct{  
  41.                 u_short name;  
  42.                 u_short type;  
  43.                 u_short cls;  
  44.                 u_short live_l;  
  45.                 u_short live_h;  
  46.                 u_short len;  
  47.                 struct in_addr addr;  
  48.         }resp;  
  49. }dns_res;  
  50.   
  51. int hgetaddrinfo(const char *node, const char *service,  
  52.                 const struct addrinfo *hints,  
  53.                 struct addrinfo **res){  
  54.         /*    int rc = getaddrinfo(node,service,hints,res); 
  55.          *            if(rc == 0)//todo: != -> == 
  56.          *                            return rc; 
  57.          *                                            */  
  58.         char *ip = name2ip(node);               /// 如果 ping www.baidu.com  
  59.         return getaddrinfo(ip,service,hints,res);   /// 那麼此時 node 指向字符串 "www.baidu.com"  
  60. }  
  61.   
  62. char *get_dns_name()  
  63. {  
  64.     int fd;  
  65.     static char buf[1024],*pstr,*pdns;  
  66.   
  67.     fd = open("/etc/resolv.conf",O_RDWR);  
  68.     read(fd,buf,1020);  
  69.     pstr = strstr(buf,"nameserver");  
  70.     pstr += strlen("nameserver");  
  71.     while(!isdigit(*pstr)){  
  72.         pstr ++;  
  73.     }  
  74.     pdns = pstr;  
  75.       
  76.     while(isdigit(*pstr) || (*pstr == '.') ){  
  77.         pstr ++;  
  78.     }  
  79.     *pstr = '\0';    
  80.     close(fd);  
  81.     return pdns;  
  82. }  
  83.   
  84.   
  85. char * name2ip(const char *node){  
  86.         struct sockaddr_in dns;  
  87.         dns_req req;  
  88.         dns_res res;  
  89.         int sockid, len, index;  
  90.         get_dns_name();  
  91.         char  dnsip[32];  
  92.   
  93.         strcpy(dnsip,get_dns_name());  
  94.   
  95.         sockid = socket(PF_INET, SOCK_DGRAM, 0);  
  96.         if(sockid == -1)  
  97.                 oops("socket");  
  98.         memset((void*)&dns, 0, sizeof(dns));  
  99.         dns.sin_family = AF_INET;  
  100.         dns.sin_port = htons(53);  
  101.         dns.sin_addr.s_addr = inet_addr(dnsip);  
  102.   
  103.         memset((void*)&req, 0, sizeof(req));  
  104.         req.txid = htons(0x4419);  
  105.         req.flag = htons(0x0100);  
  106.         req.question = htons(1);  
  107.         fillip(req.buffer,node);  
  108.         req.query.type=htons(1);  
  109.         req.query.cls=htons(1);  
  110.         memcpy(req.buffer+strlen(req.buffer)+1, (void*)(&req.query), sizeof(req.query));  
  111.   
  112.         sendto(sockid, (void*)&req, strlen(req.buffer)+17, 0,   
  113.                         (struct sockaddr*)&dns, sizeof(dns));  
  114.         recvfrom(sockid, (void*)&res, sizeof(res), 0,   
  115.                         (struct sockaddr*)&dns, &len);  
  116.         index = strlen(res.buffer)+5;  
  117.         while(1){  
  118.                 memcpy((void*)&(res.resp), res.buffer+index, 12);  
  119.                 if(ntohs(res.resp.type)==1){  
  120.                         memcpy((void*)&(res.resp.addr), res.buffer+index+12, 4);  
  121.                         break;  
  122.                 }  
  123.                 index += ntohs(res.resp.len) + 12;  
  124.         }  
  125.   
  126.         return inet_ntoa(res.resp.addr);  
  127. }  
  128.   
  129. void fillip(char* buffer, const char* ip){  
  130.         int i,j=0;  
  131.         for(i = 0; ip[i] != 0; i ++){  
  132.                 if(ip[i] != '.'){  
  133.                         buffer[i+1] = ip[i];  
  134.                 }  
  135.                 else{  
  136.                         buffer[j] = i - j;  
  137.                         j = i + 1;  
  138.                 }  
  139.         }  
  140.         buffer[j] = i - j;  
  141. }  
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define oops(msg) { perror(msg); exit(1);}
#include<ctype.h>



void fillip(char* buffer, const char* ip);
char* name2ip(const char* name);
/**
 *  * head len: 12
 *   * query: ? + 4
 *    * total: strlen(query.buffer) + 16
 *     */
typedef struct{
        u_short txid;
        u_short flag;
        u_short question;
        u_short answer;
        u_short authority;
        u_short additional;
        char buffer[256];
        struct {
                u_short type;
                u_short cls;
        }query;
}dns_req;
/** length of resp: 12 */
typedef struct{
        u_short txid;
        u_short flag;
        u_short question;
        u_short answer;
        u_short authority;
        u_short addtional;
        char buffer[1024];
        struct{
                u_short name;
                u_short type;
                u_short cls;
                u_short live_l;
                u_short live_h;
                u_short len;
                struct in_addr addr;
        }resp;
}dns_res;

int hgetaddrinfo(const char *node, const char *service,
                const struct addrinfo *hints,
                struct addrinfo **res){
        /*    int rc = getaddrinfo(node,service,hints,res);
         *            if(rc == 0)//todo: != -> ==
         *                            return rc;
         *                                            */
        char *ip = name2ip(node);				/// 如果 ping www.baidu.com
        return getaddrinfo(ip,service,hints,res);   /// 那麼此時 node 指向字符串 "www.baidu.com"
}

char *get_dns_name()
{
	int fd;
	static char	buf[1024],*pstr,*pdns;

	fd = open("/etc/resolv.conf",O_RDWR);
	read(fd,buf,1020);
	pstr = strstr(buf,"nameserver");
	pstr += strlen("nameserver");
	while(!isdigit(*pstr)){
		pstr ++;
	}
	pdns = pstr;
	
	while(isdigit(*pstr) || (*pstr == '.') ){
		pstr ++;
	}
	*pstr = '\0';  
	close(fd);
	return pdns;
}


char * name2ip(const char *node){
        struct sockaddr_in dns;
        dns_req req;
        dns_res res;
        int sockid, len, index;
		get_dns_name();
		char  dnsip[32];

		strcpy(dnsip,get_dns_name());

        sockid = socket(PF_INET, SOCK_DGRAM, 0);
        if(sockid == -1)
                oops("socket");
        memset((void*)&dns, 0, sizeof(dns));
        dns.sin_family = AF_INET;
        dns.sin_port = htons(53);
        dns.sin_addr.s_addr = inet_addr(dnsip);

        memset((void*)&req, 0, sizeof(req));
        req.txid = htons(0x4419);
        req.flag = htons(0x0100);
        req.question = htons(1);
        fillip(req.buffer,node);
        req.query.type=htons(1);
        req.query.cls=htons(1);
        memcpy(req.buffer+strlen(req.buffer)+1, (void*)(&req.query), sizeof(req.query));

        sendto(sockid, (void*)&req, strlen(req.buffer)+17, 0, 
                        (struct sockaddr*)&dns, sizeof(dns));
        recvfrom(sockid, (void*)&res, sizeof(res), 0, 
                        (struct sockaddr*)&dns, &len);
        index = strlen(res.buffer)+5;
        while(1){
                memcpy((void*)&(res.resp), res.buffer+index, 12);
                if(ntohs(res.resp.type)==1){
                        memcpy((void*)&(res.resp.addr), res.buffer+index+12, 4);
                        break;
                }
                index += ntohs(res.resp.len) + 12;
        }

        return inet_ntoa(res.resp.addr);
}

void fillip(char* buffer, const char* ip){
        int i,j=0;
        for(i = 0; ip[i] != 0; i ++){
                if(ip[i] != '.'){
                        buffer[i+1] = ip[i];
                }
                else{
                        buffer[j] = i - j;
                        j = i + 1;
                }
        }
        buffer[j] = i - j;
}


原文鏈接:

http://hankjin.blog.163.com/blog/static/337319372009327101324432/


另外如果是出現:

ping: sendto: Network is unreachable

則需要查看一下默認網關有沒有設置,可以通route命令查看

route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.1.0     *               255.255.255.0           U          0      0        0      rausb0

發現網關(Gateway),是空着的沒有設置,於是執行一下命令設置了網關:

# route add default gw 192.168.1.1
route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.1.0     *               255.255.255.0   U     0      0        0 rausb0

default         192.168.1.1     0.0.0.0         UG    0      0        0 rausb0


發佈了16 篇原創文章 · 獲贊 40 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章