当前位置: 首页 > news >正文

江苏泰州建设局网站钓鱼网站图片

江苏泰州建设局网站,钓鱼网站图片,网推是干嘛的,咨询装修IPv4允许在20字节的首部固定部分后跟最多共40字节的选项。尽管已经定义了10种IPv4选项#xff0c;但最常用的是源路径选项。我们可通过存取IP_OPTIONS套接字选项访问这些选项#xff0c;我们存取该套接字选项时#xff0c;所用的缓冲区中的值就是它们置于IP数据报中的格式。…IPv4允许在20字节的首部固定部分后跟最多共40字节的选项。尽管已经定义了10种IPv4选项但最常用的是源路径选项。我们可通过存取IP_OPTIONS套接字选项访问这些选项我们存取该套接字选项时所用的缓冲区中的值就是它们置于IP数据报中的格式。 IPv6允许在固定长度40字节的IPv6首部之后传输层首部如ICMPv6、TCP、UDP之前出现扩展首部目前定义了6种扩展首部。与IPv4不同的是IPv6扩展首部的访问途径是函数接口而非强求用户理解这些首部如何呈现在IPv6分组中的真实细节。 IPv4选项跟在20字节IPv4首部固定部分之后且IPv4首部中的首部长度字段长4位首部长度字段的单位是32位字因此IP首部的总长度为15个32位字60字节因此IPv4选项字段最长40字节。IPv4定义了10种不同的选项 1.NOPno-operation。单字节选项用途是为某个后续选项落在4字节边界上提供填充。 2.EOLend-of-list。单字节选项终止选项列表。既然各个IP选项的总长度必须是4字节的倍数因此最后一个有效选项后可能跟以0~3个EOL字节。 3.LSRRloose source and record route。 4.SSRRstrict source and record route。 5.Timestamp。 6.Record route。 7.Basic security已作废。 8.Extended security已作废。 9.Stream identifier已作废。 10.Router alert。它是在RFC 2113中叙述的一种选项所有转发数据报的路由器都应查看该选项。 RFC 1108给出了以上两种安全选项7和8的细节但它们没有得到广泛使用。 读取和设置IP选项字段使用getsockopt和setsockopt函数level参数为IPPROTO_IPoptname参数为IP_OPTIONS。这两个函数的第4个参数是指向某个缓冲区大小为44字节的一个指针第5个参数是该缓冲区的大小。该缓冲区大小可以比选项字段的最大长度多出4字节是由于源路径选项的处理方式稍后介绍。除了两种源路径选项外其他选项在该缓冲区中的格式就是把它们置于IP数据报中的格式。 使用setsockopt函数设置IP选项后相应套接字上发送的所有IP数据报都包含这些选项。可以在TCP、UDP、原始IP套接字上设置IP选项。清除这些选项同样使用setsockopt函数既可把第4个参数设为空指针也可把第5个参数设为0。 对于已经设置了IP_HDRINCL套接字选项的一个原始IP套接字并非所有实现都支持再为它设置IP选项。许多源自Berkeley的实现在IP_HDRINCL选项开启时不发送使用IP_OPTIONS设置的IP选项因为应用可能在它构造的IP首部中设置了它自己的IP选项其他系统如FreeBSD允许应用进程或使用IP_OPTIONS套接字选项设置IP选项或者通过开启IP_HDRINCL并在自己构造的IP首部中包括IP选项达到设置目的但不能混用两种方式。 当调用getsockopt获取由accept函数创建的某个已连接TCP套接字的IP选项时返回的是在相应监听套接字上收到的客户SYN分节所在IP数据报中可能出现的源路径选项的逆转源路径被TCP自动逆转顺序因为由客户指定的是从客户到服务器的源路径服务器需要在发送到客户的数据报中使用该路径的逆转如果没有源路径伴随SYN分节那么由getsockopt函数返回的第5个值-结果参数长度为0。对于所有其他TCP套接字、所有UDP套接字、原始IP套接字调用getsockopt获取IP选项返回的是以前对于同一个套接字调用setsockopt设置的IP选项的一个副本。对于一个原始IP套接字输入函数读函数总是返回包括IP选项在内的接收到的IP首部因此到达的IP选项总是可得的。 源自Berkeley的内核从不为UDP套接字返回所收取的源路径选项或其他任何IP选项TCPv2中所示的返回IP选项的代码从BSD 4.3 Reno以来一直存在但它一直被注释掉因为这段代码有问题是无效的这使得UDP接收进程不可能在发送响应IP数据报时使用接收路径的逆转。 许多源自Berkeley的内核在为原始IP套接字调用getsockopt或setsockopt时发生系统停机普通用户无法使用该手段攻击系统因为创建原始IP套接字要求具备超级用户权限而超级用户权限拥有者本就可以对系统进行更为恶意的活动。 源路径是由IP数据报的发送者指定的一个IP地址列表如果源路径是严格的那么数据报只能逐一经过所列的节点即列在源路径中的节点必须前后互为邻居如果源路径是宽松的那么数据报需要逐一经过所列节点但两个节点之间可经过其他节点。 IPv4的源路由是有争议的尽管它可能对网络排障非常有用但也可能用于源地址欺骗等攻击中。[ Cheswick, Bellovin, and Rubin 2003 ]倡议在所有路由器上禁用此特性许多组织机构和服务提供商也这么做了。源路由的合理用途之一是使用traceroute程序检测非对称的路径但随着因特网上越来越多的路由器禁用源路由这个用途也将消失。不论如何指定和收取源路径是套接字API的一部分。 IPv4源路径称为源和记录路径source and record routesSRR其中LSRR表示宽松的选项SSRR表示严格的选项因为随着数据报逐一经过所列的节点每个节点都把列在源路径中的自己的地址替换为外出接口的地址。SRR允许接收者逆转新的列表的顺序得到沿相反方向回到发送者的路径。 我们把源路径指定为一个IPv4地址数组并冠以3个单字节字段下图就是我们传递给setsockopt函数的缓冲区的格式 我们在源路径选项之前放置一个NOP选项使得所有IP地址在各自的4字节边界对齐这么做并非必须但这样做无须占用额外空间IP选项总是填充成4字节的倍数还对齐了地址。如果我们没有在缓冲区开始处放置一个NOP由于setsockopt函数设置IP_OPTIONS套接字选项时指定的缓冲区长度必须是4字节的倍数因此我们可以在缓冲区末尾放置一个EOL值为0的单个字节。 上图我们展示了源路径最多有10个IP地址但所列的第一个地址将在相应套接字的每个外出IP数据报即将离开源主机时被移出源路径选项并成为IP数据报的目的地址。40字节的IP选项空间只能存放9个IP地址还有3字节的选项首部所占空间。 code字段对于LSRR为0x83对于SSRR为0x89。len字段指定选项的字节长度包括3字节选项首部和处于末尾的额外的目的IP地址该地址不属于源路径由1个IP地址构成的源路径len为11由2个IP地址构成的源路径len为15以此类推直到由9个IP地址构成的源路径len为最大值43。上图中的NOP不属于SSR选项它自成一个单字节IP选项因此不包括在len字段的涵盖范围内但包含在给setsockopt函数指定的缓冲区大小中。当源路径地址列表中第一个地址被移走并置于IP首部的目的地址字段时这个len字段值减去4。ptr字段是一个指针即路径中下一个待处理IP地址的偏移量初始值为4表示指向第一个IP地址该字段值随IP数据报被每个所列节点处理而逐次加上4。 我们现在开发3个函数分别初始化、创建、处理一个源路径选项这些函数只处理源路径IP选项尽管源路径结合其他IP选项如路由器警告也是可能的以下是这3个函数其中两个的实现 #include unp.h #include netinet/in_systm.h #include netinet/ip.h// 用于构造内容的一些静态变量 static u_char *optr; /* pointer into options being formed */ static u_char *lenptr; /* pointer to length byte in SRR option */ static int ocnt; /* count of # addresses */// 函数inet_srcrt_init为构建一个源路径进行初始化 u_char *inet_srcrt_init(int type) {// 分配一个长44字节的缓冲区optr Malloc(44); /* NOP, code, len, ptr, up to 10 addresses */// EOL选项的值为0清零操作把整个选项缓冲区初始化为EOL字节bzero(optr, 44); /* guarantees EOLS at end */ocnt 0;*optr IPOPT_NOP; /* NOP for alignment */*optr type ? IPOPT_SSRR : IPOPT_LSRR;// 保存指向len字段的指针以后每往地址列表中加入一个地址就在该字段中存入新值lenptr optr; /* we fill in length later */*optr 4; /* offset to first address */// 把指向选项缓冲区的指针返回给调用者以便作为第4个参数传递给setsockopt函数return optr - 4; /* pointer for setsockopt() */ }// 向源路径中加入一个IPv4地址参数指向一个主机名或点分十进制数串IP地址 int inet_srcrt_add(char *hostptr) {int len;struct addrinfo *ai;struct sockaddr_in *sin;if (ocnt 9) {err_quit(too many source routes with: %s, hostptr);}// 调用自定义的host_serv函数转换主机名或点分十进制数串到二进制地址ai Host_serv(hostptr, NULL, AF_INET, 0);sin (struct sockaddr_in *)ai-ai_addr;// 把二进制地址存入地址列表memcpy(optr, sin-sin_addr, sizeof(struct in_addr));freeaddrinfo(ai);// 更新len字段值optr sizeof(struct in_addr);ocnt;len 3 (ocnt * sizeof(struct in_addr));*lenptr len;// 返回缓冲区总长度包括NOP以便调用者把该长度作为第5个参数传递给setsockopt函数return len 1; /* size for setsockopt() */ }以下是getsockopt函数返回给应用的接收到的源路径格式它不同于图27-1所示的发送源路径格式 返回给应用进程的地址顺序是所收取的源路径被内核逆转后的顺序如果收到的源路径按顺序包含A、B、C、D 4个地址该路径返回给应用的顺序即逆转后的顺序是D、C、B、A。如上图前4个字节是该列表的第一个IP地址即收到的源路径中的地址D后跟一个单字节NOP为了对齐再跟以3字节源路径选项首部最后再跟以其余的IP地址3字节选项首部后最多可跟以9个IP地址所返回首部中len字段的最大值为39。由于存在NOP做填充因此由getsockopt函数返回的长度总是4字节的倍数。 上图格式在netinet/ip_var.h头文件中定义为如下结构 以上getsockopt函数返回的源路径选项的结构不同于我们传递给setsockopt函数的格式如果要把图27-4中的格式转换为27-1中的格式我们需要对换头4个字节和随后4个字节再给len字段加4但我们并非必须这么做源自Berkeley的实现对于TCP套接字自动使用来自SYN所在IP数据报的接收源路径的逆转即我们不必调用setsockopt告诉内核使用该路径发送相应TCP连接上的外出IP数据报内核会自动这么做图27-4展示的由getsockopt函数返回的源路径信息纯粹用于了解目的。 以下函数显示一个接收到的源路径 void inet_srcrt_print(u_char *ptr, int len) {u_char c;char str[INET_ADDRSTRLEN];struct in_addr hop1;// 保存缓冲区中的第1个IP地址memcpy(hop1, ptr, sizeof(struct in_addr));ptr sizeof(struct in_addr);// 跳过后续的NOPwhile ((c *ptr) IPOPT_NOP); /* skip any leading NOPs */if (c IPOPT_LSRR) {printf(received LSRR: );} else if (c IPOPT_SSRR) {printf(received SSRR: );} else {printf(received option type %s\n, c);return;}printf(%s , Inet_ntop(AF_INET, hop1, str, sizeof(str)));// 不显示末尾的那个目的IP地址len *ptr - sizeof(struct in_addr); /* subtract dest IP addr */ptr; /* skip over pointer */while (len 0) {printf(%s , Inet_ntop(AF_INET, ptr, str, sizeof(str)));ptr sizeof(struct in_addr);len - sizeof(struct in_addr);}printf(\n); }修改TCP回射客户程序为指定一个源路径修改TCP回射服务器程序为显示一个接收源路径 #include unp.hint main(int argc, char **argv) {int c, sockfd, len 0;u_char *ptr NULL;struct addrinfo *ai;if (argc 2) {err_quit(usage: tcpcli01 [ -[gG] hostname ... ] hostname);}opterr 0; /* dont want getopt() writing to stderr */while ((c getopt(argc, argv, gG)) ! -1) {switch (c) {case g: /* loose source route */if (ptr) {err_quit(cant use both -g and -G);}// 初始化源路径ptr inet_srcrt_init(0);break;case G: /* strict source route */if (ptr) {err_quit(cant use both -g and -G);}// 初始化源路径ptr inet_srcrt_init(1);break;case ?:err_quit(unrecognized option: %c, c);}}// 如果初始化成功ptr不为空if (ptr) {// 把命令行指定的每个中间地址加到源路径中while (optind argc - 1) {len inet_srcrt_add(argv[optind]);}// 否则如果剩余命令行参数不止一个意味着用户指定了路径却没有指定其类型显示错误消息并退出} else if (optind argc - 1) {err_quit(need -g or -G to specify route);}// 最后一个参数是服务器主机的主机名或点分十进制数串地址if (optind ! argc - 1) {err_quit(missing hostname);}ai Host_serv(argv[optind], SERV_PORT_STR, AF_INET, SOCK_STREAM);sockfd Socket(ai-ai_family, ai-ai_socktype, ai-ai_protocol);// 如果用户指定了源路径我们需要把服务器的IP地址加到地址列表末尾if (ptr) {len inet_srcrt_add(argv[optind]); /* dest at end */// 设置外出分节的IP首部选项字段Setsockopt(sockfd, IPPROTO_IP, IP_OPTIONS, ptr, len);free(ptr);}// connect函数将发起三路握手我们期望SYN分节所在初始外出分组和后续外出分组都使用此源路径Connect(sockfd, ai-ai_addr, ai-ai_addrlen);str_cli(stdin, sockfd); /* do it all */exit(0); }而TCP服务器程序几乎等同于第五章中的版本只有两处改动首先为IP选项分配空间 int len; u_char *opts;opts Malloc(44);然后在调用accept后调用fork前获取并显示IP选项 len 44; Getsockopt(connfd, IPROTO_IP, IP_IPTIONS, opts, len); if (len 0) {printf(received IP options, len %d\n, len);inet_srcrt_print(opts, len); }如果所收取的来自客户SYN分节所在IP数据报中不包含IP选项则由getsockopt函数返回的len变量结果将是0len是一个值-结果参数。为了使用所收取源路径的逆转作为回送数据报的选项我们不必做任何事这是由内核自动完成的。我们调用getsockopt只是为了获取逆转后的接收源路径的一个副本如果不希望TCP使用此路径我们可在accept函数返回后通过指定第5个参数长度为0调用setsockopt从而去除当前正在用的IP选项。TCP已在三路握手的第二个分节所在IP数据报中使用接收源路径的逆转但我们可以在accept函数返回后去除这些选项去除后相应TCP连接中以后发送到客户的分组将由客户IP地址确定外出路径。 运行以上指定源路径的回射客户和服务器程序我们在主机freebsd4上按以下方式运行客户 该命令导致IP数据报从freebsd4转发到macosx再转发回freebsd4最后到达服务器主机macosx。macosx和freebsd4必须进行适当配置以接受并转发源路由的数据报从而使本例工作。 连接建立时服务器的输出如下 172.24.37.94是freebsd4的IP172.24.37.78是macosx的IP可见显示的第一个IP地址是逆转路径的第一跳。 如果上例使用-G代替-g则不会有任何变化因为上例中所有系统都是邻居因此严格的源路径等同于宽松的源路径。 不幸的是IP_OPTIONS套接字选项的操作从未有过正式文档因此在不是源自Berkeley源代码的系统上可能会有变化例如Solaris 2.5上由getsockopt函数返回的缓冲区的头部地址不是反转路径的第一跳的地址而是对端主机的地址但TCP使用的逆转路径仍是正确的。另外Solaris 2.5总是在源路径选项前填充4个NOP从而限制源路径最多有8个地址而非9个。 但源路径对于单纯使用源IP地址进行认证的服务器程序来说存在一个安全漏洞如果某个黑客作为客户发送的分组以一个受服务器信任的地址作为源地址又把本地地址包括在源路径中那么由服务器使用逆转后的接收源路径返回的分组将无需经过列在源路径中的所有节点就到达黑客的本地主机。从Net/1版本一个早期的Unix操作系统版本开始rlogind和rshd这两个服务器程序就有了如下类似代码 u_char buf[44]; char lbuf[BUFSIZ]; int optsize;optsize sizeof(buf); // 如果到达的已完成连接含有IP选项即getsockopt函数返回的optsize不为0 if (getsockopt(0, IPPROTO_IP, IP_OPTIONS, buf, optsize) 0 optsize ! 0) {/* format the options as hex numbers to print in lbuf[] */// 使用syslog函数登记一条消息syslog(LOG_NOTICE, Connection received using IP options (ignored): %s, lbuf);// 调用setsockopt去除选项防止该连接上以后发送的TCP分节使用接收源路径的逆转实际由承载TCP分节的IP数据报使用setsockopt(0, IPPROTO_IP, IP_OPTIONS, NULL, 0); }以上代码中清除源路径选项的代码曾经是这样的 optsize 0; setsockopt(0, IPPROTO_IP, IP_OPTIONS, NULL, optsize);区别在于第5个参数是指向长度的指针而非长度本身这是一个bug它可能在开始使用ANSI C原型时被修复但这个bug是无害的因为禁止IP_OPTIONS套接字选项既可指定一个空指针作为第4个参数也可使用0值作为第5个参数。 以上代码中getsockopt和setsockopt函数的描述符参数为0这是由于rlogind是由inetd派生的而描述符0正是通往客户的套接字。 以上代码所用技巧是不充分的因为到应用进程接受该连接前TCP三路握手已经完成而三路握手的第二个分节已经沿所收取源路径的逆转回到客户或回到了列在源路径中的某个黑客所在的中间节点既然黑客已经看到两个方向上的TCP序列号即使来自服务器的后续分组不再使用源路径发送黑客仍能够以正确的序列号向服务器发送分组。 解决以上问题的唯一方法是当使用源IP地址进行某种形式的认证时禁止使用源路径到达的所有TCP连接。在以上给出的代码中把setsockopt函数替换为关闭刚接受的连接并终止新派生的服务器这样尽管三路握手的第二个分节已经送出但连接不会仍然打开着。 IPv6首部后可跟如下几种可选的扩展首部 1.步跳选项hop_by_hop options。如果有此选项它必须紧跟40字节的IPv6首部。目前没有定义可供应用程序使用的此类选项。 2.目的地选项destination options。目前没有定义可供应用程序使用的此类选项。 3.路由首部routing header。类似于IPv4源路径选项。 4.分片首部fragmentation header。该首部由对IPv6数据报执行分片的主机自动产生然后由最终目的主机在重组片段时处理。 5.认证首部authentication headerAH。该首部用法在RFC 2402中说明。 6.安全净荷封装encapsulating security payloadESP。该首部用法在RFC 2406中说明。 其中分片首部完全由内核处理AH和ESP这两个首部可以由内核基于SADB和SPDB自动处理SADB和SPDB使用PF_KEY套接字维护第十九章。RFC 3542定义了指定和获取这些扩展首部的API。 步跳选项和目的地选项有类似的格式如下图 8位的下一个首部字段标识出跟在本扩展首部之后的下一个扩展首部。8位的首部扩展长度字段是本扩展首部的长度以8字节为单位但不包括它自己例如如果本扩展首部不包含下一个首部字段占8字节其首部扩展长度字段值就为0如果本扩展首部占16字节其首部扩展长度字段值就为1。这两种首部都被填充成8字节的整数倍所用填充方式有两种pad1和padN。 步跳选项首部和目的地选项首部都容纳任意数量的个体选项个体选项的格式如下 个体选项的编排格式称为TVL编码因为每个个体选项都由类型type、长度length、值value三个字段组成。8位的类型字段标识选项的类型此外该字段的高2位指定IPv6节点在不理解本选项时如何处理它 1.00跳过本个体选项继续处理本首部。 2.01丢弃本分组。 3.10丢弃本分组且不论本分组的目的地址是否为一个多播地址均发送一个ICMPv6错误给发送者ICMPv6消息类型为4代码为2下图是部分ICMPv6消息 4.11丢弃本分组且只有当本分组的目的地址不是多播地址时发送一个ICMPv6错误给发送者ICMPv6消息类型为4代码为2。 下一个高序位第3高序位指定本个体选项的数据在途中是否会有变化 1.0选项数据在途中无变化。 2.1选项数据在途中可能变化。 低序5位指定选项本身但低序5位不能标识一个选项而是需要由高序3位共同标识尽管如此类型字段的赋值仍尽可能保持低序5位的唯一性。 8位的长度字段指定个体选项数据字段的字节长度类型字段和本长度字段不计算在内。 pad1和padN两种填充方式定义在RFC 2460中在步跳选项首部和目的地选项首部中都可使用。特大净荷长度是一个步跳选项定义在RFC 2675中它完全由内核在需要时产生在收到时处理。路由器告警也是一个步跳选项它定义在RFC 2711中类似于IPv4的路由器告警。下图展示了这些选项 pad1选项是唯一没有长度和值字段的选项它提供1字节的填充。padN选项用于需要2个或多个字节填充的场合对于2字节填充本选项的长度字段为0整个选项只由类型和长度这两个字段构成对于3字节填充本选项的长度字段值为1后跟1字节的0值。特大净荷长度选项提供一个32位的数据报长度用于展示16位净荷长度字段不够大的场合。路由器告警选项指示本分组应由沿途路由器截取其值指出哪些路由器需关注本分组。 我们展示以上选项的原因在于每个步跳选项和目的地选项都有一个对齐要求可用xny表示含义为这个个体选项必须出现在距离所在扩展首部开始处x字节整数倍加y字节的位置例如特大净荷长度选项的对齐要求是4n2该要求迫使4字节的选项值处于某个4字节边界y值取2是因为在选项值字段之前有各1字节的类型字段和长度字段。路由器告警选项的对齐要求是2n0该要求迫使2字节的选项值处于某2字节边界。 步跳选项和目的地选项通常作为辅助数据通过sendmsg函数指定并由recvmsg函数作为辅助数据返回。进程无需为发送这两类选项做任何特别之事只需在某个sendmsg调用中指定它们。为了接收这两类选项应用必须开启对应的套接字选项步跳选项对应IPV6_RECVHOPOPTS目的地选项对应IPV6_RECVDSTOPTS。允许这两类选项都返回的代码如下 const int on 1;setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVHOPOPTS, on, sizeof(on)); setsockopt(sockfd, IPOROTO_IPV6, IPV6_RECVDSTOPTS, on, sizeof(on));下图展示了用于发送和接收步跳选项和目的地选项的辅助数据对象的格式 这两类选项首部的实际内容作为辅助数据对象的cmsg_data部分在进程和内核之间传递为了避免直接定义上图内容相关API定义了7个用于创建和处理这些辅助数据对象数据部分的函数。以下4个函数用于构造待发送的选项 inet6_opt_init函数返回容纳一个空扩展首部即没有任何选项的首部所需的字节数如果extbuf参数非空会在其指向的缓冲区中初始化这个扩展首部此时如果extlen参数不是8的倍数所有IPv6步跳和目的地选项扩展首部必须是8的倍数inet6_opt_init函数会返回-1。 inet6_opt_append函数返回添加指定的个体选项后的扩展首部总长度如果extbuf参数非空本函数会初始化该个体选项并按对齐要求插入必要的填充如果所提供的的缓冲区放不下新选项它就失败返回-1。offset参数是当前extbuf参数指向的缓冲区中扩展首部的总长度该值必须是先前某个inet6_opt_init或inet6_opt_append调用的返回值。type和len参数分别指定了选项的类型和长度并被直接复制到选项首部中。align参数指定对齐要求即xny中的x值而y值可由align参数和len参数算出不用显式指定。databufp参数用于返回指向所添加选项值的填写位置的指针调用者随后可使用inet6_opt_set_val函数或其他方法往这个位置复制选项值。 inet6_opt_finish函数用于结束一个扩展首部的设置添加任何必要的填充使得总长度为8字节的倍数。如果extbuf参数非空就把填充真正插入缓冲区中否则只是计算并返回新的总长度。offset参数是当前extbuf参数指向的缓冲区中扩展首部的总长度该值必须是先前某个inet6_opt_init或inet6_opt_append调用的返回值。本函数返回已完成设置的扩展首部总长度但如果所提供的缓冲区放不下所需的填充则返回-1。 inet6_opt_set_val函数用于把给定的选项值复制到由inet6_opt_addend函数返回的数据缓冲区中。databuf参数是由inet6_opt_addend函数返回的指针。offset参数指定选项值要插入到缓冲区中的位置该参数是前一个inet6_opt_set_val函数的返回值首次调用时该参数必须初始化为0。参数val和valen用于指定复制到选项值缓冲区中的值。 以上4个函数的期望用法是遍历两趟待添加的个体选项列表第一趟用于计算预期的长度第二趟用于把各个选项实际构造到大小合适的缓冲区中。两趟都是先调用inet6_opt_init再为每个待添加的选项调用一次inet6_opt_append最后以调用inet6_opt_finish结束。第一趟中传递给extbuf和extlen参数的值分别为NULL和0。第一趟结束后使用由inet6_opt_finish函数返回的大熊动态分配用于存放选项扩展首部的缓冲区第二趟中就使用指向该缓冲区的一个指针及该缓冲区长度作为extbuf和extlen参数的值。第二趟中每个选项的值或者手动复制或者调用inet6_opt_set_val复制。我们也可预先分配一个足够大的缓冲区从而省略掉第一趟但缓冲区的大小有时不易预估省略第一趟时有可能导致第二趟失败。 以下函数用于处理所接收的选项 inet6_opt_next函数处理某缓冲区中的下一个选项。extbuf和extlen参数用于指定存放扩展首部的缓冲区。offset参数是当前extbuf参数指向的缓冲区中当前处理到的选项偏移与inet6_opt_append函数的offset函数类似首次调用本函数时应将offset参数指定为0后续调用就使用前一个调用的返回值。typep、lenp、databufp参数分别用于返回当前处理到的选项的类型、长度、值。如果缓冲区中内容不符合选项扩展首部格式或已经到达该缓冲区末尾函数就返回-1。 inet6_opt_find函数类似inet6_opt_next函数但让调用者指定待搜索的选项类型type参数。 inet6_opt_get_val函数从databuf参数指定的某个选项中获取值有些选项值中有多个字段。databuf参数是由inet6_opt_next或inet6_opt_find函数返回的databufp参数指针。offset参数类似inet_6_opt_next函数首次调用时需要用0作为参数值后续调用使用前一个调用的返回值作为offset参数。 IPv6路由首部用于IPv6的源路由 下一个首部和首部扩展长度字段与图27-7中的含义相同。路由类型字段当前只定义了一种类型它的此字段值为0。剩余网段字段是所列节点中还有几个需要拜访即尚未路由到。 路由首部中可以出现的地址数目仅受限于分组允许长度等外在因素剩余网段字段的值必须小于等于所列的地址数目。RFC 2460说明了一个具有路由首部的分组在发送到最终目的地的过程中各个途径节点如何处理该路由首部的具体细节。 路由首部通常作为辅助数据由sendmsg函数指定并由recvmsg函数作为辅助数据返回。应用发送此首部时需要做的仅仅是在某个sendmsg调用中指定它。为了接收路由首部应用进程需要开启IPV6_RECVRTHDR套接字选项 const int on 1; setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVRTHDR, on, sizeof(on));用于发送和接收路由首部的辅助数据对象的格式 相关API为创建和处理路由首部定义了6个函数以下3个函数用于构造待发送的路由首部 inet6_rth_space函数返回容纳一个类型为type参数该参数通常为IPV6_RTHDR_TYPE_0网段总数为segments参数值的路由首部所需的字节数。 inet6_rth_init函数初始化由rthbuf参数指向的缓冲区以容纳一个类型为type参数值网段总数为segments参数值的路由首部。返回值是指向该缓冲区的指针但如果发生错误如所提供的缓冲区不够大则为空指针。非空指针的返回值用作inet6_rth_add函数的第1个参数。 inet6_rth_add函数把addr参数指向的IPv6地址加到构建中的路由首部的末尾调用成功时该路由首部的剩余网段字段会被更新为新的地址数目。 以下3个函数用于处理所接收的路由首部 inet6_rth_reverse函数的in参数所指缓冲区中存放的是某个接收路由首部本函数将该路由首部逆转并存放在由out参数所指的缓冲区中以便接收进程沿逆转的路径发送回数据报。in和out参数可以指向同一个缓冲区即原地逆转。 inet6_rth_segments函数返回由rhbuf所指路由首部中的网段数目调用成功时返回值应大于0。 inet6_rth_getaddr函数用于返回由rthbuf参数所指的路由首部中索引号为index的那个IPv6地址返回值是指向该地址所在位置的指针。index参数的值必须在0和inet6_rth_segments函数的返回值减去1为界限的闭区间内。 为展示IPv6路由首部的用法我们编写一对UDP客户程序和服务器程序客户程序从命令行接受一个源路径服务器程序显示所接收IPv6数据报的接收源路径再把该数据报沿接收源路径的逆转发送回客户。以下是客户程序 #include unp.hint main(int argc, char **argv) {int sockfd, len 0;u_char *ptr NULL;struct addrinfo *ai;if (argc 2) {// 如果提供的主机名参数不止一个那么源路径由除最后一个之外的所有参数构成err_quit(usage: udpcli01 [ hostname ... ] hostname);}if (argc 2) {int i;// 首先调用inet6_rth_space确定创建路由首部需要多大空间len Inet6_rth_space(IPV6_RTHDR_TYPE_0, argc - 2);// 分配所需空间ptr Malloc(len);// 初始化所分配的缓冲区Inet6_rth_init(ptr, len, IPV6_RTHDR_TYPE_0, argc - 2);for (i 1; i argc - 1; i) {// 对源路径中每个地址先调用host_serv把它转换成in6_addr结构ai Host_serv(argv[i], NULL, AF_INET6, 0);// 把该源路径添加到构建中的源路径中Inet6_rth_add(ptr, ((struct sockaddr_in6 *)ai-ai_addr)-sin6_addr);}}// 获取目的主机名的套接字地址结构ai Host_serv(argv[argc - 1], SERV_PORT_STR, AF_INET6, SOCK_DGRAM);sockfd Socket(ai-ai_family, ai-ai_socktype, ai-ai_protocol);if (ptr) {// 通过设置IPV6_RTHDR套接字选项可以把一个路由首部应用于从某个套接字发送的所有分组// 以取代为每个分组发送同样的辅助数据的做法Setsockopt(sockfd, IPPROTO_IPV6, IPV6_RTHDR, ptr, len);free(ptr);}dg_cli(stdin, sockfd, ai-ai_addr, ai-ai_addrlen); /* do it all */exit(0); }服务器程序比较简单它打开一个UDP套接字并调用dg_echo我们不给出其main函数但给出它调用的dg_echo函数版本该函数如果收到一个携带源路径的分组就打印这个源路径并逆转它用于回射该分组 #include unp.hvoid dg_echo(int sockfd, SA *pcliaddr, socklen_t clilen) {int n;char mesg[MAXLINE];int on;char control[MAXLINE];struct msghdr msg;struct cmsghdr *cmsg;struct iovec iov[1];// 为接收外来源路径必须开启IPV6_RECVRTHDR套接字选项on 1;Setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVRTHDR, on, sizeof(on));// 设置用于接收外来源路径的msghdr结构中不变的字段bzero(msg, sizeof(msg));iov[0].iov_base mesg;msg.msg_name pcliaddr;msg.msg_iov iov;msg.msg_iovlen 1;msg.msg_control control;for (; ; ) {// msghdr结构中的以下3项会被recvmsg函数修改每次调用recvmsg前重置它们msg.msg_namelen clilen;msg.msg_controllen sizeof(control);iov[0].iov_len MAXLINE;n Recvmsg(sockfd, msg, 0);// 遍历辅助数据以寻找路由首部for (cmsg CMSG_FIRSTHDR(msg); cmsg ! NULL; cmsg CMSG_NXTHDR(msg, cmsg)) {if (cmsg-cmsg_level IPPROTO_IPV6 cmsg-cmsg_type IPV6_RTHDR) {// 调用inet6_srcrt_print打印接收到的源路径inet6_srcrt_print(CMSG_DATA(cmsg));// 逆转接收到的源路径以便沿同样的路径返送所接收的分组此处原地逆转路径Inet6_rth_reverse(CMSG_DATA(cmsg), CMSG_DATA(cmsg));}}// 设置回送数据的长度然后回射所接收的分组iov[0].iov_len n;Sendmsg(sockfd, msg, 0);} }inet6_srcrt_print函数 #include unp.hvoid inet6_srcrt_print(void *ptr) {int i, segments;char str[INET6_ADDRSTRLEN];// 调用inet6_rth_segments确定源路径中存在的网段数segments Inet6_rth_segments(ptr);printf(received source route: );for (i 0; i segments; i) {// 调用inet_ntop把IP地址从网络字节序in6_addr结构转换为点分十进制格式printf(%s , Inet_ntop(AF_INET6, Inet6_rth_getaddr(ptr, i), str, sizeof(str)));}printf(\n); }处理IPv6原路径的客户和服务器程序无需了解源路径在分组中是如何格式化的API提供的库函数隐藏了分组格式的细节。 我们已经讲解了sendmsg和recvmsg函数发送和接收的7种IPv6辅助数据对象 1.IPv6分组信息in6_pktinfo结构或者包含目的地址和外出接口索引或者包含源地址和到达接口索引。第二十二章 2.外出跳限或接收跳限。第二十二章 3.下一跳地址。只能发送不能接受。第二十二章 4.外出流通类别或接收流通类别。第二十二章 5.步跳选项。第二十七章 6.目的地选项。第二十七章 7.路由首部。第二十七章 这些辅助数据对象可通过设置相应的套接字选项使得从某个套接字发送的所有分组都使用相同的辅助数据值这些套接字选项所用常值与辅助数据对象一致即调用setsockopt的level参数总是IPPROTO_IPV6选项名参数按以上IPv6辅助数据列出的顺序分别为IPV6_PKTINFO、IPV6_HOPLIMIT、IPV6_NEXTHOP、IPV6_TCLASS、IPV6_HOPOPTS、IPV6_DSTOPTS、IPV6_RTHDR。对于UDP套接字和原始IPv6套接字我们可以通过在sendmsg调用中指定相应辅助数据使得针对每个分组覆写这些粘附性选项。 粘附性选项的概念也适用于TCP由于TCP套接字上不能使用sendmsg或recvmsg函数发送或接收辅助数据可通过设置相应套接字选项指定辅助数据对象这些对象随后影响在相应套接字上发送的所有分组。但如果某个分组需要重传且发送原分组和重传的分组之间粘附性选项的设置发生变更那么重传的分组上的粘附性选项既可能是旧的也可能是新的。 希望在某个套接字上调用recvmsg接收辅助数据的进程必须预先在该套接字上开启相应的套接字选项选项名参数按以上IPv6辅助数据列出的顺序跳过了下一跳地址选项因为该选项不能接收只能发送分别为IPV6_RECVPKTINFO、IPV6_RECVHOPLIMIT、IPV6_RECVTCLASS、IPV6_RECVHOPOPTS、IPV6_RECVDSTOPTS、IPV6_RECVRTHDR。TCP应用也能使用同样的方式获取这些辅助数据对象但TCP套接字上不能使用recvmsg函数与用户数据一道接收辅助数据由recvmsg函数返回的这些粘附性选项实际来自最近收取的分节所在IPv6分组这些选项除非对端TCP修改过否则所有IPv6分组都具有相同的选项。 RFC 2292定义了本章中IPv6 API的一个早期版本。 ping程序会创建一个原始套接字能通过recvfrom函数读入每个数据报的完整IP首部。
http://mrfarshtey.net/news/52166/

