Changeset View
Changeset View
Standalone View
Standalone View
head/usr.sbin/traceroute6/traceroute6.c
Show First 20 Lines • Show All 243 Lines • ▼ Show 20 Lines | |||||
* back to yourself. Unfortunately, SO many gateways botch source | * back to yourself. Unfortunately, SO many gateways botch source | ||||
* routing, the thing is almost worthless. Maybe one day... | * routing, the thing is almost worthless. Maybe one day... | ||||
* | * | ||||
* -- Van Jacobson (van@helios.ee.lbl.gov) | * -- Van Jacobson (van@helios.ee.lbl.gov) | ||||
* Tue Dec 20 03:50:13 PST 1988 | * Tue Dec 20 03:50:13 PST 1988 | ||||
*/ | */ | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/capsicum.h> | |||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <sys/uio.h> | #include <sys/uio.h> | ||||
#include <sys/file.h> | #include <sys/file.h> | ||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <arpa/inet.h> | #include <arpa/inet.h> | ||||
#include <libcasper.h> | |||||
#include <casper/cap_dns.h> | |||||
#include <capsicum_helpers.h> | |||||
#include <netdb.h> | #include <netdb.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <err.h> | #include <err.h> | ||||
#ifdef HAVE_POLL | #ifdef HAVE_POLL | ||||
#include <poll.h> | #include <poll.h> | ||||
#endif | #endif | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
Show All 13 Lines | |||||
#endif | #endif | ||||
#include "as.h" | #include "as.h" | ||||
#define DUMMY_PORT 10010 | #define DUMMY_PORT 10010 | ||||
#define MAXPACKET 65535 /* max ip packet size */ | #define MAXPACKET 65535 /* max ip packet size */ | ||||
#ifndef HAVE_GETIPNODEBYNAME | |||||
#define getipnodebyname(x, y, z, u) gethostbyname2((x), (y)) | |||||
#define freehostent(x) | |||||
#endif | |||||
static u_char packet[512]; /* last inbound (icmp) packet */ | static u_char packet[512]; /* last inbound (icmp) packet */ | ||||
static char *outpacket; /* last output packet */ | static char *outpacket; /* last output packet */ | ||||
int main(int, char *[]); | int main(int, char *[]); | ||||
int wait_for_reply(int, struct msghdr *); | int wait_for_reply(int, struct msghdr *); | ||||
#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) | #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) | ||||
int setpolicy(int so, char *policy); | int setpolicy(int so, char *policy); | ||||
#endif | #endif | ||||
void send_probe(int, u_long); | void send_probe(int, u_long); | ||||
void *get_uphdr(struct ip6_hdr *, u_char *); | void *get_uphdr(struct ip6_hdr *, u_char *); | ||||
void capdns_open(void); | |||||
int get_hoplim(struct msghdr *); | int get_hoplim(struct msghdr *); | ||||
double deltaT(struct timeval *, struct timeval *); | double deltaT(struct timeval *, struct timeval *); | ||||
const char *pr_type(int); | const char *pr_type(int); | ||||
int packet_ok(struct msghdr *, int, int, u_char *, u_char *); | int packet_ok(struct msghdr *, int, int, u_char *, u_char *); | ||||
void print(struct msghdr *, int); | void print(struct msghdr *, int); | ||||
const char *inetname(struct sockaddr *); | const char *inetname(struct sockaddr *); | ||||
u_int32_t sctp_crc32c(void *, u_int32_t); | u_int32_t sctp_crc32c(void *, u_int32_t); | ||||
u_int16_t in_cksum(u_int16_t *addr, int); | u_int16_t in_cksum(u_int16_t *addr, int); | ||||
u_int16_t udp_cksum(struct sockaddr_in6 *, struct sockaddr_in6 *, | |||||
void *, u_int32_t); | |||||
u_int16_t tcp_chksum(struct sockaddr_in6 *, struct sockaddr_in6 *, | u_int16_t tcp_chksum(struct sockaddr_in6 *, struct sockaddr_in6 *, | ||||
void *, u_int32_t); | void *, u_int32_t); | ||||
void usage(void); | void usage(void); | ||||
static int rcvsock; /* receive (icmp) socket file descriptor */ | static int rcvsock; /* receive (icmp) socket file descriptor */ | ||||
static int sndsock; /* send (raw/udp) socket file descriptor */ | static int sndsock; /* send (raw/udp) socket file descriptor */ | ||||
static struct msghdr rcvmhdr; | static struct msghdr rcvmhdr; | ||||
static struct iovec rcviov[2]; | static struct iovec rcviov[2]; | ||||
static int rcvhlim; | static int rcvhlim; | ||||
static struct in6_pktinfo *rcvpktinfo; | static struct in6_pktinfo *rcvpktinfo; | ||||
static struct sockaddr_in6 Src, Dst, Rcv; | static struct sockaddr_in6 Src, Dst, Rcv; | ||||
static u_long datalen = 20; /* How much data */ | static u_long datalen = 20; /* How much data */ | ||||
#define ICMP6ECHOLEN 8 | #define ICMP6ECHOLEN 8 | ||||
/* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */ | /* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */ | ||||
static char rtbuf[2064]; | static char rtbuf[2064]; | ||||
static struct ip6_rthdr *rth; | static struct ip6_rthdr *rth; | ||||
static struct cmsghdr *cmsg; | static struct cmsghdr *cmsg; | ||||
static char *source = NULL; | static char *source = NULL; | ||||
static char *hostname; | static char *hostname; | ||||
static cap_channel_t *capdns; | |||||
static u_long nprobes = 3; | static u_long nprobes = 3; | ||||
static u_long first_hop = 1; | static u_long first_hop = 1; | ||||
static u_long max_hops = 30; | static u_long max_hops = 30; | ||||
static u_int16_t srcport; | static u_int16_t srcport; | ||||
static u_int16_t port = 32768+666; /* start udp dest port # for probe packets */ | static u_int16_t port = 32768+666; /* start udp dest port # for probe packets */ | ||||
static u_int16_t ident; | static u_int16_t ident; | ||||
static int options; /* socket options */ | static int options; /* socket options */ | ||||
static int verbose; | static int verbose; | ||||
Show All 17 Lines | main(int argc, char *argv[]) | ||||
struct hostent *hp; | struct hostent *hp; | ||||
size_t size, minlen; | size_t size, minlen; | ||||
uid_t uid; | uid_t uid; | ||||
u_char type, code; | u_char type, code; | ||||
#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) | #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) | ||||
char ipsec_inpolicy[] = "in bypass"; | char ipsec_inpolicy[] = "in bypass"; | ||||
char ipsec_outpolicy[] = "out bypass"; | char ipsec_outpolicy[] = "out bypass"; | ||||
#endif | #endif | ||||
cap_rights_t rights; | |||||
capdns_open(); | |||||
/* | /* | ||||
* Receive ICMP | * Receive ICMP | ||||
*/ | */ | ||||
if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { | if ((rcvsock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { | ||||
perror("socket(ICMPv6)"); | perror("socket(ICMPv6)"); | ||||
exit(5); | exit(5); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | case 'f': | ||||
first_hop = strtoul(optarg, &ep, 0); | first_hop = strtoul(optarg, &ep, 0); | ||||
if (errno || !*optarg || *ep || first_hop > 255) { | if (errno || !*optarg || *ep || first_hop > 255) { | ||||
fprintf(stderr, | fprintf(stderr, | ||||
"traceroute6: invalid min hoplimit.\n"); | "traceroute6: invalid min hoplimit.\n"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
break; | break; | ||||
case 'g': | case 'g': | ||||
/* XXX use after capability mode is entered */ | |||||
hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno); | hp = getipnodebyname(optarg, AF_INET6, 0, &h_errno); | ||||
if (hp == NULL) { | if (hp == NULL) { | ||||
fprintf(stderr, | fprintf(stderr, | ||||
"traceroute6: unknown host %s\n", optarg); | "traceroute6: unknown host %s\n", optarg); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
if (rth == NULL) { | if (rth == NULL) { | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | #endif | ||||
/* | /* | ||||
* Open socket to send probe packets. | * Open socket to send probe packets. | ||||
*/ | */ | ||||
switch (useproto) { | switch (useproto) { | ||||
case IPPROTO_ICMPV6: | case IPPROTO_ICMPV6: | ||||
sndsock = rcvsock; | sndsock = rcvsock; | ||||
break; | break; | ||||
case IPPROTO_UDP: | case IPPROTO_UDP: | ||||
if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { | if ((sndsock = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP)) < 0) { | ||||
perror("socket(SOCK_DGRAM)"); | perror("socket(SOCK_RAW)"); | ||||
exit(5); | exit(5); | ||||
} | } | ||||
break; | break; | ||||
case IPPROTO_NONE: | case IPPROTO_NONE: | ||||
case IPPROTO_SCTP: | case IPPROTO_SCTP: | ||||
case IPPROTO_TCP: | case IPPROTO_TCP: | ||||
if ((sndsock = socket(AF_INET6, SOCK_RAW, useproto)) < 0) { | if ((sndsock = socket(AF_INET6, SOCK_RAW, useproto)) < 0) { | ||||
perror("socket(SOCK_RAW)"); | perror("socket(SOCK_RAW)"); | ||||
Show All 28 Lines | #else | ||||
setlinebuf(stdout); | setlinebuf(stdout); | ||||
#endif | #endif | ||||
memset(&hints, 0, sizeof(hints)); | memset(&hints, 0, sizeof(hints)); | ||||
hints.ai_family = PF_INET6; | hints.ai_family = PF_INET6; | ||||
hints.ai_socktype = SOCK_RAW; | hints.ai_socktype = SOCK_RAW; | ||||
hints.ai_protocol = IPPROTO_ICMPV6; | hints.ai_protocol = IPPROTO_ICMPV6; | ||||
hints.ai_flags = AI_CANONNAME; | hints.ai_flags = AI_CANONNAME; | ||||
error = getaddrinfo(*argv, NULL, &hints, &res); | |||||
error = cap_getaddrinfo(capdns, *argv, NULL, &hints, &res); | |||||
if (error) { | if (error) { | ||||
fprintf(stderr, | fprintf(stderr, | ||||
"traceroute6: %s\n", gai_strerror(error)); | "traceroute6: %s\n", gai_strerror(error)); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
if (res->ai_addrlen != sizeof(Dst)) { | if (res->ai_addrlen != sizeof(Dst)) { | ||||
fprintf(stderr, | fprintf(stderr, | ||||
"traceroute6: size of sockaddr mismatch\n"); | "traceroute6: size of sockaddr mismatch\n"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
memcpy(&Dst, res->ai_addr, res->ai_addrlen); | memcpy(&Dst, res->ai_addr, res->ai_addrlen); | ||||
hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv; | hostname = res->ai_canonname ? strdup(res->ai_canonname) : *argv; | ||||
if (!hostname) { | if (!hostname) { | ||||
fprintf(stderr, "traceroute6: not enough core\n"); | fprintf(stderr, "traceroute6: not enough core\n"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
if (res->ai_next) { | if (res->ai_next) { | ||||
if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, | if (cap_getnameinfo(capdns, res->ai_addr, res->ai_addrlen, hbuf, | ||||
sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) | sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) | ||||
strlcpy(hbuf, "?", sizeof(hbuf)); | strlcpy(hbuf, "?", sizeof(hbuf)); | ||||
fprintf(stderr, "traceroute6: Warning: %s has multiple " | fprintf(stderr, "traceroute6: Warning: %s has multiple " | ||||
"addresses; using %s\n", hostname, hbuf); | "addresses; using %s\n", hostname, hbuf); | ||||
} | } | ||||
freeaddrinfo(res); | freeaddrinfo(res); | ||||
if (*++argv) { | if (*++argv) { | ||||
ep = NULL; | ep = NULL; | ||||
▲ Show 20 Lines • Show All 162 Lines • ▼ Show 20 Lines | #endif /* !(IPSEC && IPSEC_POLICY_IPSEC) */ | ||||
* Source selection | * Source selection | ||||
*/ | */ | ||||
bzero(&Src, sizeof(Src)); | bzero(&Src, sizeof(Src)); | ||||
if (source) { | if (source) { | ||||
memset(&hints, 0, sizeof(hints)); | memset(&hints, 0, sizeof(hints)); | ||||
hints.ai_family = AF_INET6; | hints.ai_family = AF_INET6; | ||||
hints.ai_socktype = SOCK_DGRAM; /*dummy*/ | hints.ai_socktype = SOCK_DGRAM; /*dummy*/ | ||||
hints.ai_flags = AI_NUMERICHOST; | hints.ai_flags = AI_NUMERICHOST; | ||||
error = getaddrinfo(source, "0", &hints, &res); | error = cap_getaddrinfo(capdns, source, "0", &hints, &res); | ||||
if (error) { | if (error) { | ||||
printf("traceroute6: %s: %s\n", source, | printf("traceroute6: %s: %s\n", source, | ||||
gai_strerror(error)); | gai_strerror(error)); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
if (res->ai_addrlen > sizeof(Src)) { | if (res->ai_addrlen > sizeof(Src)) { | ||||
printf("traceroute6: %s: %s\n", source, | printf("traceroute6: %s: %s\n", source, | ||||
gai_strerror(error)); | gai_strerror(error)); | ||||
Show All 19 Lines | if (connect(dummy, (struct sockaddr *)&Nxt, Nxt.sin6_len) < 0) { | ||||
perror("connect"); | perror("connect"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
len = sizeof(Src); | len = sizeof(Src); | ||||
if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) { | if (getsockname(dummy, (struct sockaddr *)&Src, &len) < 0) { | ||||
perror("getsockname"); | perror("getsockname"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
if (getnameinfo((struct sockaddr *)&Src, Src.sin6_len, | if (cap_getnameinfo(capdns, (struct sockaddr *)&Src, Src.sin6_len, | ||||
src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) { | src0, sizeof(src0), NULL, 0, NI_NUMERICHOST)) { | ||||
fprintf(stderr, "getnameinfo failed for source\n"); | fprintf(stderr, "getnameinfo failed for source\n"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
source = src0; | source = src0; | ||||
close(dummy); | close(dummy); | ||||
} | } | ||||
Show All 23 Lines | if (asn == NULL) { | ||||
(void)fflush(stderr); | (void)fflush(stderr); | ||||
as_path = 0; | as_path = 0; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Message to users | * Message to users | ||||
*/ | */ | ||||
if (getnameinfo((struct sockaddr *)&Dst, Dst.sin6_len, hbuf, | if (cap_getnameinfo(capdns, (struct sockaddr *)&Dst, Dst.sin6_len, hbuf, | ||||
sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) | sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) | ||||
strlcpy(hbuf, "(invalid)", sizeof(hbuf)); | strlcpy(hbuf, "(invalid)", sizeof(hbuf)); | ||||
fprintf(stderr, "traceroute6"); | fprintf(stderr, "traceroute6"); | ||||
fprintf(stderr, " to %s (%s)", hostname, hbuf); | fprintf(stderr, " to %s (%s)", hostname, hbuf); | ||||
if (source) | if (source) | ||||
fprintf(stderr, " from %s", source); | fprintf(stderr, " from %s", source); | ||||
fprintf(stderr, ", %lu hops max, %lu byte packets\n", | fprintf(stderr, ", %lu hops max, %lu byte packets\n", | ||||
max_hops, | max_hops, | ||||
datalen + ((useproto == IPPROTO_UDP) ? sizeof(struct udphdr) : 0)); | datalen + ((useproto == IPPROTO_UDP) ? sizeof(struct udphdr) : 0)); | ||||
(void) fflush(stderr); | (void) fflush(stderr); | ||||
if (first_hop > 1) | if (first_hop > 1) | ||||
printf("Skipping %lu intermediate hops\n", first_hop - 1); | printf("Skipping %lu intermediate hops\n", first_hop - 1); | ||||
if (connect(sndsock, (struct sockaddr *)&Dst, | |||||
sizeof(Dst)) != 0) { | |||||
fprintf(stderr, "connect: %s\n", strerror(errno)); | |||||
exit(1); | |||||
} | |||||
/* | /* | ||||
* Here we enter capability mode. Further down access to global | |||||
* namespaces (e.g filesystem) is restricted (see capsicum(4)). | |||||
* We must connect(2) our socket before this point. | |||||
*/ | |||||
if (caph_enter_casper() < 0) { | |||||
fprintf(stderr, "caph_enter_casper: %s\n", strerror(errno)); | |||||
exit(1); | |||||
} | |||||
cap_rights_init(&rights, CAP_SEND, CAP_SETSOCKOPT); | |||||
if (caph_rights_limit(sndsock, &rights) < 0) { | |||||
fprintf(stderr, "caph_rights_limit sndsock: %s\n", | |||||
strerror(errno)); | |||||
exit(1); | |||||
} | |||||
/* | |||||
* Main loop | * Main loop | ||||
*/ | */ | ||||
for (hops = first_hop; hops <= max_hops; ++hops) { | for (hops = first_hop; hops <= max_hops; ++hops) { | ||||
struct in6_addr lastaddr; | struct in6_addr lastaddr; | ||||
int got_there = 0; | int got_there = 0; | ||||
unsigned unreachable = 0; | unsigned unreachable = 0; | ||||
printf("%2lu ", hops); | printf("%2lu ", hops); | ||||
▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
#endif | #endif | ||||
void | void | ||||
send_probe(int seq, u_long hops) | send_probe(int seq, u_long hops) | ||||
{ | { | ||||
struct icmp6_hdr *icp; | struct icmp6_hdr *icp; | ||||
struct sctphdr *sctp; | struct sctphdr *sctp; | ||||
struct udphdr *outudp; | |||||
struct sctp_chunkhdr *chk; | struct sctp_chunkhdr *chk; | ||||
struct sctp_init_chunk *init; | struct sctp_init_chunk *init; | ||||
struct sctp_paramhdr *param; | struct sctp_paramhdr *param; | ||||
struct tcphdr *tcp; | struct tcphdr *tcp; | ||||
int i; | int i; | ||||
i = hops; | i = hops; | ||||
if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, | if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, | ||||
Show All 9 Lines | case IPPROTO_ICMPV6: | ||||
icp->icmp6_type = ICMP6_ECHO_REQUEST; | icp->icmp6_type = ICMP6_ECHO_REQUEST; | ||||
icp->icmp6_code = 0; | icp->icmp6_code = 0; | ||||
icp->icmp6_cksum = 0; | icp->icmp6_cksum = 0; | ||||
icp->icmp6_id = ident; | icp->icmp6_id = ident; | ||||
icp->icmp6_seq = htons(seq); | icp->icmp6_seq = htons(seq); | ||||
break; | break; | ||||
case IPPROTO_UDP: | case IPPROTO_UDP: | ||||
outudp = (struct udphdr *) outpacket; | |||||
outudp->uh_sport = htons(ident); | |||||
outudp->uh_dport = htons(port+seq); | |||||
outudp->uh_ulen = htons(datalen); | |||||
outudp->uh_sum = udp_cksum(&Src, &Dst, outpacket, datalen); | |||||
break; | break; | ||||
case IPPROTO_NONE: | case IPPROTO_NONE: | ||||
/* No space for anything. No harm as seq/tv32 are decorative. */ | /* No space for anything. No harm as seq/tv32 are decorative. */ | ||||
break; | break; | ||||
case IPPROTO_SCTP: | case IPPROTO_SCTP: | ||||
sctp = (struct sctphdr *)outpacket; | sctp = (struct sctphdr *)outpacket; | ||||
sctp->src_port = htons(ident); | sctp->src_port = htons(ident); | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | case IPPROTO_TCP: | ||||
tcp->th_flags = TH_SYN; | tcp->th_flags = TH_SYN; | ||||
tcp->th_sum = 0; | tcp->th_sum = 0; | ||||
tcp->th_sum = tcp_chksum(&Src, &Dst, outpacket, datalen); | tcp->th_sum = tcp_chksum(&Src, &Dst, outpacket, datalen); | ||||
break; | break; | ||||
default: | default: | ||||
fprintf(stderr, "Unknown probe protocol %d.\n", useproto); | fprintf(stderr, "Unknown probe protocol %d.\n", useproto); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
i = sendto(sndsock, (char *)outpacket, datalen, 0, | i = send(sndsock, (char *)outpacket, datalen, 0); | ||||
(struct sockaddr *)&Dst, Dst.sin6_len); | |||||
if (i < 0 || (u_long)i != datalen) { | if (i < 0 || (u_long)i != datalen) { | ||||
if (i < 0) | if (i < 0) | ||||
perror("sendto"); | perror("send"); | ||||
printf("traceroute6: wrote %s %lu chars, ret=%d\n", | printf("traceroute6: wrote %s %lu chars, ret=%d\n", | ||||
hostname, datalen, i); | hostname, datalen, i); | ||||
(void) fflush(stdout); | (void) fflush(stdout); | ||||
} | } | ||||
} | } | ||||
int | int | ||||
get_hoplim(struct msghdr *mhdr) | get_hoplim(struct msghdr *mhdr) | ||||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | #ifdef OLDRAWSOCKET | ||||
struct ip6_hdr *ip; | struct ip6_hdr *ip; | ||||
#endif | #endif | ||||
#ifdef OLDRAWSOCKET | #ifdef OLDRAWSOCKET | ||||
ip = (struct ip6_hdr *) buf; | ip = (struct ip6_hdr *) buf; | ||||
hlen = sizeof(struct ip6_hdr); | hlen = sizeof(struct ip6_hdr); | ||||
if (cc < hlen + sizeof(struct icmp6_hdr)) { | if (cc < hlen + sizeof(struct icmp6_hdr)) { | ||||
if (verbose) { | if (verbose) { | ||||
if (getnameinfo((struct sockaddr *)from, from->sin6_len, | if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len, | ||||
hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) | hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) | ||||
strlcpy(hbuf, "invalid", sizeof(hbuf)); | strlcpy(hbuf, "invalid", sizeof(hbuf)); | ||||
printf("packet too short (%d bytes) from %s\n", cc, | printf("packet too short (%d bytes) from %s\n", cc, | ||||
hbuf); | hbuf); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
cc -= hlen; | cc -= hlen; | ||||
icp = (struct icmp6_hdr *)(buf + hlen); | icp = (struct icmp6_hdr *)(buf + hlen); | ||||
#else | #else | ||||
if (cc < (int)sizeof(struct icmp6_hdr)) { | if (cc < (int)sizeof(struct icmp6_hdr)) { | ||||
if (verbose) { | if (verbose) { | ||||
if (getnameinfo((struct sockaddr *)from, from->sin6_len, | if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len, | ||||
hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) | hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) | ||||
strlcpy(hbuf, "invalid", sizeof(hbuf)); | strlcpy(hbuf, "invalid", sizeof(hbuf)); | ||||
printf("data too short (%d bytes) from %s\n", cc, hbuf); | printf("data too short (%d bytes) from %s\n", cc, hbuf); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
icp = (struct icmp6_hdr *)buf; | icp = (struct icmp6_hdr *)buf; | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | if ((*type == ICMP6_TIME_EXCEEDED && | ||||
case IPPROTO_ICMPV6: | case IPPROTO_ICMPV6: | ||||
icmp = (struct icmp6_hdr *)up; | icmp = (struct icmp6_hdr *)up; | ||||
if (icmp->icmp6_id == ident && | if (icmp->icmp6_id == ident && | ||||
icmp->icmp6_seq == htons(seq)) | icmp->icmp6_seq == htons(seq)) | ||||
return (1); | return (1); | ||||
break; | break; | ||||
case IPPROTO_UDP: | case IPPROTO_UDP: | ||||
udp = (struct udphdr *)up; | udp = (struct udphdr *)up; | ||||
if (udp->uh_sport == htons(srcport) && | if (udp->uh_sport == htons(ident) && | ||||
udp->uh_dport == htons(port + seq)) | udp->uh_dport == htons(port + seq)) | ||||
return (1); | return (1); | ||||
break; | break; | ||||
case IPPROTO_SCTP: | case IPPROTO_SCTP: | ||||
sctp = (struct sctphdr *)up; | sctp = (struct sctphdr *)up; | ||||
if (sctp->src_port != htons(ident) || | if (sctp->src_port != htons(ident) || | ||||
sctp->dest_port != htons(port + seq)) { | sctp->dest_port != htons(port + seq)) { | ||||
break; | break; | ||||
Show All 39 Lines | if (icp->icmp6_id == ident && | ||||
icp->icmp6_seq == htons(seq)) | icp->icmp6_seq == htons(seq)) | ||||
return (1); | return (1); | ||||
} | } | ||||
if (verbose) { | if (verbose) { | ||||
char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN]; | char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN]; | ||||
u_int8_t *p; | u_int8_t *p; | ||||
int i; | int i; | ||||
if (getnameinfo((struct sockaddr *)from, from->sin6_len, | if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len, | ||||
sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0) | sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0) | ||||
strlcpy(sbuf, "invalid", sizeof(sbuf)); | strlcpy(sbuf, "invalid", sizeof(sbuf)); | ||||
printf("\n%d bytes from %s to %s", cc, sbuf, | printf("\n%d bytes from %s to %s", cc, sbuf, | ||||
rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, | rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr, | ||||
dbuf, sizeof(dbuf)) : "?"); | dbuf, sizeof(dbuf)) : "?"); | ||||
printf(": icmp type %d (%s) code %d\n", *type, pr_type(*type), | printf(": icmp type %d (%s) code %d\n", *type, pr_type(*type), | ||||
*code); | *code); | ||||
p = (u_int8_t *)(icp + 1); | p = (u_int8_t *)(icp + 1); | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) { | ||||
cp += hlen; | cp += hlen; | ||||
} | } | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
void | void | ||||
capdns_open() | |||||
{ | |||||
const char *types[] = { "NAME", "ADDR" }; | |||||
int families[1]; | |||||
cap_channel_t *casper; | |||||
casper = cap_init(); | |||||
if (casper == NULL) | |||||
errx(1, "unable to create casper process"); | |||||
capdns = cap_service_open(casper, "system.dns"); | |||||
if (capdns == NULL) | |||||
errx(1, "unable to open system.dns service"); | |||||
if (cap_dns_type_limit(capdns, types, nitems(types)) < 0) | |||||
errx(1, "unable to limit access to system.dns service"); | |||||
families[0] = AF_INET6; | |||||
if (cap_dns_family_limit(capdns, families, nitems(families)) < 0) | |||||
errx(1, "unable to limit access to system.dns service"); | |||||
cap_close(casper); | |||||
} | |||||
void | |||||
print(struct msghdr *mhdr, int cc) | print(struct msghdr *mhdr, int cc) | ||||
{ | { | ||||
struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; | struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; | ||||
char hbuf[NI_MAXHOST]; | char hbuf[NI_MAXHOST]; | ||||
if (getnameinfo((struct sockaddr *)from, from->sin6_len, | if (cap_getnameinfo(capdns, (struct sockaddr *)from, from->sin6_len, | ||||
hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) | hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) | ||||
strlcpy(hbuf, "invalid", sizeof(hbuf)); | strlcpy(hbuf, "invalid", sizeof(hbuf)); | ||||
if (as_path) | if (as_path) | ||||
printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6)); | printf(" [AS%u]", as_lookup(asn, hbuf, AF_INET6)); | ||||
if (nflag) | if (nflag) | ||||
printf(" %s", hbuf); | printf(" %s", hbuf); | ||||
else if (lflag) | else if (lflag) | ||||
printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf); | printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf); | ||||
Show All 30 Lines | if (first && !nflag) { | ||||
if (gethostname(domain, sizeof(domain)) == 0 && | if (gethostname(domain, sizeof(domain)) == 0 && | ||||
(cp = strchr(domain, '.'))) | (cp = strchr(domain, '.'))) | ||||
(void) strlcpy(domain, cp + 1, sizeof(domain)); | (void) strlcpy(domain, cp + 1, sizeof(domain)); | ||||
else | else | ||||
domain[0] = 0; | domain[0] = 0; | ||||
} | } | ||||
cp = NULL; | cp = NULL; | ||||
if (!nflag) { | if (!nflag) { | ||||
if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, | if (cap_getnameinfo(capdns, sa, sa->sa_len, line, sizeof(line), NULL, 0, | ||||
NI_NAMEREQD) == 0) { | NI_NAMEREQD) == 0) { | ||||
if ((cp = strchr(line, '.')) && | if ((cp = strchr(line, '.')) && | ||||
!strcmp(cp + 1, domain)) | !strcmp(cp + 1, domain)) | ||||
*cp = 0; | *cp = 0; | ||||
cp = line; | cp = line; | ||||
} | } | ||||
} | } | ||||
if (cp) | if (cp) | ||||
return cp; | return cp; | ||||
if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, | if (cap_getnameinfo(capdns, sa, sa->sa_len, line, sizeof(line), NULL, 0, | ||||
NI_NUMERICHOST) != 0) | NI_NUMERICHOST) != 0) | ||||
strlcpy(line, "invalid", sizeof(line)); | strlcpy(line, "invalid", sizeof(line)); | ||||
return line; | return line; | ||||
} | } | ||||
/* | /* | ||||
* CRC32C routine for the Stream Control Transmission Protocol | * CRC32C routine for the Stream Control Transmission Protocol | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | in_cksum(u_int16_t *addr, int len) | ||||
/* | /* | ||||
* add back carry outs from top 16 bits to low 16 bits | * add back carry outs from top 16 bits to low 16 bits | ||||
*/ | */ | ||||
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ | sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ | ||||
sum += (sum >> 16); /* add carry */ | sum += (sum >> 16); /* add carry */ | ||||
answer = ~sum; /* truncate to 16 bits */ | answer = ~sum; /* truncate to 16 bits */ | ||||
return (answer); | return (answer); | ||||
} | |||||
u_int16_t | |||||
udp_cksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst, | |||||
void *payload, u_int32_t len) | |||||
{ | |||||
struct { | |||||
struct in6_addr src; | |||||
struct in6_addr dst; | |||||
u_int32_t len; | |||||
u_int8_t zero[3]; | |||||
u_int8_t next; | |||||
} pseudo_hdr; | |||||
u_int16_t sum[2]; | |||||
pseudo_hdr.src = src->sin6_addr; | |||||
pseudo_hdr.dst = dst->sin6_addr; | |||||
pseudo_hdr.len = htonl(len); | |||||
pseudo_hdr.zero[0] = 0; | |||||
pseudo_hdr.zero[1] = 0; | |||||
pseudo_hdr.zero[2] = 0; | |||||
pseudo_hdr.next = IPPROTO_UDP; | |||||
sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr)); | |||||
sum[0] = in_cksum(payload, len); | |||||
return (~in_cksum(sum, sizeof(sum))); | |||||
} | } | ||||
u_int16_t | u_int16_t | ||||
tcp_chksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst, | tcp_chksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst, | ||||
void *payload, u_int32_t len) | void *payload, u_int32_t len) | ||||
{ | { | ||||
struct { | struct { | ||||
struct in6_addr src; | struct in6_addr src; | ||||
Show All 31 Lines |