[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[DNA-DT] Patch available for DNA on RADVD.
Hi,
I'd like to make this available to the DT early,
but there's not been much SQA.
If you're interested a patch is attached, which
works with RADVD 0.7.3.
I hope it's OK to send this to the DT list...
apologies if it's not.
Greg.
A few differences from DNA:
---------------------------
TSLLAO and SLLAO processing are performed.
The DNAO is currently variant 2,
The scheduling of fastRAs is not checked, and sometimes
sends a fast multicast RA.
No variation in message format is made if the landmark is Y
(easier to not change)
Fast RAs scheduled regardless of RA contents (no landmark).
Most of my heresies have been cut out of this branch, for use
in a later paper, so it should really just be DNA proposal
behaviour.
----------------------------
Here's the build instructions.
patch -p1 --dry-run < ../DNARADVD.0.01.patch
patch -p1 < ../DNARADVD.0.01.patch
./auto; ./configure --sysconfdir=/etc ; make
setting "DNASupport on;"
Should probably be sufficient to start DNA on an Interface.
This may not yet do Hash Based FastRA.
so you may also need:
UnnegotiatedFastRA on;
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/Makefile.am radvddna/Makefile.am
--- radvd/Makefile.am 2004-08-20 17:25:59.000000000 +1000
+++ radvddna/Makefile.am 2005-05-24 16:12:36.727222218 +1000
@@ -23,25 +23,28 @@
########################################################################
COMMON_SRC = log.c socket.c recv.c util.c radvd.h defaults.h pathnames.h \
- includes.h
+ includes.h dna.h
sbin_PROGRAMS = radvd radvdump
radvd_SOURCES = $(COMMON_SRC) radvd.c timer.c send.c process.c interface.c \
- device.c device-common.c gram.y gram.h scanner.l
-radvd_LDADD = -lfl
+ device.c device-common.c gram.y gram.h scanner.l dna.c
+radvd_LDADD = -lfl -lcrypto
+radvd_LDFLAGS = #-static # ARRGH! uml problems GD??
EXTRA_radvd_SOURCES = device-linux.c device-bsd44.c
YFLAGS = -d
radvdump_SOURCES = $(COMMON_SRC) radvdump.c
+radvdump_LDADD = -lcrypto
+radvdump_LDFLAGS = -dynamic #-static # not strictly necessary GD??
man_MANS = radvd.8 radvdump.8 radvd.conf.5
EXTRA_DIST = radvd.8.man radvdump.8.man radvd.conf.5.man VERSION CHANGES \
COPYRIGHT INTRO.html copyright.blurb radvd.conf.example
-BUILT_SOURCES = device.c
+BUILT_SOURCES = device.c gram.c scanner.c gram.h
CLEANFILES = radvd.8 radvdump.8 radvd.conf.5
-DISTCLEANFILES = device.c
+DISTCLEANFILES = device.c gram.c scanner.c gram.h
SUFFIXES = .man
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/auto radvddna/auto
--- radvd/auto 1970-01-01 10:00:00.000000000 +1000
+++ radvddna/auto 2005-05-24 16:30:21.008158773 +1000
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+aclocal
+autoheader
+automake -a
+autoconf
+
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/bug.txt radvddna/bug.txt
--- radvd/bug.txt 1970-01-01 10:00:00.000000000 +1000
+++ radvddna/bug.txt 2005-05-24 13:04:40.214513883 +1000
@@ -0,0 +1,65 @@
+
+
+#0 0x40086391 in _IO_file_sync () from /lib/libc.so.6
+No symbol table info available.
+#1 0x4007d58b in fflush () from /lib/libc.so.6
+No symbol table info available.
+#2 0x0804966f in ?? ()
+No symbol table info available.
+#3 0x08049750 in ?? ()
+No symbol table info available.
+#4 0x0804ad62 in ?? ()
+No symbol table info available.
+#5 0x0804b7fc in ?? ()
+No symbol table info available.
+#6 0x40045928 in sigaction () from /lib/libc.so.6
+No symbol table info available.
+#7 0x40085ff8 in _IO_do_write () from /lib/libc.so.6
+No symbol table info available.
+#8 0x40085f56 in _IO_do_write () from /lib/libc.so.6
+No symbol table info available.
+#9 0x4008632b in _IO_file_overflow () from /lib/libc.so.6
+No symbol table info available.
+#10 0x400870f5 in __overflow () from /lib/libc.so.6
+No symbol table info available.
+#11 0x40082dcf in fputc () from /lib/libc.so.6
+---Type <return> to continue, or q <return> to quit---
+No symbol table info available.
+#12 0x080496e4 in ?? ()
+No symbol table info available.
+#13 0x08049750 in ?? ()
+No symbol table info available.
+#14 0x0804f10f in ?? ()
+No symbol table info available.
+#15 0x0804d4bb in ?? ()
+No symbol table info available.
+#16 0x0804c6a5 in ?? ()
+No symbol table info available.
+#17 0x0804c536 in ?? ()
+No symbol table info available.
+#18 0x0804ab5a in ?? ()
+No symbol table info available.
+#19 0x400356cf in __libc_start_main () from /lib/libc.so.6
+No symbol table info available.
+
+
+ith this command or "print".
+(gdb) x/i 0x0804f10f
+0x804f10f <install_nc_entry+187>: add $0xc,%esp
+(gdb) x/i 0x08049750
+0x8049750 <dlog+36>: jmp 0x804973e <dlog+18>
+(gdb) x/i 0x080496e4
+0x80496e4 <vlog+336>: pop %ecx
+(gdb) f 0x40082dcf
+#0 0x00000000 in ?? ()
+(gdb) x/i 0x40082dcf
+0x40082dcf: Cannot access memory at address 0x40082dcf
+(gdb) x/i 0x0804b7fc
+0x804b7fc <alarm_handler+140>: mov 0xffffffe8(%ebp),%eax
+(gdb) x/i 0x0804ad62
+0x804ad62 <timer_handler+30>: push $0x0
+(gdb) x/i 0x08049750
+0x8049750 <dlog+36>: jmp 0x804973e <dlog+18>
+(gdb) x/i 0x0804966f
+0x804966f <vlog+219>: add $0x10,%esp
+(gdb)
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/defaults.h radvddna/defaults.h
--- radvd/defaults.h 2005-05-24 15:56:49.187348064 +1000
+++ radvddna/defaults.h 2005-05-24 15:59:31.302993238 +1000
@@ -25,6 +25,7 @@
#define MSG_SIZE 4096
#define MAX2(X,Y) ( (( X ) >= ( Y )) ? ( X ) : ( Y ))
+#define MIN2(X,Y) ( (( X ) > ( Y )) ? ( Y ) : ( X ))
/* Router Configuration Variables: */
@@ -46,10 +47,41 @@
#define DFLT_MinDelayBetweenRAs MIN_DELAY_BETWEEN_RAS
#define DFLT_AdvDefaultPreference 0
+#define DFLT_PrefixLandmarking 0
+#define DFLT_CompleteRA 0
+#define DFLT_CompleteRAMaxAdv 8
+#define DFLT_MaxDNAPrefixes 8
+#define DFLT_InitialOverloadTime 15 /* Seconds before accounting */
+#define DFLT_OverloadTime 1800 /* Seconds before lose state */
+
/* Options sent with RA */
#define DFLT_AdvSourceLLAddress 1
+
+
+/* Unnegotiated FastRA */
+#define DFLT_MaxFastRARouters 10
+
+
+/* FastRA token refreshing */
+
+#define DFLT_MaxFastResponses 3 /* 3 fastras?? depletion??*/
+#define DFLT_NumUnicastFastRAs 0 /* testing */
+#define DFLT_MaxUnicastFastRAs 10
+#define DFLT_FastRATokenInterval 1000 /* milliseconds */
+
+/* separation of fast responses in ranked fastras */
+#define DFLT_FastRASeparation 20 /* ms */
+
+/* Process SLLAOs and create static NCEs: */
+
+#define DFLT_RecvSourceLLAddress 0
+
+/* Process Tentative Source Link Layer Address Options */
+
+#define DFLT_RecvTentativeLLAddress 0 /* draft-daley-ipv6-tsllao-01.txt */
+
/* Each prefix has an associated: */
#define DFLT_AdvValidLifetime 2592000 /* seconds */
@@ -73,6 +105,7 @@
#define MIN_DELAY_BETWEEN_RAS_MIPv6 (30.0/1000.0)
#define MAX_RA_DELAY_TIME (1000.0/2.0) /* milliseconds */
+
/* Host constants: */
#define MAX_RTR_SOLICITATION_DELAY 1
@@ -150,6 +183,12 @@
#endif
+/* draft-daley-ipv6-tsllao-00.txt */
+#ifndef ND_OPT_TENTATIVE_SLLA
+#define ND_OPT_TENTATIVE_SLLA 0x11 /* Not assigned yet */
+#endif
+
+
/* Flags */
#ifndef ND_RA_FLAG_HOME_AGENT
@@ -159,11 +198,24 @@
#define ND_OPT_PI_FLAG_RADDR 0x20
#endif
+
+/* TBD unnegotiated FastRA flag */
+#ifndef ND_RA_FLAG_FASTRA
+#define ND_RA_FLAG_FASTRA 0x04 /* DNA flag!! GD */
+#endif
+
+/* TBD DNA Complete RA flag */
+#ifndef ND_RA_FLAG_COMPLETERA
+#define ND_RA_FLAG_COMPLETERA 0x02 /* DNA Flag!! GD */
+#endif
+
+
/* Configurable values */
#define DFLT_HomeAgentPreference 0
#define DFLT_HomeAgentLifetime(iface) DFLT_AdvDefaultLifetime(iface)
+
/* Other */
#define MIN_MinRtrAdvInterval_MIPv6 (3.0/100.0)
@@ -176,7 +228,16 @@
#define MIN_HomeAgentLifetime 1 /* 0 must NOT be used */
#define MAX_HomeAgentLifetime 65520 /* 18.2 hours in secs */
+#define MAX_ResponseOptionLen 64 /* octets */
+
+#define MAX_Outstanding_Unicast DFLT_MaxUnicastFastRAs
+ /* unicast RAs scheduled at any time */
+
+#define FREE_Dynamic_Timers ( MAX_Outstanding_Unicast )
+#define USED_Dynamic_Timers ( ( MAX_Outstanding_Unicast ) + 1 )
+
/* #define MAX_RTR_SOLICITATIONS This MAY be ignored by MIPv6 */
+#define IID_HASH_MASK32 0x00ffffff
#endif
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/device-bsd44.c radvddna/device-bsd44.c
--- radvd/device-bsd44.c 2005-05-24 15:56:49.194347228 +1000
+++ radvddna/device-bsd44.c 2005-05-24 16:17:49.117926202 +1000
@@ -248,3 +248,18 @@
return 0;
}
+
+
+int bind_rtnlsock(void){
+ /* Not yet implemented */
+ return -1;
+}
+
+
+int install_nc_entry(int sock, struct Interface *iface, struct in6_addr *addr, unsigned char *hwaddr,
+ int hwl , int replace){
+ /* Not yet implemented */
+ return;
+}
+
+
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/device-linux.c radvddna/device-linux.c
--- radvd/device-linux.c 2005-05-24 15:56:49.203346154 +1000
+++ radvddna/device-linux.c 2005-05-24 16:17:35.311574529 +1000
@@ -11,6 +11,7 @@
* applies to this software. If your distribution is missing this file, you
* may request it from <lutchann@litech.org>.
*
+ * Greg Daley Sept 2004: Added support for SLLAO NCE installs
*/
#include <config.h>
@@ -19,10 +20,33 @@
#include <defaults.h>
#include <pathnames.h> /* for PATH_PROC_NET_IF_INET6 */
+#ifndef NUD_VALID
+#define NUD_VALID (NUD_REACHABLE|NUD_STALE|NUD_DELAY|NUD_PROBE)
+#endif /* NUD_VALID */
+
+/* rtnetlink socket includes */
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <sys/socket.h>
+
#ifndef IPV6_ADDR_LINKLOCAL
#define IPV6_ADDR_LINKLOCAL 0x0020U
#endif
+static int new_nd_rtnetlink(int sock, int ifindex, unsigned char *dst,
+ unsigned char *lladdr, int lll, int state,
+ int replace);
+static int process_ndmsg(struct ndmsg *ndm, int nll, unsigned char *dst,
+ unsigned char *lladdr, int lll);
+static int check_nd_rtnetlink(int sock, int ifindex, unsigned char *dst,
+ unsigned char *lladdr, int lll);
+static void clean_nl_inbuff(int sock);
+static int get_nlsequence(void);
+static int make_ndmsg(struct nlmsghdr *nlm, unsigned char *dst,
+ unsigned char *lladdr, int lll, int state,
+ int ifindex);
+
/*
* this function gets the hardware type and address of an interface,
* determines the link layer token length and checks it against
@@ -209,6 +233,7 @@
return(0);
}
+
int
get_v4addr(const char *ifn, unsigned int *dst)
{
@@ -247,3 +272,380 @@
return 0;
}
+
+int
+bind_rtnlsock(void)
+{
+ int rtnetlink_socket;
+ struct sockaddr_nl local;
+
+ memset(&local, 0, sizeof(local));
+ local.nl_family = AF_NETLINK;
+
+ if ((rtnetlink_socket =
+ socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE))
+ < 0) {
+ flog(LOG_ERR, "Unable to get a netlink socket: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ if (bind
+ (rtnetlink_socket, (struct sockaddr *) &local,
+ sizeof(local)) < 0) {
+ flog(LOG_ERR, "Unable to bind a netlink socket: %s",
+ strerror(errno));
+ return -1;
+ }
+ return rtnetlink_socket;
+}
+
+/**************************************************************************/
+
+
+
+
+static int
+new_nd_rtnetlink(int sock, int ifindex, unsigned char *dst,
+ unsigned char *lladdr, int lll, int state,
+ int replace)
+{
+ struct {
+ struct nlmsghdr nh;
+ struct ndmsg nd;
+ char attrbuf[360];
+ } req;
+
+ struct ndmsg *ndm;
+ struct nlmsghdr *nlm;
+ int nll;
+
+ memset(&req, 0, sizeof(req));
+
+ nlm = (struct nlmsghdr *) &req;
+
+ nlm->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
+
+ nlm->nlmsg_flags |= (replace ? NLM_F_REPLACE : NLM_F_EXCL);
+ nlm->nlmsg_seq = get_nlsequence();
+ nlm->nlmsg_type = RTM_NEWNEIGH;
+ ndm = NLMSG_DATA(nlm);
+ nlm->nlmsg_len = make_ndmsg(nlm, dst, lladdr, lll, state, ifindex);
+ nll = nlm->nlmsg_len;
+
+ if (send(sock, &req, req.nh.nlmsg_len, 0) < 0) {
+ flog(LOG_ERR, "unable to send netlink message: %s",
+ strerror(errno));
+ return -1;
+ }
+ /*system("/sbin/ip -f inet6 neigh show");*/
+ return 0;
+}
+
+
+static int
+process_ndmsg(struct ndmsg *ndm, int nll, unsigned char *dst,
+ unsigned char *lladdr, int lll)
+{
+ int ret = 0;
+ unsigned int mlll = 0;
+ unsigned char *m_lladdr = NULL;
+ unsigned char *m_dst = NULL;
+ struct rtattr *rta;
+
+ rta = NDA_RTA(ndm);
+
+ dlog(LOG_DEBUG, 5, "NCE process i(%d) t(%d)", ndm->ndm_ifindex,
+ ndm->ndm_type);
+
+ while (RTA_OK(rta, nll)) {
+ switch (rta->rta_type) {
+ case NDA_DST:
+ dlog(LOG_DEBUG, 4,
+ "ent: %x:%x:%x:%x:%x:%x:%x:%x",
+ ntohs(((struct in6_addr *)
+ RTA_DATA(rta))->s6_addr16[0]),
+ ntohs(((struct in6_addr *)
+ RTA_DATA(rta))->s6_addr16[1]),
+ ntohs(((struct in6_addr *)
+ RTA_DATA(rta))->s6_addr16[2]),
+ ntohs(((struct in6_addr *)
+ RTA_DATA(rta))->s6_addr16[3]),
+ ntohs(((struct in6_addr *)
+ RTA_DATA(rta))->s6_addr16[4]),
+ ntohs(((struct in6_addr *)
+ RTA_DATA(rta))->s6_addr16[5]),
+ ntohs(((struct in6_addr *)
+ RTA_DATA(rta))->s6_addr16[6]),
+ ntohs(((struct in6_addr *)
+ RTA_DATA(rta))->s6_addr16[7]));
+
+ dlog(LOG_DEBUG, 4,
+ "dst: %x:%x:%x:%x:%x:%x:%x:%x",
+ ntohs(((struct in6_addr *)
+ dst)->s6_addr16[0]),
+ ntohs(((struct in6_addr *)
+ dst)->s6_addr16[1]),
+ ntohs(((struct in6_addr *)
+ dst)->s6_addr16[2]),
+ ntohs(((struct in6_addr *)
+ dst)->s6_addr16[3]),
+ ntohs(((struct in6_addr *)
+ dst)->s6_addr16[4]),
+ ntohs(((struct in6_addr *)
+ dst)->s6_addr16[5]),
+ ntohs(((struct in6_addr *)
+ dst)->s6_addr16[6]),
+ ntohs(((struct in6_addr *)
+ dst)->s6_addr16[7]));
+
+ if (!memcmp(RTA_DATA(rta), dst,
+ sizeof(struct in6_addr))) {
+ m_dst = RTA_DATA(rta);
+ }
+ break;
+ case NDA_LLADDR:
+ m_lladdr = RTA_DATA(rta);
+ mlll = RTA_PAYLOAD(rta);
+ break;
+ default:
+ break;
+ }
+ rta = RTA_NEXT(rta, nll);
+ }
+ if (m_dst) {
+ /* we have the correct entry */
+ ret = -2;
+ if (ndm->ndm_state & NUD_VALID) {
+ if (m_lladdr && (mlll == lll) && !memcmp(lladdr,
+ m_lladdr,
+ lll *
+ sizeof
+ (unsigned
+ char))) {
+ /* entry matches, update with same state */
+ flog(LOG_ERR, "state:%x "
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ ndm->ndm_state,
+ m_lladdr[0], m_lladdr[1],
+ m_lladdr[2], m_lladdr[3],
+ m_lladdr[4], m_lladdr[5]);
+ ret = ndm->ndm_state;
+ } else { /* conflicting NCE ignores */
+ ret = -1;
+ }
+ }
+ }
+ return ret;
+}
+
+
+
+static int
+check_nd_rtnetlink(int sock, int ifindex, unsigned char *dst,
+ unsigned char *lladdr, int lll)
+{
+ int recvsize;
+ struct {
+ struct nlmsghdr nh;
+ struct ndmsg nd;
+ char attrbuf[3000];
+ } req;
+ unsigned char *m_lladdr = NULL;
+
+ struct ndmsg *ndm;
+ struct nlmsghdr *nlm;
+ int nll;
+ int ret = 0;
+
+ memset(&req, 0, sizeof(struct nlmsghdr) + sizeof(struct ndmsg));
+
+ nlm = (struct nlmsghdr *) &req;
+ nlm->nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH;
+ nlm->nlmsg_seq = get_nlsequence();
+ nlm->nlmsg_type = RTM_GETNEIGH;
+ ndm = NLMSG_DATA(nlm);
+ ndm->ndm_family = AF_INET6;
+ ndm->ndm_ifindex = ifindex;
+ ndm->ndm_type = RTN_UNICAST;
+
+ nlm->nlmsg_len = make_ndmsg(nlm, dst, lladdr, lll, 0, ifindex);
+ nll = nlm->nlmsg_len;
+
+ if (send(sock, &req, nll, 0) < 0) {
+ flog(LOG_ERR, "unable to send netlink message: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ while ((recvsize = recv(sock, &req, sizeof(req), 0)) > 0) {
+ nlm = (struct nlmsghdr *) &req;
+ flog(LOG_WARNING,
+ "received rtnetlink info of length %d %x", recvsize,
+ nlm->nlmsg_flags);
+
+
+ while (NLMSG_OK(nlm, recvsize)) {
+
+ switch (nlm->nlmsg_type) {
+ case RTM_NEWNEIGH:
+ m_lladdr = NULL;
+ ndm = NLMSG_DATA(nlm);
+
+ nll = nlm->nlmsg_len;
+
+ if ((ret =
+ process_ndmsg(ndm, nll, dst, lladdr,
+ lll))) {
+ if (ret == -2)
+ ret = 0;
+ clean_nl_inbuff(sock);
+ return ret;
+ }
+ break;
+ case NLMSG_ERROR:
+ flog(LOG_ERR,
+ "netlink error message received: %s",
+ strerror(-((struct nlmsgerr *)
+ NLMSG_DATA(&req))->error));
+ return 0;
+ case NLMSG_DONE:
+ flog(LOG_WARNING,
+ "netlink done message received");
+ return ret;
+ default:
+ break;
+ }
+ nlm = NLMSG_NEXT(nlm, recvsize);
+ }
+ }
+ if (recvsize < 0) {
+ flog(LOG_ERR, "unable to receive netlink message: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void
+clean_nl_inbuff(int sock)
+{
+ char buff[1500];
+ int recvsize;
+ struct nlmsghdr *nlm;
+
+ while ((recvsize = recv(sock, &buff, sizeof(buff), 0)) > 0) {
+ nlm = (struct nlmsghdr *) &buff;
+ while (NLMSG_OK(nlm, recvsize)) {
+ switch (nlm->nlmsg_type) {
+ case NLMSG_DONE:
+ return;
+ break;
+ default:
+ break;
+ }
+ nlm = NLMSG_NEXT(nlm, recvsize);
+ }
+ }
+ if (recvsize < 0) {
+ flog(LOG_ERR, "unable to receive netlink message: %s",
+ strerror(errno));
+ return;
+ }
+}
+
+static int
+get_nlsequence(void)
+{
+ static int seq = 500;
+ return ++seq;
+}
+
+
+static int
+make_ndmsg(struct nlmsghdr *nlm, unsigned char *dst,
+ unsigned char *lladdr, int lll, int state,
+ int ifindex)
+{
+ struct rtattr *rta;
+ unsigned long *rtap;
+ int i;
+ struct ndmsg *ndm;
+ int nll;
+
+ ndm = NLMSG_DATA(nlm);
+ ndm->ndm_family = AF_INET6;
+ ndm->ndm_type = RTN_UNICAST;
+ ndm->ndm_ifindex = ifindex;
+ ndm->ndm_state = state;
+
+ nlm->nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
+ nll = nlm->nlmsg_len;
+
+ rta = NDA_RTA(ndm);
+
+ rta->rta_type = NDA_DST;
+ rta->rta_len = RTA_LENGTH(sizeof(struct in6_addr));
+ rtap = (unsigned long *) RTA_DATA(rta);
+
+ for (i = 0; i < 4; i++) {
+ /*rtap[i] = ntohl(((struct in6_addr *)dst)->s6_addr32[i]); */
+ rtap[i] = ((struct in6_addr *) dst)->s6_addr32[i];
+ }
+ /*memcpy(RTA_DATA(rta),dst,sizeof(struct in6_addr)); */
+
+ nlm->nlmsg_len =
+ NLMSG_ALIGN(nlm->nlmsg_len) + NLMSG_ALIGN(rta->rta_len);
+ nll = nlm->nlmsg_len;
+
+ rta = RTA_NEXT(rta, nll);
+
+ rta->rta_type = NDA_LLADDR;
+ rta->rta_len = RTA_LENGTH(lll * sizeof(unsigned char));
+ memcpy(RTA_DATA(rta), lladdr, lll);
+
+ nlm->nlmsg_len =
+ NLMSG_ALIGN(nlm->nlmsg_len) + NLMSG_ALIGN(rta->rta_len);
+ nll = nlm->nlmsg_len;
+
+ return nll;
+}
+
+
+void
+install_nc_entry(int sock, struct Interface *iface, struct in6_addr *addr,
+ unsigned char *hwaddr, int hwl, int replace)
+{
+ int state;
+
+ dlog(LOG_DEBUG, 4, "installing NCE on %s replace: %d, len %d",
+ iface->Name, replace, hwl);
+
+
+ state =
+ check_nd_rtnetlink(sock, iface->if_index,
+ (unsigned char *) addr, hwaddr, hwl);
+
+ if (state > 0) {
+ dlog(LOG_DEBUG, 4, "entry match\n");
+ if (new_nd_rtnetlink
+ (sock, iface->if_index, (unsigned char *) addr, hwaddr,
+ hwl, state, replace) < 0) {
+
+ flog(LOG_ERR, "unable to update neighbour cache");
+ return;
+ }
+ } else {
+ dlog(LOG_DEBUG, 4,
+ "no entry or mismatch SLLAO --> STALE\n");
+ if (new_nd_rtnetlink
+ (sock, iface->if_index, (unsigned char *) addr, hwaddr,
+ hwl, NUD_STALE, replace) < 0) {
+ flog(LOG_ERR, "unable to %s neighbour cache entry",
+ (replace ? "replace" : "create"));
+ return;
+ }
+ }
+}
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/dna.c radvddna/dna.c
--- radvd/dna.c 1970-01-01 10:00:00.000000000 +1000
+++ radvddna/dna.c 2005-05-24 15:33:58.685970864 +1000
@@ -0,0 +1,258 @@
+/*
+ * $Id: $
+ *
+ * Authors:
+ * Greg Daley <greg.daley@eng.monash.edu.au>
+ *
+ * This software is Copyright 2004 by the above mentioned author(s),
+ * All Rights Reserved.
+ *
+ * The license which is distributed with this software in the file COPYRIGHT
+ * applies to this software. If your distribution is missing this file, you
+ * may request it from <lutchann@litech.org>.
+ *
+ */
+
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+#include <dna.h>
+
+
+
+ /* For each of the following functions, */
+ /* Option must be complete before return */
+
+int hdr_completera_option(struct Interface *iface, unsigned char *buffer,
+ int offset){
+ struct nd_dna_opt_hdr *dnao;
+ struct timeval tv;
+ struct RtrPrefixList *landlist;
+ struct AdvPrefix *prefix;
+ char addr_str[INET6_ADDRSTRLEN];
+ int i;
+
+ /* Clear the landmark list */
+
+ dnao = (struct nd_dna_opt_hdr *)&buffer[offset];
+ dnao->nd_dna_opt_type=ND_DNA_OPT_TYPE;
+ dnao->nd_dna_opt_rsvd1=0;
+ dnao->nd_dna_opt_rsvd2=0;
+
+ dnao->nd_dna_opt_len=1; /* Initially */
+
+ landlist = iface->DNAPrefixList;
+ gettimeofday(&tv, NULL);
+
+ iface->CurrDNAPrefixes =
+ clean_rtrprefix(landlist, iface->CurrDNAPrefixes, &tv);
+
+ dnao->nd_dna_opt_numprefs=0;
+
+ return sizeof(struct nd_dna_opt_hdr);
+}
+
+
+
+int add_completera_option(struct Interface *iface, unsigned char *buffer,
+ int offset, int optlen, int *complete){
+ struct nd_dna_opt_hdr *dnao;
+ unsigned char *pptr;
+ struct RtrPrefixList *landlist;
+ int skip=0;
+ int i=0,j=0;
+ int poff=0;
+ int oldpref=0;
+ int plens=0;
+ int added=0,newpref=0;
+ char addr_str[INET6_ADDRSTRLEN];
+ struct timeval now;
+
+ if(complete)
+ *complete=0;
+
+ dnao = (struct nd_dna_opt_hdr *)&buffer[offset];
+ pptr = ((unsigned char *)dnao) + sizeof(struct nd_dna_opt_hdr) ;
+ landlist = iface->DNAPrefixList;
+
+ oldpref = (optlen - sizeof(struct nd_dna_opt_hdr)) >>4;
+ plens = dnao->nd_dna_opt_numprefs;
+
+ /* not checking end of message */
+ for (i = 0; (i < iface->CurrDNAPrefixes) && ((oldpref + newpref) <
+ iface->CompleteRAMaxAdv); i++){
+ skip=0;
+ for(poff=0; (poff + sizeof(struct nd_dna_opt_hdr)) < optlen;
+ poff+=IN6_ADDR_SZ){
+
+ if(!memcmp(&pptr[poff], &landlist[i].Prefix,
+ IN6_ADDR_SZ)){
+ skip=1;
+ break;
+ }
+ }
+
+ if(skip)
+ continue;
+
+
+ if(((plens+3)%8)==0){ /* need to shift across */
+ for(j=offset+optlen+added; j >=(offset+3+plens) ; j--){
+ buffer[j+8]= buffer[j];
+ }
+ memset(&buffer[offset+plens+3], 0, 8);
+ added+=8;
+ }
+
+ buffer[offset+plens+3]=landlist[i].plen;
+ plens++;
+ memcpy(&buffer[offset+added+optlen], &landlist[i].Prefix,
+ 8<< (((unsigned)landlist[i].plen) - 64));
+
+ print_addr((struct in6_addr *)&landlist[i].Prefix,addr_str);
+ dlog(LOG_DEBUG,5,"completeRA loop %s/%d", addr_str, landlist[i].plen);
+ added+= 8<< (((unsigned)landlist[i].plen) - 64);
+ newpref++;
+ }
+
+ gettimeofday(&now, NULL);
+ if(complete && i >= iface->CurrDNAPrefixes &&
+ (tv_diff(&now, &iface->DNAOverloadExpiry) >0)){
+ *complete=1;
+ }
+ if(complete)
+ dlog(LOG_DEBUG,5,"completeRA is complete? %d", *complete);
+ dnao->nd_dna_opt_numprefs=plens;
+ dnao->nd_dna_opt_len=(added+optlen) >>3;
+ return added+optlen;
+}
+
+int make_completera_option(struct Interface *iface, unsigned char *buffer,
+ int offset, int *complete){
+
+ int optlen;
+
+ optlen = hdr_completera_option(iface, buffer, offset);
+ optlen = add_completera_option(iface, buffer, offset, optlen, complete);
+
+ return optlen;
+}
+
+
+int check_landmark(struct Interface *iface, struct in6_addr *prefix,
+ struct timeval *now, int ll){
+ int i;
+ char addr_str[INET6_ADDRSTRLEN];
+ int curr;
+ struct AdvPrefix *advprefix;
+ struct RtrPrefixList *landlist;
+
+ print_addr(prefix,addr_str);
+ dlog(LOG_DEBUG,5,"checking landmarks %s",addr_str);
+
+ /* start by inspecting the local prefix list */
+
+ advprefix = iface->AdvPrefixList;
+ while (advprefix)
+ {
+ if (advprefix->enabled && addr_match(&advprefix->Prefix,prefix,
+ ll)){ /* watch out for short prefix lengths...*/
+ return ND_OPT_LANDMARK_FLAGS_SEEN;
+ }
+ advprefix=advprefix->next;
+ }
+
+ landlist=iface->DNAPrefixList;
+ curr=iface->CurrDNAPrefixes;
+
+ for (i = 0; (i < curr) ; i++){
+
+ print_addr(&landlist[i].Prefix,addr_str);
+ dlog(LOG_DEBUG,5,"landmark check loop %d %s",i,addr_str);
+ if(addr_match(&landlist[i].Prefix, prefix, ll) &&
+ (landlist[i].plen == ll)){
+ dlog(LOG_DEBUG,5,"landmark check match %d %f",i,
+ tv_diff(&landlist[i].expiry,now));
+ if(tv_diff(&landlist[i].expiry, now) >= 0){
+ return ND_OPT_LANDMARK_FLAGS_SEEN;
+ }
+ else{
+ return ND_OPT_LANDMARK_FLAGS_UNSEEN;
+ }
+ }
+
+ }
+ return (tv_diff(now, &iface->DNAOverloadExpiry) >0)?
+ ND_OPT_LANDMARK_FLAGS_UNSEEN : ND_OPT_LANDMARK_FLAGS_UNKNOWN;
+}
+
+#if 0
+int prefix_landmark_option(unsigned char *buffer, int offset,
+ unsigned char *new, int nl, int optlen){
+
+ struct nd_dna_opt_hdr *dnao;
+ unsigned char *pptr;
+ int np=0;
+ int skip=0;
+ int i,j,added=0;
+ int poff=0;
+ unsigned char optbuf[1500];
+
+ dnao = (struct nd_dna_opt_hdr *)&buffer[offset];
+ pptr = ((unsigned char *)dnao) + sizeof(struct nd_dna_opt_hdr) ;
+
+ np=dnao->nd_dna_opt_numprefs;
+
+ /* O(N^2)! small N */
+ /* also, not checking end of message or end of option */
+
+ for(i=0; i < nl; i+=IN6_ADDR_SZ){
+ skip=0;
+ for(poff=0; poff < optlen; poff+=IN6_ADDR_SZ){
+ if(!memcmp(&pptr[poff], &new[i], IN6_ADDR_SZ)){
+ skip=1;
+ break;
+ }
+ dlog(LOG_DEBUG,5,"completeRA pfx %d poff: %d ",i, poff);
+ }
+ if(skip)
+ continue;
+
+ if(((np+3)%8)==0){ /* need to shift across */
+ for(j=offset+optlen+added; j >=(offset+3+np) ; j--){
+ buffer[j+8]= buffer[j];
+ }
+ memset(&buffer[offset+np+3], 0, 8);
+ added+=8;
+ }
+ buffer[offset+np+3]=64;
+ np++;
+ memcpy(&buffer[offset+optlen+added],&new[i], IN6_ADDR_SZ);
+ added+=IN6_ADDR_SZ;
+ }
+ dnao->nd_dna_opt_numprefs=np;
+ dnao->nd_dna_opt_len=(added+optlen)>>3;
+ return optlen+added;
+}
+#endif /* 0 */
+
+int make_landmark_option(unsigned char *buffer, int offset,
+ unsigned char *option, uint8_t flags){
+ struct nd_opt_landmark *lmark;
+ char addr_str[INET6_ADDRSTRLEN];
+
+ if(!option)
+ return;
+
+ memcpy(&buffer[offset], option, sizeof(struct nd_opt_landmark));
+ lmark = (struct nd_opt_landmark *)&buffer[offset];
+
+ lmark->nd_opt_landmark_flags=flags;
+
+ print_addr(&lmark->nd_opt_landmark_prefix,addr_str);
+ /**addr_str=0;*/
+ printf("Making Prefix Landmark option for transmission: %hhx %hhx %hhx %s",
+ buffer[offset], buffer[offset+1],buffer[offset+2], addr_str);
+
+ return sizeof (struct nd_opt_landmark);
+}
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/dna.h radvddna/dna.h
--- radvd/dna.h 1970-01-01 10:00:00.000000000 +1000
+++ radvddna/dna.h 2005-05-24 15:28:19.563458364 +1000
@@ -0,0 +1,68 @@
+/*
+ * $Id: $
+ *
+ * Authors:
+ * Greg Daley <Greg.Daley@eng.monash.edu.au>
+ *
+ * This software is Copyright 2004 by the above mentioned author(s),
+ * All Rights Reserved.
+ *
+ * The license which is distributed with this software in the file COPYRIGHT
+ * applies to this software. If your distribution is missing this file, you
+ * may request it from <lutchann@litech.org>.
+ *
+ */
+
+#ifndef ND_DNA_H
+#define ND_DNA_H
+
+
+#include <includes.h>
+
+#ifndef IN6_ADDR_SZ
+#define IN6_ADDR_SZ (sizeof(struct in6_addr))
+#endif /* IN6_ADDR_SZ */
+
+#ifndef ND_DNA_OPT_TYPE
+#define ND_DNA_OPT_TYPE 32
+#endif /* ND_DNA_OPT_TYPE */
+
+#ifndef DNA_PREFIX_ON_LINK_UNKNOWN
+#define DNA_PREFIX_ON_LINK_UNKNOWN 255
+#endif /* PREFIX_ON_LINK_UNKNOWN */
+
+struct nd_dna_opt_hdr{
+
+ uint8_t nd_dna_opt_type;
+ uint8_t nd_dna_opt_len;
+ uint8_t nd_dna_opt_numprefs;
+ uint8_t nd_dna_opt_rsvd1;
+ uint32_t nd_dna_opt_rsvd2;
+};
+
+
+
+#ifndef ND_OPT_LANDMARK
+#define ND_OPT_LANDMARK 0x13
+
+struct nd_opt_landmark{
+ uint8_t nd_opt_landmark_type;
+ uint8_t nd_opt_landmark_len;
+ uint8_t nd_opt_landmark_plen;
+ uint8_t nd_opt_landmark_flags;
+ uint32_t nd_opt_landmark_reserved2;
+ struct in6_addr nd_opt_landmark_prefix;
+};
+
+#define ND_OPT_LANDMARK_FLAGS_SEEN 128
+#define ND_OPT_LANDMARK_FLAGS_UNSEEN 64
+#define ND_OPT_LANDMARK_FLAGS_UNKNOWN 0
+
+#endif /* ND_OPT_LANDMARK*/
+
+
+
+
+int make_completera_option(struct Interface *iface, unsigned char *buffer,
+ int offset, int *complete);
+#endif /* ND_DNA_H */
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/gram.y radvddna/gram.y
--- radvd/gram.y 2005-05-24 15:56:49.206345796 +1000
+++ radvddna/gram.y 2005-05-24 15:59:31.846928298 +1000
@@ -28,6 +28,7 @@
extern int num_lines;
extern char *yytext;
extern int sock;
+extern int rtnl_sock;
static void cleanup(void);
static void yyerror(char *msg);
@@ -71,6 +72,16 @@
%token T_AdvDefaultLifetime
%token T_AdvDefaultPreference
%token T_AdvSourceLLAddress
+%token T_RecvSourceLLAddress
+%token T_RecvTentativeLLAddress
+
+%token T_UnnegotiatedFastRA
+%token T_MaxFastRARouters
+%token T_MaxFastResponses
+
+%token T_FastRASeparation
+%token T_FastRATokenInterval
+%token T_MaxUnicastFastRAs
%token T_AdvOnLink
%token T_AdvAutonomous
@@ -85,12 +96,22 @@
%token T_Base6to4Interface
%token T_UnicastOnly
+
+%token T_PrefixLandmarking
+%token T_MaxDNAPrefixes
+
%token T_HomeAgentPreference
%token T_HomeAgentLifetime
%token T_AdvRoutePreference
%token T_AdvRouteLifetime
+%token T_CompleteRA
+%token T_CompleteRAMaxAdv
+%token T_OverloadTime
+
+%token T_DNASupport
+
%token T_BAD_TOKEN
%type <str> name
@@ -149,6 +170,8 @@
ABORT;
if (setup_allrouters_membership(sock, iface) < 0)
ABORT;
+ if(check_if_addr(iface) < 0 )
+ ABORT;
iface->next = IfaceList;
IfaceList = iface;
@@ -278,6 +301,20 @@
{
iface->AdvSourceLLAddress = $2;
}
+ | T_RecvSourceLLAddress SWITCH ';'
+ {
+ if(rtnl_sock < 0){
+ rtnl_sock = bind_rtnlsock();
+ }
+ iface->RecvSourceLLAddress = $2;
+ }
+ | T_RecvTentativeLLAddress SWITCH ';'
+ {
+ if(rtnl_sock < 0){
+ rtnl_sock = bind_rtnlsock();
+ }
+ iface->RecvTentativeLLAddress = $2;
+ }
| T_AdvIntervalOpt SWITCH ';'
{
iface->AdvIntervalOpt = $2;
@@ -306,6 +343,62 @@
{
iface->UnicastOnly = $2;
}
+ | T_MaxUnicastFastRAs NUMBER ';'
+ {
+ iface->MaxUnicastFastRAs = $2;
+ }
+ | T_FastRASeparation NUMBER ';'
+ {
+ if($2 > 255){
+ iface->FastRASeparation = 255;
+ }
+ else if ($2 > 0){
+ iface->FastRASeparation = $2;
+ }
+ }
+ | T_PrefixLandmarking SWITCH ';'
+ {
+ iface->PrefixLandmarking = $2;
+ }
+ | T_MaxDNAPrefixes NUMBER ';'
+ {
+ iface->MaxDNAPrefixes = $2;
+ }
+ | T_UnnegotiatedFastRA SWITCH ';'
+ {
+ iface->UnnegotiatedFastRA = $2;
+ }
+ | T_MaxFastRARouters NUMBER ';'
+ {
+ iface->MaxFastRARouters = $2;
+ }
+ | T_MaxFastResponses NUMBER ';'
+ {
+ iface->MaxFastResponses = $2;
+ }
+ | T_FastRATokenInterval NUMBER ';'
+ {
+ iface->FastRATokenInterval = $2;
+ }
+ | T_CompleteRA SWITCH ';'
+ {
+ iface->CompleteRA = $2;
+ }
+ | T_CompleteRAMaxAdv NUMBER ';'
+ {
+ iface->CompleteRAMaxAdv = $2;
+ }
+ | T_OverloadTime NUMBER ';'
+ {
+ iface->OverloadTime = $2;
+ }
+ | T_DNASupport SWITCH ';'
+ {
+ if ($2 && (!iface->CompleteRA))
+ iface->CompleteRA = $2;
+ if ($2 && (!iface->PrefixLandmarking))
+ iface->PrefixLandmarking = $2;
+ }
;
prefixlist : prefixdef
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/includes.h radvddna/includes.h
--- radvd/includes.h 2002-06-15 20:25:04.000000000 +1000
+++ radvddna/includes.h 2005-05-24 13:04:40.121524985 +1000
@@ -95,4 +95,6 @@
# include <getopt.h>
#endif
+#include <openssl/sha.h>
+
#endif /* INCLUDES_H */
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/interface.c radvddna/interface.c
--- radvd/interface.c 2005-05-24 15:56:49.209345438 +1000
+++ radvddna/interface.c 2005-05-24 15:59:32.045904542 +1000
@@ -21,12 +21,15 @@
void
iface_init_defaults(struct Interface *iface)
{
+ int i;
memset(iface, 0, sizeof(struct Interface));
iface->IgnoreIfMissing = DFLT_IgnoreIfMissing;
iface->AdvSendAdvert = DFLT_AdvSendAdv;
iface->MaxRtrAdvInterval = DFLT_MaxRtrAdvInterval;
iface->AdvSourceLLAddress = DFLT_AdvSourceLLAddress;
+ iface->RecvSourceLLAddress= DFLT_RecvSourceLLAddress;
+ iface->RecvTentativeLLAddress= DFLT_RecvTentativeLLAddress;
iface->AdvReachableTime = DFLT_AdvReachableTime;
iface->AdvRetransTimer = DFLT_AdvRetransTimer;
iface->AdvLinkMTU = DFLT_AdvLinkMTU;
@@ -37,10 +40,42 @@
iface->HomeAgentPreference = DFLT_HomeAgentPreference;
iface->MinDelayBetweenRAs = DFLT_MinDelayBetweenRAs;
+
+ iface->PrefixLandmarking = DFLT_PrefixLandmarking;
+ iface->MaxDNAPrefixes = DFLT_MaxDNAPrefixes;
+ iface->CompleteRA = DFLT_CompleteRA;
+ iface->CompleteRAMaxAdv = DFLT_CompleteRAMaxAdv;
+ iface->OverloadTime = DFLT_OverloadTime;
+
+ iface->NumUnicastFastRAs = DFLT_NumUnicastFastRAs;
+ iface->MaxUnicastFastRAs = DFLT_MaxUnicastFastRAs;
+
+ iface->FastRATokenInterval = DFLT_FastRATokenInterval;
+
+ gettimeofday(&iface->LastFastRAToken,NULL);
+
iface->MinRtrAdvInterval = -1;
iface->AdvDefaultLifetime = -1;
iface->AdvDefaultPreference = DFLT_AdvDefaultPreference;
iface->HomeAgentLifetime = 0;
+
+ iface->FastRASeparation = DFLT_FastRASeparation;
+ iface->MaxUnicastFastRAs = DFLT_MaxUnicastFastRAs;
+ iface->NumUnicastFastRAs = 0;
+
+ iface->dyntimers[FREE_Dynamic_Timers].next=NULL;
+ iface->dyntimers[USED_Dynamic_Timers].next=NULL;
+
+ for(i = 0 ; i < MAX_Outstanding_Unicast ; i++){
+ init_timer(&iface->uni_tm[i], dynamic_handler, (void *) iface);
+ iface->dyntimers[i].tm=&iface->uni_tm[i];
+ insert_into_list(&iface->dyntimers[FREE_Dynamic_Timers],
+ &iface->dyntimers[i]);
+ }
+ /* start:remove from production */
+ log_list(&iface->dyntimers[FREE_Dynamic_Timers],"FREE");
+ log_list(&iface->dyntimers[USED_Dynamic_Timers],"USED");
+ /* end: remove from production */
}
void
@@ -194,7 +229,25 @@
res = -1;
}
+ /* make space for a number of unknown prefixes */
+ if((iface->PrefixLandmarking || iface->CompleteRA)
+ && iface->MaxDNAPrefixes >0)
+ {
+ if((iface->DNAPrefixList = (struct RtrPrefixList *)malloc(
+ iface->MaxDNAPrefixes *
+ sizeof(struct RtrPrefixList))) == NULL){
+ iface->PrefixLandmarking = 0;
+ iface->CompleteRA = 0;
+ iface->CompleteRAMaxAdv = 0;
+ iface->MaxDNAPrefixes = 0;
+ }
+ iface->CurrDNAPrefixes = 0;
+ gettimeofday(&iface->DNAOverloadExpiry,NULL);
+ iface->DNAOverloadExpiry.tv_sec += DFLT_InitialOverloadTime;
+ }
+
/* XXX: need this? prefix = iface->AdvPrefixList; */
+ prefix = iface->AdvPrefixList;
while (prefix)
{
@@ -231,3 +284,41 @@
return res;
}
+
+
+check_if_addr(struct Interface *iface){
+ int res=0;
+ char addr_str[40];
+ unsigned char digest[SHA_DIGEST_LENGTH];
+
+ if(iface->UnnegotiatedFastRA && iface->MaxFastRARouters >0)
+ {
+ if((iface->RouterList = (struct RtrPrefixList *)malloc(
+ iface->MaxFastRARouters *
+ sizeof(struct RtrPrefixList))) == NULL){
+ iface->UnnegotiatedFastRA = 0;
+ iface->MaxFastRARouters = 0;
+ flog(LOG_ERR, "Unable to allocate routers list on %s",
+ iface->Name);
+ res = -1;
+ }
+ iface->CurrFastRARouters = 0;
+ if(SHA1((unsigned char *)&iface->if_addr,
+ sizeof(struct in6_addr), digest)){
+
+ print_addr(&iface->if_addr,addr_str);
+ memcpy(&iface->FastRAOwnHashBits, digest , 8);
+ flog(LOG_ERR, "SHA1-hash: %8.8lx%8.8lx %s",
+ ntohl(iface->FastRAOwnHashBits.b32[0]),
+ ntohl(iface->FastRAOwnHashBits.b32[1]),
+ addr_str);
+ }
+ else{
+ flog(LOG_ERR, "Msg Digest failure on %s", iface->Name);
+ res = -1;
+ }
+ }
+
+ return res;
+
+}
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/process.c radvddna/process.c
--- radvd/process.c 2005-05-24 15:56:49.212345079 +1000
+++ radvddna/process.c 2005-05-24 16:02:01.197097529 +1000
@@ -17,12 +17,21 @@
#include <config.h>
#include <includes.h>
#include <radvd.h>
+#include <dna.h>
+
+
+extern int rtnl_sock;
+
+static void process_rs(int sock, struct Interface *iface, unsigned char *msg,
+ int len, struct sockaddr_in6 *addr);
+static unsigned char *process_rs_options(struct Interface *, unsigned char *,
+ int, struct sockaddr_in6 *, unsigned char **,
+ struct timeval *tv, uint8_t *);
-static void process_rs(int, struct Interface *, struct sockaddr_in6 *);
static void process_ra(struct Interface *, unsigned char *msg, int len,
struct sockaddr_in6 *);
-static int addr_match(struct in6_addr *a1, struct in6_addr *a2,
- int prefixlen);
+/*static int addr_match(struct in6_addr *a1, struct in6_addr *a2,
+ int prefixlen);*/
static int rs_has_srclladdr(unsigned char *, int);
void
@@ -138,7 +147,7 @@
if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
{
- process_rs(sock, iface, addr);
+ process_rs(sock, iface, msg, len, addr);
}
else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
{
@@ -147,37 +156,144 @@
}
static void
-process_rs(int sock, struct Interface *iface, struct sockaddr_in6 *addr)
+process_rs(int sock, struct Interface *iface, unsigned char *msg,
+ int len, struct sockaddr_in6 *addr)
{
- double delay;
- double next;
+ struct in6_addr unspec = { { { 0 } } };
+ struct in6_addr bitdiff;
+ int delay=0;
+ int delayset=0;
+ double next, resdelay;
struct timeval tv;
+ int tokens =-1;
+ uint8_t lmv=0;
+ int do_multicast=1;
+ struct dtimer_list *dtm_tmp=NULL;
+ int calcnr=0, probslot=0, i=0;
+ uint32_t flags=0;
+ int rank;
+ char addr_str[40];
+ struct nd_opt_landmark *lmark=NULL;
gettimeofday(&tv, NULL);
- delay = MAX_RA_DELAY_TIME*rand()/(RAND_MAX+1.0);
- dlog(LOG_DEBUG, 3, "random mdelay for %s: %.2f", iface->Name, delay);
+ dlog(LOG_DEBUG, 5, "PROCESS ROUTER SOLICIT ON %s", iface->Name);
+
+
+ lmark=NULL;
+ process_rs_options(iface, msg, len, addr, (unsigned char**)&lmark ,
+ &tv, &lmv);
+
+ if(iface->UnnegotiatedFastRA)
+ tokens = token_bucket_update(iface, &tv);
+
+ if(!delayset && iface->UnnegotiatedFastRA && tokens &&
+ memcmp(&addr->sin6_addr, &unspec, sizeof(struct in6_addr))){
+
+ rank=check_before(iface->RouterList,iface->CurrFastRARouters,
+ (uint32_t *)&iface->FastRAOwnHashBits,
+ &addr->sin6_addr);
+ iface->NumUnicastFastRAs--;
+ delay=rank * iface->FastRASeparation;
+ dlog(LOG_DEBUG, 3, "Unneg FastRA delay for %s %d r(%d)",
+ iface->Name, delay, rank);
+ delayset=1;
+ }
+
+
+ if(!delayset){
+ delay = (int) (MAX_RA_DELAY_TIME*rand()/(RAND_MAX+1.0));
+ dlog(LOG_DEBUG, 3, "random mdelay for %s: %d", iface->Name, delay);
+ }
+
+ next=tv_diff(&(iface->tm.expires), &tv);
+
+ /* residual delay for multicast */
+ resdelay = MAX2((((double)delay)/1000.0),
+ MAX2(0.0, (iface->MinDelayBetweenRAs) -
+ tv_diff(&tv,&iface->last_multicast)));
+
+ dlog(LOG_DEBUG, 4, "next:%10.10f resdelay: %10.10f (%f) [%f]",next,
+ resdelay,MAX2(0.0, (iface->MinDelayBetweenRAs) -
+ tv_diff(&tv,&iface->last_multicast)),
+ iface->MinDelayBetweenRAs - tv_diff(&tv,&iface->last_multicast) );
+ /* GD: not sure here: on no more fastras need multicast! */
+ if(!tokens){
+ dlog(LOG_DEBUG, 4, "Run out of FastRA tokens on %s, Mcast",
+ iface->Name);
+ }
+ else if((!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
+ (resdelay > ((double)delay)/1000.0))|| iface->UnicastOnly ||
+ delayset){
+ dlog(LOG_DEBUG, 4, "too soon for mcast on %s", iface->Name);
+ do_multicast=0;
+ }
- if (iface->UnicastOnly) {
- mdelay(delay);
- send_ra(sock, iface, &addr->sin6_addr);
- }
- else if ((tv.tv_sec + tv.tv_usec / 1000000.0) - (iface->last_multicast_sec +
- iface->last_multicast_usec / 1000000.0) < iface->MinDelayBetweenRAs) {
- /* last RA was sent only a few moments ago, don't send another immediately */
+
+ /* MCast rescheduling */
+
+ if(do_multicast){
+ dlog(LOG_DEBUG, 5, "multicast response on %s",iface->Name);
+ /* Reschedule multicast if nearer */
+ if((resdelay + 0.001) < next){
+ dlog(LOG_DEBUG, 3, "Reschedule multicast to %f on %s",
+ resdelay,iface->Name);
+ next=resdelay;
clear_timer(&iface->tm);
- next = iface->MinDelayBetweenRAs - (tv.tv_sec + tv.tv_usec / 1000000.0) +
- (iface->last_multicast_sec + iface->last_multicast_usec / 1000000.0) + delay/1000.0;
set_timer(&iface->tm, next);
}
- else {
- /* no RA sent in a while, send an immediate multicast reply */
- clear_timer(&iface->tm);
- send_ra(sock, iface, NULL);
+ return;
+ }
- next = rand_between(iface->MinRtrAdvInterval, iface->MaxRtrAdvInterval);
- set_timer(&iface->tm, next);
+ /*
+ * unicast reply
+ */
+
+ if(delay == 0){ /* No need to take a schedule slot */
+ *addr_str='\0';
+ if(lmark){
+ /*print_addr(&lmark->nd_opt_landmark_prefix,addr_str);*/
+ dlog(LOG_DEBUG, 5,
+ "Responding LM: T:%hhu L:%hhu F:%hhu %hx:%hx:%hx:%hx/%hhu",
+ lmark->nd_opt_landmark_type,
+ lmark->nd_opt_landmark_len,
+ lmv,
+ ntohs(lmark->nd_opt_landmark_prefix.s6_addr16[0]),
+ ntohs(lmark->nd_opt_landmark_prefix.s6_addr16[1]),
+ ntohs(lmark->nd_opt_landmark_prefix.s6_addr16[2]),
+ ntohs(lmark->nd_opt_landmark_prefix.s6_addr16[3]),
+ lmark->nd_opt_landmark_plen);
+ }
+
+ dlog(LOG_DEBUG, 5, "Zero Delay response %s",iface->Name);
+ send_ra(sock, iface, &addr->sin6_addr, (unsigned char *)lmark,
+ lmv);
+ return;
+ }
+ dlog(LOG_DEBUG, 3, "delay on %s %d",iface->Name, delay);
+
+ if((dtm_tmp = remove_from_list(&iface->dyntimers[FREE_Dynamic_Timers],
+ NULL)) == NULL){
+ dlog(LOG_DEBUG, 3, "No entries on free list %s",iface->Name);
+ return;
+ }
+ if(lmark){
+ memcpy(dtm_tmp->lmark, lmark, sizeof(struct nd_opt_landmark));
+ dtm_tmp->lmv=lmv;
}
+ memcpy(&dtm_tmp->addr, &addr->sin6_addr, sizeof (struct in6_addr));
+
+ insert_into_list(&iface->dyntimers[USED_Dynamic_Timers], dtm_tmp);
+
+ /* start: remove from production */
+ log_list(&iface->dyntimers[FREE_Dynamic_Timers], "FREE p");
+ log_list(&iface->dyntimers[USED_Dynamic_Timers], "USED p");
+ /* end: remove from production */
+
+ next = ((double)delay)/1000.0;
+
+ set_timer(dtm_tmp->tm, next);
+ return;
}
/*
@@ -188,11 +304,31 @@
struct sockaddr_in6 *addr)
{
struct nd_router_advert *radvert;
+ unsigned int advint=0;
char addr_str[INET6_ADDRSTRLEN];
+ int matched=0;
+ int new_landmark=0;
+ int new_overload=0;
+ struct timeval tv,now;
+ int num;
+
uint8_t *opt_str;
print_addr(&addr->sin6_addr, addr_str);
+ if(!memcmp(&addr->sin6_addr, &iface->if_addr, sizeof(struct in6_addr))){
+ dlog(LOG_DEBUG, 5, "own RA from %s on %s", addr_str,
+ iface->Name);
+ return;
+ }
+
+ gettimeofday(&now, NULL);
+
+
+ dlog(LOG_DEBUG, 1, "RECEIVE ROUTER ADV from %s on %s", addr_str,
+ iface->Name);
+
+
radvert = (struct nd_router_advert *) msg;
if ((radvert->nd_ra_curhoplimit && iface->AdvCurHopLimit) &&
@@ -230,6 +366,8 @@
iface->Name, addr_str);
}
+ dlog(LOG_DEBUG, 1, "About to check length %d %d", len,
+ sizeof(struct nd_router_advert));
len -= sizeof(struct nd_router_advert);
if (len == 0)
@@ -284,6 +422,11 @@
pinfo = (struct nd_opt_prefix_info *) opt_str;
preferred = ntohl(pinfo->nd_opt_pi_preferred_time);
valid = ntohl(pinfo->nd_opt_pi_valid_time);
+ matched=0;
+
+ print_addr(&pinfo->nd_opt_pi_prefix, prefix_str);
+ dlog(LOG_DEBUG,5,"received PIO: %s/%d",
+ prefix_str, pinfo->nd_opt_pi_prefix_len);
prefix = iface->AdvPrefixList;
while (prefix)
@@ -294,6 +437,7 @@
prefix->PrefixLen))
{
print_addr(&prefix->Prefix, prefix_str);
+ matched=1;
if (valid != prefix->AdvValidLifetime)
{
@@ -314,9 +458,42 @@
);
}
}
-
+ dlog(LOG_DEBUG,5,"PIO match: %d",matched);
prefix = prefix->next;
}
+ if(!matched && (iface->PrefixLandmarking ||
+ iface->CompleteRA)){
+ struct in6_addr prefaddr;
+ /* add prefix to landmark list */
+ prefix_mask(&prefaddr,
+ &pinfo->nd_opt_pi_prefix,
+ pinfo->nd_opt_pi_prefix_len);
+ print_addr(&prefaddr, prefix_str);
+
+ if((num = add_rtrprefix(iface->DNAPrefixList,
+ iface->MaxDNAPrefixes,
+ iface->CurrDNAPrefixes,
+ &prefaddr, MIN2(preferred,
+ iface->OverloadTime),0,
+ pinfo->nd_opt_pi_prefix_len))){
+
+ new_landmark=1;
+ iface->CurrDNAPrefixes=num;
+ dlog(LOG_DEBUG,5,"DNA prefix %s %d",
+ prefix_str,
+ iface->CurrDNAPrefixes);
+ }
+ else{
+ /* overload */
+ new_overload=1;
+ dlog(LOG_DEBUG,5,"DNA Overload %s/%d %lu.%lu",
+ prefix_str,
+ pinfo->
+ nd_opt_pi_prefix_len,
+ iface->DNAOverloadExpiry.tv_sec,
+ iface->DNAOverloadExpiry.tv_usec);
+ }
+ }
break;
case ND_OPT_ROUTE_INFORMATION:
/* not checked: these will very likely vary a lot */
@@ -331,6 +508,9 @@
break;
/* Mobile IPv6 extensions */
case ND_OPT_RTR_ADV_INTERVAL:
+ advint=ntohl(((struct nd_opt_adv_interval *)opt_str)->nd_opt_adv_interval_ival);
+ dlog(LOG_DEBUG, 5, "Advint %d in RA on %s from %s",
+ advint, iface->Name, addr_str);
case ND_OPT_HOME_AGENT_INFO:
/* not checked */
break;
@@ -343,8 +523,54 @@
len -= optlen;
opt_str += optlen;
}
+
+ /* GD XXX update with processed Advertisement Interval */
+ if(iface->UnnegotiatedFastRA && (radvert->nd_ra_flags_reserved &
+ ND_RA_FLAG_FASTRA)){
+ uint32_t life;
+
+ life = (advint/1000 ? MIN2(advint/1000,
+ ntohs(radvert->nd_ra_router_lifetime)):
+ ntohs(radvert->nd_ra_router_lifetime));
+
+ if((num = add_rtrprefix(iface->RouterList,
+ iface->MaxFastRARouters,
+ iface->CurrFastRARouters,
+ &addr->sin6_addr, life,1,128))){
+
+ iface->CurrFastRARouters=num;
+ }
+ }
+
+
+ if(iface->PrefixLandmarking || iface->CompleteRA){
+
+ //tv.tv_usec = tv.tv_sec=0;
+
+ if(advint && (new_overload || new_landmark)){
+ struct timeval ai_timeval;
+
+ ai_timeval.tv_usec = (advint % 1000) * 1000;
+ ai_timeval.tv_sec = advint / 1000;
+ timeradd(&now, &ai_timeval, &tv);
+ }
+ if(new_overload){
+ gettimeofday(&iface->DNAOverloadExpiry,NULL);
+ iface->DNAOverloadExpiry.tv_sec += DFLT_OverloadTime;
+ dlog(LOG_DEBUG, 1, "new overload timer: %lu.%lu , now:%lu.%lu",
+ iface->DNAOverloadExpiry.tv_sec, iface->DNAOverloadExpiry.tv_usec, tv.tv_sec, tv.tv_usec);
+ }
+
+ /*if(new_landmark){
+ update_landtimers(iface->DNAPrefixList,
+ iface->CurrDNAPrefixes,&tv);
+ }*/
+ }
+
+
}
+#if 0
static int
addr_match(struct in6_addr *a1, struct in6_addr *a2, int prefixlen)
{
@@ -376,6 +602,7 @@
return 1;
}
+#endif /* 0 */
static int
rs_has_srclladdr(unsigned char *msg, int len)
@@ -426,3 +653,120 @@
return has_lladdr;
}
+
+
+
+
+static unsigned char *process_rs_options(struct Interface *iface,
+ unsigned char *msg, int len, struct sockaddr_in6 *addr,
+ unsigned char **lmark, struct timeval *tv, uint8_t*lmv)
+{
+ uint8_t *opt_str;
+ int i;
+ unsigned char *copy=NULL;
+ unsigned char hw_addr[16];
+ struct AdvPrefix *prefix=NULL;
+ struct nd_opt_landmark *lm_opt=NULL;
+ struct in6_addr tmp_addr;
+ char addr_str[INET6_ADDRSTRLEN];
+
+ len -= sizeof(struct nd_router_solicit);
+ opt_str = (uint8_t *)(msg + sizeof(struct nd_router_solicit));
+
+ while (len > 0)
+ {
+ int optlen;
+
+ if (len < 2)
+ {
+ flog(LOG_ERR, "trailing garbage in RS");
+ break;
+ }
+
+ optlen = (opt_str[1] << 3);
+
+ dlog(LOG_DEBUG,4, "option type %d, length %d", (int)*opt_str,
+ optlen);
+
+ if (optlen == 0)
+ {
+ flog(LOG_ERR, "zero length option in RA");
+ break;
+ }
+ else if (optlen > len)
+ {
+ flog(LOG_ERR, "option length greater than total"
+ " length in RA (type %d, optlen %d, len %d)",
+ (int)*opt_str, optlen, len);
+ break;
+ }
+ switch (*opt_str)
+ {
+ case ND_OPT_SOURCE_LINKADDR:
+ dlog(LOG_DEBUG, 4, "RecvSourceLLAddress: %d l:%d",
+ iface->RecvSourceLLAddress, optlen);
+
+ if(iface->RecvSourceLLAddress && (optlen <= 16)){
+ for (i = 2; i < optlen; i++)
+ {
+ hw_addr[i-2] = opt_str[i];
+ }
+ install_nc_entry(rtnl_sock,iface,
+ &addr->sin6_addr, hw_addr, 6,1);
+ }
+ break;
+ case ND_OPT_TENTATIVE_SLLA:
+ dlog(LOG_DEBUG, 4, "RecvTentativeLLAddress: ");
+
+ if(iface->RecvTentativeLLAddress && (optlen <= 16)){
+ for (i = 2; i < optlen; i++)
+ {
+ hw_addr[i-2] = opt_str[i];
+ }
+ install_nc_entry(rtnl_sock,iface,
+ &addr->sin6_addr, hw_addr, 6,0);
+ }
+ break;
+ case ND_OPT_LANDMARK:
+ dlog(LOG_DEBUG, 4, "received Landmark opt in RS on %s %hhu",
+ iface->Name, opt_str );
+ if(iface->PrefixLandmarking){
+
+ lm_opt = (struct nd_opt_landmark *)opt_str;
+
+ i = lm_opt->nd_opt_landmark_plen;
+ /* store in an ipv6 address for comparison */
+ prefix_mask(&tmp_addr,
+ &lm_opt->nd_opt_landmark_prefix, i);
+
+ /* check if a known prefix */
+ *lmv=check_landmark(iface, &tmp_addr, tv, i);
+ *lmark=opt_str;
+ /*print_addr(&((struct nd_opt_landmark *)opt_str)->nd_opt_landmark_prefix, addr_str);*/
+ copy=opt_str;
+ dlog(LOG_DEBUG,5, "Received LM: T:%hhu L:%hhu F:%hhu %hx:%hx:%hx:%hx/%d (%p, %d)",
+ lm_opt->nd_opt_landmark_type,
+ lm_opt->nd_opt_landmark_len,
+ lm_opt->nd_opt_landmark_flags,
+ ntohs(lm_opt->nd_opt_landmark_prefix.s6_addr16[0]),
+ ntohs(lm_opt->nd_opt_landmark_prefix.s6_addr16[1]),
+ ntohs(lm_opt->nd_opt_landmark_prefix.s6_addr16[2]),
+ ntohs(lm_opt->nd_opt_landmark_prefix.s6_addr16[3]),
+ lm_opt->nd_opt_landmark_plen,
+ *lmark,*lmv);
+ }
+ break;
+ default:
+ dlog(LOG_DEBUG, 1, "unknown option %d in RS",
+ (int)*opt_str);
+ break;
+ }
+
+ len -= optlen;
+ opt_str += optlen;
+
+ }
+ return copy;
+}
+
+
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/radvd.c radvddna/radvd.c
--- radvd/radvd.c 2005-05-24 15:56:49.421320130 +1000
+++ radvddna/radvd.c 2005-05-24 15:59:32.293874937 +1000
@@ -18,6 +18,7 @@
#include <includes.h>
#include <radvd.h>
#include <pathnames.h>
+#include <dna.h>
struct Interface *IfaceList = NULL;
@@ -46,6 +47,7 @@
char *conf_file = NULL;
char *pname;
int sock = -1;
+int rtnl_sock = -1;
volatile int sighup_received = 0;
volatile int sigterm_received = 0;
@@ -285,15 +287,64 @@
exit(0);
}
+
+void
+dynamic_handler(void *data)
+{
+ struct timer_lst *tm = (struct timer_lst *) data;
+ struct Interface *iface;
+ char addr_str[40];
+ struct in6_addr unspec = { { { 0 } } };
+ struct in6_addr *dst=NULL;
+ unsigned char *lmark=NULL;
+ uint8_t lmv=0;
+ struct dtimer_list *dtm_tmp = NULL;
+
+ iface= tm->iface;
+
+ dlog(LOG_DEBUG, 4, "dynamic_handler called for %s", iface->Name);
+
+
+ if((dtm_tmp = remove_from_list(&iface->dyntimers[USED_Dynamic_Timers],
+ tm)) == NULL){
+ return;
+ }
+ print_addr(&dtm_tmp->addr, addr_str);
+ dlog(LOG_DEBUG, 4, "dynamic_handler:address: %s on %s f(%8.8x)",
+ iface->Name, addr_str,dtm_tmp->flags);
+
+ if(memcmp(&dtm_tmp->addr,&unspec, sizeof(struct in6_addr))){
+ dst=&dtm_tmp->addr;
+ }
+
+ if(dtm_tmp->lmark[0]){
+ lmark=dtm_tmp->lmark;
+ print_addr(&((struct nd_opt_landmark *)lmark)->nd_opt_landmark_prefix, addr_str);
+ lmv=dtm_tmp->lmv;
+ dlog(LOG_DEBUG, 4, "dynamic_handler:lmark prefix: %s on %s lf(%8.8x)",
+ iface->Name, addr_str,dtm_tmp->lmv);
+ }
+ send_ra(sock, iface, dst, lmark, lmv);
+
+ dtm_tmp->lmv=0;
+ memset(dtm_tmp->lmark, 0, sizeof(struct nd_opt_landmark));
+ insert_into_list(&iface->dyntimers[FREE_Dynamic_Timers], dtm_tmp);
+}
+
+
void
timer_handler(void *data)
{
- struct Interface *iface = (struct Interface *) data;
+ struct timer_lst *tm = (struct timer_lst *) data;
+ struct Interface *iface;
double next;
+ double lidc;
+
+ iface= tm->iface;
dlog(LOG_DEBUG, 4, "timer_handler called for %s", iface->Name);
- send_ra(sock, iface, NULL);
+ send_ra(sock, iface, NULL, NULL, 0);
next = rand_between(iface->MinRtrAdvInterval, iface->MaxRtrAdvInterval);
set_timer(&iface->tm, next);
@@ -316,7 +367,7 @@
if (iface->AdvSendAdvert)
{
/* send an initial advertisement */
- send_ra(sock, iface, NULL);
+ send_ra(sock, iface, NULL, NULL,0);
set_timer(&iface->tm, iface->MaxRtrAdvInterval);
}
@@ -338,7 +389,7 @@
if (iface->AdvSendAdvert) {
/* send a final advertisement with zero Router Lifetime */
iface->AdvDefaultLifetime = 0;
- send_ra(sock, iface, NULL);
+ send_ra(sock, iface, NULL, NULL,0);
}
}
}
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/radvd.conf.5.man radvddna/radvd.conf.5.man
--- radvd/radvd.conf.5.man 2004-10-27 16:13:40.000000000 +1000
+++ radvddna/radvd.conf.5.man 2005-05-24 16:22:05.724290223 +1000
@@ -83,7 +83,7 @@
A flag indicating whether or not the router sends
periodic router advertisements and responds to
-router solicitations.
+Router Solicitations.
This option no longer has to be specified first, but it
needs to be
@@ -242,6 +242,62 @@
Default: on
.TP
+.BR RecvSourceLLAddress " " on | off
+
+When set, the source link-layer address option in an incoming
+Router Solicitation is used to create a STALE neighbour cache
+entry for the solicitor, if one didn't exist already.
+It also overrides an existing neighbour cache entry, if
+the link-layer addresses differ.
+
+Default: off
+
+.TP
+.BR RecvTentativeLLAddress " " on | off
+
+When set, the processing of Tentative Source Link-Layer Address
+Options is supported. These options allow creation of a
+neighbour cache entry only if there is no pre-existing valid
+entry.
+The receivd Router Solicitation creates a STALE neighbour cache
+entry for the solicitor, if one didn't exist already.
+
+Default: off
+
+
+.TP
+.BR MaxUnicastFastRAs " " integer
+
+Provides the maximum size of the token bucket used to
+rate limit fast unicast Router Advertisement responses
+to solicitation, generated by either of the FastRA
+algorithms.
+In order to affect transmission, either of
+ProbabilisticFastRA or DetermineFastRA must be on.
+
+Default: 10
+
+.TP
+.BR "FastRATokenInterval " milliseconds
+
+Provides the interval between token arrivals for
+allowing fast responses to Router Solicitations.
+The maximum amount of tokens outstanding is determined by
+MaxUnicastFastRAs.
+In order to affect transmission, either of
+ProbabilisticFastRA or DetermineFastRA must be on.
+
+Default: 1000
+
+.TP
+.BR "FastRASeparation " milliseconds
+
+The interval between responses of FastRA routers,
+upon reception of a solicitation.
+
+Default: 20
+
+.TP
.BR AdvHomeAgentFlag " " on | off
When set, indicates that sending router is able to serve as Mobile
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/radvd.conf.example radvddna/radvd.conf.example
--- radvd/radvd.conf.example 2004-08-20 17:17:53.000000000 +1000
+++ radvddna/radvd.conf.example 2005-05-24 13:04:40.122524865 +1000
@@ -25,6 +25,12 @@
AdvDefaultPreference low;
#
+# Add a STALE neighbour cache entry for previously unseen soliciting
+# hosts, which have the SLLAO set
+#
+ RecvSourceLLAddress on;
+
+#
# Disable Mobile IPv6 support
#
AdvHomeAgentFlag off;
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/radvd.h radvddna/radvd.h
--- radvd/radvd.h 2005-05-24 15:56:49.443317504 +1000
+++ radvddna/radvd.h 2005-05-24 16:06:49.509676177 +1000
@@ -31,15 +31,35 @@
#define LOG_TIME_FORMAT "%b %d %H:%M:%S"
+struct Interface;
+
struct timer_lst {
struct timeval expires;
void (*handler)(void *);
void * data;
struct timer_lst *next;
struct timer_lst *prev;
+ struct Interface *iface;
+};
+
+
+struct dtimer_list{
+ struct timer_lst *tm;
+ struct dtimer_list *next;
+ /* other data for dynamic timers...*/
+ struct in6_addr addr;
+ uint32_t flags;
+ uint8_t lmv;
+ unsigned char lmark[MAX_ResponseOptionLen];
+};
+
+struct fastralist{
+ struct in6_addr addr;
+ struct timeval expires;
};
struct AdvPrefix;
+struct RtrPrefixList;
#define HWADDR_MAX 16
@@ -68,8 +88,29 @@
int AdvDefaultLifetime;
int AdvDefaultPreference;
int AdvSourceLLAddress;
+ int RecvSourceLLAddress;
+ int RecvTentativeLLAddress;
int UnicastOnly;
+ int UnnegotiatedFastRA;
+
+ union {
+ uint8_t b8[8];
+ uint16_t b16[4];
+ uint32_t b32[2];
+ } FastRAOwnHashBits;
+
+ int MaxFastRARouters;
+ int CurrFastRARouters;
+ struct RtrPrefixList *RouterList;
+
+ int MaxFastResponses; /* not implemented for Detfra */
+ int FastRASeparation;
+ struct timeval LastFastRAToken;
+ int FastRATokenInterval;
+ int NumUnicastFastRAs;
+ int MaxUnicastFastRAs;
+
/* Mobile IPv6 extensions */
int AdvIntervalOpt;
int AdvHomeAgentInfo;
@@ -77,12 +118,27 @@
int16_t HomeAgentPreference;
uint16_t HomeAgentLifetime;
+ struct timer_lst rtrtm;
+ struct timeval last_rtrmc;
+
+ int DetFastRASeparation;
+
+ int PrefixLandmarking;
+ int MaxDNAPrefixes;
+ int CurrDNAPrefixes;
+ int CompleteRA;
+ int CompleteRAMaxAdv;
+ int OverloadTime;
+ struct RtrPrefixList *DNAPrefixList;
+ struct timeval DNAOverloadExpiry;
+
struct AdvPrefix *AdvPrefixList;
struct AdvRoute *AdvRouteList;
struct timer_lst tm;
- time_t last_multicast_sec;
- suseconds_t last_multicast_usec;
+ struct timeval last_multicast;
struct Interface *next;
+ struct dtimer_list dyntimers[MAX_Outstanding_Unicast+2];
+ struct timer_lst uni_tm[MAX_Outstanding_Unicast];
};
@@ -105,6 +161,7 @@
struct AdvPrefix *next;
};
+
/* More-Specific Routes extensions */
struct AdvRoute {
@@ -134,6 +191,15 @@
uint16_t lifetime;
};
+struct RtrPrefixList{
+ struct in6_addr Prefix;
+ struct timeval expiry;
+ int plen;
+ int this_adv;
+ unsigned char hash[8];
+};
+
+
/* gram.y */
int yyparse(void);
@@ -164,19 +230,26 @@
int setup_linklocal_addr(int, struct Interface *);
int setup_allrouters_membership(int, struct Interface *);
int check_allrouters_membership(int, struct Interface *);
+int check_routertorouter_membership(int sock, struct Interface *iface);
int get_v4addr(const char *, unsigned int *);
+int bind_rtnlsock(void);
+int open_rtnlsock(void);
+void install_nc_entry(int, struct Interface *, struct in6_addr *, unsigned char *, int , int);
/* interface.c */
void iface_init_defaults(struct Interface *);
void prefix_init_defaults(struct AdvPrefix *);
void route_init_defaults(struct AdvRoute *, struct Interface *);
int check_iface(struct Interface *);
+int check_if_addr(struct Interface *);
-/* socket.c */
-int open_icmpv6_socket(void);
+/* socket.c */ int open_icmpv6_socket(void);
/* send.c */
-void send_ra(int, struct Interface *iface, struct in6_addr *dest);
+void send_ra(int sock, struct Interface *iface, struct in6_addr *dest,
+ unsigned char *lmark, uint8_t lmv);
+void send_r2r(int sock, struct Interface *iface, struct in6_addr *dest,
+ int req);
/* process.c */
void process(int sock, struct Interface *, unsigned char *, int,
@@ -189,5 +262,29 @@
void mdelay(int);
double rand_between(double, double);
void print_addr(struct in6_addr *, char *);
+double tv_diff(struct timeval *, struct timeval *);
+struct dtimer_list *remove_from_list(struct dtimer_list *, struct timer_lst *);
+void insert_into_drtrlist(struct dtimer_list *, struct dtimer_list *);
+void insert_into_list(struct dtimer_list *list, struct dtimer_list *entry);
+void log_list(struct dtimer_list *list, const char *listname);
+int add_to_fastralist(struct Interface *iface, struct in6_addr *addr,
+ unsigned int lifetime);
+void clear_fastralist(struct Interface *iface, struct timeval *tv);
+int token_bucket_update(struct Interface *iface, struct timeval *tv);
+int prefix_mask(struct in6_addr *prefix, struct in6_addr *addr, int plen);
+int check_landmark(struct Interface *iface, struct in6_addr *prefix,
+ struct timeval *now, int plen);
+int addr_match(struct in6_addr *a1, struct in6_addr *a2, int prefixlen);
+int add_rtrprefix(struct RtrPrefixList *landlist, int num, int curr,
+ struct in6_addr *prefix, uint32_t expires, int hash, int plen);
+int update_landtimers(struct RtrPrefixList *landlist, int curr,
+ uint32_t expires);
+
+int check_before(struct RtrPrefixList *list, int curr,
+ uint32_t *ownhash, struct in6_addr *addr);
+
+/* radvd.c */
+void timer_handler(void *data);
+void dynamic_handler(void *data);
#endif
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/scanner.l radvddna/scanner.l
--- radvd/scanner.l 2004-10-27 16:13:40.000000000 +1000
+++ radvddna/scanner.l 2005-05-24 15:44:47.271536876 +1000
@@ -58,6 +58,8 @@
AdvDefaultLifetime { return T_AdvDefaultLifetime; }
AdvDefaultPreference { return T_AdvDefaultPreference; }
AdvSourceLLAddress { return T_AdvSourceLLAddress; }
+RecvSourceLLAddress { return T_RecvSourceLLAddress; }
+RecvTentativeLLAddress { return T_RecvTentativeLLAddress; }
AdvOnLink { return T_AdvOnLink; }
AdvAutonomous { return T_AdvAutonomous; }
@@ -70,6 +72,15 @@
AdvHomeAgentInfo { return T_AdvHomeAgentInfo; }
UnicastOnly { return T_UnicastOnly; }
+PrefixLandmarking { return T_PrefixLandmarking; }
+
+CompleteRA { return T_CompleteRA;}
+CompleteRAMaxAdv { return T_CompleteRAMaxAdv;}
+OverloadTime { return T_OverloadTime;}
+
+MaxDNAPrefixes { return T_MaxDNAPrefixes; }
+
+
Base6to4Interface { return T_Base6to4Interface; }
HomeAgentPreference { return T_HomeAgentPreference; }
@@ -80,6 +91,16 @@
MinDelayBetweenRAs { return T_MinDelayBetweenRAs; }
+UnnegotiatedFastRA { return T_UnnegotiatedFastRA; }
+MaxFastRARouters { return T_MaxFastRARouters; }
+
+MaxFastResponses { return T_MaxFastResponses; }
+FastRATokenInterval { return T_FastRATokenInterval; }
+MaxUnicastFastRAs { return T_MaxUnicastFastRAs; }
+FastRASeparation { return T_FastRASeparation; }
+
+DNASupport { return T_DNASupport; }
+
{addr} {
static struct in6_addr addr;
int i;
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/send.c radvddna/send.c
--- radvd/send.c 2005-05-24 15:56:49.466314758 +1000
+++ radvddna/send.c 2005-05-24 16:06:29.513063552 +1000
@@ -17,9 +17,11 @@
#include <config.h>
#include <includes.h>
#include <radvd.h>
+#include <dna.h>
void
-send_ra(int sock, struct Interface *iface, struct in6_addr *dest)
+send_ra(int sock, struct Interface *iface, struct in6_addr *dest,
+ unsigned char *lmark, uint8_t lmv)
{
uint8_t all_hosts_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
struct sockaddr_in6 addr;
@@ -34,22 +36,26 @@
unsigned char buff[MSG_SIZE];
int len = 0;
int err;
+ struct timeval tv;
/* Make sure that we've joined the all-routers multicast group */
if (check_allrouters_membership(sock, iface) < 0)
flog(LOG_WARNING, "problem checking all-routers membership on %s", iface->Name);
+
dlog(LOG_DEBUG, 3, "sending RA on %s", iface->Name);
+ gettimeofday(&tv, NULL);
+
if (dest == NULL)
{
- struct timeval tv;
dest = (struct in6_addr *)all_hosts_addr;
- gettimeofday(&tv, NULL);
- iface->last_multicast_sec = tv.tv_sec;
- iface->last_multicast_usec = tv.tv_usec;
+ iface->last_multicast.tv_sec = tv.tv_sec;
+ iface->last_multicast.tv_usec = tv.tv_usec;
+
+ dlog(LOG_DEBUG, 5, "RA is Multicast on %s", iface->Name);
}
memset((void *)&addr, 0, sizeof(addr));
@@ -77,6 +83,15 @@
radvert->nd_ra_flags_reserved |=
(iface->AdvDefaultPreference << ND_OPT_RI_PRF_SHIFT) & ND_OPT_RI_PRF_MASK;
+ /* Completeness DNA !!! */
+ radvert->nd_ra_flags_reserved |=
+ (iface->UnnegotiatedFastRA)?ND_RA_FLAG_FASTRA:0;
+
+#if 0
+ radvert->nd_ra_flags_reserved |= flags & ND_RA_FLAG_LANDMARK_SEEN;
+ radvert->nd_ra_flags_reserved |= flags & ND_RA_FLAG_LANDMARK_INVALID;
+#endif /* 0 */
+
radvert->nd_ra_reachable = htonl(iface->AdvReachableTime);
radvert->nd_ra_retransmit = htonl(iface->AdvRetransTimer);
@@ -232,6 +247,32 @@
len += sizeof(ha_info);
}
+ /*
+ * Add a complete list of prefixes to the RA.
+ */
+
+ if(iface->PrefixLandmarking && lmark){
+ int added=0;
+ dlog(LOG_DEBUG, 4, "Send LM/CRA: %p %s",lmark, lmark);
+ added = make_landmark_option(buff,len,lmark,lmv);
+ len += added;
+ }
+
+ if(iface->CompleteRA){
+ int added;
+ int complete=0;
+ added = make_completera_option(iface,buff,len, &complete);
+
+ if(buff[len+1]==1)/* no RA in completeRA */
+ added=0;
+
+ /* still need completeRA flag management */
+ radvert->nd_ra_flags_reserved |=
+ (complete)?ND_RA_FLAG_COMPLETERA:0;
+
+ len += added;
+ }
+
iov.iov_len = len;
iov.iov_base = (caddr_t) buff;
@@ -265,3 +306,4 @@
flog(LOG_WARNING, "sendmsg: %s", strerror(errno));
}
}
+
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/timer.c radvddna/timer.c
--- radvd/timer.c 2001-11-15 06:58:11.000000000 +1100
+++ radvddna/timer.c 2005-05-24 13:04:40.123524746 +1000
@@ -77,6 +77,7 @@
gettimeofday(&tv, NULL);
timeradd(&tv, &firein, &tm->expires);
+ dlog(LOG_DEBUG, 5, "expiry: %d.%d", tm->expires.tv_sec, tm->expires.tv_usec);
sigemptyset(&bmask);
sigaddset(&bmask, SIGALRM);
sigprocmask(SIG_BLOCK, &bmask, &oldmask);
@@ -85,6 +86,7 @@
do {
lst = lst->next;
+ dlog(LOG_DEBUG, 5, "list: %d.%d (%p)", lst->expires.tv_sec, lst->expires.tv_usec, lst->prev);
} while ((tm->expires.tv_sec > lst->expires.tv_sec) ||
((tm->expires.tv_sec == lst->expires.tv_sec) &&
(tm->expires.tv_usec > lst->expires.tv_usec)));
@@ -98,6 +100,7 @@
schedule_timer();
sigprocmask(SIG_SETMASK, &oldmask, NULL);
+ dlog(LOG_DEBUG, 5, "finished scheduling");
}
void
@@ -129,6 +132,10 @@
gettimeofday(&tv, NULL);
tm = timers_head.next;
+ dlog(LOG_DEBUG, 5, "calling alarm_handler %p p(%p) n(%p)", tm, tm->prev,
+ tm->next);
+
+
while ((tm->expires.tv_sec < tv.tv_sec)
|| ((tm->expires.tv_sec == tv.tv_sec)
&& (tm->expires.tv_usec <= tv.tv_usec)))
@@ -153,5 +160,6 @@
{
memset(tm, 0, sizeof(struct timer_lst));
tm->handler = handler;
- tm->data = data;
+ tm->iface= data;
+ tm->data = tm;
}
diff -rub --exclude=CVS --exclude='config.[gsh]*' --exclude=depcomp --exclude=Makefile.in --new-file radvd/util.c radvddna/util.c
--- radvd/util.c 2005-05-24 15:56:49.474313803 +1000
+++ radvddna/util.c 2005-05-24 16:03:04.084589454 +1000
@@ -16,6 +16,7 @@
#include <config.h>
#include <includes.h>
#include <radvd.h>
+#include <dna.h>
void
mdelay(int msecs)
@@ -47,3 +48,439 @@
strcpy(str, "[invalid address]");
}
}
+
+/*return number of milliseconds */
+
+double tv_diff(struct timeval *tv1, struct timeval *tv2){
+ double sdiff=0.0;
+ int sign=0;
+
+ /* reduce gap by ms diff if tv1.sec - tv2.sec negative */
+ sign=((tv2->tv_sec > tv1->tv_sec)? -1 : 1);
+
+ sdiff = ((long int)tv1->tv_sec - (long int)tv2->tv_sec);
+
+ sdiff += sign *
+ (((long int)tv1->tv_usec - (long int)tv2->tv_usec) * 0.000001);
+ return sdiff;
+}
+
+
+ /* compares two blocks of memory byte by byte in
+ reverse order */
+int revcmp(const void *s1, const void *s2, size_t n){
+ int ret=0;
+ uint8_t *c1, *c2;
+ int i;
+
+ if(!s1 || ! s2){
+ dlog(LOG_DEBUG, 5, "revcmp invalid arg: %p %p",s1, s2);
+ return 0;
+ }
+
+ c1 = (uint8_t *)s1;
+ c2 = (uint8_t *)s2;
+ for(i = n-1; i >= 0; i--){
+ if(c1[i] < c2[i])
+ ret = -1;
+
+ if(c1[i] > c2[i])
+ ret = 1;
+ if(ret){
+ /*dlog(LOG_DEBUG, 5,
+ "revcmp i%d c:%d c1[i]:%hhx c2[i]:%hhx:",
+ i, ret, c1[i], c2[i]);*/
+ return ret;
+ }
+
+ }
+ /*dlog(LOG_DEBUG, 5, "revcmp i%d cmp:%d",i, ret);*/
+ return ret;
+}
+
+struct dtimer_list *remove_from_list(struct dtimer_list *list,
+ struct timer_lst *tm){
+ struct dtimer_list *entry, *tmp=NULL;
+
+ if(list == NULL)
+ return NULL;
+
+ if(tm == NULL){ /* any entry will do (free list only) */
+ entry=list->next;
+ if(entry){
+ list->next=entry->next;
+ entry->next=NULL;
+ }
+ return entry;
+ }
+ tmp=list;
+ while(tmp->next !=NULL){
+ if(tmp->next->tm == tm){
+ entry=tmp->next;
+ tmp->next=entry->next;
+ entry->next=NULL;
+ return entry;
+ }
+ tmp=tmp->next;
+ }
+ return NULL;
+}
+
+
+void insert_into_list(struct dtimer_list *list, struct dtimer_list *entry){
+ if(!(list && entry))
+ return;
+
+ entry->next=list->next;
+ list->next=entry;
+}
+
+
+void log_list(struct dtimer_list *list, const char *listname){
+
+ char emptystring[1]={'\0'};
+ char *tmpstr=NULL;
+ struct dtimer_list *tmp;
+
+ tmpstr=emptystring;
+
+ if(list==NULL){
+ return;
+ }
+ if (listname){
+ tmpstr=(char *)listname;
+ }
+
+ dlog(LOG_DEBUG, 5, "Printing %s list: %p n(%p)", tmpstr,
+ list, list->next);
+
+ tmp=list;
+ while(tmp != NULL){
+
+ dlog(LOG_DEBUG, 5, "\t%p tm(%p) n(%p)", tmp, tmp->tm,
+ tmp->next);
+ tmp=tmp->next;
+ }
+
+}
+
+
+
+addr_match(struct in6_addr *a1, struct in6_addr *a2, int prefixlen)
+{
+ int pdw;
+ int pbi;
+
+ pdw = prefixlen >> 0x05; /* num of whole uint32_t in prefix */
+ pbi = prefixlen & 0x1f; /* num of bits in incomplete uint32_t in prefix */
+
+ if (pdw)
+ {
+ if (memcmp(a1, a2, pdw << 2))
+ return 0;
+ }
+
+ if (pbi)
+ {
+ uint32_t w1, w2;
+ uint32_t mask;
+
+ w1 = *((uint32_t *)a1 + pdw);
+ w2 = *((uint32_t *)a2 + pdw);
+
+ mask = htonl(((uint32_t) 0xffffffff) << (0x20 - pbi));
+
+ if ((w1 ^ w2) & mask)
+ return 0;
+ }
+ return 1;
+}
+
+
+
+
+
+int token_bucket_update(struct Interface *iface, struct timeval *tv)
+{
+ /* returns the number of tokens in the bucket for FastRA */
+ double difference;
+ int new_tokens;
+ struct timeval offsettv;
+ struct timeval newtokentv;
+ /*double offset;*/
+
+ difference = tv_diff(tv,&iface->LastFastRAToken);
+
+ if(difference < (((double)iface->FastRATokenInterval)/1000.0))
+ {
+ dlog(LOG_DEBUG, 5, "token bucket: No New tokens (%d)",
+ iface->NumUnicastFastRAs);
+ return iface->NumUnicastFastRAs;
+ }
+
+ dlog(LOG_DEBUG, 5, "token bucket: last(%d.%d) now(%d.%d) %f %f",
+ iface->LastFastRAToken.tv_sec, iface->LastFastRAToken.tv_usec,
+ tv->tv_sec, tv->tv_usec, difference,
+ tv_diff(tv,&iface->LastFastRAToken) );
+
+ new_tokens = (int) (difference * 1000)/iface->FastRATokenInterval;
+
+ dlog(LOG_DEBUG, 5, "new tokens: %d (ival:%d) ", new_tokens,
+ iface->FastRATokenInterval);
+
+ offsettv.tv_sec = (iface->FastRATokenInterval * new_tokens)/ 1000;
+ offsettv.tv_usec = ((iface->FastRATokenInterval * new_tokens)% 1000)
+ * 1000;
+
+ dlog(LOG_DEBUG, 5, "token offset: %ld secs %ld usecs",
+ offsettv.tv_sec, offsettv.tv_usec);
+
+ timeradd(&iface->LastFastRAToken, &offsettv, &newtokentv);
+
+ memcpy(&iface->LastFastRAToken, &newtokentv, sizeof(struct timeval));
+ if(new_tokens >= (iface->MaxUnicastFastRAs - iface->NumUnicastFastRAs))
+ {
+ iface->NumUnicastFastRAs = iface->MaxUnicastFastRAs;
+ }
+ else{
+ iface->NumUnicastFastRAs += new_tokens;
+ }
+
+ dlog(LOG_DEBUG, 5, "Tokens %d Max %d last token time: %d.%d",
+ iface->NumUnicastFastRAs, iface->MaxUnicastFastRAs,
+ iface->LastFastRAToken.tv_sec,
+ iface->LastFastRAToken.tv_usec);
+
+ return iface->NumUnicastFastRAs;
+}
+
+
+int prefix_mask(struct in6_addr *prefix, struct in6_addr *addr, int plen){
+ uint32_t mask;
+ int i=0;
+
+ while(plen > 32){
+ plen -=32;
+ prefix->s6_addr32[i] = addr->s6_addr32[i];
+ dlog(LOG_DEBUG, 5, "(%d)%2.2hx:%2.2hx", i,
+ ntohs(prefix->s6_addr16[2 * i]),
+ ntohs(prefix->s6_addr16[(2 * i)+1]));
+ i++;
+ }
+
+ mask = 0xffffffff << (32 - plen);
+
+ prefix->s6_addr32[i] = addr->s6_addr32[i] & htonl(mask);
+
+ dlog(LOG_DEBUG, 5, "(m%d)%2.2hx:%2.2hx -[%d]", i,
+ ntohs(prefix->s6_addr16[2 * i]),
+ ntohs(prefix->s6_addr16[(2 * i)+1]),plen);
+
+ i++;
+
+ for( ; i < 4; i++){
+ prefix->s6_addr32[i]=0;
+ dlog(LOG_DEBUG, 5, "(a%d)%2.2hx:%2.2hx", i,
+ ntohs(prefix->s6_addr16[2 * i]),
+ ntohs(prefix->s6_addr16[(2 * i)+1]));
+ }
+ return 0;
+}
+
+int clean_rtrprefix(struct RtrPrefixList *landlist, int curr,
+ struct timeval *now){
+ char addr_str[INET6_ADDRSTRLEN];
+ int i, j, found=0;
+ struct in6_addr astruct, *prefix;
+
+ dlog(LOG_DEBUG,5,"cleaning landmarks: num: %d (%lu.%lu) ",
+ curr, now->tv_sec, now->tv_usec);
+
+ for (i = 0; i < curr ; i++){
+
+ dlog(LOG_DEBUG,5,"landmark loop: %d curr:%d %f x(%d.%d) n(%d.%d)",
+ i,curr,tv_diff(&landlist[i].expiry, now),
+ landlist[i].expiry.tv_sec, landlist[i].expiry.tv_usec,
+ now->tv_sec, now->tv_usec);
+
+ while ((i < curr) && (tv_diff(&landlist[i].expiry, now) < 0)){
+
+ dlog(LOG_DEBUG,5,"landmark loop expiry: %d %f",i,
+ tv_diff(now, &landlist[i].expiry));
+
+ memset(&landlist[0], 0, sizeof(struct RtrPrefixList));
+ curr--;
+
+ for(j = i; j < curr; j++){
+ memcpy( &landlist[j], &landlist[j+1],
+ sizeof(struct RtrPrefixList));
+ }
+ memset(&landlist[j], 0, sizeof(struct RtrPrefixList));
+ }
+ }
+
+ dlog(LOG_DEBUG,5,"landmark loop exit: %d c:%d",i,curr);
+
+ return curr;
+}
+
+
+int add_rtrprefix(struct RtrPrefixList *landlist, int num, int curr,
+ struct in6_addr *prefix, uint32_t expires, int hash, int plen){
+ struct timeval now, tv, expirestimer;
+ unsigned char digest[SHA_DIGEST_LENGTH];
+ char addr_str[INET6_ADDRSTRLEN];
+ int i, j, found=0;
+ expirestimer.tv_sec=expires;
+ expirestimer.tv_usec=0;
+ gettimeofday(&now, NULL);
+ timeradd(&now, &expirestimer, &tv);
+
+ dlog(LOG_DEBUG,5,"adding landmarks: Prefix expiry: %lu %d (%d.%d) ",
+ expires, curr, tv.tv_sec, tv.tv_usec);
+
+ for (i = 0; i < curr ; i++){
+
+ dlog(LOG_DEBUG,5,"landmark loop: %d curr:%d %f x(%d.%d) n(%d.%d)",
+ i,curr,tv_diff(&landlist[i].expiry, &now),
+ landlist[i].expiry.tv_sec, landlist[i].expiry.tv_usec,
+ now.tv_sec, now.tv_usec);
+
+
+
+ while ((i < curr) && (tv_diff(&landlist[i].expiry, &now) < 0)){
+
+ dlog(LOG_DEBUG,5,"landmark loop expiry: %d %f",i,
+ tv_diff(&now, &landlist[i].expiry));
+
+ memset(&landlist[0], 0, sizeof(struct RtrPrefixList));
+ curr--;
+
+ for(j = i; j < curr; j++){
+ memcpy( &landlist[j], &landlist[j+1],
+ sizeof(struct RtrPrefixList));
+ }
+ memset(&landlist[j], 0, sizeof(struct RtrPrefixList));
+ }
+ if(!memcmp(&landlist[i].Prefix, prefix,
+ sizeof(struct in6_addr))){
+
+ dlog(LOG_DEBUG,5,"landmark match: %d e(%d.%d)",i,
+ landlist[i].expiry.tv_sec,
+ landlist[i].expiry.tv_usec);
+ if(tv_diff(&tv , &landlist[i].expiry) > 0){
+ memcpy(&landlist[i].expiry, &tv, sizeof (struct
+ timeval));
+ }
+ landlist[i].this_adv=1;
+ found=1;
+ return curr;
+ }
+ }
+
+ dlog(LOG_DEBUG,5,"landmark loop exit: %d c:%d n:%d",i,curr, num);
+ if(curr == num)
+ return 0;
+
+ dlog(LOG_DEBUG,5,"landmark curr != num ");
+ dlog(LOG_DEBUG,5,"landmark expiry: %lu.%lu",tv.tv_sec, tv.tv_usec);
+
+ memcpy(&landlist[curr].Prefix, prefix, sizeof(struct in6_addr));
+ memcpy(&landlist[curr].expiry, &tv, sizeof (struct timeval));
+ landlist[curr].this_adv=1;
+ landlist[curr].plen=plen;
+
+ print_addr(&landlist[curr].Prefix, addr_str);
+
+ dlog(LOG_DEBUG,5,"landmark prefix(%d): %s",curr,addr_str);
+
+ dlog(LOG_DEBUG,5,"about to hash? (%d)");
+ if(hash){
+ SHA1((unsigned char *)&landlist[curr].Prefix,
+ sizeof(struct in6_addr), digest);
+ memcpy(&landlist[curr].hash, digest, 8);
+ dlog(LOG_DEBUG,5,"hash install: %d c:%d %8.8lx%8.8lx",i, curr,
+ ntohl(((uint32_t *)landlist[curr].hash)[0]),
+ ntohl(((uint32_t *)landlist[curr].hash)[1]));
+ }
+ dlog(LOG_DEBUG,5,"landmark install: %d c:%d e(%d.%d)",i, curr,
+ landlist[curr].expiry.tv_sec,
+ landlist[curr].expiry.tv_usec);
+ return curr+1;
+}
+
+
+
+/* the land timers need to be set to a nearer expiry if that exists */
+
+int update_landtimers(struct RtrPrefixList *landlist, int curr,
+ uint32_t expires){
+ int i;
+ struct timeval now, tv, expirestimer;
+
+ expirestimer.tv_sec=expires;
+ expirestimer.tv_usec=0;
+ gettimeofday(&now, NULL);
+ timeradd(&now, &expirestimer, &tv);
+
+ for(i = 0; i < curr ; i++){
+
+ dlog(LOG_DEBUG,5,"landmark update loop",i);
+ if(landlist[i].this_adv && (tv_diff(&tv, &landlist[i].expiry)
+ < 0)){
+ memcpy(&landlist[i].expiry, &tv, sizeof
+ (struct timeval));
+ }
+ landlist[i].this_adv=0;
+ }
+ return i;
+}
+
+
+
+int check_before(struct RtrPrefixList *list, int curr,
+ uint32_t *ownhash, struct in6_addr *addr){
+ int count = 0;
+ int i;
+ uint64_t ownval[8], calcval[8];
+ char addr_str[INET6_ADDRSTRLEN];
+
+ if(curr == 0)
+ return 0;
+
+ ownval[0] = *((uint64_t *)ownhash) ^ *((uint64_t *)&addr->s6_addr[8]);
+
+ dlog(LOG_DEBUG,5,"own hash: c:%d %8.8lx%8.8lx",curr,
+ ntohl(ownhash[0]), ntohl(ownhash[1]));
+ print_addr(addr, addr_str);
+ dlog(LOG_DEBUG,4,"own xor: %8.8lx%8.8lx %s",
+ ntohl(((uint32_t *)ownval)[0]),
+ ntohl(((uint32_t *)ownval)[1]),
+ addr_str);
+
+ for(i = 0; i < curr; i ++){
+ print_addr(&list[i].Prefix, addr_str);
+ calcval[0] = *((uint64_t *)list[i].hash) ^
+ *((uint64_t *)&addr->s6_addr[8]);
+ /*calcval[1] = list[i].hash[1] ^ addr->s6_addr32[3];*/
+ dlog(LOG_DEBUG,5,"peer hash: %d %8.8lx%8.8lx %s",i,
+ ntohl(((uint32_t *)list[i].hash)[0]),
+ ntohl(((uint32_t *)list[i].hash)[1]),addr_str);
+ dlog(LOG_DEBUG,5,"rec pattern: %d %8.8lx%8.8lx",i,
+ ntohl(addr->s6_addr32[2]),
+ ntohl(addr->s6_addr32[3]));
+
+ print_addr(addr, addr_str);
+ dlog(LOG_DEBUG,4,"peer xor: %d %8.8lx%8.8lx %s %d",i,
+ ntohl(((uint32_t *)calcval)[0]),
+ ntohl(((uint32_t *)calcval)[1]),
+ addr_str,
+ revcmp(ownval, calcval, 8));
+
+ if(revcmp(ownval, calcval, 8) < 0 ){
+ count++;
+ }
+ }
+
+ return count;
+}