UNP卷一chapter18 路由套接字

2024-04-25 19:48
文章标签 路由 接字 chapter18 unp

本文主要是介绍UNP卷一chapter18 路由套接字,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

相比较第17章用ioctl函数获取整个路由表,利用sysctl函数也是可以做到而且无需超级用户权限。

1、路由套接字上支持3种类型的操作

i、进程可以通过写出到路由套接字而往内核发送消息。路径的增加和删除采用这种操作实现。

ii、进程可以通过从路由套接字读入来自内核接收消息。内核采用这种操作通知进程已收到并处理一个ICMP重定向消息,或者请求外部路由进程解析一个路径。

iii、进程可以使用sysctl函数倾泻出路由表或列出所有已配置的接口。

数据链路套接字地址结构(定义在net/if_dl.h文件中,我的机器上没有这文件,所以本章的程序都无法编译通过,需要的可以参考if_dl.h文件,如果已有的话,可以发份我,感激不尽!)

struct sockaddr_dl {uint8_t	sdl_len;sa_family_t sdl_family;//AF_LINKuint16_t	sdl_index;//system assigned index, if>0uint8_t	sdl_type;//IFT_ETHER, ect. from <net/if_types.h>uint8_t sdl_nlen;//name length, starting in sdl_data[0]uint8_t	sdl_alen;//link-layer address lengthuint8_t	sdl_slen;//link-layer selector lengthchar	sdl_data[12];//minimum work area, can be larger
};                       //contains i/f name and link-layer address

2、介绍路由套接字的相关信息

i、通过路由套接字交换的消息类型(见书上P383)

ii、在路由消息中用于指称套接字地址结构的常值(见书上P385)

iii、获取并输出一个路由表项的代码实现(没有用sysctl函数实现)

以下程序通过命令参数取得一个ipv4点分十进制数地址,并就这个地址向内核发送一个RTM_GET消息。内核在它的ipv4路由表中查找这个地址,并作为一个RTM_GET消息返回相应路由表项的信息。先见图,再见代码。


#include	"unproute.h"#define	BUFLEN	(sizeof(struct rt_msghdr) + 512)/* sizeof(struct sockaddr_in6) * 8 = 192 */
#define	SEQ		9999int
main(int argc, char **argv)
{int					sockfd;char				*buf;pid_t				pid;ssize_t				n;struct rt_msghdr	*rtm;//rt_msghdr、if_msghdr、ifa_msghdr、ifma_msghdr和if_announcemsghdr的具体定义在书上P384,图18-3所示struct sockaddr		*sa, *rti_info[RTAX_MAX];struct sockaddr_in	*sin;if (argc != 2)err_quit("usage: getrt <IPaddress>");sockfd = Socket(AF_ROUTE, SOCK_RAW, 0);	/* need superuser privileges */buf = Calloc(1, BUFLEN);	/* and initialized to 0 */rtm = (struct rt_msghdr *) buf;rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);rtm->rtm_version = RTM_VERSION;rtm->rtm_type = RTM_GET;rtm->rtm_addrs = RTA_DST;rtm->rtm_pid = pid = getpid();//获取进程ID,并赋值rtm->rtm_seq = SEQ;sin = (struct sockaddr_in *) (rtm + 1);//在buf的第二个缓存位置构造一个rt_msghdr结构sin->sin_len = sizeof(struct sockaddr_in);sin->sin_family = AF_INET;Inet_pton(AF_INET, argv[1], &sin->sin_addr);Write(sockfd, rtm, rtm->rtm_msglen);//很关键哈,这是向内核传递消息do {n = Read(sockfd, rtm, BUFLEN);} while (rtm->rtm_type != RTM_GET || rtm->rtm_seq != SEQ ||rtm->rtm_pid != pid);rtm = (struct rt_msghdr *) buf;sa = (struct sockaddr *) (rtm + 1);get_rtaddrs(rtm->rtm_addrs, sa, rti_info);//此函数将构造指向路由消息中各个套接字地址结构的指针数组,由于篇幅,此处不再给出,具体见书上P389if ((sa = rti_info[RTAX_DST]) != NULL)printf("dest: %s\n", Sock_ntop_host(sa, sa->sa_len));if ((sa = rti_info[RTAX_GATEWAY]) != NULL)printf("gateway: %s\n", Sock_ntop_host(sa, sa->sa_len));if ((sa = rti_info[RTAX_NETMASK]) != NULL)printf("netmask: %s\n", Sock_masktop(sa, sa->sa_len));if ((sa = rti_info[RTAX_GENMASK]) != NULL)printf("genmask: %s\n", Sock_masktop(sa, sa->sa_len));exit(0);
}

