MFC ver. 1.30:
date: 2007/04/19 15:41:00; author: mtm; state: Exp; lines: +68 -19 o Increase the buffer to hold extra headers to 10240 bytes (the minimum according to RFC3542 sec. 20.1) and allocate it dynamically. o In verbose mode, specify a warning if any control data from recvmsg(2) was truncated because the buffer was too small. o When printing the extra headers make sure not to overrun the buffer boundaries. PR: kern/99425
This commit is contained in:
parent
7106545fe1
commit
b2c7a3ca2a
@ -150,6 +150,7 @@ struct tv32 {
|
||||
#define ICMP6ECHOLEN 8 /* icmp echo header len excluding time */
|
||||
#define ICMP6ECHOTMLEN sizeof(struct tv32)
|
||||
#define ICMP6_NIQLEN (ICMP6ECHOLEN + 8)
|
||||
# define CONTROLLEN 10240 /* ancillary data buffer size RFC3542 20.1 */
|
||||
/* FQDN case, 64 bits of nonce + 32 bits ttl */
|
||||
#define ICMP6_NIRLEN (ICMP6ECHOLEN + 12)
|
||||
#define EXTRA 256 /* for AH and various other headers. weird. */
|
||||
@ -269,8 +270,8 @@ char *dnsdecode(const u_char **, const u_char *, const u_char *,
|
||||
char *, size_t);
|
||||
void pr_pack(u_char *, int, struct msghdr *);
|
||||
void pr_exthdrs(struct msghdr *);
|
||||
void pr_ip6opt(void *);
|
||||
void pr_rthdr(void *);
|
||||
void pr_ip6opt(void *, size_t);
|
||||
void pr_rthdr(void *, size_t);
|
||||
int pr_bitrange(u_int32_t, int, int);
|
||||
void pr_retip(struct ip6_hdr *, u_char *);
|
||||
void summary(void);
|
||||
@ -307,6 +308,7 @@ main(argc, argv)
|
||||
char *e, *target, *ifname = NULL, *gateway = NULL;
|
||||
int ip6optlen = 0;
|
||||
struct cmsghdr *scmsgp = NULL;
|
||||
struct cmsghdr *cm;
|
||||
#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
|
||||
u_long lsockbufsize;
|
||||
int sockbufsize = 0;
|
||||
@ -1057,10 +1059,13 @@ main(argc, argv)
|
||||
seeninfo = 0;
|
||||
#endif
|
||||
|
||||
/* For control (ancillary) data received from recvmsg() */
|
||||
cm = (struct cmsghdr *)malloc(CONTROLLEN);
|
||||
if (cm == NULL)
|
||||
err(1, "malloc");
|
||||
|
||||
for (;;) {
|
||||
struct msghdr m;
|
||||
struct cmsghdr *cm;
|
||||
u_char buf[1024];
|
||||
struct iovec iov[2];
|
||||
|
||||
/* signal handling */
|
||||
@ -1127,9 +1132,9 @@ main(argc, argv)
|
||||
iov[0].iov_len = packlen;
|
||||
m.msg_iov = iov;
|
||||
m.msg_iovlen = 1;
|
||||
cm = (struct cmsghdr *)buf;
|
||||
m.msg_control = (caddr_t)buf;
|
||||
m.msg_controllen = sizeof(buf);
|
||||
memset(cm, 0, CONTROLLEN);
|
||||
m.msg_control = (void *)cm;
|
||||
m.msg_controllen = CONTROLLEN;
|
||||
|
||||
cc = recvmsg(s, &m, 0);
|
||||
if (cc < 0) {
|
||||
@ -1493,6 +1498,9 @@ pr_pack(buf, cc, mhdr)
|
||||
pr_addr(from, fromlen));
|
||||
return;
|
||||
}
|
||||
if (((mhdr->msg_flags & MSG_CTRUNC) != 0) &&
|
||||
(options & F_VERBOSE) != 0)
|
||||
warnx("some control data discarded, insufficient buffer size");
|
||||
icp = (struct icmp6_hdr *)buf;
|
||||
ni = (struct icmp6_nodeinfo *)buf;
|
||||
off = 0;
|
||||
@ -1735,28 +1743,35 @@ void
|
||||
pr_exthdrs(mhdr)
|
||||
struct msghdr *mhdr;
|
||||
{
|
||||
ssize_t bufsize;
|
||||
void *bufp;
|
||||
struct cmsghdr *cm;
|
||||
|
||||
bufsize = 0;
|
||||
bufp = mhdr->msg_control;
|
||||
for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
|
||||
cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
|
||||
if (cm->cmsg_level != IPPROTO_IPV6)
|
||||
continue;
|
||||
|
||||
bufsize = CONTROLLEN - ((caddr_t)CMSG_DATA(cm) - (caddr_t)bufp);
|
||||
if (bufsize <= 0)
|
||||
continue;
|
||||
switch (cm->cmsg_type) {
|
||||
case IPV6_HOPOPTS:
|
||||
printf(" HbH Options: ");
|
||||
pr_ip6opt(CMSG_DATA(cm));
|
||||
pr_ip6opt(CMSG_DATA(cm), (size_t)bufsize);
|
||||
break;
|
||||
case IPV6_DSTOPTS:
|
||||
#ifdef IPV6_RTHDRDSTOPTS
|
||||
case IPV6_RTHDRDSTOPTS:
|
||||
#endif
|
||||
printf(" Dst Options: ");
|
||||
pr_ip6opt(CMSG_DATA(cm));
|
||||
pr_ip6opt(CMSG_DATA(cm), (size_t)bufsize);
|
||||
break;
|
||||
case IPV6_RTHDR:
|
||||
printf(" Routing: ");
|
||||
pr_rthdr(CMSG_DATA(cm));
|
||||
pr_rthdr(CMSG_DATA(cm), (size_t)bufsize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1764,12 +1779,12 @@ pr_exthdrs(mhdr)
|
||||
|
||||
#ifdef USE_RFC2292BIS
|
||||
void
|
||||
pr_ip6opt(void *extbuf)
|
||||
pr_ip6opt(void *extbuf, size_t bufsize)
|
||||
{
|
||||
struct ip6_hbh *ext;
|
||||
int currentlen;
|
||||
u_int8_t type;
|
||||
socklen_t extlen, len;
|
||||
socklen_t extlen, len, origextlen;
|
||||
void *databuf;
|
||||
size_t offset;
|
||||
u_int16_t value2;
|
||||
@ -1780,6 +1795,18 @@ pr_ip6opt(void *extbuf)
|
||||
printf("nxt %u, len %u (%lu bytes)\n", ext->ip6h_nxt,
|
||||
(unsigned int)ext->ip6h_len, (unsigned long)extlen);
|
||||
|
||||
/*
|
||||
* Bounds checking on the ancillary data buffer:
|
||||
* subtract the size of a cmsg structure from the buffer size.
|
||||
*/
|
||||
if (bufsize < (extlen + CMSG_SPACE(0))) {
|
||||
origextlen = extlen;
|
||||
extlen = bufsize - CMSG_SPACE(0);
|
||||
warnx("options truncated, showing only %u (total=%u)",
|
||||
(unsigned int)(extlen / 8 - 1),
|
||||
(unsigned int)(ext->ip6h_len));
|
||||
}
|
||||
|
||||
currentlen = 0;
|
||||
while (1) {
|
||||
currentlen = inet6_opt_next(extbuf, extlen, currentlen,
|
||||
@ -1816,7 +1843,7 @@ pr_ip6opt(void *extbuf)
|
||||
#else /* !USE_RFC2292BIS */
|
||||
/* ARGSUSED */
|
||||
void
|
||||
pr_ip6opt(void *extbuf)
|
||||
pr_ip6opt(void *extbuf, size_t bufsize __unused)
|
||||
{
|
||||
putchar('\n');
|
||||
return;
|
||||
@ -1825,21 +1852,43 @@ pr_ip6opt(void *extbuf)
|
||||
|
||||
#ifdef USE_RFC2292BIS
|
||||
void
|
||||
pr_rthdr(void *extbuf)
|
||||
pr_rthdr(void *extbuf, size_t bufsize)
|
||||
{
|
||||
struct in6_addr *in6;
|
||||
char ntopbuf[INET6_ADDRSTRLEN];
|
||||
struct ip6_rthdr *rh = (struct ip6_rthdr *)extbuf;
|
||||
int i, segments;
|
||||
int i, segments, origsegs, rthsize, size0, size1;
|
||||
|
||||
/* print fixed part of the header */
|
||||
printf("nxt %u, len %u (%d bytes), type %u, ", rh->ip6r_nxt,
|
||||
rh->ip6r_len, (rh->ip6r_len + 1) << 3, rh->ip6r_type);
|
||||
if ((segments = inet6_rth_segments(extbuf)) >= 0)
|
||||
if ((segments = inet6_rth_segments(extbuf)) >= 0) {
|
||||
printf("%d segments, ", segments);
|
||||
else
|
||||
printf("%d left\n", rh->ip6r_segleft);
|
||||
} else {
|
||||
printf("segments unknown, ");
|
||||
printf("%d left\n", rh->ip6r_segleft);
|
||||
printf("%d left\n", rh->ip6r_segleft);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Bounds checking on the ancillary data buffer. When calculating
|
||||
* the number of items to show keep in mind:
|
||||
* - The size of the cmsg structure
|
||||
* - The size of one segment (the size of a Type 0 routing header)
|
||||
* - When dividing add a fudge factor of one in case the
|
||||
* dividend is not evenly divisible by the divisor
|
||||
*/
|
||||
rthsize = (rh->ip6r_len + 1) * 8;
|
||||
if (bufsize < (rthsize + CMSG_SPACE(0))) {
|
||||
origsegs = segments;
|
||||
size0 = inet6_rth_space(IPV6_RTHDR_TYPE_0, 0);
|
||||
size1 = inet6_rth_space(IPV6_RTHDR_TYPE_0, 1);
|
||||
segments -= (rthsize - (bufsize - CMSG_SPACE(0))) /
|
||||
(size1 - size0) + 1;
|
||||
warnx("segments truncated, showing only %d (total=%d)",
|
||||
segments, origsegs);
|
||||
}
|
||||
|
||||
for (i = 0; i < segments; i++) {
|
||||
in6 = inet6_rth_getaddr(extbuf, i);
|
||||
@ -1860,7 +1909,7 @@ pr_rthdr(void *extbuf)
|
||||
#else /* !USE_RFC2292BIS */
|
||||
/* ARGSUSED */
|
||||
void
|
||||
pr_rthdr(void *extbuf)
|
||||
pr_rthdr(void *extbuf, size_t bufsize __unused)
|
||||
{
|
||||
putchar('\n');
|
||||
return;
|
||||
|
Loading…
x
Reference in New Issue
Block a user