diff --git a/usr.sbin/ndp/ndp.c b/usr.sbin/ndp/ndp.c --- a/usr.sbin/ndp/ndp.c +++ b/usr.sbin/ndp/ndp.c @@ -453,10 +453,7 @@ sdl_m.sdl_alen = 6; while (argc-- > 0) { if (strncmp(argv[0], "temp", 4) == 0) { - struct timeval now; - - gettimeofday(&now, 0); - opts.expire_time = now.tv_sec + 20 * 60; + opts.expire_time = 20 * 60; } else if (strncmp(argv[0], "proxy", 5) == 0) opts.flags |= RTF_ANNOUNCE; argv++; @@ -957,7 +954,11 @@ case RTM_ADD: rtm->rtm_addrs |= RTA_GATEWAY; if (opts.expire_time) { - rtm->rtm_rmx.rmx_expire = opts.expire_time; + struct timespec uptime; + clock_gettime(CLOCK_UPTIME_FAST, &uptime); + + /* XXX: kernel expects uptime here */ + rtm->rtm_rmx.rmx_expire = uptime.tv_sec + opts.expire_time; rtm->rtm_inits = RTV_EXPIRE; } rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA); diff --git a/usr.sbin/ndp/ndp_netlink.c b/usr.sbin/ndp/ndp_netlink.c --- a/usr.sbin/ndp/ndp_netlink.c +++ b/usr.sbin/ndp/ndp_netlink.c @@ -481,11 +481,16 @@ hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; struct ndmsg *ndmsg = snl_reserve_msg_object(&nw, struct ndmsg); if (ndmsg != NULL) { - uint8_t nl_flags = NTF_STICKY; + uint8_t nl_flags = 0; ndmsg->ndm_family = AF_INET6; ndmsg->ndm_ifindex = ifindex; - ndmsg->ndm_state = NUD_PERMANENT; + if (opts.expire_time == 0) { + nl_flags |= NTF_STICKY; + ndmsg->ndm_state = NUD_PERMANENT; + } else { + ndmsg->ndm_state = NUD_NONE; + } if (opts.flags & RTF_ANNOUNCE) nl_flags |= NTF_PROXY; @@ -494,6 +499,15 @@ snl_add_msg_attr_ip(&nw, NDA_DST, (struct sockaddr *)dst); snl_add_msg_attr(&nw, NDA_LLADDR, sdl->sdl_alen, LLADDR(sdl)); + if (opts.expire_time > 0) { + struct timeval now; + + gettimeofday(&now, 0); + int off = snl_add_msg_attr_nested(&nw, NDA_FREEBSD); + snl_add_msg_attr_u32(&nw, NDAF_NEXT_STATE_TS, now.tv_sec + opts.expire_time); + snl_end_attr_nested(&nw, off); + } + if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(&ss, hdr)) { snl_free(&ss); return (1);