路由套接字上支持3种类型的操作
1). 进程能通过写路由套接字向内核发消息。
2). 进程能通过路由套接字从内核读消息。
3). 进程可以用sysctl函数得到路由表或列出所有已配置的接口。
数据链路套接字地址结构
通过路由套接字返回的一些消息中含有作为返回值给出的数据链路套接字地址结构
struct sockaddr_dl { uint8_t sdl_len; sa_family_t sdl_family; /* AF_LINK */ uint16_t sdl_index; /* system assigned index, if > 0 */ uint8_t sdl_type; /* IFT_ETHER, etc. from */ uint8_t sdl_nlen; /* name length, starting in sdl_data[0] */
uint8_t sdl_alen; /* link-layer address length */
uint8_t sdl_slen; /* link-layer selector length */
char sdl_data[12]; /* minimum work area, can be larger;*/
};
sdl_data成员含有名字和链路层地址(例如以太网接口的48位MAC地址)。
名字从sdl_data[0]开始,而且不以空字符结尾。链路层地址从sdl_data[sdl_nlen]开始
读和写
创建一个路由套接字后,进程可以通过写到该套接字向内核发送命令,通过读自该套接字从内核接收信息。
路由域套接字共有12个路由消息(还有黑体3个是新增的)
通过路由套接字交换的结构有5个类型:rt_msghdr、if_msghdr、ifa_msghdr、ifma_msghdr和if_announcemsghdr
每个结构有相同的前3个成员:本消息的长度、版本和类型。类型成员是上图第一列中的常值之一。
例子:获取并输出一个路由表项
这个程序使用一个IPv4点分十进制数地址作为命令行参数,并就这个地址向内核发送一个RTM_GET消息。
内核在它的IPv4路由表中查找这个地址,并作为一个RTM_GET消息返回相应路由表项的消息。
该程序代码如下
1 /* include getrt1 */ 2 #include "unproute.h" 3 4 #define BUFLEN (sizeof(struct rt_msghdr) + 512) 5 /* sizeof(struct sockaddr_in6) * 8 = 192 */ 6 #define SEQ 9999 7 8 int 9 main(int argc, char **argv) 10 { 11 int sockfd; 12 char *buf; 13 pid_t pid; 14 ssize_t n; 15 struct rt_msghdr *rtm; 16 struct sockaddr *sa, *rti_info[RTAX_MAX]; 17 struct sockaddr_in *sin; 18 19 if (argc != 2) 20 err_quit("usage: getrt <IPaddress>"); 21 22 sockfd = Socket(AF_ROUTE, SOCK_RAW, 0); /* need superuser privileges */ 23 24 buf = Calloc(1, BUFLEN); /* and initialized to 0 */ 25 26 rtm = (struct rt_msghdr *) buf; 27 rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in); 28 rtm->rtm_version = RTM_VERSION; 29 rtm->rtm_type = RTM_GET; 30 rtm->rtm_addrs = RTA_DST; 31 rtm->rtm_pid = pid = getpid(); 32 rtm->rtm_seq = SEQ; 33 34 sin = (struct sockaddr_in *) (rtm + 1); 35 sin->sin_len = sizeof(struct sockaddr_in); 36 sin->sin_family = AF_INET; 37 Inet_pton(AF_INET, argv[1], &sin->sin_addr); 38 39 Write(sockfd, rtm, rtm->rtm_msglen); 40 41 do { 42 n = Read(sockfd, rtm, BUFLEN); 43 } while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ || 44 rtm->rtm_pid != pid); 45 /* end getrt1 */ 46 47 /* include getrt2 */ 48 rtm = (struct rt_msghdr *) buf; 49 sa = (struct sockaddr *) (rtm + 1); 50 get_rtaddrs(rtm->rtm_addrs, sa, rti_info); 51 if ( (sa = rti_info[RTAX_DST]) != NULL) 52 printf("dest: %s\n", Sock_ntop_host(sa, sa->sa_len)); 53 54 if ( (sa = rti_info[RTAX_GATEWAY]) != NULL) 55 printf("gateway: %s\n", Sock_ntop_host(sa, sa->sa_len)); 56 57 if ( (sa = rti_info[RTAX_NETMASK]) != NULL) 58 printf("netmask: %s\n", Sock_masktop(sa, sa->sa_len)); 59 60 if ( (sa = rti_info[RTAX_GENMASK]) != NULL) 61 printf("genmask: %s\n", Sock_masktop(sa, sa->sa_len)); 62 63 exit(0); 64 } 65 /* end getrt2 */