2011-03-21 69 views
0

我學習一本名爲Unix網絡編程第3版 的書,我寫了下面的代碼,我發現它需要一個名爲if_dl.h的庫 我沒有有因爲我在Ubuntu上工作,所以我安裝了lib-newlib,並使用它..使用newlib與gcc的路由套接字(unix網絡編程)

但在編譯時,我得到了很多錯誤,指的是頭文件newlib有像 /usr/lib/newlib/i486-linux-gnu/include/net/route.h:54:error:field ro_dst has incomplete type and same for rt_dst and rt_gateway but also another problem ... that code uses sa_len which is assume成爲sockaddr結構中的成員.. 但sockaddr只有sa_family,sa_data成員.. 所以是我需要在freeBSD上工作的問題?

的代碼,我在說什麼

#include <stdio.h> 
    #include <stdlib.h> 
    #include <net/route.h> 
    #include <net/if.h> 
    #include <net/if_dl.h> 
    #include <netinet/in.h> 
    #include <sys/socket.h> 
    #include <unistd.h> 

2 #define BUFLEN (sizeof(struct rt_msghdr) + 512) 
3      /* sizeof(struct sockaddr_in6) * 8 = 192 */ 
4 #define SEQ  9999 

5 int 
6 main(int argc, char **argv) 
7 { 
8  int  sockfd; 
9  char *buf; 
10  pid_t pid; 
11  ssize_t n; 
12  struct rt_msghdr *rtm; 
13  struct sockaddr *sa, *rti_info[RTAX_MAX]; 
14  struct sockaddr_in *sin; 

15  if (argc != 2) 
16   err_quit("usage: getrt <IPaddress>"); 

17  sockfd = Socket(AF_ROUTE, SOCK_RAW, 0); /* need superuser privileges */ 

18  buf = Calloc(1, BUFLEN);  /* and initialized to 0 */ 

19  rtm = (struct rt_msghdr *) buf; 
20  rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in); 
21  rtm->rtm_version = RTM_VERSION; 
22  rtm->rtm_type = RTM_GET; 
23  rtm->rtm_addrs = RTA_DST; 
24  rtm->rtm_pid = pid = getpid(); 
25  rtm->rtm_seq = SEQ; 

26  sin = (struct sockaddr_in *) (rtm + 1); 
27  sin->sin_len = sizeof(struct sockaddr_in); 
28  sin->sin_family = AF_INET; 
29  Inet_pton(AF_INET, argv[1], &sin->sin_addr); 

30  Write(sockfd, rtm, rtm->rtm_msglen); 

31  do { 
32   n = Read(sockfd, rtm, BUFLEN); 
33  } while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ || 
34    rtm->rtm_pid != pid); 
35  rtm = (struct rt_msghdr *) buf; 
36  sa = (struct sockaddr *) (rtm + 1); 
37  get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 
38  if ((sa = rti_info[RTAX_DST]) != NULL) 
39   printf("dest: %s\n", Sock_ntop_host(sa, sa->sa_len)); 

40  if ((sa = rti_info[RTAX_GATEWAY]) != NULL) 
41   printf("gateway: %s\n", Sock_ntop_host(sa, sa->sa_len)); 

42  if ((sa = rti_info[RTAX_NETMASK]) != NULL) 
43   printf("netmask: %s\n", Sock_masktop(sa, sa->sa_len)); 

44  if ((sa = rti_info[RTAX_GENMASK]) != NULL) 
45   printf("genmask: %s\n", Sock_masktop(sa, sa->sa_len)); 

46  exit(0); 
47 } 

2 /* 
3 * Round up 'a' to next multiple of 'size', which must be a power of 2 
4 */ 
5 #define ROUNDUP(a, size) (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a)) 
6 /* 
7 * Step to next socket address structure; 
8 * if sa_len is 0, assume it is sizeof(u_long). 
9 */ 
10 #define NEXT_SA(ap) ap = (SA *) \ 
11  ((caddr_t) ap + (ap->sa_len ? ROUNDUP(ap->sa_len, sizeof (u_long)) : \ 
12          sizeof(u_long))) 
13 void 
14 get_rtaddrs(int addrs, SA *sa, SA **rti_info) 
15 { 
16  int  i; 
17  for (i = 0; i < RTAX_MAX; i++) { 
18   if (addrs & (1 << i)) { 
19    rti_info[i] = sa; 
20    NEXT_SA(sa); 
21   } else 
22    rti_info[i] = NULL; 
23  } 
24 } 

2 const char * 
3 sock_masktop(SA *sa, socklen_t salen) 
4 { 
5  static char str[INET6_ADDRSTRLEN]; 
6  unsigned char *ptr = &sa->sa_data[2]; 
7  if (sa->sa_len == 0) 
8   return ("0.0.0.0"); 
9  else if (sa->sa_len == 5) 
10   snprintf(str, sizeof(str), "%d.0.0.0", *ptr); 
11  else if (sa->sa_len == 6) 
12   snprintf(str, sizeof(str), "%d.%d.0.0", *ptr, *(ptr + 1)); 
13  else if (sa->sa_len == 7) 
14   snprintf(str, sizeof(str), "%d.%d.%d.0", *ptr, *(ptr + 1), 
15     *(ptr + 2)); 
16  else if (sa->sa_len == 8) 
17   snprintf(str, sizeof(str), "%d.%d.%d.%d", 
18     *ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3)); 
19  else 
20   snprintf(str, sizeof(str), "(unknown mask, len = %d, family = %d)", 
21     sa->sa_len, sa->sa_family); 
22  return (str); 
23 } 

回答

-1

你爲什麼要使用newlib(C庫用於嵌入式應用的實現),而不是glibc的?

嘗試和使用glibc的編譯(應與你的Ubuntu發行版的安裝,如果拿不到安裝的libc6-DEV)

+0

我怎麼能包括:) ?? ?? – 2011-03-21 16:21:44

1

該代碼將無法在Linux上運行。 Stevens在他的Solaris,AIX和FreeBSD測試機器上測試過它(我們預計它會工作)。 Linux有AF_NETLINK,它應該是等效的,但是與BSD AF_ROUTE有一些細微的差別。

在linux上使用<linux/netlink.h>而不是<net/if_dl.h>中的定義。查看重複問題What package do i need to install for using routing sockets?

正如你發現的那樣,sa_len不在linux上(實際上也不在Solaris上),所以返回地址的所有字節都是有效的。這將工作爲sock_masktop

const char * sock_masktop(SA *sa, socklen_t salen) { 
    static char str[INET6_ADDRSTRLEN]; 
    unsigned char *ptr = &sa->sa_data[2]; 
    snprintf(str, sizeof(str), "%d.%d.%d.%d", 
      *ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3)); 
    return (str); 
}