简体   繁体   English

将newlib与gcc一起使用以路由套接字(unix网络编程)

[英]using newlib with gcc for routing sockets (unix network programming)

I study from a book called Unix network programming 3rd edition and I wrote the following code and i found it needs a library called if_dl.h which i didn't has cuz i work on ubuntu so i installed the lib-newlib and used it.. 我从一本名为《 Unix网络编程第三版》的书中学习,我编写了以下代码,我发现它需要一个名为if_dl.h的库,因为我没有在ubuntu上工作,所以我安装了lib-newlib并使用了它。 。

but on compile time i get alot of errors that refer to the header files that the newlib has like /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 there is another problem... that the code uses sa_len which is assumed to be a member in the sockaddr structure.. but the sockaddr only has the sa_family,sa_data members.. so is the problem that i need to work on freeBSD or what? 但是在编译时,我得到很多错误,这些错误指向newlib所具有的头文件,例如/usr/lib/newlib/i486-linux-gnu/include/net/route.h:54:错误:字段ro_dst的类型不完整和rt_dst和rt_gateway相同,但是还有另一个问题...代码使用了sa_len,它被假定为sockaddr结构的成员..但是sockaddr仅具有sa_family,sa_data成员。所以我遇到的问题是需要在freeBSD上工作还是什么?

the code I am talkin about 我正在谈论的代码

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

That code won't work on Linux. 该代码在Linux上不起作用。 It's implied on page 486 that Stevens tested it on his Solaris, AIX, and FreeBSD test machines (where we would expect it to work). 在第486页上暗示Stevens在他的Solaris,AIX和FreeBSD测试计算机上(我们希望它可以在其中运行)对其进行测试。 Linux has AF_NETLINK, which is supposed to be equivalent, but does have some minor differences to BSD AF_ROUTE. Linux具有AF_NETLINK,应该被认为是等效的,但与BSD AF_ROUTE确实有一些细微的差异。

Use the definitions in <linux/netlink.h> instead of <net/if_dl.h> on linux. <linux/netlink.h>使用定义,而不是在<linux/netlink.h>使用<net/if_dl.h> See duplicate question What package do i need to install for using routing sockets? 看到重复的问题,使用路由套接字需要安装什么软件包? .

As you spotted, sa_len isn't present on linux (nor is it on Solaris, in fact), so all bytes of the address returned will be valid. 如您所见,sa_len在linux上不存在(实际上,在Solaris上也不存在),因此返回的地址的所有字节都是有效的。 This would work for sock_masktop : 这将适用于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);
}

Why are you using newlib (a C library implementation intended for embedded use) instead of glibc? 为什么使用newlib(供嵌入式使用的C库实现)而不是glibc?

try and compile it using glibc (should be installed with your ubuntu distro, if not get libc6-dev installed) 尝试使用glibc进行编译(如果未安装libc6-dev,则应随ubuntu发行版一起安装)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM