diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 463d8aa073c5..013bfa025999 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -364,6 +364,7 @@ in6_control(so, cmd, data, ifp, td)
 		/* FALLTHROUGH */
 	case OSIOCGIFINFO_IN6:
 	case SIOCGIFINFO_IN6:
+	case SIOCSIFINFO_IN6:
 	case SIOCGDRLST_IN6:
 	case SIOCGPRLST_IN6:
 	case SIOCGNBRINFO_IN6:
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index 34f52fde88ea..a718c2dc085e 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -404,6 +404,7 @@ struct	in6_rrenumreq {
 #define OSIOCGIFINFO_IN6	_IOWR('i', 76, struct in6_ondireq)
 #endif
 #define SIOCGIFINFO_IN6		_IOWR('i', 108, struct in6_ndireq)
+#define SIOCSIFINFO_IN6		_IOWR('i', 109, struct in6_ndireq)
 #define SIOCSNDFLUSH_IN6	_IOWR('i', 77, struct in6_ifreq)
 #define SIOCGNBRINFO_IN6	_IOWR('i', 78, struct in6_nbrinfo)
 #define SIOCSPFXFLUSH_IN6	_IOWR('i', 79, struct in6_ifreq)
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 0707a29ca428..44228fd817ec 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1426,6 +1426,7 @@ nd6_ioctl(cmd, data, ifp)
 
 		break;
 	case OSIOCGIFINFO_IN6:
+#define ND	ndi->ndi
 		/* XXX: old ndp(8) assumes a positive value for linkmtu. */
 		bzero(&ndi->ndi, sizeof(ndi->ndi));
 		ndi->ndi.linkmtu = IN6_LINKMTU(ifp);
@@ -1441,9 +1442,38 @@ nd6_ioctl(cmd, data, ifp)
 		ndi->ndi = *ND_IFINFO(ifp);
 		ndi->ndi.linkmtu = IN6_LINKMTU(ifp);
 		break;
+	case SIOCSIFINFO_IN6:
+		/*
+		 * used to change host variables from userland.
+		 * intented for a use on router to reflect RA configurations.
+		 */
+		/* 0 means 'unspecified' */
+		if (ND.linkmtu != 0) {
+			if (ND.linkmtu < IPV6_MMTU ||
+			    ND.linkmtu > IN6_LINKMTU(ifp)) {
+				error = EINVAL;
+				break;
+			}
+			ND_IFINFO(ifp)->linkmtu = ND.linkmtu;
+		}
+
+		if (ND.basereachable != 0) {
+			int obasereachable = ND_IFINFO(ifp)->basereachable;
+
+			ND_IFINFO(ifp)->basereachable = ND.basereachable;
+			if (ND.basereachable != obasereachable)
+				ND_IFINFO(ifp)->reachable =
+				    ND_COMPUTE_RTIME(ND.basereachable);
+		}
+		if (ND.retrans != 0)
+			ND_IFINFO(ifp)->retrans = ND.retrans;
+		if (ND.chlim != 0)
+			ND_IFINFO(ifp)->chlim = ND.chlim;
+		/* FALLTHROUGH */
 	case SIOCSIFINFO_FLAGS:
 		ND_IFINFO(ifp)->flags = ndi->ndi.flags;
 		break;
+#undef ND
 	case SIOCSNDFLUSH_IN6:	/* XXX: the ioctl name is confusing... */
 		/* flush default router list */
 		/*
diff --git a/usr.sbin/ndp/ndp.8 b/usr.sbin/ndp/ndp.8
index 9d853827c0ea..4d99527d781f 100644
--- a/usr.sbin/ndp/ndp.8
+++ b/usr.sbin/ndp/ndp.8
@@ -63,7 +63,7 @@
 .Op Fl nt
 .Fl i
 .Ar interface
-.Op Ar flags ...
+.Op Ar expressions ...
 .Nm
 .Op Fl nt
 .Fl I Op Ar interface | Li delete
@@ -153,19 +153,20 @@ The
 will be used as the default.
 .It Fl I Li delete
 The current default interface will be deleted from the kernel.
-.It Fl i Ar interface Op Ar flags ...
+.It Fl i Ar interface Op Ar expressions ...
 View ND information for the specified interface.
 If additional arguments
-.Ar flags
+.Ar expressions
 are given,
 .Nm
-sets or clears the specified flags for the interface.
-Each flag should be separated by white spaces or tab characters.
-Possible flags are as follows.
-All of the flags can begin with the
+sets or clears the flags or variables for the interface as specified in
+the expression.
+Each expression should be separated by white spaces or tab characters.
+Possible expressions are as follows.
+Some of the expressions can begin with the
 special character
 .Ql - ,
-which means the flag should be cleared.
+which means the flag specified in the expression should be cleared.
 Note that you need
 .Fl -
 before
@@ -209,6 +210,18 @@ a certain failure of Duplicate Address Detection.
 While the flag can be set or cleared by hand with the
 .Nm
 command, it is not generally advisable to modify this flag manually.
+.It Xo
+.Ic basereachable=(number)
+.Xc
+Specify the BaseReachbleTimer on the interface in millisecond.
+.It Xo
+.Ic retrans=(number)
+.Xc
+Specify the RetransTimer on the interface in millisecond.
+.It Xo
+.Ic curhlim=(number)
+.Xc
+Specify the Cur Hop Limit on the interface.
 .El
 .It Fl n
 Do not try to resolve numeric addresses to hostnames.
diff --git a/usr.sbin/ndp/ndp.c b/usr.sbin/ndp/ndp.c
index 9287f9a4efe4..5068ce9a761a 100644
--- a/usr.sbin/ndp/ndp.c
+++ b/usr.sbin/ndp/ndp.c
@@ -969,6 +969,27 @@ ifinfo(ifname, argc, argv)
 				newflags |= (f);\
 		}\
 	} 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; \
+		} \
+	} while (0)
+
 		SETFLAG("disabled", ND6_IFF_IFDISABLED);
 		SETFLAG("nud", ND6_IFF_PERFORMNUD);
 #ifdef ND6_IFF_ACCEPT_RTADV
@@ -977,13 +998,17 @@ ifinfo(ifname, argc, argv)
 #ifdef ND6_IFF_PREFER_SOURCE
 		SETFLAG("prefer_source", ND6_IFF_PREFER_SOURCE);
 #endif
+		SETVALUE("basereachable", ND.basereachable);
+		SETVALUE("retrans", ND.retrans);
+		SETVALUE("curhlim", ND.chlim);
 
 		ND.flags = newflags;
-		if (ioctl(s, SIOCSIFINFO_FLAGS, (caddr_t)&nd) < 0) {
-			err(1, "ioctl(SIOCSIFINFO_FLAGS)");
+		if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd) < 0) {
+			err(1, "ioctl(SIOCSIFINFO_IN6)");
 			/* NOTREACHED */
 		}
 #undef SETFLAG
