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

相关文章

【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),提供可靠的、面向连接的通信。数据

如何为 DigitalOcean 静态路由操作员设置故障转移

静态路由操作器的主要目的是提供更大的灵活性,并在 Kubernetes 环境中控制网络流量。它使你能够根据应用程序的需求自定义路由配置,从而优化网络性能。该操作器作为 DaemonSet 部署,因此将在你的 DigitalOcean Managed Kubernetes 集群的每个节点上运行。 在本教程中,你将学习如何根据 CRD 规范管理每个工作节点的路由表,并设置故障转移网关。

JAVAEE初阶第六节——网络编程套接字

系列文章目录 JAVAEE初阶第六节——网络编程套接字 文章目录 系列文章目录JAVAEE初阶第六节——网络编程套接字 一. 网络编程基础1. 为什么需要网络编程2. 什么是网络编程3.网络编程中的基本概念 3.1 发送端和接收端 3.2 请求和响应 3.3 客户端和服务端 4. 常见的客户端服务端模型 5. TCP和UDP特点上的差别(初识) 二.Socket套接字 1. 概

若依框架登录鉴权详解(动态路由)

若依框架登录鉴权:1.获取token(过期在响应拦截器中实现),2.基于RBAC模型获取用户、角色和权限信息(在路由前置守卫),3.根据用户权限动态生成(从字符串->组件,根据permission添加动态路由信息)和添加路由addRoutes(在路由前置守卫) 若依框架(Ruoyi)后端的登录权限身份认证流程是一个复杂但高效的过程,它确保了系统的安全性和数据的保护。以下是一个典型的若依

Vue - 关于Router路由跳转时显示的animate.css动画

Vue - 关于Router路由跳转时显示的animate.css动画 在Vue中,操作路由跳转时页面是闪白的,没有动画效果,我们可以通过在router-view中设置transition,并搭配animate丰富的动画效果来美化路由跳转时的显示效果. 1.安装animate npm i -S animate.css 2.在main中引入animate.css import 'anim

Avoided redundant navigation to current location: 路由相同报错

vue-router有一个内置保护机制,它会阻止不必要的重复导航,以提高性能并避免不必要的计算。 具体来说,错误信息中的就是试图访问的路径时,应用程序已经在当前这个路径上。因此,vue-router检测到了这个重复的导航请求,就发出了警告。 通常情况下,这种警告并不需要特别处理,因为这只是一个优化措施,防止不必要的导航。但是如果你频繁遇到这种情况,可能需要检查触发导航的部分代码逻辑是否有必要进