busybox无法ping域名的解决办法
$ 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。
#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/
但是这位大神的博客已经注销了。我们还是收藏先。