+#undef SETVALUE
 	}
 
 	if (!ND.initialized) {
@@ -991,6 +1016,10 @@ ifinfo(ifname, argc, argv)
 		/* NOTREACHED */
 	}
 
+	if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) {
+		err(1, "ioctl(SIOCGIFINFO_IN6)");
+		/* NOTREACHED */
+	}
 	printf("linkmtu=%d", ND.linkmtu);
 	printf(", maxmtu=%d", ND.maxmtu);
 	printf(", curhlim=%d", ND.chlim);
diff --git a/usr.sbin/rtadvd/config.c b/usr.sbin/rtadvd/config.c
index 09e4eac659b5..e9e3b97246c9 100644
--- a/usr.sbin/rtadvd/config.c
+++ b/usr.sbin/rtadvd/config.c
@@ -46,6 +46,7 @@
 #include <netinet/ip6.h>
 #include <netinet6/ip6_var.h>
 #include <netinet/icmp6.h>
+#include <netinet6/nd6.h>
 
 #include <arpa/inet.h>
 
@@ -407,6 +408,35 @@ getconfig(intface)
 		exit(1);
 	}
 
+#ifdef SIOCSIFINFO_IN6
+	{
+		struct in6_ndireq ndi;
+		int s;
+
+		if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+			syslog(LOG_ERR, "<%s> socket: %s", __func__,
+			       strerror(errno));
+			exit(1);
+		}
+		memset(&ndi, 0, sizeof(ndi));
+		strncpy(ndi.ifname, intface, IFNAMSIZ);
+		if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&ndi) < 0) {
+			syslog(LOG_INFO, "<%s> ioctl:SIOCGIFINFO_IN6 at %s: %s",
+			     __func__, intface, strerror(errno));
+		}
+
+		/* reflect the RA info to the host variables in kernel */
+		ndi.ndi.chlim = tmp->hoplimit;
+		ndi.ndi.retrans = tmp->retranstimer;
+		ndi.ndi.basereachable = tmp->reachabletime;
+		if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&ndi) < 0) {
+			syslog(LOG_INFO, "<%s> ioctl:SIOCSIFINFO_IN6 at %s: %s",
+			     __func__, intface, strerror(errno));
+		}
+		close(s);
+	}
+#endif
+
 	/* route information */
 #ifdef ROUTEINFO
 	tmp->routes = 0;