int sockunion_cmp(const union sockunion *su1, const union sockunion *su2) { if (su1->sa.sa_family > su2->sa.sa_family) return 1; if (su1->sa.sa_family < su2->sa.sa_family) return -1; if (su1->sa.sa_family == AF_INET) { if (ntohl(sockunion2ip(su1)) == ntohl(sockunion2ip(su2))) return 0; if (ntohl(sockunion2ip(su1)) > ntohl(sockunion2ip(su2))) return 1; else return -1; } if (su1->sa.sa_family == AF_INET6) return in6addr_cmp(&su1->sin6.sin6_addr, &su2->sin6.sin6_addr); return 0; }
int sockunion_cmp (union sockunion *su1, union sockunion *su2) { if (su1->sa.sa_family > su2->sa.sa_family) return 1; if (su1->sa.sa_family < su2->sa.sa_family) return -1; if (su1->sa.sa_family == AF_INET) { if (ntohl (su1->sin.sin_addr.s_addr) == ntohl (su2->sin.sin_addr.s_addr)) return 0; if (ntohl (su1->sin.sin_addr.s_addr) > ntohl (su2->sin.sin_addr.s_addr)) return 1; else return -1; } #ifdef HAVE_IPV6 if (su1->sa.sa_family == AF_INET6) return in6addr_cmp (&su1->sin6.sin6_addr, &su2->sin6.sin6_addr); #endif /* HAVE_IPV6 */ return 0; }
static int parse_echo_response6(struct host_entry *host_entry, char *packet, int len) { int records, i; struct ipmp *ipmp; struct ipmp_trailer *ipmp_trailer; struct ipmp_pathrecord6 *pr; char ctime_buf[26]; char addr_buf[INET6_ADDRSTRLEN]; char fs_buf[25]; struct ipmp_pathrecord6 *out = NULL, *there = NULL, *back = NULL; int temp, max; struct dns_entry *dns; struct ipmptime t, t2; long base_sec = tv_sec() & 0xffff0000; time_t tt; char *name; char c; struct in6_addr *in6; /* get the offsets into the packet received */ ipmp = (struct ipmp *)packet; pr = (struct ipmp_pathrecord6 *)(packet + sizeof(struct ipmp)); ipmp_trailer = (struct ipmp_trailer *)(packet + len - 4); ipmp_trailer->path_pointer = ntohs(ipmp_trailer->path_pointer); /* get the number of path records */ records = (ipmp_trailer->path_pointer - sizeof(struct ipmp)) / sizeof(struct ipmp_pathrecord6); /* get a pointer to the first timestamp so we can do a rtt calculation */ if(is_localaddress6(&pr->ip)) out = pr; /* find out how many chars it is to represent the longest address */ if(!(options & OPT_NLANR)) { if(records <= 0) return 1; max = 0; for(i=0; i<records; i++) { if(options & OPT_RESOLV && (dns=dnsentry_lookup6(&pr->ip)) != NULL) { temp = strlen(dns->name); } else { inet_ntop(AF_INET6, &pr->ip, addr_buf, sizeof(addr_buf)); temp = strlen(addr_buf); } if(temp > max) max = temp; pr++; } pr--; temp = ipv6_hlim - pr->hlim; if(temp < 9) i = 1; else if(temp < 99) i = 2; else i = 3; snprintf(fs_buf, sizeof(fs_buf), "%%c %%%dd %%%ds %%s %%9u\n", i, max); pr = (struct ipmp_pathrecord6 *)(packet + sizeof(struct ipmp)); in6 = &((struct sockaddr_in6 *)host_entry->addr)->sin6_addr; /* print the path records out */ for(i=0; i<records; i++) { t.sec = base_sec + ntohs(pr->sec); t.nsec = ntohl(pr->nsec); /* format the timestamp and remove the \n char from the end */ tt = (time_t)t.sec; strncpy(ctime_buf, ctime(&tt), 24); ctime_buf[24] = '\0'; /* sort out the name we are going to show to the user */ if(options & OPT_RESOLV && (dns=dnsentry_lookup6(&pr->ip)) != NULL) { name = dns->name; } else { inet_ntop(AF_INET6, &pr->ip, addr_buf, sizeof(addr_buf)); name = addr_buf; } /* * check to see if the address in this path record is either a * local address or a target address. if it is, we want to show * the user */ if(is_localaddress6(&pr->ip)) { c = '*'; } else if(in6addr_cmp(&pr->ip, in6) == 0) { c = '*'; there = pr; } else c = ' '; printf(fs_buf, c, ipv6_hlim - pr->hlim, name, ctime_buf+4, t.nsec); pr++; } pr--; if(is_localaddress6(&pr->ip)) back = pr; if(options & OPT_HOPS && there != NULL) { printf("forward path = "); if(out != NULL) printf("%d", out->hlim - there->hlim); else printf("?"); printf(" hops, reverse path = "); if(back != NULL) printf("%d", there->hlim - back->hlim); else printf("%d", there->hlim - host_entry->ttl); printf(" hops\n"); } /* calculate the RTT if we have been asked to */ if((options & OPT_RTT) && out != NULL && back != NULL) { t.sec = ntohs(out->sec); t.nsec = ntohl(out->nsec); t2.sec = ntohs(back->sec); t2.nsec = ntohl(back->nsec); if(t.sec > t2.sec) t2.sec += 0xffff; printf("rtt: %sms\n", rtt(&t, &t2)); } /* beep the pc speaker if we have been asked to */ if(options & OPT_AUDIBLE) printf("\a"); } else { /* * this output is the only stuff that the NLANR side (should) output to * stdio, thus making the perl scripts that much simpler to write */ for(i=0; i<records-1; i++) { pr++; } if(is_localaddress6(&pr->ip)) { back = pr; t.sec = out->sec; t.nsec = out->nsec; t2.sec = back->sec; t2.nsec = back->nsec; if(t.sec > t2.sec) t2.sec += 0xffff; printf("%s %s\n", host_entry->name, rtt(&t, &t2)); } } fflush(stdout); return 1; }