/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
* All rights reserved.
*
* 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. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*/
/*
* Copyright (c) 1984, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Sun Microsystems, Inc.
*
* 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. 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.
*/
/*
* Copyright (c) 1997
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
* Based on:
* "@(#) Copyright (c) 1984, 1993\n\
* The Regents of the University of California. All rights reserved.\n";
*
* "@(#)arp.c 8.2 (Berkeley) 1/2/94";
*/
static pid_t pid;
static int nflag;
static int tflag;
static int32_t thiszone; /* time difference with gmt */
static int my_s = -1;
static unsigned int repeat = 0;
/*
* Some OSes can produce a route that has the LINK flag but
* has a non-AF_LINK gateway (e.g. fe80::xx%lo0 on FreeBSD
* and BSD/OS, where xx is not the interface identifier on
* lo0). Such routes entry would annoy getnbrinfo() below,
* so we skip them.
* XXX: such routes should have the GATEWAY flag, not the
* LINK flag. However, there is rotten routing software
* that advertises all routes that have the GATEWAY flag.
* Thus, KAME kernel intentionally does not set the LINK flag.
* What is to be fixed is not ndp, but such routing software
* (and the kernel workaround)...
*/
if (sdl->sdl_family != AF_LINK)
continue;
if (!(rtm->rtm_flags & RTF_HOST))
continue;
if (addr) {
if (!IN6_ARE_ADDR_EQUAL(addr, &mysin->sin6_addr))
continue;
found_entry = 1;
} else if (IN6_IS_ADDR_MULTICAST(&mysin->sin6_addr))
continue;
if (dflag) {
(void)delete(rtm, host_buf);
continue;
}
if (IN6_IS_ADDR_LINKLOCAL(&mysin->sin6_addr) ||
IN6_IS_ADDR_MC_LINKLOCAL(&mysin->sin6_addr)) {
uint16_t scopeid = mysin->sin6_scope_id;
inet6_getscopeid(mysin, INET6_IS_ADDR_LINKLOCAL|
INET6_IS_ADDR_MC_LINKLOCAL);
if (scopeid == 0)
mysin->sin6_scope_id = sdl->sdl_index;
}
(void)getnameinfo((struct sockaddr *)(void *)mysin,
(socklen_t)mysin->sin6_len,
host_buf, sizeof(host_buf), NULL, 0,
(nflag ? NI_NUMERICHOST : 0));
if (cflag) {
/* Restore scopeid */
if (IN6_IS_ADDR_LINKLOCAL(&mysin->sin6_addr) ||
IN6_IS_ADDR_MC_LINKLOCAL(&mysin->sin6_addr))
inet6_putscopeid(mysin, INET6_IS_ADDR_LINKLOCAL|
INET6_IS_ADDR_MC_LINKLOCAL);
if ((rtm->rtm_flags & RTF_STATIC) == 0)
(void)delete(rtm, host_buf);
continue;
}
(void)gettimeofday(&tim, 0);
if (tflag)
ts_print(&tim);
NEXTADDR(RTA_DST, sin_m);
NEXTADDR(RTA_GATEWAY, sdl_m);
#ifdef notdef /* we don't support ipv6addr/128 type proxying. */
(void)memset(&so_mask.sin6_addr, 0xff, sizeof(so_mask.sin6_addr));
NEXTADDR(RTA_NETMASK, so_mask);
#endif
rtm->rtm_msglen = cp - (char *)(void *)&m_rtmsg;
doit:
l = rtm->rtm_msglen;
rtm->rtm_seq = ++seq;
rtm->rtm_type = cmd;
if (prog_write(my_s, &m_rtmsg, (size_t)l) == -1) {
if (errno != ESRCH || cmd != RTM_DELETE)
err(1, "writing to routing socket");
}
do {
l = prog_read(my_s, &m_rtmsg, sizeof(m_rtmsg));
} while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid));
if (l < 0)
warn("read from routing socket");
return (0);
}
static void
ifinfo(char *ifname, int argc, char **argv)
{
struct in6_ndireq nd;
int i, s;
u_int32_t newflags;
bool valset = false, flagset = false;
if ((s = prog_socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
err(1, "socket");
(void)memset(&nd, 0, sizeof(nd));
(void)strlcpy(nd.ifname, ifname, sizeof(nd.ifname));
if (prog_ioctl(s, SIOCGIFINFO_IN6, &nd) < 0)
err(1, "ioctl(SIOCGIFINFO_IN6)");
#define ND nd.ndi
newflags = ND.flags;
for (i = 0; i < argc; i++) {
int clear = 0;
char *cp = argv[i];
if (*cp == '-') {
clear = 1;
cp++;
}
#define SETFLAG(s, f) \
do {\
if (strcmp(cp, (s)) == 0) {\
if (clear)\
newflags &= ~(f);\
else\
newflags |= (f);\
flagset = true; \
}\
} while (0)
/*
* XXX: this macro is not 100% correct, in that it matches "nud" against
* "nudbogus". But we just let it go since this is minor.
*/
#define SETVALUE(f, v) \
do { \
char *valptr; \
unsigned long newval; \
v = 0; /* unspecified */ \
if (strncmp(cp, f, strlen(f)) == 0) { \
valptr = strchr(cp, '='); \
if (valptr == NULL) \
err(1, "syntax error in %s field", (f)); \
errno = 0; \
newval = strtoul(++valptr, NULL, 0); \
if (errno) \
err(1, "syntax error in %s's value", (f)); \
v = newval; \
valset = true; \
} \
} while (0)
static const char *
sec2str(time_t total)
{
static char result[256];
int days, hours, mins, secs;
int first = 1;
char *p = result;
char *ep = &result[sizeof(result)];
int n;
days = total / 3600 / 24;
hours = (total / 3600) % 24;
mins = (total / 60) % 60;
secs = total % 60;
if (days) {
first = 0;
n = snprintf(p, (size_t)(ep - p), "%dd", days);
if (n < 0 || n >= ep - p)
return "?";
p += n;
}
if (!first || hours) {
first = 0;
n = snprintf(p, (size_t)(ep - p), "%dh", hours);
if (n < 0 || n >= ep - p)
return "?";
p += n;
}
if (!first || mins) {
first = 0;
n = snprintf(p, (size_t)(ep - p), "%dm", mins);
if (n < 0 || n >= ep - p)
return "?";
p += n;
}
(void)snprintf(p, (size_t)(ep - p), "%ds", secs);
return(result);
}
/*
* Print the timestamp
* from tcpdump/util.c
*/
static void
ts_print(const struct timeval *tvp)
{
int s;
/* Default */
s = (tvp->tv_sec + thiszone) % 86400;
(void)printf("%02d:%02d:%02d.%06u ",
s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tvp->tv_usec);
}
/*
* Returns the difference between gmt and local time in seconds.
* Use gmtime() and localtime() to keep things simple.
*/
static int32_t
gmt2local(time_t t)
{
int dt, dir;
struct tm *gmt, *loc;
struct tm sgmt;
/*
* If the year or julian day is different, we span 00:00 GMT
* and must add or subtract a day. Check the year first to
* avoid problems when the julian day wraps.
*/
dir = loc->tm_year - gmt->tm_year;
if (dir == 0)
dir = loc->tm_yday - gmt->tm_yday;
dt += dir * 24 * 60 * 60;