3、sysctl函数及其使用(上述程序创建一个AF_ROUTE域raw socket,需要root权限,使用此函数不限用户权限)

#include<sys/param.h>
#include<sys/sysctl.h>
//oldp供内核存放值的buffer,oldlenp代表buffer大小(值-结果参数)
int sysctl(int *name, u_int namelen, void* oldp, size_t* oldlenp,void* newp, size_t newlen);//若成功则为0,若出错则为-1

上述函数中的形参还需要着重强调一下name,name参数是指定名字的一个整数数组,namelen参数指定该数组中的元素数目。该数组中的第一个指定本请求定向到内核的哪个子系统。第二个及其后元素逐次细化指定该子系统的某个部分。


当name数组的第二个元素为AF_ROUTE时,第三个元素(协议号)总是为0(因为AF_ROUTE族不像比如说AF_INET族那样其中有协议),第四个元素是一个地址族,第五和第六级指定做什么。如下图所示:

name[]返回IPv4路由表返回IPv4ARP高速缓存返回IPv6路由表返回接口清单
0CTL_NETCTL_NETCTL_NETCTL_NET
1AF_ROUTEAF_ROUTEAF_ROUTEAF_ROUTE
20000
3AF_INETAF_INETAF_INET60
4NET_RT_DUMPNET_RT_FLAGSNET_RT_DUMPNET_RT_IFLIST
50RTF_LLINFO0

0

NET_RT_DUMP返回由name[3]指定的地址族的路由表。如果所指定的地址族为0,那么返回所有地址族的路由表。

NET_RT_FLAGS返回由name[3]指定的地址族的路由表,但是仅限于那些所带标志(若干个RTF_xxx常值的逻辑或)与name[5]指定的标志相匹配的路由表项。路由表中所有ARP高速缓存表项均设置了RTF_LLINFO标志位。

NET_RT_IFLIST返回所有已配置接口的信息。如果name[5]不为0,它就是某个接口的索引号,于是仅仅返回该接口的信息。已赋予每个接口的所有地址也同时返回,不过如果name[3]不为0,那么仅限于返回指定地址族的地址。

利用sysctl函数实现char* net_rt_iflist(int family,int flags,size_t *lenp);代码如下:

#include	"unproute.h"char *
net_rt_iflist(int family, int flags, size_t *lenp)
{int		mib[6];char	*buf;mib[0] = CTL_NET;mib[1] = AF_ROUTE;mib[2] = 0;mib[3] = family;		/* only addresses of this family */mib[4] = NET_RT_IFLIST;//表示返回所有已配置接口信息mib[5] = flags;			/* interface index or 0 */if (sysctl(mib, 6, NULL, lenp, NULL, 0) < 0)//首先获取buffer大小return(NULL);if ( (buf = malloc(*lenp)) == NULL)//再根据lenp的大小分配内存return(NULL);if (sysctl(mib, 6, buf, lenp, NULL, 0) < 0) {//通过内核返回在buffer中信息获取网络、路由、接口信息free(buf);return(NULL);}return(buf);
}

由于本人所装ubuntu14.04实现不了本章的程序,所以此处利用sysctl函数实现get_ifi_info函数不再给出,具体见书上P395-P396。

4、接口名字和索引函数(用于需要描述一个接口的场合,为ipv6 API引入,也适用于ipv4)

每个接口都有一个唯一的名字和一个唯一的正值索引(0从不用作索引)。

#include<net/if.h>
unsigned in if_nametoindex(const char* ifname);//返回:若成功则为正的接口索引,若出错则为0;
char* if_indextoname(unsigned int ifindex, char* ifname);//返回:若成功则为指向接口名字的指针,若出错则为NULL
struct if_nameindex* if_nameindex(void);//返回:若成功则为非空指针,若出错则为NULL
void if_freenameindex(struct if_nameindex* ptr);

