网络程序设计教材第三章 IP协议(7)

2020-05-12 11:48

4 5 NET_RT_DUMP 0 NET_RT_FLAGS RTF_LLINFO NET_RT_IFLIST 0 从表3-6可以看出由name[4]指明的三种操作(NET_RT_xxx常值在头文件定义)。这三种操作是通过sysctl调用中的oldp指针返回信息的。这个缓冲区中包含可变数目的RTM_xxx消息(表3-5所示)。 对于name[4]的内容,它们的含义如下:

1. NET_RT_DUMP返回由name[3]指定的地址族路由表。如果这个地址族是0,则返

回所有地址族的路由表。

路由表作为可变数目的RTM_GET消息返回,每个消息后最多可接四个套接口地址结构:本路由表项的目的地址、网关、网络掩码和复制掩码。

2. NET_RT_FLAGS返回由name[3]指定的地址族的路由表,但只返回那些具有由

name[5]指定的RTF_xxx标志的路由表项。路由表中所有的ARP高速缓存项其RTF_LLINFO标志位都是置位的。信息返回的格式和前一条相同。

3. NET_RT_IFLIST返回所有已配置接口的信息。如果name[5]不为0,那它就是一个

接口的索引号,于是只返回这个接口的信息。每个接口被赋予的所有地址也都返回,但如果name[3]不为0,则只返回指定地址族的地址。 给每个接口返回一个RTM_IFINFO消息,后面接着的是赋给该接口的每个地址对应的各个RTM_NEWADDR消息。RTM_IFINFO消息后接的是一个数据链路套接口地址结构,RTM_NEWADDR消息后接最多三个套接口地址结构:接口地址、网络掩码和广播地址。图3-15说明了这两种消息。

内核返回的缓冲区

if_msghdr {}

ifm_type=RTM_IFINFO 每个接口一个RTM_IFINFO:

接口名、索引和硬件地址

数据链路套接口

地址结构

ifa_msgaddr{} ifam_type=RTM_NEWADDR

网络掩码套接口

地址结构 本接口每个已配置的地址一 单播地址套接口 个RTM_NEWADDR 地址结构

广播地址套接口

地址结构

图3-15 sysctl的CTL_NET,NET_RT_IFLIST命令返回的信息 由于源自4.4BSD的内核加入了对IPv6的支持,因此应加入对name[1]成员为AF_INET6

的支持(以设置和获取IPv6特定变量),以及对表3-6中的name[3]为AF_INET6的支持(以列出IPv6路由表或IPv6邻居高速缓存,或者返回IPv6接口地址)。 下面是一个判断UDP校验和是否打开的程序例子。这个例子使用网际协议检查UDP校验和是否打开。一些UDP应用程序(例如bind)在启动时检查UDP校验和是否打开。如果没有打开,则试图打开它。当然这需要超级用户权限打开这样的特性。下面是这个程序的代码。 #include \

#include #include #include

int

main(int argc, char **argv) {

}

exit(0);

len = sizeof(val);

