Changeset View
Standalone View
sbin/ping6/ping6.c
Show First 20 Lines • Show All 307 Lines • ▼ Show 20 Lines | main(int argc, char *argv[]) | ||||
struct cmsghdr *scmsgp = NULL; | struct cmsghdr *scmsgp = NULL; | ||||
/* For control (ancillary) data received from recvmsg() */ | /* For control (ancillary) data received from recvmsg() */ | ||||
struct cmsghdr cm[CONTROLLEN]; | struct cmsghdr cm[CONTROLLEN]; | ||||
#if defined(SO_SNDBUF) && defined(SO_RCVBUF) | #if defined(SO_SNDBUF) && defined(SO_RCVBUF) | ||||
u_long lsockbufsize; | u_long lsockbufsize; | ||||
int sockbufsize = 0; | int sockbufsize = 0; | ||||
#endif | #endif | ||||
int usepktinfo = 0; | int usepktinfo = 0; | ||||
struct in6_pktinfo *pktinfo = NULL; | struct in6_pktinfo pktinfo; | ||||
char *cmsg_pktinfo = NULL; | |||||
struct ip6_rthdr *rthdr = NULL; | struct ip6_rthdr *rthdr = NULL; | ||||
#ifdef IPSEC_POLICY_IPSEC | #ifdef IPSEC_POLICY_IPSEC | ||||
char *policy_in = NULL; | char *policy_in = NULL; | ||||
char *policy_out = NULL; | char *policy_out = NULL; | ||||
#endif | #endif | ||||
double t; | double t; | ||||
u_long alarmtimeout; | u_long alarmtimeout; | ||||
size_t rthlen; | size_t rthlen; | ||||
#ifdef IPV6_USE_MIN_MTU | #ifdef IPV6_USE_MIN_MTU | ||||
int mflag = 0; | int mflag = 0; | ||||
#endif | #endif | ||||
cap_rights_t rights_srecv; | cap_rights_t rights_srecv; | ||||
cap_rights_t rights_ssend; | cap_rights_t rights_ssend; | ||||
cap_rights_t rights_stdin; | cap_rights_t rights_stdin; | ||||
/* just to be sure */ | /* just to be sure */ | ||||
memset(&smsghdr, 0, sizeof(smsghdr)); | memset(&smsghdr, 0, sizeof(smsghdr)); | ||||
memset(&smsgiov, 0, sizeof(smsgiov)); | memset(&smsgiov, 0, sizeof(smsgiov)); | ||||
memset(&pktinfo, 0, sizeof(pktinfo)); | |||||
alarmtimeout = preload = 0; | alarmtimeout = preload = 0; | ||||
datap = &outpack[ICMP6ECHOLEN + ICMP6ECHOTMLEN]; | datap = &outpack[ICMP6ECHOLEN + ICMP6ECHOTMLEN]; | ||||
capdns = capdns_setup(); | capdns = capdns_setup(); | ||||
#ifndef IPSEC | #ifndef IPSEC | ||||
#define ADDOPTS | #define ADDOPTS | ||||
#else | #else | ||||
#ifdef IPSEC_POLICY_IPSEC | #ifdef IPSEC_POLICY_IPSEC | ||||
▲ Show 20 Lines • Show All 545 Lines • ▼ Show 20 Lines | if (hoplimit != -1) | ||||
ip6optlen += CMSG_SPACE(sizeof(int)); | ip6optlen += CMSG_SPACE(sizeof(int)); | ||||
/* set IP6 packet options */ | /* set IP6 packet options */ | ||||
if (ip6optlen) { | if (ip6optlen) { | ||||
if ((scmsg = (char *)malloc(ip6optlen)) == NULL) | if ((scmsg = (char *)malloc(ip6optlen)) == NULL) | ||||
errx(1, "can't allocate enough memory"); | errx(1, "can't allocate enough memory"); | ||||
smsghdr.msg_control = (caddr_t)scmsg; | smsghdr.msg_control = (caddr_t)scmsg; | ||||
smsghdr.msg_controllen = ip6optlen; | smsghdr.msg_controllen = ip6optlen; | ||||
scmsgp = (struct cmsghdr *)scmsg; | scmsgp = CMSG_FIRSTHDR(&smsghdr); | ||||
} | } | ||||
if (usepktinfo) { | if (usepktinfo) { | ||||
pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp)); | cmsg_pktinfo = CMSG_DATA(scmsgp); | ||||
memset(pktinfo, 0, sizeof(*pktinfo)); | |||||
scmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); | scmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); | ||||
scmsgp->cmsg_level = IPPROTO_IPV6; | scmsgp->cmsg_level = IPPROTO_IPV6; | ||||
scmsgp->cmsg_type = IPV6_PKTINFO; | scmsgp->cmsg_type = IPV6_PKTINFO; | ||||
scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp); | scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp); | ||||
} | } | ||||
/* set the outgoing interface */ | /* set the outgoing interface */ | ||||
if (ifname) { | if (ifname) { | ||||
#ifndef USE_SIN6_SCOPE_ID | #ifndef USE_SIN6_SCOPE_ID | ||||
/* pktinfo must have already been allocated */ | /* pktinfo must have already been allocated */ | ||||
if ((pktinfo->ipi6_ifindex = if_nametoindex(ifname)) == 0) | if ((pktinfo.ipi6_ifindex = if_nametoindex(ifname)) == 0) | ||||
errx(1, "%s: invalid interface name", ifname); | errx(1, "%s: invalid interface name", ifname); | ||||
#else | #else | ||||
if ((dst.sin6_scope_id = if_nametoindex(ifname)) == 0) | if ((dst.sin6_scope_id = if_nametoindex(ifname)) == 0) | ||||
errx(1, "%s: invalid interface name", ifname); | errx(1, "%s: invalid interface name", ifname); | ||||
#endif | #endif | ||||
} | } | ||||
if (hoplimit != -1) { | if (hoplimit != -1) { | ||||
scmsgp->cmsg_len = CMSG_LEN(sizeof(int)); | scmsgp->cmsg_len = CMSG_LEN(sizeof(int)); | ||||
scmsgp->cmsg_level = IPPROTO_IPV6; | scmsgp->cmsg_level = IPPROTO_IPV6; | ||||
scmsgp->cmsg_type = IPV6_HOPLIMIT; | scmsgp->cmsg_type = IPV6_HOPLIMIT; | ||||
*(int *)(CMSG_DATA(scmsgp)) = hoplimit; | memcpy(CMSG_DATA(scmsgp), &hoplimit, sizeof(hoplimit)); | ||||
scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp); | scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp); | ||||
} | } | ||||
if (argc > 1) { /* some intermediate addrs are specified */ | if (argc > 1) { /* some intermediate addrs are specified */ | ||||
int hops; | int hops; | ||||
int rthdrlen; | int rthdrlen; | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | if (!(options & F_SRCADDR)) { | ||||
if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) | if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) | ||||
err(1, "UDP socket"); | err(1, "UDP socket"); | ||||
src.sin6_family = AF_INET6; | src.sin6_family = AF_INET6; | ||||
src.sin6_addr = dst.sin6_addr; | src.sin6_addr = dst.sin6_addr; | ||||
src.sin6_port = ntohs(DUMMY_PORT); | src.sin6_port = ntohs(DUMMY_PORT); | ||||
src.sin6_scope_id = dst.sin6_scope_id; | src.sin6_scope_id = dst.sin6_scope_id; | ||||
if (pktinfo && | if (usepktinfo && | ||||
setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTINFO, | setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTINFO, | ||||
(void *)pktinfo, sizeof(*pktinfo))) | (void *)&pktinfo, sizeof(pktinfo))) | ||||
err(1, "UDP setsockopt(IPV6_PKTINFO)"); | err(1, "UDP setsockopt(IPV6_PKTINFO)"); | ||||
if (hoplimit != -1 && | if (hoplimit != -1 && | ||||
setsockopt(dummy, IPPROTO_IPV6, IPV6_UNICAST_HOPS, | setsockopt(dummy, IPPROTO_IPV6, IPV6_UNICAST_HOPS, | ||||
(void *)&hoplimit, sizeof(hoplimit))) | (void *)&hoplimit, sizeof(hoplimit))) | ||||
err(1, "UDP setsockopt(IPV6_UNICAST_HOPS)"); | err(1, "UDP setsockopt(IPV6_UNICAST_HOPS)"); | ||||
if (hoplimit != -1 && | if (hoplimit != -1 && | ||||
Show All 10 Lines | if (connect(dummy, (struct sockaddr *)&src, len) < 0) | ||||
err(1, "UDP connect"); | err(1, "UDP connect"); | ||||
if (getsockname(dummy, (struct sockaddr *)&src, &len) < 0) | if (getsockname(dummy, (struct sockaddr *)&src, &len) < 0) | ||||
err(1, "getsockname"); | err(1, "getsockname"); | ||||
close(dummy); | close(dummy); | ||||
} | } | ||||
/* Save pktinfo in the ancillary data. */ | |||||
if (usepktinfo) | |||||
memcpy(cmsg_pktinfo, &pktinfo, sizeof(pktinfo)); | |||||
if (connect(ssend, (struct sockaddr *)&dst, sizeof(dst)) != 0) | if (connect(ssend, (struct sockaddr *)&dst, sizeof(dst)) != 0) | ||||
err(1, "connect() ssend"); | err(1, "connect() ssend"); | ||||
caph_cache_catpages(); | caph_cache_catpages(); | ||||
if (caph_enter_casper() < 0) | if (caph_enter_casper() < 0) | ||||
err(1, "caph_enter_casper"); | err(1, "caph_enter_casper"); | ||||
cap_rights_init(&rights_stdin); | cap_rights_init(&rights_stdin); | ||||
▲ Show 20 Lines • Show All 282 Lines • ▼ Show 20 Lines | pinger(void) | ||||
icp = (struct icmp6_hdr *)outpack; | icp = (struct icmp6_hdr *)outpack; | ||||
nip = (struct icmp6_nodeinfo *)outpack; | nip = (struct icmp6_nodeinfo *)outpack; | ||||
memset(icp, 0, sizeof(*icp)); | memset(icp, 0, sizeof(*icp)); | ||||
icp->icmp6_cksum = 0; | icp->icmp6_cksum = 0; | ||||
seq = ntransmitted++; | seq = ntransmitted++; | ||||
CLR(seq % mx_dup_ck); | CLR(seq % mx_dup_ck); | ||||
if (options & F_FQDN) { | if (options & F_FQDN) { | ||||
uint16_t s; | |||||
icp->icmp6_type = ICMP6_NI_QUERY; | icp->icmp6_type = ICMP6_NI_QUERY; | ||||
icp->icmp6_code = ICMP6_NI_SUBJ_IPV6; | icp->icmp6_code = ICMP6_NI_SUBJ_IPV6; | ||||
nip->ni_qtype = htons(NI_QTYPE_FQDN); | nip->ni_qtype = htons(NI_QTYPE_FQDN); | ||||
nip->ni_flags = htons(0); | nip->ni_flags = htons(0); | ||||
memcpy(nip->icmp6_ni_nonce, nonce, | memcpy(nip->icmp6_ni_nonce, nonce, | ||||
sizeof(nip->icmp6_ni_nonce)); | sizeof(nip->icmp6_ni_nonce)); | ||||
*(u_int16_t *)nip->icmp6_ni_nonce = htons(seq); | s = htons(seq); | ||||
memcpy(nip->icmp6_ni_nonce, &s, sizeof(s)); | |||||
asomers: Yes, it should be `htons`. The existing code works, though, because `htons` and `ntohs` are… | |||||
Done Inline ActionsYes. It looks like the author wanted to use short when he or she used ntohs and type casting to u_int16_t. Would it be better to use short or uint16_t? jansucan: Yes. It looks like the author wanted to use `short` when he or she used `ntohs` and type… | |||||
Not Done Inline ActionsThe definition of htons says uint16_t, so that would be the best. asomers: The definition of `htons` says `uint16_t`, so that would be the best. | |||||
Done Inline Actionsseq variable in other parts of the code uses u_int16_t. What's the difference between u_int16_t and uint16_t? Shouldn't only one "family" of fixed-width types be used in the code? jansucan: `seq` variable in other parts of the code uses `u_int16_t`. What's the difference between… | |||||
Not Done Inline ActionsTypes like uint16_t were standardized by C99. Code that predates C99 used a plethora of nonstandard alternatives. New code should use the standard types. asomers: Types like `uint16_t` were standardized by C99. Code that predates C99 used a plethora of… | |||||
Done Inline ActionsSo I will keep u_int16_t for the other seq variables and use uint16_t only for the single one. jansucan: So I will keep `u_int16_t` for the other `seq` variables and use `uint16_t` only for the single… | |||||
Done Inline Actionsjansucan: Fixed in D21218 and D21219. | |||||
memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr, | memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr, | ||||
sizeof(dst.sin6_addr)); | sizeof(dst.sin6_addr)); | ||||
cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr); | cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr); | ||||
datalen = 0; | datalen = 0; | ||||
} else if (options & F_FQDNOLD) { | } else if (options & F_FQDNOLD) { | ||||
uint16_t s; | |||||
/* packet format in 03 draft - no Subject data on queries */ | /* packet format in 03 draft - no Subject data on queries */ | ||||
icp->icmp6_type = ICMP6_NI_QUERY; | icp->icmp6_type = ICMP6_NI_QUERY; | ||||
icp->icmp6_code = 0; /* code field is always 0 */ | icp->icmp6_code = 0; /* code field is always 0 */ | ||||
nip->ni_qtype = htons(NI_QTYPE_FQDN); | nip->ni_qtype = htons(NI_QTYPE_FQDN); | ||||
nip->ni_flags = htons(0); | nip->ni_flags = htons(0); | ||||
memcpy(nip->icmp6_ni_nonce, nonce, | memcpy(nip->icmp6_ni_nonce, nonce, | ||||
sizeof(nip->icmp6_ni_nonce)); | sizeof(nip->icmp6_ni_nonce)); | ||||
*(u_int16_t *)nip->icmp6_ni_nonce = htons(seq); | s = htons(seq); | ||||
memcpy(nip->icmp6_ni_nonce, &s, sizeof(s)); | |||||
cc = ICMP6_NIQLEN; | cc = ICMP6_NIQLEN; | ||||
datalen = 0; | datalen = 0; | ||||
} else if (options & F_NODEADDR) { | } else if (options & F_NODEADDR) { | ||||
uint16_t s; | |||||
icp->icmp6_type = ICMP6_NI_QUERY; | icp->icmp6_type = ICMP6_NI_QUERY; | ||||
icp->icmp6_code = ICMP6_NI_SUBJ_IPV6; | icp->icmp6_code = ICMP6_NI_SUBJ_IPV6; | ||||
nip->ni_qtype = htons(NI_QTYPE_NODEADDR); | nip->ni_qtype = htons(NI_QTYPE_NODEADDR); | ||||
nip->ni_flags = naflags; | nip->ni_flags = naflags; | ||||
memcpy(nip->icmp6_ni_nonce, nonce, | memcpy(nip->icmp6_ni_nonce, nonce, | ||||
sizeof(nip->icmp6_ni_nonce)); | sizeof(nip->icmp6_ni_nonce)); | ||||
*(u_int16_t *)nip->icmp6_ni_nonce = htons(seq); | s = htons(seq); | ||||
memcpy(nip->icmp6_ni_nonce, &s, sizeof(s)); | |||||
memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr, | memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr, | ||||
sizeof(dst.sin6_addr)); | sizeof(dst.sin6_addr)); | ||||
cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr); | cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr); | ||||
datalen = 0; | datalen = 0; | ||||
} else if (options & F_SUPTYPES) { | } else if (options & F_SUPTYPES) { | ||||
uint16_t s; | |||||
icp->icmp6_type = ICMP6_NI_QUERY; | icp->icmp6_type = ICMP6_NI_QUERY; | ||||
icp->icmp6_code = ICMP6_NI_SUBJ_FQDN; /*empty*/ | icp->icmp6_code = ICMP6_NI_SUBJ_FQDN; /*empty*/ | ||||
nip->ni_qtype = htons(NI_QTYPE_SUPTYPES); | nip->ni_qtype = htons(NI_QTYPE_SUPTYPES); | ||||
/* we support compressed bitmap */ | /* we support compressed bitmap */ | ||||
nip->ni_flags = NI_SUPTYPE_FLAG_COMPRESS; | nip->ni_flags = NI_SUPTYPE_FLAG_COMPRESS; | ||||
memcpy(nip->icmp6_ni_nonce, nonce, | memcpy(nip->icmp6_ni_nonce, nonce, | ||||
sizeof(nip->icmp6_ni_nonce)); | sizeof(nip->icmp6_ni_nonce)); | ||||
*(u_int16_t *)nip->icmp6_ni_nonce = htons(seq); | s = htons(seq); | ||||
memcpy(nip->icmp6_ni_nonce, &s, sizeof(s)); | |||||
cc = ICMP6_NIQLEN; | cc = ICMP6_NIQLEN; | ||||
datalen = 0; | datalen = 0; | ||||
} else { | } else { | ||||
icp->icmp6_type = ICMP6_ECHO_REQUEST; | icp->icmp6_type = ICMP6_ECHO_REQUEST; | ||||
icp->icmp6_code = 0; | icp->icmp6_code = 0; | ||||
icp->icmp6_id = htons(ident); | icp->icmp6_id = htons(ident); | ||||
icp->icmp6_seq = htons(seq); | icp->icmp6_seq = htons(seq); | ||||
if (timing) { | if (timing) { | ||||
struct timespec tv; | struct timespec tv; | ||||
struct tv32 *tv32; | struct tv32 tv32; | ||||
(void)clock_gettime(CLOCK_MONOTONIC, &tv); | (void)clock_gettime(CLOCK_MONOTONIC, &tv); | ||||
tv32 = (struct tv32 *)&outpack[ICMP6ECHOLEN]; | |||||
/* | /* | ||||
Not Done Inline ActionsThis is a bug. ping6 making two calls to gettimeofday and comparing the (usually subsecond) output to compute a duration. That will produce incorrect results if the system clock changes in the meantime. The correct way to measure durations is with clock_gettime and CLOCK_MONOTONIC. However, this bug is wholly unrelated to your task at hand, so you should fix it separately. asomers: This is a bug. ping6 making two calls to `gettimeofday` and comparing the (usually subsecond)… | |||||
Done Inline ActionsThanks. I looked at the gettimeofday calls in ping6. There are 5 of them. Three are used for getting timeout value for select and two are used for measuring a packet trip time. I think all of them should be replaced by clock_gettime with CLOCK_MONOTONIC. I'm going to do that. jansucan: Thanks. I looked at the `gettimeofday` calls in ping6. There are 5 of them. Three are used for… | |||||
Done Inline Actionsjansucan: It's done D21226. But it's based on master so I will have to rebase it after D21220 is applied. | |||||
* Truncate seconds down to 32 bits in order | * Truncate seconds down to 32 bits in order | ||||
* to fit the timestamp within 8 bytes of the | * to fit the timestamp within 8 bytes of the | ||||
* packet. We're only concerned with | * packet. We're only concerned with | ||||
* durations, not absolute times. | * durations, not absolute times. | ||||
*/ | */ | ||||
tv32->tv32_sec = (uint32_t)htonl(tv.tv_sec); | tv32.tv32_sec = (uint32_t)htonl(tv.tv_sec); | ||||
tv32->tv32_nsec = (uint32_t)htonl(tv.tv_nsec); | tv32.tv32_nsec = (uint32_t)htonl(tv.tv_nsec); | ||||
memcpy(&outpack[ICMP6ECHOLEN], &tv32, sizeof(tv32)); | |||||
Not Done Inline ActionsThis line silently truncates tv.tv_sec down to 32 bits. It's ok given how it's used, but it looks like a bug. Better to annotate with a comment, and/or explicitly cast tv.tv_sec to a uint32_t. asomers: This line silently truncates tv.tv_sec down to 32 bits. It's ok given how it's used, but it… | |||||
Done Inline ActionsFixed in D21220. jansucan: Fixed in D21220. | |||||
} | } | ||||
cc = ICMP6ECHOLEN + datalen; | cc = ICMP6ECHOLEN + datalen; | ||||
} | } | ||||
#ifdef DIAGNOSTIC | #ifdef DIAGNOSTIC | ||||
if (pingerlen() != cc) | if (pingerlen() != cc) | ||||
errx(1, "internal error; length mismatch"); | errx(1, "internal error; length mismatch"); | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 113 Lines • ▼ Show 20 Lines | #define safeputc(c) printf((isprint((c)) ? "%c" : "\\%03o"), c) | ||||
struct icmp6_nodeinfo *ni; | struct icmp6_nodeinfo *ni; | ||||
int i; | int i; | ||||
int hoplim; | int hoplim; | ||||
struct sockaddr *from; | struct sockaddr *from; | ||||
int fromlen; | int fromlen; | ||||
u_char *cp = NULL, *dp, *end = buf + cc; | u_char *cp = NULL, *dp, *end = buf + cc; | ||||
struct in6_pktinfo *pktinfo = NULL; | struct in6_pktinfo *pktinfo = NULL; | ||||
struct timespec tv, tp; | struct timespec tv, tp; | ||||
struct tv32 *tpp; | struct tv32 tpp; | ||||
double triptime = 0; | double triptime = 0; | ||||
int dupflag; | int dupflag; | ||||
size_t off; | size_t off; | ||||
int oldfqdn; | int oldfqdn; | ||||
u_int16_t seq; | u_int16_t seq; | ||||
char dnsname[MAXDNAME + 1]; | char dnsname[MAXDNAME + 1]; | ||||
(void)clock_gettime(CLOCK_MONOTONIC, &tv); | (void)clock_gettime(CLOCK_MONOTONIC, &tv); | ||||
Show All 28 Lines | if ((pktinfo = get_rcvpktinfo(mhdr)) == NULL) { | ||||
warnx("failed to get receiving packet information"); | warnx("failed to get receiving packet information"); | ||||
return; | return; | ||||
} | } | ||||
if (icp->icmp6_type == ICMP6_ECHO_REPLY && myechoreply(icp)) { | if (icp->icmp6_type == ICMP6_ECHO_REPLY && myechoreply(icp)) { | ||||
seq = ntohs(icp->icmp6_seq); | seq = ntohs(icp->icmp6_seq); | ||||
++nreceived; | ++nreceived; | ||||
if (timing) { | if (timing) { | ||||
tpp = (struct tv32 *)(icp + 1); | memcpy(&tpp, icp + 1, sizeof(tpp)); | ||||
tp.tv_sec = ntohl(tpp->tv32_sec); | tp.tv_sec = ntohl(tpp.tv32_sec); | ||||
tp.tv_nsec = ntohl(tpp->tv32_nsec); | tp.tv_nsec = ntohl(tpp.tv32_nsec); | ||||
timespecsub(&tv, &tp, &tv); | timespecsub(&tv, &tp, &tv); | ||||
triptime = ((double)tv.tv_sec) * 1000.0 + | triptime = ((double)tv.tv_sec) * 1000.0 + | ||||
((double)tv.tv_nsec) / 1000000.0; | ((double)tv.tv_nsec) / 1000000.0; | ||||
tsum += triptime; | tsum += triptime; | ||||
tsumsq += triptime * triptime; | tsumsq += triptime * triptime; | ||||
if (triptime < tmin) | if (triptime < tmin) | ||||
tmin = triptime; | tmin = triptime; | ||||
if (triptime > tmax) | if (triptime > tmax) | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | else { | ||||
for (i = 8; cp < end; ++i, ++cp, ++dp) { | for (i = 8; cp < end; ++i, ++cp, ++dp) { | ||||
if (*cp != *dp) { | if (*cp != *dp) { | ||||
(void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", i, *dp, *cp); | (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", i, *dp, *cp); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} else if (icp->icmp6_type == ICMP6_NI_REPLY && mynireply(ni)) { | } else if (icp->icmp6_type == ICMP6_NI_REPLY && mynireply(ni)) { | ||||
seq = ntohs(*(u_int16_t *)ni->icmp6_ni_nonce); | memcpy(&seq, ni->icmp6_ni_nonce, sizeof(seq)); | ||||
seq = ntohs(seq); | |||||
++nreceived; | ++nreceived; | ||||
if (TST(seq % mx_dup_ck)) { | if (TST(seq % mx_dup_ck)) { | ||||
++nrepeats; | ++nrepeats; | ||||
--nreceived; | --nreceived; | ||||
dupflag = 1; | dupflag = 1; | ||||
} else { | } else { | ||||
SET(seq % mx_dup_ck); | SET(seq % mx_dup_ck); | ||||
dupflag = 0; | dupflag = 0; | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | default: /* XXX: for backward compatibility */ | ||||
dnsname[strlen(dnsname) - 1] = '\0'; | dnsname[strlen(dnsname) - 1] = '\0'; | ||||
cp++; | cp++; | ||||
} | } | ||||
printf("%s%s", i > 0 ? "," : "", | printf("%s%s", i > 0 ? "," : "", | ||||
dnsname); | dnsname); | ||||
} | } | ||||
} | } | ||||
if (options & F_VERBOSE) { | if (options & F_VERBOSE) { | ||||
u_long t; | |||||
int32_t ttl; | int32_t ttl; | ||||
int comma = 0; | int comma = 0; | ||||
(void)printf(" ("); /*)*/ | (void)printf(" ("); /*)*/ | ||||
switch (ni->ni_code) { | switch (ni->ni_code) { | ||||
case ICMP6_NI_REFUSED: | case ICMP6_NI_REFUSED: | ||||
(void)printf("refused"); | (void)printf("refused"); | ||||
comma++; | comma++; | ||||
break; | break; | ||||
case ICMP6_NI_UNKNOWN: | case ICMP6_NI_UNKNOWN: | ||||
(void)printf("unknown qtype"); | (void)printf("unknown qtype"); | ||||
comma++; | comma++; | ||||
break; | break; | ||||
} | } | ||||
if ((end - (u_char *)ni) < ICMP6_NIRLEN) { | if ((end - (u_char *)ni) < ICMP6_NIRLEN) { | ||||
/* case of refusion, unknown */ | /* case of refusion, unknown */ | ||||
/*(*/ | /*(*/ | ||||
putchar(')'); | putchar(')'); | ||||
goto fqdnend; | goto fqdnend; | ||||
} | } | ||||
ttl = (int32_t)ntohl(*(u_long *)&buf[off+ICMP6ECHOLEN+8]); | memcpy(&t, &buf[off+ICMP6ECHOLEN+8], sizeof(t)); | ||||
ttl = (int32_t)ntohl(t); | |||||
if (comma) | if (comma) | ||||
printf(","); | printf(","); | ||||
if (!(ni->ni_flags & NI_FQDN_FLAG_VALIDTTL)) { | if (!(ni->ni_flags & NI_FQDN_FLAG_VALIDTTL)) { | ||||
(void)printf("TTL=%d:meaningless", | (void)printf("TTL=%d:meaningless", | ||||
(int)ttl); | (int)ttl); | ||||
} else { | } else { | ||||
if (ttl < 0) { | if (ttl < 0) { | ||||
(void)printf("TTL=%d:invalid", | (void)printf("TTL=%d:invalid", | ||||
▲ Show 20 Lines • Show All 349 Lines • ▼ Show 20 Lines | pr_nodeaddr(struct icmp6_nodeinfo *ni, int nilen) | ||||
* is incomplete. We assume the latest draft by default. | * is incomplete. We assume the latest draft by default. | ||||
*/ | */ | ||||
if (nilen % (sizeof(u_int32_t) + sizeof(struct in6_addr)) == 0) | if (nilen % (sizeof(u_int32_t) + sizeof(struct in6_addr)) == 0) | ||||
withttl = 1; | withttl = 1; | ||||
while (nilen > 0) { | while (nilen > 0) { | ||||
u_int32_t ttl; | u_int32_t ttl; | ||||
if (withttl) { | if (withttl) { | ||||
/* XXX: alignment? */ | uint32_t t; | ||||
ttl = (u_int32_t)ntohl(*(u_int32_t *)cp); | |||||
memcpy(&t, cp, sizeof(t)); | |||||
ttl = (u_int32_t)ntohl(t); | |||||
cp += sizeof(u_int32_t); | cp += sizeof(u_int32_t); | ||||
nilen -= sizeof(u_int32_t); | nilen -= sizeof(u_int32_t); | ||||
} | } | ||||
if (inet_ntop(AF_INET6, cp, ntop_buf, sizeof(ntop_buf)) == | if (inet_ntop(AF_INET6, cp, ntop_buf, sizeof(ntop_buf)) == | ||||
NULL) | NULL) | ||||
strlcpy(ntop_buf, "?", sizeof(ntop_buf)); | strlcpy(ntop_buf, "?", sizeof(ntop_buf)); | ||||
printf(" %s", ntop_buf); | printf(" %s", ntop_buf); | ||||
Show All 22 Lines | get_hoplim(struct msghdr *mhdr) | ||||
for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; | for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; | ||||
cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { | cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { | ||||
if (cm->cmsg_len == 0) | if (cm->cmsg_len == 0) | ||||
return(-1); | return(-1); | ||||
if (cm->cmsg_level == IPPROTO_IPV6 && | if (cm->cmsg_level == IPPROTO_IPV6 && | ||||
cm->cmsg_type == IPV6_HOPLIMIT && | cm->cmsg_type == IPV6_HOPLIMIT && | ||||
cm->cmsg_len == CMSG_LEN(sizeof(int))) | cm->cmsg_len == CMSG_LEN(sizeof(int))) { | ||||
return(*(int *)CMSG_DATA(cm)); | int r; | ||||
memcpy(&r, CMSG_DATA(cm), sizeof(r)); | |||||
return(r); | |||||
} | } | ||||
} | |||||
return(-1); | return(-1); | ||||
} | } | ||||
static struct in6_pktinfo * | static struct in6_pktinfo * | ||||
get_rcvpktinfo(struct msghdr *mhdr) | get_rcvpktinfo(struct msghdr *mhdr) | ||||
{ | { | ||||
static struct in6_pktinfo pi; | |||||
struct cmsghdr *cm; | struct cmsghdr *cm; | ||||
for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; | for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; | ||||
cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { | cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { | ||||
if (cm->cmsg_len == 0) | if (cm->cmsg_len == 0) | ||||
return(NULL); | return(NULL); | ||||
if (cm->cmsg_level == IPPROTO_IPV6 && | if (cm->cmsg_level == IPPROTO_IPV6 && | ||||
cm->cmsg_type == IPV6_PKTINFO && | cm->cmsg_type == IPV6_PKTINFO && | ||||
cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) | cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) { | ||||
return((struct in6_pktinfo *)CMSG_DATA(cm)); | memcpy(&pi, CMSG_DATA(cm), sizeof(pi)); | ||||
return(&pi); | |||||
} | } | ||||
} | |||||
return(NULL); | return(NULL); | ||||
} | } | ||||
static int | static int | ||||
get_pathmtu(struct msghdr *mhdr) | get_pathmtu(struct msghdr *mhdr) | ||||
{ | { | ||||
#ifdef IPV6_RECVPATHMTU | #ifdef IPV6_RECVPATHMTU | ||||
struct cmsghdr *cm; | struct cmsghdr *cm; | ||||
struct ip6_mtuinfo *mtuctl = NULL; | struct ip6_mtuinfo mtuctl; | ||||
for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; | for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm; | ||||
cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { | cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) { | ||||
if (cm->cmsg_len == 0) | if (cm->cmsg_len == 0) | ||||
return(0); | return(0); | ||||
if (cm->cmsg_level == IPPROTO_IPV6 && | if (cm->cmsg_level == IPPROTO_IPV6 && | ||||
cm->cmsg_type == IPV6_PATHMTU && | cm->cmsg_type == IPV6_PATHMTU && | ||||
cm->cmsg_len == CMSG_LEN(sizeof(struct ip6_mtuinfo))) { | cm->cmsg_len == CMSG_LEN(sizeof(struct ip6_mtuinfo))) { | ||||
mtuctl = (struct ip6_mtuinfo *)CMSG_DATA(cm); | memcpy(&mtuctl, CMSG_DATA(cm), sizeof(mtuctl)); | ||||
/* | /* | ||||
* If the notified destination is different from | * If the notified destination is different from | ||||
* the one we are pinging, just ignore the info. | * the one we are pinging, just ignore the info. | ||||
* We check the scope ID only when both notified value | * We check the scope ID only when both notified value | ||||
* and our own value have non-0 values, because we may | * and our own value have non-0 values, because we may | ||||
* have used the default scope zone ID for sending, | * have used the default scope zone ID for sending, | ||||
* in which case the scope ID value is 0. | * in which case the scope ID value is 0. | ||||
*/ | */ | ||||
if (!IN6_ARE_ADDR_EQUAL(&mtuctl->ip6m_addr.sin6_addr, | if (!IN6_ARE_ADDR_EQUAL(&mtuctl.ip6m_addr.sin6_addr, | ||||
&dst.sin6_addr) || | &dst.sin6_addr) || | ||||
(mtuctl->ip6m_addr.sin6_scope_id && | (mtuctl.ip6m_addr.sin6_scope_id && | ||||
dst.sin6_scope_id && | dst.sin6_scope_id && | ||||
mtuctl->ip6m_addr.sin6_scope_id != | mtuctl.ip6m_addr.sin6_scope_id != | ||||
dst.sin6_scope_id)) { | dst.sin6_scope_id)) { | ||||
if ((options & F_VERBOSE) != 0) { | if ((options & F_VERBOSE) != 0) { | ||||
printf("path MTU for %s is notified. " | printf("path MTU for %s is notified. " | ||||
"(ignored)\n", | "(ignored)\n", | ||||
pr_addr((struct sockaddr *)&mtuctl->ip6m_addr, | pr_addr((struct sockaddr *)&mtuctl.ip6m_addr, | ||||
sizeof(mtuctl->ip6m_addr))); | sizeof(mtuctl.ip6m_addr))); | ||||
} | } | ||||
return(0); | return(0); | ||||
} | } | ||||
/* | /* | ||||
* Ignore an invalid MTU. XXX: can we just believe | * Ignore an invalid MTU. XXX: can we just believe | ||||
* the kernel check? | * the kernel check? | ||||
*/ | */ | ||||
if (mtuctl->ip6m_mtu < IPV6_MMTU) | if (mtuctl.ip6m_mtu < IPV6_MMTU) | ||||
return(0); | return(0); | ||||
/* notification for our destination. return the MTU. */ | /* notification for our destination. return the MTU. */ | ||||
return((int)mtuctl->ip6m_mtu); | return((int)mtuctl.ip6m_mtu); | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
return(0); | return(0); | ||||
} | } | ||||
/* | /* | ||||
* onint -- | * onint -- | ||||
▲ Show 20 Lines • Show All 354 Lines • ▼ Show 20 Lines | if ((size_t)(end - (u_char *)ip6) < sizeof(*ip6)) { | ||||
goto trunc; | goto trunc; | ||||
} | } | ||||
pr_iph(ip6); | pr_iph(ip6); | ||||
hlen = sizeof(*ip6); | hlen = sizeof(*ip6); | ||||
nh = ip6->ip6_nxt; | nh = ip6->ip6_nxt; | ||||
cp += hlen; | cp += hlen; | ||||
while (end - cp >= 8) { | while (end - cp >= 8) { | ||||
struct ah ah; | |||||
switch (nh) { | switch (nh) { | ||||
case IPPROTO_HOPOPTS: | case IPPROTO_HOPOPTS: | ||||
printf("HBH "); | printf("HBH "); | ||||
hlen = (((struct ip6_hbh *)cp)->ip6h_len+1) << 3; | hlen = (((struct ip6_hbh *)cp)->ip6h_len+1) << 3; | ||||
nh = ((struct ip6_hbh *)cp)->ip6h_nxt; | nh = ((struct ip6_hbh *)cp)->ip6h_nxt; | ||||
break; | break; | ||||
case IPPROTO_DSTOPTS: | case IPPROTO_DSTOPTS: | ||||
printf("DSTOPT "); | printf("DSTOPT "); | ||||
hlen = (((struct ip6_dest *)cp)->ip6d_len+1) << 3; | hlen = (((struct ip6_dest *)cp)->ip6d_len+1) << 3; | ||||
nh = ((struct ip6_dest *)cp)->ip6d_nxt; | nh = ((struct ip6_dest *)cp)->ip6d_nxt; | ||||
break; | break; | ||||
case IPPROTO_FRAGMENT: | case IPPROTO_FRAGMENT: | ||||
printf("FRAG "); | printf("FRAG "); | ||||
hlen = sizeof(struct ip6_frag); | hlen = sizeof(struct ip6_frag); | ||||
nh = ((struct ip6_frag *)cp)->ip6f_nxt; | nh = ((struct ip6_frag *)cp)->ip6f_nxt; | ||||
break; | break; | ||||
case IPPROTO_ROUTING: | case IPPROTO_ROUTING: | ||||
printf("RTHDR "); | printf("RTHDR "); | ||||
hlen = (((struct ip6_rthdr *)cp)->ip6r_len+1) << 3; | hlen = (((struct ip6_rthdr *)cp)->ip6r_len+1) << 3; | ||||
nh = ((struct ip6_rthdr *)cp)->ip6r_nxt; | nh = ((struct ip6_rthdr *)cp)->ip6r_nxt; | ||||
break; | break; | ||||
#ifdef IPSEC | #ifdef IPSEC | ||||
case IPPROTO_AH: | case IPPROTO_AH: | ||||
printf("AH "); | printf("AH "); | ||||
hlen = (((struct ah *)cp)->ah_len+2) << 2; | memcpy(&ah, cp, sizeof(ah)); | ||||
nh = ((struct ah *)cp)->ah_nxt; | hlen = (ah.ah_len+2) << 2; | ||||
nh = ah.ah_nxt; | |||||
break; | break; | ||||
#endif | #endif | ||||
case IPPROTO_ICMPV6: | case IPPROTO_ICMPV6: | ||||
printf("ICMP6: type = %d, code = %d\n", | printf("ICMP6: type = %d, code = %d\n", | ||||
*cp, *(cp + 1)); | *cp, *(cp + 1)); | ||||
return; | return; | ||||
case IPPROTO_ESP: | case IPPROTO_ESP: | ||||
printf("ESP\n"); | printf("ESP\n"); | ||||
▲ Show 20 Lines • Show All 197 Lines • Show Last 20 Lines |
Yes, it should be htons. The existing code works, though, because htons and ntohs are identical. My bigger worry is about the type of seq. Shouldn't it be short instead of int?