上述四个接口名字和索引函数均通过net_rt_iflist函数实现,具体实现见书上P397-P400。

以上知识点来均来自steven先生所著UNP卷一(version3),刚开始学习网络编程,如有不正确之处请大家多多指正。

这篇关于UNP卷一chapter18 路由套接字的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/935628

相关文章

golang实现动态路由的项目实践

《golang实现动态路由的项目实践》本文主要介绍了golang实现动态路由项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习... 目录一、动态路由1.结构体(数据库的定义)2.预加载preload3.添加关联的方法一、动态路由1

Nginx路由匹配规则及优先级详解

《Nginx路由匹配规则及优先级详解》Nginx作为一个高性能的Web服务器和反向代理服务器,广泛用于负载均衡、请求转发等场景,在配置Nginx时,路由匹配规则是非常重要的概念,本文将详细介绍Ngin... 目录引言一、 Nginx的路由匹配规则概述二、 Nginx的路由匹配规则类型2.1 精确匹配(=)2

SpringIntegration消息路由之Router的条件路由与过滤功能

《SpringIntegration消息路由之Router的条件路由与过滤功能》本文详细介绍了Router的基础概念、条件路由实现、基于消息头的路由、动态路由与路由表、消息过滤与选择性路由以及错误处理... 目录引言一、Router基础概念二、条件路由实现三、基于消息头的路由四、动态路由与路由表五、消息过滤

Go路由注册方法详解

《Go路由注册方法详解》Go语言中,http.NewServeMux()和http.HandleFunc()是两种不同的路由注册方式,前者创建独立的ServeMux实例,适合模块化和分层路由,灵活性高... 目录Go路由注册方法1. 路由注册的方式2. 路由器的独立性3. 灵活性4. 启动服务器的方式5.

关于Gateway路由匹配规则解读

《关于Gateway路由匹配规则解读》本文详细介绍了SpringCloudGateway的路由匹配规则,包括基本概念、常用属性、实际应用以及注意事项,路由匹配规则决定了请求如何被转发到目标服务,是Ga... 目录Gateway路由匹配规则一、基本概念二、常用属性三、实际应用四、注意事项总结Gateway路由

【vue3|第28期】 Vue3 + Vue Router:探索路由重定向的使用与作用

日期:2024年9月8日 作者:Commas 签名:(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释:如果您觉在这里插入代码片得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方,还望各位大佬不吝赐教,谢谢^ - ^ 1.01365 = 37.7834;0.99365 = 0.0255 1.02365 = 1377.4083;0.98365 = 0.0006 说

HCIA--实验十:路由的递归特性

递归路由的理解 一、实验内容 1.需求/要求: 使用4台路由器,在AR1和AR4上分别配置一个LOOPBACK接口,根据路由的递归特性,写一系列的静态路由实现让1.1.1.1和4.4.4.4的双向通信。 二、实验过程 1.拓扑图: 2.步骤: (下列命令行可以直接复制在ensp) 1.如拓扑图所示,配置各路由器的基本信息: 各接口的ip地址及子网掩码,给AR1和AR4分别配置

微软C#套接字异步通信代码

Asynchronous Server Socket Example.NET Framework 4 其他版本 The following example program creates a server that receives connection requests from clients. The server is built with an asynchronous socket,

微信小程序路由跳转之间的区别

navigateTo: 功能描述: navigateTo用于保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。 页面栈变化: 当使用navigateTo进行页面跳转时,当前页面会被推入页面栈中,但不会被销毁,新页面则显示在屏幕上。因此,页面栈中的元素数量会增加。 注意:一般定制返回时候不要用navigateTo,用navigateBack,否则会导致页面栈过多。 nav

套接字的介绍

套接字(Socket)是计算机网络中用于实现不同主机之间通信的一种抽象概念。它提供了一种标准的接口,使得应用程序能够通过网络发送和接收数据。以下是关于套接字的详细介绍: 1. 套接字的基本概念 定义:套接字是一种用于网络通信的端点,通常由 IP 地址和端口号组成。它允许不同的程序进行网络通信。类型: 流套接字(TCP Socket):使用传输控制协议(TCP),提供可靠的、面向连接的通信。数据