Sysctl(mib, 4, &val, &len, NULL, 0); printf(\

mib[0] = CTL_NET; mib[1] = AF_INET; mib[2] = IPPROTO_UDP; mib[3] = UDPCTL_CHECKSUM;

int

mib[5], val;

size_t len;

/* for UDPCTL_xxx constants */

该程序必须包含头文件,以得到对UDP sysctl常值的定义。程序的主体是分配一个四个元素的整数数组,存放图3-14中表示的各层对应的常值。因为只取变量而不存入变量,所以把sysctl的newp参数设置为空指针,newlen参数设置为0。oldp指向一个整数变量以存放结果,oldlenp指向的值-结果参数是这个整数的大小。输出的这个标志将为0(关闭)或1(打开)。

sysctl函数是获取和设置操作系统参数的常规方法,包括输出接口列表、输出路由表、输出ARP高速缓存等。

3.7.4 接口名和索引函数 RFC2133定义了四个处理接口名和索引的函数。这四个函数用于IPv6多播通信。基本概念是每个接口有一个唯一的名字和一个唯一的大于0的索引(0不用做索引)。这四个函数的具体使用方法如下: #include unsigned int if_nametoindex(const char *ifname); char *if_indextoname(unsigned int ifindex, char *ifname);

struct if_nameindex *if_nameindex(void); void if_freenameindex(struct if_nameindex *ptr); if_nametoindex函数成功时返回名为ifname的接口的索引,出错时返回为0。if_indextoname对给定的ifindex返回一个指向其接口名的指针,出错时返回NULL。Ifname参数指向一个大小为IFNAMSIZ(在头文件中定义)的缓冲区,调用者必须分配这个缓冲区以保存结果,成功时这个指针也是函数的返回值。 if_nameindex返回一个指向if_nameindex结构的数组的指针: struct if_nameindex { unsigned int if_index; /*1, 2,…*/ char if_name; /*null terminated name:”le0”, …*/ 数组的最后一项是一个if_index为0,if_name为空指针的结构。这个数组和数组中各元素指向的名字所用的内存是动态分配的,调用if_freenameindex函数可以释放这些内存。 下面是使用路由套接口提供这四个函数的一个实现。这四个函数都使用了两个头文件unpifi.h和unproute.h。 unpifi.h代码如下:

/* Our own header for the programs that need interface configuration info. Include this file, instead of \

#ifndef __unp_ifi_h #define __unp_ifi_h

#include \#include

#define IFI_NAME 16 /* same as IFNAMSIZ in */ #define IFI_HADDR 8 /* allow for 64-bit EUI-64 in future */

struct ifi_info {

char ifi_name[IFI_NAME]; /* interface name, null terminated */ u_char ifi_haddr[IFI_HADDR]; /* hardware address */ u_short ifi_hlen; /* #bytes in hardware address: 0, 6, 8 */ short ifi_flags; /* IFF_xxx constants from */ short ifi_myflags; /* our own IFI_xxx flags */ struct sockaddr *ifi_addr; /* primary address */ struct sockaddr *ifi_brdaddr;/* broadcast address */

struct sockaddr *ifi_dstaddr;/* destination address */ struct ifi_info *ifi_next; /* next of these structures */ };

#define IFI_ALIAS 1 /* ifi_addr is an alias */ /* function prototypes */

struct ifi_info *get_ifi_info(int, int); struct ifi_info *Get_ifi_info(int, int); void free_ifi_info(struct ifi_info *); #endif /* __unp_ifi_h */

unproute.h代码如下:

#include \#include /* if_msghdr{} */ #include /* sockaddr_sdl{} */ #include /* RTA_xxx constants */ #include

#ifdef HAVE_SYS_SYSCTL_H #include /* sysctl() */ #endif /* function prototypes */

void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); char *net_rt_iflist(int, int, size_t *); char *net_rt_dump(int, int, size_t *);

char *sock_masktop(struct sockaddr *, socklen_t); /* wrapper functions */

char *Net_rt_iflist(int, int, size_t *); char *Net_rt_dump(int, int, size_t *); #define Sock_masktop(a,b) sock_masktop((a), (b))

1. if_nametoindex函数

下面给出了if_nametoindex函数的实现代码。

/* include if_nametoindex */ #include \#include \

unsigned int

if_nametoindex(const char *name) {

lim = buf + len;

if ( (buf = net_rt_iflist(0, 0, &len)) == NULL)

return(0); unsigned int char

size_t

index;

*buf, *next, *lim;

len;

*sa, *rti_info[RTAX_MAX]; *sdl;

struct if_msghdr *ifm; struct sockaddr struct sockaddr_dl

}

for (next = buf; next < lim; next += ifm->ifm_msglen) { }

free(buf); return(0);

/* no match for name */

ifm = (struct if_msghdr *) next; if (ifm->ifm_type == RTM_IFINFO) { }

sa = (struct sockaddr *) (ifm + 1); get_rtaddrs(ifm->ifm_addrs, sa, rti_info); if ( (sa = rti_info[RTAX_IFP]) != NULL) { }

if (sa->sa_family == AF_LINK) { }

sdl = (struct sockaddr_dl *) sa;

if (strncmp(&sdl->sdl_data[0], name, sdl->sdl_nlen) == 0) { }

index = sdl->sdl_index; /* save before free() */ free(buf); return(index);

/* end if_nametoindex */ unsigned int

If_nametoindex(const char *name) {

}

int

index;

if ( (index = if_nametoindex(name)) == 0)

err_quit(\return(index);

net_rt_iflist函数返回接口列表。该函数的主要功能是处理缓冲区中的消息(图3-15),只查找RTM_IFINFO消息。当找到一个时,调用get_rtaddrs函数设置指向各套接口地址结构的指针;如果存在一个接口名结构(rti_info数组的RTAX_IFP元素),就把该接口名和调用者使用的参数做一下比较。

2. if_indextoname函数

下面给出了if_indextoname函数的实现代码。

/* include if_indextoname */ #include \#include \

char *

if_indextoname(unsigned int index, char *name) {


网络程序设计教材第三章 IP协议(7).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:江苏卫生正高职称评审条件 江苏省卫生正高职称评审条件

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: