ALT Linux Bugzilla
– Attachment 2358 Details for
Bug 13916
ping6 & tracepath6 не работают даже от root
New bug
|
Search
|
[?]
|
Help
Register
|
Log In
[x]
|
Forgot Password
Login:
[x]
|
EN
|
RU
[patch]
fixing patch
iputils-20020927-alt-hoplimit.patch (text/plain), 34.36 KB, created by
Denis Ovsienko
on 2008-01-07 13:51:01 MSK
(
hide
)
Description:
fixing patch
Filename:
MIME Type:
Creator:
Denis Ovsienko
Created:
2008-01-07 13:51:01 MSK
Size:
34.36 KB
patch
obsolete
>diff -Nur iputils.p8/ping6.c iputils/ping6.c >--- iputils.p8/ping6.c 2008-01-07 13:24:25 +0300 >+++ iputils/ping6.c 2008-01-07 13:28:47 +0300 >@@ -486,7 +486,7 @@ > > if (1) { > int on = 1; >- if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_HOPLIMIT, >+ if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_2292HOPLIMIT, > &on, sizeof(on)) == -1) { > perror ("can't receive hop limit"); > exit(2); >@@ -704,7 +704,7 @@ > > for (c = CMSG_FIRSTHDR(msg); c; c = CMSG_NXTHDR(msg, c)) { > if (c->cmsg_level != SOL_IPV6 || >- c->cmsg_type != IPV6_HOPLIMIT) >+ c->cmsg_type != IPV6_2292HOPLIMIT) > continue; > if (c->cmsg_len < CMSG_LEN(sizeof(int))) > continue; >diff -Nur iputils.p8/ping6.c~ iputils/ping6.c~ >--- iputils.p8/ping6.c~ 1970-01-01 03:00:00 +0300 >+++ iputils/ping6.c~ 2008-01-07 13:24:25 +0300 >@@ -0,0 +1,922 @@ >+/* >+ * >+ * Modified for AF_INET6 by Pedro Roque >+ * >+ * <roque@di.fc.ul.pt> >+ * >+ * Original copyright notice included bellow >+ */ >+ >+/* >+ * Copyright (c) 1989 The Regents of the University of California. >+ * All rights reserved. >+ * >+ * This code is derived from software contributed to Berkeley by >+ * Mike Muuss. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * 3. All advertising materials mentioning features or use of this software >+ * must display the following acknowledgement: >+ * This product includes software developed by the University of >+ * California, Berkeley and its contributors. >+ * 4. Neither the name of the University nor the names of its contributors >+ * may be used to endorse or promote products derived from this software >+ * without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND >+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE >+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >+ * SUCH DAMAGE. >+ */ >+ >+#ifndef lint >+char copyright[] = >+"@(#) Copyright (c) 1989 The Regents of the University of California.\n\ >+ All rights reserved.\n"; >+#endif /* not lint */ >+ >+/* >+ * P I N G . C >+ * >+ * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility, >+ * measure round-trip-delays and packet loss across network paths. >+ * >+ * Author - >+ * Mike Muuss >+ * U. S. Army Ballistic Research Laboratory >+ * December, 1983 >+ * >+ * Status - >+ * Public Domain. Distribution Unlimited. >+ * Bugs - >+ * More statistics could always be gathered. >+ * This program has to run SUID to ROOT to access the ICMP socket. >+ */ >+#include "ping_common.h" >+#include "fixfds.h" >+#include "droppriv.h" >+ >+#include <linux/in6.h> >+#include <linux/ipv6.h> >+#include <linux/icmpv6.h> >+ >+#define BIT_CLEAR(nr, addr) do { ((__u32 *)(addr))[(nr) >> 5] &= ~(1U << ((nr) & 31)); } while(0) >+#define BIT_SET(nr, addr) do { ((__u32 *)(addr))[(nr) >> 5] |= (1U << ((nr) & 31)); } while(0) >+#define BIT_TEST(nr, addr) do { (__u32 *)(addr))[(nr) >> 5] & (1U << ((nr) & 31)); } while(0) >+ >+#define ICMPV6_FILTER_WILLPASS(type, filterp) \ >+ (BIT_TEST((type), filterp) == 0) >+ >+#define ICMPV6_FILTER_WILLBLOCK(type, filterp) \ >+ BIT_TEST((type), filterp) >+ >+#define ICMPV6_FILTER_SETPASS(type, filterp) \ >+ BIT_CLEAR((type), filterp) >+ >+#define ICMPV6_FILTER_SETBLOCK(type, filterp) \ >+ BIT_SET((type), filterp) >+ >+#define ICMPV6_FILTER_SETPASSALL(filterp) \ >+ memset(filterp, 0, sizeof(struct icmp6_filter)); >+ >+#define ICMPV6_FILTER_SETBLOCKALL(filterp) \ >+ memset(filterp, 0xFF, sizeof(struct icmp6_filter)); >+ >+ >+#define MAXPACKET 128000 /* max packet size */ >+ >+#ifdef SO_TIMESTAMP >+#define HAVE_SIN6_SCOPEID 1 >+#endif >+ >+ >+__u32 flowlabel; >+__u32 tclass; >+struct cmsghdr *srcrt; >+ >+struct sockaddr_in6 whereto; /* who to ping */ >+u_char outpack[MAXPACKET]; >+int maxpacket = sizeof(outpack); >+ >+static unsigned char cmsgbuf[4096]; >+static int cmsglen = 0; >+ >+static char * pr_addr(struct in6_addr *addr); >+static char * pr_addr_n(struct in6_addr *addr); >+static int pr_icmph(__u8 type, __u8 code, __u32 info); >+static void usage(void) __attribute((noreturn)); >+ >+struct sockaddr_in6 source; >+char *device; >+int pmtudisc=-1; >+ >+static int icmp_sock; >+ >+ >+ >+static struct in6_addr in6_anyaddr; >+static __inline__ int ipv6_addr_any(struct in6_addr *addr) >+{ >+ return (memcmp(addr, &in6_anyaddr, 16) == 0); >+} >+ >+size_t inet6_srcrt_space(int type, int segments) >+{ >+ if (type != 0 || segments > 24) >+ return 0; >+ >+ return (sizeof(struct cmsghdr) + sizeof(struct rt0_hdr) + >+ segments * sizeof(struct in6_addr)); >+} >+ >+extern struct cmsghdr * inet6_srcrt_init(void *bp, int type) >+{ >+ struct cmsghdr *cmsg; >+ >+ if (type) >+ return NULL; >+ >+ memset(bp, 0, sizeof(struct cmsghdr) + sizeof(struct rt0_hdr)); >+ cmsg = (struct cmsghdr *) bp; >+ >+ cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct rt0_hdr); >+ cmsg->cmsg_level = SOL_IPV6; >+ cmsg->cmsg_type = IPV6_RTHDR; >+ >+ return cmsg; >+} >+ >+int inet6_srcrt_add(struct cmsghdr *cmsg, const struct in6_addr *addr) >+{ >+ struct rt0_hdr *hdr; >+ >+ hdr = (struct rt0_hdr *) CMSG_DATA(cmsg); >+ >+ cmsg->cmsg_len += sizeof(struct in6_addr); >+ hdr->rt_hdr.hdrlen += sizeof(struct in6_addr) / 8; >+ >+ memcpy(&hdr->addr[hdr->rt_hdr.segments_left++], addr, >+ sizeof(struct in6_addr)); >+ >+ return 0; >+} >+ >+int main(int argc, char *argv[]) >+{ >+ int ch, hold, packlen; >+ u_char *packet; >+ char *target; >+ struct sockaddr_in6 firsthop; >+ int socket_errno; >+ struct icmp6_filter filter; >+ int err, csum_offset, sz_opt; >+ >+ fix_fds(); >+ >+ icmp_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); >+ socket_errno = errno; >+ >+ drop_priv(); >+ >+ source.sin6_family = AF_INET6; >+ memset(&firsthop, 0, sizeof(firsthop)); >+ firsthop.sin6_family = AF_INET6; >+ >+ preload = 1; >+ while ((ch = getopt(argc, argv, COMMON_OPTSTR "F:")) != EOF) { >+ switch(ch) { >+ case 'F': >+ sscanf(optarg, "%x", &flowlabel); >+ options |= F_FLOWINFO; >+ break; >+ case 'Q': >+ sscanf(optarg, "%x", &tclass); >+ options |= F_TCLASS; >+ break; >+ case 'I': >+ if (strchr(optarg, ':')) { >+ if (inet_pton(AF_INET6, optarg, (char*)&source.sin6_addr) <= 0) { >+ fprintf(stderr, "ping: invalid source address %s\n", optarg); >+ exit(2); >+ } >+ options |= F_STRICTSOURCE; >+ } else { >+ device = optarg; >+ } >+ break; >+ case 'M': >+ if (strcmp(optarg, "do") == 0) >+ pmtudisc = IPV6_PMTUDISC_DO; >+ else if (strcmp(optarg, "dont") == 0) >+ pmtudisc = IPV6_PMTUDISC_DONT; >+ else if (strcmp(optarg, "want") == 0) >+ pmtudisc = IPV6_PMTUDISC_WANT; >+ else { >+ fprintf(stderr, "ping: wrong value for -M: do, dont, want are valid ones.\n"); >+ exit(2); >+ } >+ break; >+ case 'V': >+ printf("ping6 utility, iputils-ss%s\n", SNAPSHOT); >+ exit(0); >+ COMMON_OPTIONS >+ common_options(ch); >+ break; >+ default: >+ usage(); >+ } >+ } >+ argc -= optind; >+ argv += optind; >+ >+ while (argc > 1) { >+ struct in6_addr addr; >+ >+ if (srcrt == NULL) { >+ int space; >+ >+ space = inet6_srcrt_space(IPV6_SRCRT_TYPE_0, argc - 1); >+ >+ if (space == 0) { >+ fprintf(stderr, "srcrt_space failed\n"); >+ exit(2); >+ } >+ if (space + cmsglen > sizeof(cmsgbuf)) { >+ fprintf(stderr, "no room for options\n"); >+ exit(2); >+ } >+ >+ srcrt = (struct cmsghdr*)(cmsgbuf+cmsglen); >+ cmsglen += CMSG_ALIGN(space); >+ inet6_srcrt_init(srcrt, IPV6_SRCRT_TYPE_0); >+ } >+ >+ target = *argv; >+ >+ if (inet_pton(AF_INET6, target, &addr) <= 0) { >+ struct hostent *hp; >+ >+ hp = gethostbyname2(target, AF_INET6); >+ >+ if (hp == NULL) { >+ fprintf(stderr, "unknown host %s\n", target); >+ exit(2); >+ } >+ >+ memcpy(&addr, hp->h_addr_list[0], 16); >+ } >+ >+ inet6_srcrt_add(srcrt, &addr); >+ if (ipv6_addr_any(&firsthop.sin6_addr)) >+ memcpy(&firsthop.sin6_addr, &addr, 16); >+ >+ argv++; >+ argc--; >+ } >+ >+ if (argc != 1) >+ usage(); >+ target = *argv; >+ >+ memset(&whereto, 0, sizeof(struct sockaddr_in6)); >+ whereto.sin6_family = AF_INET6; >+ whereto.sin6_port = htons(IPPROTO_ICMPV6); >+ >+ if (inet_pton(AF_INET6, target, &whereto.sin6_addr) <= 0) { >+ struct hostent *hp; >+ >+ hp = gethostbyname2(target, AF_INET6); >+ >+ if (hp == NULL) { >+ fprintf(stderr, "unknown host\n"); >+ exit(2); >+ } >+ >+ memcpy(&whereto.sin6_addr, hp->h_addr_list[0], 16); >+ } else { >+ options |= F_NUMERIC; >+ } >+ if (ipv6_addr_any(&firsthop.sin6_addr)) >+ memcpy(&firsthop.sin6_addr, &whereto.sin6_addr, 16); >+ >+ hostname = target; >+ >+ if (ipv6_addr_any(&source.sin6_addr)) { >+ int alen; >+ int probe_fd = socket(AF_INET6, SOCK_DGRAM, 0); >+ >+ if (probe_fd < 0) { >+ perror("socket"); >+ exit(2); >+ } >+ if (device) { >+ struct ifreq ifr; >+ memset(&ifr, 0, sizeof(ifr)); >+ strncpy(ifr.ifr_name, device, IFNAMSIZ-1); >+ if (setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1) == -1) { >+#ifdef HAVE_SIN6_SCOPEID >+ if ((firsthop.sin6_addr.s6_addr16[0]&htons(0xffc0)) == htons (0xfe80) || >+ (firsthop.sin6_addr.s6_addr16[0]&htons(0xffff)) == htons (0xff02)) { >+ if (ioctl(probe_fd, SIOCGIFINDEX, &ifr) < 0) { >+ fprintf(stderr, "ping: unknown iface %s\n", device); >+ exit(2); >+ } >+ firsthop.sin6_scope_id = ifr.ifr_ifindex; >+ } >+#endif >+ } >+ } >+ firsthop.sin6_port = htons(1025); >+ if (connect(probe_fd, (struct sockaddr*)&firsthop, sizeof(firsthop)) == -1) { >+ perror("connect"); >+ exit(2); >+ } >+ alen = sizeof(source); >+ if (getsockname(probe_fd, (struct sockaddr*)&source, &alen) == -1) { >+ perror("getsockname"); >+ exit(2); >+ } >+ source.sin6_port = 0; >+ close(probe_fd); >+ } >+ >+ if (icmp_sock < 0) { >+ errno = socket_errno; >+ perror("ping: icmp open socket"); >+ exit(2); >+ } >+ >+ if (device) { >+ struct ifreq ifr; >+ struct cmsghdr *cmsg; >+ struct in6_pktinfo *ipi; >+ >+ memset(&ifr, 0, sizeof(ifr)); >+ strncpy(ifr.ifr_name, device, IFNAMSIZ-1); >+ if (ioctl(icmp_sock, SIOCGIFINDEX, &ifr) < 0) { >+ fprintf(stderr, "ping: unknown iface %s\n", device); >+ exit(2); >+ } >+ cmsg = (struct cmsghdr*)cmsgbuf; >+ cmsglen += CMSG_SPACE(sizeof(*ipi)); >+ cmsg->cmsg_len = CMSG_LEN(sizeof(*ipi)); >+ cmsg->cmsg_level = SOL_IPV6; >+ cmsg->cmsg_type = IPV6_PKTINFO; >+ >+ ipi = (struct in6_pktinfo*)CMSG_DATA(cmsg); >+ memset(ipi, 0, sizeof(*ipi)); >+ ipi->ipi6_ifindex = ifr.ifr_ifindex; >+ } >+ >+ if ((whereto.sin6_addr.s6_addr16[0]&htons(0xff00)) == htons (0xff00)) { >+ if (uid) { >+ if (interval < 1000) { >+ fprintf(stderr, "ping: multicast ping with too short interval.\n"); >+ exit(2); >+ } >+ if (pmtudisc >= 0 && pmtudisc != IPV6_PMTUDISC_DO) { >+ fprintf(stderr, "ping: multicast ping does not fragment.\n"); >+ exit(2); >+ } >+ } >+ if (pmtudisc < 0) >+ pmtudisc = IPV6_PMTUDISC_DO; >+ } >+ >+ if (pmtudisc >= 0) { >+ if (setsockopt(icmp_sock, SOL_IPV6, IPV6_MTU_DISCOVER, &pmtudisc, sizeof(pmtudisc)) == -1) { >+ perror("ping: IPV6_MTU_DISCOVER"); >+ exit(2); >+ } >+ } >+ >+ if ((options&F_STRICTSOURCE) && >+ bind(icmp_sock, (struct sockaddr*)&source, sizeof(source)) == -1) { >+ perror("ping: bind icmp socket"); >+ exit(2); >+ } >+ >+ if (datalen >= sizeof(struct timeval)) /* can we time transfer */ >+ timing = 1; >+ packlen = datalen + 8 + 4096 + 40 + 8; /* 4096 for rthdr */ >+ if (!(packet = (u_char *)malloc((u_int)packlen))) { >+ fprintf(stderr, "ping: out of memory.\n"); >+ exit(2); >+ } >+ >+ working_recverr = 1; >+ hold = 1; >+ if (setsockopt(icmp_sock, SOL_IPV6, IPV6_RECVERR, (char *)&hold, sizeof(hold))) { >+ fprintf(stderr, "WARNING: your kernel is veeery old. No problems.\n"); >+ working_recverr = 0; >+ } >+ >+ /* Estimate memory eaten by single packet. It is rough estimate. >+ * Actually, for small datalen's it depends on kernel side a lot. */ >+ hold = datalen+8; >+ hold += ((hold+511)/512)*(40+16+64+160); >+ sock_setbufs(icmp_sock, hold); >+ >+ csum_offset = 2; >+ sz_opt = sizeof(int); >+ >+ err = setsockopt(icmp_sock, SOL_RAW, IPV6_CHECKSUM, &csum_offset, sz_opt); >+ if (err < 0) { >+ perror("setsockopt(RAW_CHECKSUM)"); >+ exit(2); >+ } >+ >+ /* >+ * select icmp echo reply as icmp type to receive >+ */ >+ >+ ICMPV6_FILTER_SETBLOCKALL(&filter); >+ >+ if (!working_recverr) { >+ ICMPV6_FILTER_SETPASS(ICMPV6_DEST_UNREACH, &filter); >+ ICMPV6_FILTER_SETPASS(ICMPV6_PKT_TOOBIG, &filter); >+ ICMPV6_FILTER_SETPASS(ICMPV6_TIME_EXCEED, &filter); >+ ICMPV6_FILTER_SETPASS(ICMPV6_PARAMPROB, &filter); >+ } >+ >+ ICMPV6_FILTER_SETPASS(ICMPV6_ECHO_REPLY, &filter); >+ >+ err = setsockopt(icmp_sock, SOL_ICMPV6, ICMPV6_FILTER, &filter, >+ sizeof(struct icmp6_filter)); >+ >+ if (err < 0) { >+ perror("setsockopt(ICMPV6_FILTER)"); >+ exit(2); >+ } >+ >+ if (options & F_NOLOOP) { >+ int loop = 0; >+ if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, >+ &loop, sizeof(loop)) == -1) { >+ perror ("can't disable multicast loopback"); >+ exit(2); >+ } >+ } >+ if (options & F_TTL) { >+ if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, >+ &ttl, sizeof(ttl)) == -1) { >+ perror ("can't set multicast hop limit"); >+ exit(2); >+ } >+ if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, >+ &ttl, sizeof(ttl)) == -1) { >+ perror ("can't set unicast hop limit"); >+ exit(2); >+ } >+ } >+ >+ if (1) { >+ int on = 1; >+ if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_HOPLIMIT, >+ &on, sizeof(on)) == -1) { >+ perror ("can't receive hop limit"); >+ exit(2); >+ } >+ } >+ >+ if (options&F_FLOWINFO) { >+#ifdef IPV6_FLOWLABEL_MGR >+ char freq_buf[CMSG_ALIGN(sizeof(struct in6_flowlabel_req)) + cmsglen]; >+ struct in6_flowlabel_req *freq = (struct in6_flowlabel_req *)freq_buf; >+ int freq_len = sizeof(*freq); >+ if (srcrt) >+ freq_len = CMSG_ALIGN(sizeof(*freq)) + srcrt->cmsg_len; >+ memset(freq, 0, sizeof(*freq)); >+ freq->flr_label = htonl(flowlabel&0xFFFFF); >+ freq->flr_action = IPV6_FL_A_GET; >+ freq->flr_flags = IPV6_FL_F_CREATE; >+ freq->flr_share = IPV6_FL_S_EXCL; >+ memcpy(&freq->flr_dst, &whereto.sin6_addr, 16); >+ if (srcrt) >+ memcpy(freq_buf + CMSG_ALIGN(sizeof(*freq)), srcrt, srcrt->cmsg_len); >+ if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_FLOWLABEL_MGR, >+ freq, freq_len) == -1) { >+ perror ("can't set flowlabel"); >+ exit(2); >+ } >+ flowlabel = freq->flr_label; >+ if (srcrt) { >+ cmsglen = (char*)srcrt - (char*)cmsgbuf; >+ srcrt = NULL; >+ } >+#else >+ fprintf(stderr, "Flow labels are not supported.\n"); >+ exit(2); >+#endif >+ } >+ if (options&(F_FLOWINFO|F_TCLASS)) { >+#ifdef IPV6_FLOWINFO_SEND >+ int on = 1; >+ whereto.sin6_flowinfo = flowlabel | htonl((tclass&0xFF)<<20); >+ if (setsockopt(icmp_sock, IPPROTO_IPV6, IPV6_FLOWINFO_SEND, >+ &on, sizeof(on)) == -1) { >+ perror ("can't send flowinfo"); >+ exit(2); >+ } >+#else >+ fprintf(stderr, "Flowinfo is not supported.\n"); >+ exit(2); >+#endif >+ } >+ >+ printf("PING %s(%s) ", hostname, pr_addr(&whereto.sin6_addr)); >+ if (flowlabel) >+ printf(", flow 0x%05x, ", (unsigned)ntohl(flowlabel)); >+ if (device || (options&F_STRICTSOURCE)) { >+ printf("from %s %s: ", >+ pr_addr_n(&source.sin6_addr), device ? : ""); >+ } >+ printf("%d data bytes\n", datalen); >+ >+ setup(icmp_sock); >+ >+ main_loop(icmp_sock, packet, packlen); >+} >+ >+int receive_error_msg() >+{ >+ int res; >+ char cbuf[512]; >+ struct iovec iov; >+ struct msghdr msg; >+ struct cmsghdr *cmsg; >+ struct sock_extended_err *e; >+ struct icmp6hdr icmph; >+ struct sockaddr_in6 target; >+ int net_errors = 0; >+ int local_errors = 0; >+ int saved_errno = errno; >+ >+ iov.iov_base = &icmph; >+ iov.iov_len = sizeof(icmph); >+ msg.msg_name = (void*)⌖ >+ msg.msg_namelen = sizeof(target); >+ msg.msg_iov = &iov; >+ msg.msg_iovlen = 1; >+ msg.msg_flags = 0; >+ msg.msg_control = cbuf; >+ msg.msg_controllen = sizeof(cbuf); >+ >+ res = recvmsg(icmp_sock, &msg, MSG_ERRQUEUE|MSG_DONTWAIT); >+ if (res < 0) >+ goto out; >+ >+ e = NULL; >+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { >+ if (cmsg->cmsg_level == SOL_IPV6) { >+ if (cmsg->cmsg_type == IPV6_RECVERR) >+ e = (struct sock_extended_err *)CMSG_DATA(cmsg); >+ } >+ } >+ if (e == NULL) >+ abort(); >+ >+ if (e->ee_origin == SO_EE_ORIGIN_LOCAL) { >+ local_errors++; >+ if (options & F_QUIET) >+ goto out; >+ if (options & F_FLOOD) >+ write(STDOUT_FILENO, "E", 1); >+ else if (e->ee_errno != EMSGSIZE) >+ fprintf(stderr, "ping: local error: %s\n", strerror(e->ee_errno)); >+ else >+ fprintf(stderr, "ping: local error: Message too long, mtu=%u\n", e->ee_info); >+ nerrors++; >+ } else if (e->ee_origin == SO_EE_ORIGIN_ICMP6) { >+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)(e+1); >+ >+ if (res < sizeof(icmph) || >+ memcmp(&target.sin6_addr, &whereto.sin6_addr, 16) || >+ icmph.icmp6_type != ICMPV6_ECHO_REQUEST || >+ icmph.icmp6_identifier != ident) { >+ /* Not our error, not an error at all. Clear. */ >+ saved_errno = 0; >+ goto out; >+ } >+ >+ net_errors++; >+ nerrors++; >+ if (options & F_QUIET) >+ goto out; >+ if (options & F_FLOOD) { >+ write(STDOUT_FILENO, "\bE", 2); >+ } else { >+ printf("From %s icmp_seq=%u ", pr_addr(&sin6->sin6_addr), ntohs(icmph.icmp6_sequence)); >+ pr_icmph(e->ee_type, e->ee_code, e->ee_info); >+ putchar('\n'); >+ fflush(stdout); >+ } >+ } >+ >+out: >+ errno = saved_errno; >+ return net_errors ? : -local_errors; >+} >+ >+/* >+ * pinger -- >+ * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet >+ * will be added on by the kernel. The ID field is our UNIX process ID, >+ * and the sequence number is an ascending integer. The first 8 bytes >+ * of the data portion are used to hold a UNIX "timeval" struct in VAX >+ * byte-order, to compute the round-trip time. >+ */ >+int send_probe(void) >+{ >+ struct icmp6hdr *icmph; >+ int cc; >+ int i; >+ >+ icmph = (struct icmp6hdr *)outpack; >+ icmph->icmp6_type = ICMPV6_ECHO_REQUEST; >+ icmph->icmp6_code = 0; >+ icmph->icmp6_cksum = 0; >+ icmph->icmp6_sequence = htons(ntransmitted+1); >+ icmph->icmp6_identifier = ident; >+ >+ CLR((ntransmitted+1) % mx_dup_ck); >+ >+ if (timing) >+ gettimeofday((struct timeval *)&outpack[8], >+ (struct timezone *)NULL); >+ >+ cc = datalen + 8; /* skips ICMP portion */ >+ >+ if (cmsglen == 0) { >+ i = sendto(icmp_sock, (char *)outpack, cc, confirm, >+ (struct sockaddr *) &whereto, >+ sizeof(struct sockaddr_in6)); >+ } else { >+ struct msghdr mhdr; >+ struct iovec iov; >+ >+ iov.iov_len = cc; >+ iov.iov_base = outpack; >+ >+ mhdr.msg_name = &whereto; >+ mhdr.msg_namelen = sizeof(struct sockaddr_in6); >+ mhdr.msg_iov = &iov; >+ mhdr.msg_iovlen = 1; >+ mhdr.msg_control = cmsgbuf; >+ mhdr.msg_controllen = cmsglen; >+ >+ i = sendmsg(icmp_sock, &mhdr, confirm); >+ } >+ confirm = 0; >+ >+ return (cc == i ? 0 : i); >+} >+ >+/* >+ * parse_reply -- >+ * Print out the packet, if it came from us. This logic is necessary >+ * because ALL readers of the ICMP socket get a copy of ALL ICMP packets >+ * which arrive ('tis only fair). This permits multiple copies of this >+ * program to be run without having intermingled output (or statistics!). >+ */ >+int >+parse_reply(struct msghdr *msg, int cc, void *addr, struct timeval *tv) >+{ >+ struct sockaddr_in6 *from = addr; >+ __u8 *buf = msg->msg_iov->iov_base; >+ struct cmsghdr *c; >+ struct icmp6hdr *icmph; >+ int hops = -1; >+ >+ for (c = CMSG_FIRSTHDR(msg); c; c = CMSG_NXTHDR(msg, c)) { >+ if (c->cmsg_level != SOL_IPV6 || >+ c->cmsg_type != IPV6_HOPLIMIT) >+ continue; >+ if (c->cmsg_len < CMSG_LEN(sizeof(int))) >+ continue; >+ hops = *(int*)CMSG_DATA(c); >+ } >+ >+ >+ /* Now the ICMP part */ >+ >+ icmph = (struct icmp6hdr *) buf; >+ if (cc < 8) { >+ if (options & F_VERBOSE) >+ fprintf(stderr, "ping: packet too short (%d bytes)\n", cc); >+ return 1; >+ } >+ >+ if (icmph->icmp6_type == ICMPV6_ECHO_REPLY) { >+ if (icmph->icmp6_identifier != ident) >+ return 1; >+ if (gather_statistics((__u8*)(icmph+1), cc, >+ ntohs(icmph->icmp6_sequence), >+ hops, 0, tv, pr_addr(&from->sin6_addr))) >+ return 0; >+ } else { >+ int nexthdr; >+ struct ipv6hdr *iph1 = (struct ipv6hdr*)(icmph+1); >+ struct icmp6hdr *icmph1 = (struct icmp6hdr *)(iph1+1); >+ >+ /* We must not ever fall here. All the messages but >+ * echo reply are blocked by filter and error are >+ * received with IPV6_RECVERR. Ugly code is preserved >+ * however, just to remember what crap we avoided >+ * using RECVRERR. :-) >+ */ >+ >+ if (cc < 8+sizeof(struct ipv6hdr)+8) >+ return 1; >+ >+ if (memcmp(&iph1->daddr, &whereto.sin6_addr, 16)) >+ return 1; >+ >+ nexthdr = iph1->nexthdr; >+ >+ if (nexthdr == 44) { >+ nexthdr = *(__u8*)icmph1; >+ icmph1++; >+ } >+ if (nexthdr == IPPROTO_ICMPV6) { >+ if (icmph1->icmp6_type != ICMPV6_ECHO_REQUEST || >+ icmph1->icmp6_identifier != ident) >+ return 1; >+ acknowledge(ntohs(icmph1->icmp6_sequence)); >+ if (working_recverr) >+ return 0; >+ nerrors++; >+ if (options & F_FLOOD) { >+ write(STDOUT_FILENO, "\bE", 2); >+ return 0; >+ } >+ printf("From %s: icmp_seq=%u ", pr_addr(&from->sin6_addr), ntohs(icmph1->icmp6_sequence)); >+ } else { >+ /* We've got something other than an ECHOREPLY */ >+ if (!(options & F_VERBOSE) || uid) >+ return 1; >+ printf("From %s: ", pr_addr(&from->sin6_addr)); >+ } >+ pr_icmph(icmph->icmp6_type, icmph->icmp6_code, ntohl(icmph->icmp6_mtu)); >+ } >+ >+ if (!(options & F_FLOOD)) { >+ if (options & F_AUDIBLE) >+ putchar('\a'); >+ putchar('\n'); >+ fflush(stdout); >+ } >+ return 0; >+} >+ >+ >+int pr_icmph(__u8 type, __u8 code, __u32 info) >+{ >+ switch(type) { >+ case ICMPV6_DEST_UNREACH: >+ printf("Destination unreachable: "); >+ switch (code) { >+ case ICMPV6_NOROUTE: >+ printf("No route"); >+ break; >+ case ICMPV6_ADM_PROHIBITED: >+ printf("Administratively prohibited"); >+ break; >+ case ICMPV6_NOT_NEIGHBOUR: >+ printf("Not neighbour"); >+ break; >+ case ICMPV6_ADDR_UNREACH: >+ printf("Address unreachable"); >+ break; >+ case ICMPV6_PORT_UNREACH: >+ printf("Port unreachable"); >+ break; >+ default: >+ printf("Unknown code %d", code); >+ break; >+ } >+ break; >+ case ICMPV6_PKT_TOOBIG: >+ printf("Packet too big: mtu=%u", info); >+ if (code) >+ printf(", code=%d", code); >+ break; >+ case ICMPV6_TIME_EXCEED: >+ printf("Time exceeded: "); >+ if (code == ICMPV6_EXC_HOPLIMIT) >+ printf("Hop limit"); >+ else if (code == ICMPV6_EXC_FRAGTIME) >+ printf("Defragmentation failure"); >+ else >+ printf("code %d", code); >+ break; >+ case ICMPV6_PARAMPROB: >+ printf("Parameter problem: "); >+ if (code == ICMPV6_HDR_FIELD) >+ printf("Wrong header field "); >+ else if (code == ICMPV6_UNK_NEXTHDR) >+ printf("Unknown header "); >+ else if (code == ICMPV6_UNK_OPTION) >+ printf("Unknown option "); >+ else >+ printf("code %d ", code); >+ printf ("at %u", info); >+ break; >+ case ICMPV6_ECHO_REQUEST: >+ printf("Echo request"); >+ break; >+ case ICMPV6_ECHO_REPLY: >+ printf("Echo reply"); >+ break; >+ case ICMPV6_MGM_QUERY: >+ printf("MLD Query"); >+ break; >+ case ICMPV6_MGM_REPORT: >+ printf("MLD Report"); >+ break; >+ case ICMPV6_MGM_REDUCTION: >+ printf("MLD Reduction"); >+ break; >+ default: >+ printf("unknown icmp type"); >+ >+ } >+ return 0; >+} >+ >+#include <linux/filter.h> >+ >+void install_filter(void) >+{ >+ static int once; >+ static struct sock_filter insns[] = { >+ BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 4), /* Load icmp echo ident */ >+ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xAAAA, 0, 1), /* Ours? */ >+ BPF_STMT(BPF_RET|BPF_K, ~0U), /* Yes, it passes. */ >+ BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 0), /* Load icmp type */ >+ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ICMPV6_ECHO_REPLY, 1, 0), /* Echo? */ >+ BPF_STMT(BPF_RET|BPF_K, ~0U), /* No. It passes. This must not happen. */ >+ BPF_STMT(BPF_RET|BPF_K, 0), /* Echo with wrong ident. Reject. */ >+ }; >+ static struct sock_fprog filter = { >+ sizeof insns / sizeof(insns[0]), >+ insns >+ }; >+ >+ if (once) >+ return; >+ once = 1; >+ >+ /* Patch bpflet for current identifier. */ >+ insns[1] = (struct sock_filter)BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __constant_htons(ident), 0, 1); >+ >+ if (setsockopt(icmp_sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter))) >+ perror("WARNING: failed to install socket filter\n"); >+} >+ >+ >+/* >+ * pr_addr -- >+ * Return an ascii host address as a dotted quad and optionally with >+ * a hostname. >+ */ >+char * pr_addr(struct in6_addr *addr) >+{ >+ struct hostent *hp = NULL; >+ >+ if (!(options&F_NUMERIC)) >+ hp = gethostbyaddr((__u8*)addr, sizeof(struct in6_addr), AF_INET6); >+ >+ return hp ? hp->h_name : pr_addr_n(addr); >+} >+ >+char * pr_addr_n(struct in6_addr *addr) >+{ >+ static char str[64]; >+ inet_ntop(AF_INET6, addr, str, sizeof(str)); >+ return str; >+} >+ >+void usage(void) >+{ >+ fprintf(stderr, >+"Usage: ping6 [-LUdfnqrvVaA] [-c count] [-i interval] [-w deadline]\n" >+" [-p pattern] [-s packetsize] [-t ttl] [-I interface]\n" >+" [-M mtu discovery hint] [-S sndbuf]\n" >+" [-F flow label] [-Q traffic class] [hop1 ...] destination\n"); >+ exit(2); >+} >diff -Nur iputils.p8/tracepath6.c iputils/tracepath6.c >--- iputils.p8/tracepath6.c 2008-01-07 13:24:25 +0300 >+++ iputils/tracepath6.c 2008-01-07 13:29:59 +0300 >@@ -113,7 +113,7 @@ > if (cmsg->cmsg_level == SOL_IPV6) { > if (cmsg->cmsg_type == IPV6_RECVERR) { > e = (struct sock_extended_err *)CMSG_DATA(cmsg); >- } else if (cmsg->cmsg_type == IPV6_HOPLIMIT) { >+ } else if (cmsg->cmsg_type == IPV6_2292HOPLIMIT) { > rethops = *(int*)CMSG_DATA(cmsg); > } > } else if (cmsg->cmsg_level == SOL_IP) { >@@ -359,7 +359,7 @@ > perror("IP_RECVERR"); > exit(1); > } >- if (setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &on, sizeof(on))) { >+ if (setsockopt(fd, SOL_IPV6, IPV6_2292HOPLIMIT, &on, sizeof(on))) { > perror("IPV6_HOPLIMIT"); > exit(1); > } >diff -Nur iputils.p8/tracepath6.c~ iputils/tracepath6.c~ >--- iputils.p8/tracepath6.c~ 1970-01-01 03:00:00 +0300 >+++ iputils/tracepath6.c~ 2008-01-07 13:24:25 +0300 >@@ -0,0 +1,406 @@ >+/* >+ * tracepath6.c >+ * >+ * This program is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU General Public License >+ * as published by the Free Software Foundation; either version >+ * 2 of the License, or (at your option) any later version. >+ * >+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> >+ */ >+ >+#include <stdio.h> >+#include <stdlib.h> >+#include <unistd.h> >+#include <sys/socket.h> >+#include <netinet/in.h> >+ >+#include <linux/in6.h> >+#include <linux/errqueue.h> >+#include <errno.h> >+#include <string.h> >+#include <netdb.h> >+#include <resolv.h> >+#include <sys/time.h> >+#include <sys/uio.h> >+#include <arpa/inet.h> >+#include "fixfds.h" >+#include "droppriv.h" >+ >+int overhead = 48; >+int mtu = 128000; >+int hops_to = -1; >+int hops_from = -1; >+int no_resolve = 0; >+int show_both = 0; >+int mapped; >+ >+struct probehdr >+{ >+ __u32 ttl; >+ struct timeval tv; >+}; >+ >+void data_wait(int fd) >+{ >+ fd_set fds; >+ struct timeval tv; >+ FD_ZERO(&fds); >+ FD_SET(fd, &fds); >+ tv.tv_sec = 1; >+ tv.tv_usec = 0; >+ select(fd+1, &fds, NULL, NULL, &tv); >+} >+ >+int recverr(int fd, int ttl) >+{ >+ int res; >+ struct probehdr rcvbuf; >+ char cbuf[512]; >+ struct iovec iov; >+ struct msghdr msg; >+ struct cmsghdr *cmsg; >+ struct sock_extended_err *e; >+ struct timeval tv; >+ struct timeval *rettv; >+ int rethops; >+ int sndhops; >+ int progress = -1; >+ int broken_router; >+ >+restart: >+ memset(&rcvbuf, -1, sizeof(rcvbuf)); >+ iov.iov_base = &rcvbuf; >+ iov.iov_len = sizeof(rcvbuf); >+ msg.msg_name = NULL; >+ msg.msg_namelen = 0; >+ msg.msg_iov = &iov; >+ msg.msg_iovlen = 1; >+ msg.msg_flags = 0; >+ msg.msg_control = cbuf; >+ msg.msg_controllen = sizeof(cbuf); >+ >+ gettimeofday(&tv, NULL); >+ res = recvmsg(fd, &msg, MSG_ERRQUEUE); >+ if (res < 0) { >+ if (errno == EAGAIN) >+ return progress; >+ goto restart; >+ } >+ >+ progress = 2; >+ >+ rethops = -1; >+ sndhops = -1; >+ e = NULL; >+ rettv = NULL; >+ broken_router = 0; >+ if (res == sizeof(rcvbuf)) { >+ if (rcvbuf.ttl == 0 || rcvbuf.tv.tv_sec == 0) >+ broken_router = 1; >+ >+ sndhops = rcvbuf.ttl; >+ rettv = &rcvbuf.tv; >+ if (sndhops != ttl) >+ progress = -1; >+ } >+ if (sndhops>0) >+ printf("%2d: ", sndhops); >+ else >+ printf("%2d?: ", ttl); >+ >+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { >+ if (cmsg->cmsg_level == SOL_IPV6) { >+ if (cmsg->cmsg_type == IPV6_RECVERR) { >+ e = (struct sock_extended_err *)CMSG_DATA(cmsg); >+ } else if (cmsg->cmsg_type == IPV6_HOPLIMIT) { >+ rethops = *(int*)CMSG_DATA(cmsg); >+ } >+ } else if (cmsg->cmsg_level == SOL_IP) { >+ if (cmsg->cmsg_type == IP_TTL) { >+ rethops = *(__u8*)CMSG_DATA(cmsg); >+ } >+ } >+ } >+ if (e == NULL) { >+ printf("no info\n"); >+ return 0; >+ } >+ if (e->ee_origin == SO_EE_ORIGIN_LOCAL) >+ printf("%-32s ", "[LOCALHOST]"); >+ else if (e->ee_origin == SO_EE_ORIGIN_ICMP6 || >+ e->ee_origin == SO_EE_ORIGIN_ICMP) { >+ struct hostent * h = NULL; >+ char abuf[128]; >+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)(e+1); >+ struct sockaddr_in *sin = (struct sockaddr_in*)(e+1); >+ >+ if (!no_resolve) >+ fflush(stdout); >+ >+ if (sin->sin_family == AF_INET6) { >+ inet_ntop(AF_INET6, &sin6->sin6_addr, abuf, sizeof(abuf)); >+ if (!no_resolve) >+ h = gethostbyaddr((char *) &sin6->sin6_addr, sizeof(sin6->sin6_addr), AF_INET6); >+ } else { >+ inet_ntop(AF_INET, &sin->sin_addr, abuf, sizeof(abuf)); >+ if (!no_resolve) >+ h = gethostbyaddr((char *) &sin->sin_addr, sizeof(sin->sin_addr), AF_INET); >+ } >+ if (!no_resolve) { >+ char fabuf[256]; >+ if (show_both) { >+ if (h) >+ snprintf(fabuf, sizeof(fabuf), "%s %s", h->h_name, abuf); >+ else >+ snprintf(fabuf, sizeof(fabuf), "%s", abuf); >+ } else { >+ snprintf(fabuf, sizeof(fabuf), "%s", h ? h->h_name : abuf); >+ } >+ printf("%-40s ", fabuf); >+ } else { >+ printf("%-32s ", abuf); >+ } >+ } >+ >+ if (rethops>=0) { >+ if (rethops<=64) >+ rethops = 65-rethops; >+ else if (rethops<=128) >+ rethops = 129-rethops; >+ else >+ rethops = 256-rethops; >+ if (sndhops>=0 && rethops != sndhops) >+ printf("asymm %2d ", rethops); >+ else if (sndhops<0 && rethops != ttl) >+ printf("asymm %2d ", rethops); >+ } >+ >+ if (rettv) { >+ int diff = (tv.tv_sec-rettv->tv_sec)*1000000+(tv.tv_usec-rettv->tv_usec); >+ printf("%3d.%3dms ", diff/1000, diff%1000); >+ if (broken_router) >+ printf("(This broken router returned corrupted payload) "); >+ } >+ >+ switch (e->ee_errno) { >+ case ETIMEDOUT: >+ printf("\n"); >+ break; >+ case EMSGSIZE: >+ printf("pmtu %d\n", e->ee_info); >+ mtu = e->ee_info; >+ progress = 1; >+ break; >+ case ECONNREFUSED: >+ printf("reached\n"); >+ hops_to = sndhops<0 ? ttl : sndhops; >+ hops_from = rethops; >+ return 0; >+ case EPROTO: >+ printf("!P\n"); >+ return 0; >+ case EHOSTUNREACH: >+ if ((e->ee_origin == SO_EE_ORIGIN_ICMP && >+ e->ee_type == 11 && >+ e->ee_code == 0) || >+ (e->ee_origin == SO_EE_ORIGIN_ICMP6 && >+ e->ee_type == 3 && >+ e->ee_code == 0)) { >+ printf("\n"); >+ break; >+ } >+ printf("!H\n"); >+ return 0; >+ case ENETUNREACH: >+ printf("!N\n"); >+ return 0; >+ case EACCES: >+ printf("!A\n"); >+ return 0; >+ default: >+ printf("\n"); >+ errno = e->ee_errno; >+ perror("NET ERROR"); >+ return 0; >+ } >+ goto restart; >+} >+ >+int probe_ttl(int fd, int ttl) >+{ >+ int i; >+ char sndbuf[mtu]; >+ struct probehdr *hdr = (struct probehdr*)sndbuf; >+ >+restart: >+ >+ for (i=0; i<10; i++) { >+ int res; >+ >+ hdr->ttl = ttl; >+ gettimeofday(&hdr->tv, NULL); >+ if (send(fd, sndbuf, mtu-overhead, 0) > 0) >+ break; >+ res = recverr(fd, ttl); >+ if (res==0) >+ return 0; >+ if (res > 0) >+ goto restart; >+ } >+ >+ if (i<10) { >+ int res; >+ >+ data_wait(fd); >+ if (recv(fd, sndbuf, sizeof(sndbuf), MSG_DONTWAIT) > 0) { >+ printf("%2d?: reply received 8)\n", ttl); >+ return 0; >+ } >+ res = recverr(fd, ttl); >+ if (res == 1) >+ goto restart; >+ return res; >+ } >+ >+ printf("%2d: send failed\n", ttl); >+ return 0; >+} >+ >+static void usage(void) __attribute((noreturn)); >+ >+static void usage(void) >+{ >+ fprintf(stderr, "Usage: tracepath6 [-n] [-b] <destination>[/<port>]\n"); >+ exit(-1); >+} >+ >+ >+int main(int argc, char **argv) >+{ >+ int fd; >+ int on; >+ struct sockaddr_in6 sin; >+ int ttl; >+ char *p; >+ struct hostent *he; >+ int ch; >+ >+ fix_fds(); >+ drop_priv(); >+ >+ while ((ch = getopt(argc, argv, "nbh?")) != EOF) { >+ switch(ch) { >+ case 'n': >+ no_resolve = 1; >+ break; >+ case 'b': >+ show_both = 1; >+ break; >+ default: >+ usage(); >+ } >+ } >+ >+ argc -= optind; >+ argv += optind; >+ >+ if (argc != 1) >+ usage(); >+ >+ >+ fd = socket(AF_INET6, SOCK_DGRAM, 0); >+ if (fd < 0) { >+ perror("socket"); >+ exit(1); >+ } >+ sin.sin6_family = AF_INET6; >+ >+ p = strchr(argv[0], '/'); >+ if (p) { >+ *p = 0; >+ sin.sin6_port = htons(atoi(p+1)); >+ } else >+ sin.sin6_port = htons(0x8000 | getpid()); >+ he = gethostbyname2(argv[0], AF_INET6); >+ if (he == NULL) { >+ herror("gethostbyname2"); >+ exit(1); >+ } >+ memcpy(&sin.sin6_addr, he->h_addr, 16); >+ >+ if (connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) { >+ perror("connect"); >+ exit(1); >+ } >+ >+ if (!sin.sin6_addr.s6_addr32[0] && !sin.sin6_addr.s6_addr32[1] >+ && sin.sin6_addr.s6_addr32[2] == htonl(0xFFFF)) { >+ mtu = 65535; >+ overhead = 28; >+ mapped = 1; >+ } >+ >+ on = IPV6_PMTUDISC_DO; >+ if (setsockopt(fd, SOL_IPV6, IPV6_MTU_DISCOVER, &on, sizeof(on))) { >+ perror("IPV6_MTU_DISCOVER"); >+ exit(1); >+ } >+ if (mapped && setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &on, sizeof(on))) { >+ perror("IP_MTU_DISCOVER"); >+ exit(1); >+ } >+ on = 1; >+ if (setsockopt(fd, SOL_IPV6, IPV6_RECVERR, &on, sizeof(on))) { >+ perror("IPV6_RECVERR"); >+ exit(1); >+ } >+ if (mapped && setsockopt(fd, SOL_IP, IP_RECVERR, &on, sizeof(on))) { >+ perror("IP_RECVERR"); >+ exit(1); >+ } >+ if (setsockopt(fd, SOL_IPV6, IPV6_HOPLIMIT, &on, sizeof(on))) { >+ perror("IPV6_HOPLIMIT"); >+ exit(1); >+ } >+ if (mapped && setsockopt(fd, SOL_IP, IP_RECVTTL, &on, sizeof(on))) { >+ perror("IP_RECVTTL"); >+ exit(1); >+ } >+ >+ for (ttl=1; ttl<32; ttl++) { >+ int res = 0; >+ int i; >+ >+ on = ttl; >+ if (setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &on, sizeof(on))) { >+ perror("IPV6_UNICAST_HOPS"); >+ exit(1); >+ } >+ if (mapped && setsockopt(fd, SOL_IP, IP_TTL, &on, sizeof(on))) { >+ perror("IP_TTL"); >+ exit(1); >+ } >+ >+ for (i=0; i<3; i++) { >+ res = probe_ttl(fd, ttl); >+ if (res == 0) >+ goto done; >+ if (res > 0) >+ break; >+ } >+ >+ if (res < 0) >+ printf("%2d: no reply\n", ttl); >+ } >+ printf(" Too many hops: pmtu %d\n", mtu); >+ >+done: >+ printf(" Resume: pmtu %d ", mtu); >+ if (hops_to>=0) >+ printf("hops %d ", hops_to); >+ if (hops_from>=0) >+ printf("back %d ", hops_from); >+ printf("\n"); >+ exit(0); >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 13916
:
2358
|
2359