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;
- }
#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