相关文章:

  • 音乐主题资源网站建设附子seo
  • 潍坊做网站价格国产手机做系统下载网站
  • 金华网站建设制作seo刷排名工具
  • 网站建设服务器的搭建方式网站开发文件夹组织结构
  • 专业做互联网招聘的网站有哪些网站排名下降
  • 三角镇建网站公司wordpress自定义导航
  • 设计素材网站会员哪个最好学历提升文案
  • 网站类型定位做网站的广告语
  • 织梦网站怎么上传怎样给公司做一个网站做推广
  • c#网站开发框架有企业网站程序源码
  • 做图片的网站遵义网络科技公司
  • 网站开发的经验建筑人才市场职称评审
  • 响应式网站开发要注意哪些wordpress 附件 标签
  • 张家港网站 设计制作做网站要不要营业执照
  • 商城网站建设哪家公司好云南网络公司排名
  • 网站开发工资一般多少钱小程序商城怎么开通
  • 泉州网站建设技术公司推广联盟有哪些平台
  • 深圳网站优化课程哪里学网架报价明细表
  • 常州seo博客宁波品牌网站推广优化
  • 如何修改wordpress站名老闵行租房
  • 上海做网站比较好的公司有哪些二次元WordPress
  • 多语种网站营销网站管理设置
  • 网站推广效果怎么样佐力药业股票千股千评
  • 升阳广州做网站公司云南建设学校网站
  • 建设银行网站上改手机号码游戏推广方案
  • 微网站 建设株洲企业网站建设费用
  • 广东建设工程注册执业中心网站东莞做网站的联系电
  • 东营网站seowordpress代码板插件下载
  • 哪个品牌网站设计感强做充气气模产品一般去哪些网站
  • 网站开发工程师需要会写什么区别网络规划设计师多少分通过