Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
babeld
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
babeld
Commits
5afde873
Commit
5afde873
authored
Nov 09, 2018
by
Juliusz Chroboczek
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'rfc6126bis'
parents
8627b6fc
3a4fbbf0
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
937 additions
and
1016 deletions
+937
-1016
babeld.c
babeld.c
+25
-16
configuration.c
configuration.c
+9
-0
disambiguation.c
disambiguation.c
+2
-0
interface.c
interface.c
+43
-33
interface.h
interface.h
+25
-21
kernel_netlink.c
kernel_netlink.c
+14
-10
kernel_socket.c
kernel_socket.c
+3
-1
local.c
local.c
+2
-2
message.c
message.c
+556
-785
message.h
message.h
+13
-20
neighbour.c
neighbour.c
+23
-2
neighbour.h
neighbour.h
+1
-0
resend.c
resend.c
+9
-5
route.c
route.c
+2
-2
source.c
source.c
+2
-0
util.c
util.c
+1
-1
util.h
util.h
+1
-2
xroute.c
xroute.c
+205
-115
xroute.h
xroute.h
+1
-1
No files found.
babeld.c
View file @
5afde873
...
...
@@ -582,8 +582,9 @@ main(int argc, char **argv)
send_hello
(
ifp
);
send_wildcard_retraction
(
ifp
);
send_self_update
(
ifp
);
send_multicast_request
(
ifp
,
NULL
,
0
,
NULL
,
0
);
flushupdates
(
ifp
);
flushbuf
(
ifp
);
flushbuf
(
&
ifp
->
buf
);
}
debugf
(
"Entering main loop.
\n
"
);
...
...
@@ -591,6 +592,7 @@ main(int argc, char **argv)
while
(
1
)
{
struct
timeval
tv
;
fd_set
readfds
;
struct
neighbour
*
neigh
;
gettime
(
&
now
);
...
...
@@ -603,12 +605,14 @@ main(int argc, char **argv)
FOR_ALL_INTERFACES
(
ifp
)
{
if
(
!
if_up
(
ifp
))
continue
;
timeval_min
(
&
tv
,
&
ifp
->
flush_
timeout
);
timeval_min
(
&
tv
,
&
ifp
->
buf
.
timeout
);
timeval_min
(
&
tv
,
&
ifp
->
hello_timeout
);
timeval_min
(
&
tv
,
&
ifp
->
update_timeout
);
timeval_min
(
&
tv
,
&
ifp
->
update_flush_timeout
);
}
timeval_min
(
&
tv
,
&
unicast_flush_timeout
);
FOR_ALL_NEIGHBOURS
(
neigh
)
{
timeval_min
(
&
tv
,
&
neigh
->
buf
.
timeout
);
}
FD_ZERO
(
&
readfds
);
if
(
timeval_compare
(
&
tv
,
&
now
)
>
0
)
{
int
maxfd
=
0
;
...
...
@@ -770,17 +774,22 @@ main(int argc, char **argv)
do_resend
();
}
if
(
unicast_flush_timeout
.
tv_sec
!=
0
)
{
if
(
timeval_compare
(
&
now
,
&
unicast_flush_timeout
)
>=
0
)
flush_unicast
(
1
);
}
FOR_ALL_INTERFACES
(
ifp
)
{
if
(
!
if_up
(
ifp
))
continue
;
if
(
ifp
->
flush_timeout
.
tv_sec
!=
0
)
{
if
(
timeval_compare
(
&
now
,
&
ifp
->
flush_timeout
)
>=
0
)
flushbuf
(
ifp
);
if
(
ifp
->
buf
.
timeout
.
tv_sec
!=
0
)
{
if
(
timeval_compare
(
&
now
,
&
ifp
->
buf
.
timeout
)
>=
0
)
{
flushupdates
(
ifp
);
flushbuf
(
&
ifp
->
buf
);
}
}
}
FOR_ALL_NEIGHBOURS
(
neigh
)
{
if
(
neigh
->
buf
.
timeout
.
tv_sec
!=
0
)
{
if
(
timeval_compare
(
&
now
,
&
neigh
->
buf
.
timeout
)
>=
0
)
{
flushbuf
(
&
neigh
->
buf
);
}
}
}
...
...
@@ -803,8 +812,8 @@ main(int argc, char **argv)
send_wildcard_retraction
(
ifp
);
/* Make sure that we expire quickly from our neighbours'
association caches. */
send_hello_no
update
(
ifp
,
10
);
flushbuf
(
ifp
);
send_hello_no
ihu
(
ifp
,
10
);
flushbuf
(
&
ifp
->
buf
);
usleep
(
roughly
(
1000
));
gettime
(
&
now
);
}
...
...
@@ -813,8 +822,8 @@ main(int argc, char **argv)
continue
;
/* Make sure they got it. */
send_wildcard_retraction
(
ifp
);
send_hello_no
update
(
ifp
,
1
);
flushbuf
(
ifp
);
send_hello_no
ihu
(
ifp
,
1
);
flushbuf
(
&
ifp
->
buf
);
usleep
(
roughly
(
10000
));
gettime
(
&
now
);
interface_up
(
ifp
,
0
);
...
...
@@ -1113,7 +1122,7 @@ dump_tables(FILE *out)
FOR_ALL_NEIGHBOURS
(
neigh
)
{
fprintf
(
out
,
"Neighbour %s dev %s reach %04x ureach %04x "
"rxcost %
d txcost %d rtt %s rttcost %d
chan %d%s.
\n
"
,
"rxcost %
u txcost %d rtt %s rttcost %u
chan %d%s.
\n
"
,
format_address
(
neigh
->
address
),
neigh
->
ifp
->
name
,
neigh
->
hello
.
reach
,
...
...
configuration.c
View file @
5afde873
...
...
@@ -24,6 +24,8 @@ THE SOFTWARE.
#include <string.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <assert.h>
#ifdef __linux
...
...
@@ -560,6 +562,12 @@ parse_anonymous_ifconf(int c, gnc_t gnc, void *closure,
if
(
c
<
-
1
)
goto
error
;
if_conf
->
faraway
=
v
;
}
else
if
(
strcmp
(
token
,
"unicast"
)
==
0
)
{
int
v
;
c
=
getbool
(
c
,
&
v
,
gnc
,
closure
);
if
(
c
<
-
1
)
goto
error
;
if_conf
->
unicast
=
v
;
}
else
if
(
strcmp
(
token
,
"link-quality"
)
==
0
)
{
int
v
;
c
=
getbool
(
c
,
&
v
,
gnc
,
closure
);
...
...
@@ -711,6 +719,7 @@ merge_ifconf(struct interface_conf *dest,
MERGE
(
split_horizon
);
MERGE
(
lq
);
MERGE
(
faraway
);
MERGE
(
unicast
);
MERGE
(
channel
);
MERGE
(
enable_timestamps
);
MERGE
(
rfc6126
);
...
...
disambiguation.c
View file @
5afde873
...
...
@@ -25,6 +25,8 @@ THE SOFTWARE.
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#include "babeld.h"
...
...
interface.c
View file @
5afde873
...
...
@@ -80,8 +80,6 @@ add_interface(char *ifname, struct interface_conf *if_conf)
strncpy
(
ifp
->
name
,
ifname
,
IF_NAMESIZE
);
ifp
->
conf
=
if_conf
?
if_conf
:
default_interface_conf
;
ifp
->
bucket_time
=
now
.
tv_sec
;
ifp
->
bucket
=
BUCKET_TOKENS_MAX
;
ifp
->
hello_seqno
=
(
random
()
&
0xFFFF
);
if
(
interfaces
==
NULL
)
...
...
@@ -132,14 +130,14 @@ flush_interface(char *ifname)
/* This should be no more than half the hello interval, so that hellos
aren't sent late. The result is in milliseconds. */
unsigned
jitter
(
struct
interface
*
ifp
,
int
urgent
)
jitter
(
struct
buffered
*
buf
,
int
urgent
)
{
unsigned
interval
=
ifp
->
hello
_interval
;
unsigned
interval
=
buf
->
flush
_interval
;
if
(
urgent
)
interval
=
MIN
(
interval
,
10
0
);
interval
=
MIN
(
interval
,
2
0
);
else
interval
=
MIN
(
interval
,
4
000
);
return
roughly
(
interval
)
/
4
;
interval
=
MIN
(
interval
,
2
000
);
return
roughly
(
interval
/
2
)
;
}
unsigned
...
...
@@ -297,14 +295,20 @@ interface_up(struct interface *ifp, int up)
rc
=
kernel_setup_interface
(
1
,
ifp
->
name
,
ifp
->
ifindex
);
if
(
rc
<
0
)
{
fprintf
(
stderr
,
"kernel_setup_interface(%s, %
d
) failed.
\n
"
,
fprintf
(
stderr
,
"kernel_setup_interface(%s, %
u
) failed.
\n
"
,
ifp
->
name
,
ifp
->
ifindex
);
goto
fail
;
}
memset
(
&
ifp
->
buf
.
sin6
,
0
,
sizeof
(
ifp
->
buf
.
sin6
));
ifp
->
buf
.
sin6
.
sin6_family
=
AF_INET6
;
memcpy
(
&
ifp
->
buf
.
sin6
.
sin6_addr
,
protocol_group
,
16
);
ifp
->
buf
.
sin6
.
sin6_port
=
htons
(
protocol_port
);
ifp
->
buf
.
sin6
.
sin6_scope_id
=
ifp
->
ifindex
;
mtu
=
kernel_interface_mtu
(
ifp
->
name
,
ifp
->
ifindex
);
if
(
mtu
<
0
)
{
fprintf
(
stderr
,
"Warning: couldn't get MTU of interface %s (%
d
).
\n
"
,
fprintf
(
stderr
,
"Warning: couldn't get MTU of interface %s (%
u
).
\n
"
,
ifp
->
name
,
ifp
->
ifindex
);
mtu
=
1280
;
}
...
...
@@ -314,27 +318,27 @@ interface_up(struct interface *ifp, int up)
/* In IPv6, the minimum MTU is 1280, and every host must be able
to reassemble up to 1500 bytes, but I'd rather not rely on this. */
if
(
mtu
<
128
)
{
fprintf
(
stderr
,
"Suspiciously low MTU %d on interface %s (%
d
).
\n
"
,
fprintf
(
stderr
,
"Suspiciously low MTU %d on interface %s (%
u
).
\n
"
,
mtu
,
ifp
->
name
,
ifp
->
ifindex
);
mtu
=
128
;
}
if
(
ifp
->
send
buf
)
free
(
ifp
->
send
buf
);
if
(
ifp
->
buf
.
buf
)
free
(
ifp
->
buf
.
buf
);
/* 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
ifp
->
bufsize
=
mtu
-
sizeof
(
packet_header
)
-
60
;
ifp
->
sendbuf
=
malloc
(
ifp
->
buf
size
);
if
(
ifp
->
send
buf
==
NULL
)
{
ifp
->
buf
.
size
=
mtu
-
sizeof
(
packet_header
)
-
60
;
ifp
->
buf
.
buf
=
malloc
(
ifp
->
buf
.
size
);
if
(
ifp
->
buf
.
buf
==
NULL
)
{
fprintf
(
stderr
,
"Couldn't allocate sendbuf.
\n
"
);
ifp
->
bufsize
=
0
;
ifp
->
buf
.
size
=
0
;
goto
fail
;
}
rc
=
resize_receive_buffer
(
mtu
);
if
(
rc
<
0
)
fprintf
(
stderr
,
"Warning: couldn't resize "
"receive buffer for interface %s (%
d
) (%d bytes).
\n
"
,
"receive buffer for interface %s (%
u
) (%d bytes).
\n
"
,
ifp
->
name
,
ifp
->
ifindex
,
mtu
);
type
=
IF_CONF
(
ifp
,
type
);
...
...
@@ -345,7 +349,7 @@ interface_up(struct interface *ifp, int up)
rc
=
kernel_interface_wireless
(
ifp
->
name
,
ifp
->
ifindex
);
if
(
rc
<
0
)
{
fprintf
(
stderr
,
"Warning: couldn't determine whether %s (%
d
) "
"Warning: couldn't determine whether %s (%
u
) "
"is a wireless interface.
\n
"
,
ifp
->
name
,
ifp
->
ifindex
);
}
else
if
(
rc
)
{
...
...
@@ -387,6 +391,9 @@ interface_up(struct interface *ifp, int up)
if
(
IF_CONF
(
ifp
,
faraway
)
==
CONFIG_YES
)
ifp
->
flags
|=
IF_FARAWAY
;
if
(
IF_CONF
(
ifp
,
unicast
)
==
CONFIG_YES
)
ifp
->
flags
|=
IF_UNICAST
;
if
(
IF_CONF
(
ifp
,
hello_interval
)
>
0
)
ifp
->
hello_interval
=
IF_CONF
(
ifp
,
hello_interval
);
else
if
(
type
==
IF_TYPE_WIRELESS
)
...
...
@@ -399,6 +406,10 @@ interface_up(struct interface *ifp, int up)
IF_CONF
(
ifp
,
update_interval
)
:
ifp
->
hello_interval
*
4
;
/* This must be no more than half the Hello interval, or else
Hellos will arrive late. */
ifp
->
buf
.
flush_interval
=
ifp
->
hello_interval
/
2
;
ifp
->
rtt_decay
=
IF_CONF
(
ifp
,
rtt_decay
)
>
0
?
IF_CONF
(
ifp
,
rtt_decay
)
:
42
;
...
...
@@ -411,8 +422,8 @@ interface_up(struct interface *ifp, int up)
IF_CONF
(
ifp
,
rtt_max
)
:
120000
;
if
(
ifp
->
rtt_max
<=
ifp
->
rtt_min
)
{
fprintf
(
stderr
,
"Uh, rtt-max is less than or equal to rtt-min (%
d <= %d
). "
"Setting it to %
d
.
\n
"
,
ifp
->
rtt_max
,
ifp
->
rtt_min
,
"Uh, rtt-max is less than or equal to rtt-min (%
u <= %u
). "
"Setting it to %
u
.
\n
"
,
ifp
->
rtt_max
,
ifp
->
rtt_min
,
ifp
->
rtt_min
+
10000
);
ifp
->
rtt_max
=
ifp
->
rtt_min
+
10000
;
}
...
...
@@ -421,23 +432,20 @@ interface_up(struct interface *ifp, int up)
ifp
->
max_rtt_penalty
=
96
;
if
(
IF_CONF
(
ifp
,
enable_timestamps
)
==
CONFIG_YES
)
ifp
->
flags
|=
IF_TIMESTAMPS
;
ifp
->
buf
.
enable_timestamps
=
1
;
else
if
(
IF_CONF
(
ifp
,
enable_timestamps
)
==
CONFIG_NO
)
ifp
->
flags
&=
~
IF_TIMESTAMPS
;
ifp
->
buf
.
enable_timestamps
=
0
;
else
if
(
type
==
IF_TYPE_TUNNEL
)
ifp
->
flags
|=
IF_TIMESTAMPS
;
ifp
->
buf
.
enable_timestamps
=
1
;
else
ifp
->
flags
&=
~
IF_TIMESTAMPS
;
if
(
ifp
->
max_rtt_penalty
>
0
&&
!
(
ifp
->
flags
&
IF_TIMESTAMPS
)
)
ifp
->
buf
.
enable_timestamps
=
0
;
if
(
ifp
->
max_rtt_penalty
>
0
&&
!
ifp
->
buf
.
enable_timestamps
)
fprintf
(
stderr
,
"Warning: max_rtt_penalty is set "
"but timestamps are disabled on interface %s.
\n
"
,
ifp
->
name
);
if
(
IF_CONF
(
ifp
,
rfc6126
)
==
CONFIG_YES
)
ifp
->
flags
|=
IF_RFC6126
;
else
ifp
->
flags
&=
~
IF_RFC6126
;
ifp
->
buf
.
rfc6126_compatible
=
(
IF_CONF
(
ifp
,
rfc6126
)
==
CONFIG_YES
);
rc
=
check_link_local_addresses
(
ifp
);
if
(
rc
<
0
)
{
...
...
@@ -472,17 +480,18 @@ interface_up(struct interface *ifp, int up)
send_hello
(
ifp
);
if
(
rc
>
0
)
send_update
(
ifp
,
0
,
NULL
,
0
,
NULL
,
0
);
send_multicast_request
(
ifp
,
NULL
,
0
,
NULL
,
0
);
}
else
{
flush_interface_routes
(
ifp
,
0
);
ifp
->
buf
fered
=
0
;
ifp
->
bufsize
=
0
;
free
(
ifp
->
send
buf
);
ifp
->
buf
.
len
=
0
;
ifp
->
buf
.
size
=
0
;
free
(
ifp
->
buf
.
buf
);
ifp
->
num_buffered_updates
=
0
;
ifp
->
update_bufsize
=
0
;
if
(
ifp
->
buffered_updates
)
free
(
ifp
->
buffered_updates
);
ifp
->
buffered_updates
=
NULL
;
ifp
->
send
buf
=
NULL
;
ifp
->
buf
.
buf
=
NULL
;
if
(
ifp
->
ifindex
>
0
)
{
memset
(
&
mreq
,
0
,
sizeof
(
mreq
));
memcpy
(
&
mreq
.
ipv6mr_multiaddr
,
protocol_group
,
16
);
...
...
@@ -558,6 +567,7 @@ check_interfaces(void)
check_interface_channel
(
ifp
);
rc
=
check_interface_ipv4
(
ifp
);
if
(
rc
>
0
)
{
send_multicast_request
(
ifp
,
NULL
,
0
,
NULL
,
0
);
send_update
(
ifp
,
0
,
NULL
,
0
,
NULL
,
0
);
}
}
...
...
interface.h
View file @
5afde873
...
...
@@ -45,6 +45,7 @@ struct interface_conf {
char
split_horizon
;
char
lq
;
char
faraway
;
char
unicast
;
int
channel
;
int
enable_timestamps
;
int
rfc6126
;
...
...
@@ -69,16 +70,34 @@ struct interface_conf {
#define IF_LQ (1 << 3)
/* Nodes on the far end don't interfere with nodes on the near end. */
#define IF_FARAWAY (1 << 4)
/* Send timestamps in Hello and IHU. */
#define IF_TIMESTAMPS (1 << 5)
/* Remain compatible with RFC 6126. */
#define IF_RFC6126 (1 << 6)
/* Send most TLVs over unicast. */
#define IF_UNICAST (1 << 5)
/* Only INTERFERING can appear on the wire. */
#define IF_CHANNEL_UNKNOWN 0
#define IF_CHANNEL_INTERFERING 255
#define IF_CHANNEL_NONINTERFERING -2
struct
buffered
{
struct
sockaddr_in6
sin6
;
char
*
buf
;
int
len
;
int
size
;
int
flush_interval
;
struct
timeval
timeout
;
char
enable_timestamps
;
char
rfc6126_compatible
;
char
have_id
;
char
have_nh
;
char
have_prefix
;
unsigned
char
id
[
8
];
unsigned
char
nh
[
4
];
unsigned
char
prefix
[
16
];
/* Relative position of the Hello message in the send buffer, or
(-1) if there is none. */
int
hello
;
};
struct
interface
{
struct
interface
*
next
;
struct
interface_conf
*
conf
;
...
...
@@ -88,31 +107,16 @@ struct interface {
int
channel
;
struct
timeval
hello_timeout
;
struct
timeval
update_timeout
;
struct
timeval
flush_timeout
;
struct
timeval
update_flush_timeout
;
char
name
[
IF_NAMESIZE
];
unsigned
char
*
ipv4
;
int
numll
;
unsigned
char
(
*
ll
)[
16
];
int
buffered
;
int
bufsize
;
/* Relative position of the Hello message in the send buffer, or
(-1) if there is none. */
int
buffered_hello
;
char
have_buffered_id
;
char
have_buffered_nh
;
char
have_buffered_prefix
;
unsigned
char
buffered_id
[
8
];
unsigned
char
buffered_nh
[
4
];
unsigned
char
buffered_prefix
[
16
];
unsigned
char
*
sendbuf
;
struct
buffered
buf
;
struct
buffered_update
*
buffered_updates
;
int
num_buffered_updates
;
int
update_bufsize
;
time_t
bucket_time
;
unsigned
int
bucket
;
time_t
last_update_time
;
time_t
last_specific_update_time
;
unsigned
short
hello_seqno
;
unsigned
hello_interval
;
unsigned
update_interval
;
...
...
@@ -140,7 +144,7 @@ if_up(struct interface *ifp)
struct
interface
*
add_interface
(
char
*
ifname
,
struct
interface_conf
*
if_conf
);
int
flush_interface
(
char
*
ifname
);
unsigned
jitter
(
struct
interface
*
ifp
,
int
urgent
);
unsigned
jitter
(
struct
buffered
*
buf
,
int
urgent
);
unsigned
update_jitter
(
struct
interface
*
ifp
,
int
urgent
);
void
set_timeout
(
struct
timeval
*
timeout
,
int
msecs
);
int
interface_up
(
struct
interface
*
ifp
,
int
up
);
...
...
kernel_netlink.c
View file @
5afde873
...
...
@@ -446,7 +446,7 @@ netlink_talk(struct nlmsghdr *nh)
nh
->
nlmsg_seq
=
++
nl_command
.
seqno
;
kdebugf
(
"Sending seqno %d from address %p (talk)
\n
"
,
nl_command
.
seqno
,
&
nl_command
.
seqno
);
nl_command
.
seqno
,
(
void
*
)
&
nl_command
.
seqno
);
rc
=
sendmsg
(
nl_command
.
sock
,
&
msg
,
0
);
if
(
rc
<
0
&&
(
errno
==
EAGAIN
||
errno
==
EINTR
))
{
...
...
@@ -514,7 +514,7 @@ netlink_send_dump(int type, void *data, int len) {
buf
.
nh
.
nlmsg_len
=
NLMSG_LENGTH
(
len
);
kdebugf
(
"Sending seqno %d from address %p (dump)
\n
"
,
nl_command
.
seqno
,
&
nl_command
.
seqno
);
nl_command
.
seqno
,
(
void
*
)
&
nl_command
.
seqno
);
rc
=
sendmsg
(
nl_command
.
sock
,
&
msg
,
0
);
if
(
rc
<
buf
.
nh
.
nlmsg_len
)
{
...
...
@@ -677,14 +677,18 @@ kernel_setup_interface(int setup, const char *ifname, int ifindex)
fprintf
(
stderr
,
"Warning: cannot save old configuration for %s.
\n
"
,
ifname
);
rc
=
write_proc
(
buf
,
0
);
if
(
rc
<
0
)
return
-
1
;
if
(
old_if
[
i
].
rp_filter
)
{
rc
=
write_proc
(
buf
,
0
);
if
(
rc
<
0
)
return
-
1
;
}
}
else
{
if
(
i
>=
0
&&
old_if
[
i
].
rp_filter
>
=
0
)
if
(
i
>=
0
&&
old_if
[
i
].
rp_filter
>
0
)
rc
=
write_proc
(
buf
,
old_if
[
i
].
rp_filter
);
else
else
if
(
i
<
0
)
rc
=
-
1
;
else
rc
=
1
;
if
(
rc
<
0
)
fprintf
(
stderr
,
...
...
@@ -1590,7 +1594,7 @@ add_rule(int prio, const unsigned char *src_prefix, int src_plen, int table)
message_header
->
nlmsg_len
+=
current_attribute
->
rta_len
;
current_attribute
=
(
void
*
)
((
char
*
)
current_attribute
)
+
current_attribute
->
rta_len
;
((
char
*
)
current_attribute
+
current_attribute
->
rta_len
)
;
/* src */
current_attribute
->
rta_len
=
RTA_LENGTH
(
addr_size
);
...
...
@@ -1599,7 +1603,7 @@ add_rule(int prio, const unsigned char *src_prefix, int src_plen, int table)
message_header
->
nlmsg_len
+=
current_attribute
->
rta_len
;
current_attribute
=
(
void
*
)
((
char
*
)
current_attribute
)
+
current_attribute
->
rta_len
;
((
char
*
)
current_attribute
+
current_attribute
->
rta_len
)
;
/* send message */
if
(
message_header
->
nlmsg_len
>
64
)
{
...
...
@@ -1652,7 +1656,7 @@ flush_rule(int prio, int family)
message_header
->
nlmsg_len
+=
current_attribute
->
rta_len
;
current_attribute
=
(
void
*
)
((
char
*
)
current_attribute
)
+
current_attribute
->
rta_len
;
((
char
*
)
current_attribute
+
current_attribute
->
rta_len
)
;
/* send message */
if
(
message_header
->
nlmsg_len
>
64
)
{
...
...
kernel_socket.c
View file @
5afde873
...
...
@@ -44,11 +44,13 @@ THE SOFTWARE.
#include <net/route.h>
#include "babeld.h"
#include "interface.h"
#include "neighbour.h"
#include "kernel.h"
#include "util.h"
static
int
get_sdl
(
struct
sockaddr_dl
*
sdl
,
char
*
ifname
);
static
const
unsigned
char
v4prefix
[
16
]
=
...
...
@@ -586,7 +588,7 @@ print_kernel_route(int add, struct kernel_route *route)
memcpy
(
ifname
,
"unk"
,
4
);
fprintf
(
stderr
,
"%s kernel route: dest: %s gw: %s metric: %d if: %s(%
d
)
\n
"
,
"%s kernel route: dest: %s gw: %s metric: %d if: %s(%
u
)
\n
"
,
add
==
RTM_ADD
?
"Add"
:
add
==
RTM_DELETE
?
"Delete"
:
"Change"
,
format_prefix
(
route
->
prefix
,
route
->
plen
),
...
...
local.c
View file @
5afde873
...
...
@@ -145,7 +145,7 @@ local_notify_neighbour_1(struct local_socket *s,
rttbuf
[
0
]
=
'\0'
;
if
(
valid_rtt
(
neigh
))
{
rc
=
snprintf
(
rttbuf
,
64
,
" rtt %s rttcost %
d
"
,
rc
=
snprintf
(
rttbuf
,
64
,
" rtt %s rttcost %
u
"
,
format_thousands
(
neigh
->
rtt
),
neighbour_rttcost
(
neigh
));
if
(
rc
<
0
||
rc
>=
64
)
rttbuf
[
0
]
=
'\0'
;
...
...
@@ -154,7 +154,7 @@ local_notify_neighbour_1(struct local_socket *s,
rc
=
snprintf
(
buf
,
512
,
"%s neighbour %lx address %s "
"if %s reach %04x ureach %04x "
"rxcost %
d txcost %d%s cost %d
\n
"
,
"rxcost %
u txcost %u%s cost %u
\n
"
,
local_kind
(
kind
),
/* Neighbours never move around in memory , so we can use the
address as a unique identifier. */
...
...
message.c
View file @
5afde873
...
...
@@ -48,12 +48,6 @@ int split_horizon = 1;
unsigned
short
myseqno
=
0
;
struct
timeval
seqno_time
=
{
0
,
0
};
#define UNICAST_BUFSIZE 1024
int
unicast_buffered
=
0
;
unsigned
char
*
unicast_buffer
=
NULL
;
struct
neighbour
*
unicast_neighbour
=
NULL
;
struct
timeval
unicast_flush_timeout
=
{
0
,
0
};
extern
const
unsigned
char
v4prefix
[
16
];
#define MAX_CHANNEL_HOPS 20
...
...
@@ -121,9 +115,10 @@ network_prefix(int ae, int plen, unsigned int omitted,
}
static
int
parse_update_subtlv
(
struct
interface
*
ifp
,
int
metric
,
parse_update_subtlv
(
struct
interface
*
ifp
,
int
metric
,
int
ae
,
const
unsigned
char
*
a
,
int
alen
,
unsigned
char
*
channels
,
int
*
channels_len_return
)
unsigned
char
*
channels
,
int
*
channels_len_return
,
unsigned
char
*
src_prefix
,
unsigned
char
*
src_plen
)
{
int
type
,
len
,
i
=
0
;
int
channels_len
;
...
...
@@ -149,21 +144,28 @@ parse_update_subtlv(struct interface *ifp, int metric,
continue
;
}
if
(
i
+
1
>
alen
)
{
fprintf
(
stderr
,
"Received truncated sub-TLV on Update.
\n
"
);
return
-
1
;
}
if
(
i
+
1
>
alen
)
goto
fail
;
len
=
a
[
i
+
1
];
if
(
i
+
len
+
2
>
alen
)
{
fprintf
(
stderr
,
"Received truncated sub-TLV on Update.
\n
"
);
return
-
1
;
}
if
(
i
+
len
+
2
>
alen
)
goto
fail
;
if
(
type
==
SUBTLV_PADN
)
{
/* Nothing. */
}
else
if
(
type
==
SUBTLV_DIVERSITY
)
{
memcpy
(
channels
,
a
+
i
+
2
,
MIN
(
len
,
*
channels_len_return
));
channels_len
=
MIN
(
len
,
*
channels_len_return
);
}
else
if
(
type
==
SUBTLV_SOURCE_PREFIX
)
{
int
rc
;
if
(
len
<
1
)
goto
fail
;
*
src_plen
=
a
[
i
+
2
];
rc
=
network_prefix
(
ae
,
*
src_plen
,
0
,
a
+
i
+
3
,
NULL
,
len
-
1
,
src_prefix
);
if
(
rc
<
0
)
goto
fail
;
if
(
ae
==
1
)
(
*
src_plen
)
+=
96
;
}
else
{
debugf
(
"Received unknown%s Update sub-TLV %d.
\n
"
,
(
type
&
0x80
)
!=
0
?
" mandatory"
:
""
,
type
);
...
...
@@ -175,6 +177,10 @@ parse_update_subtlv(struct interface *ifp, int metric,
}
*
channels_len_return
=
channels_len
;
return
1
;
fail:
fprintf
(
stderr
,
"Received truncated sub-TLV on Update.
\n
"
);
return
-
1
;
}
static
int
...
...
@@ -249,6 +255,7 @@ parse_ihu_subtlv(const unsigned char *a, int alen,
fprintf
(
stderr
,
"Received truncated sub-TLV on IHU.
\n
"
);
return
-
1
;
}
len
=
a
[
i
+
1
];
if
(
i
+
len
+
2
>
alen
)
{
fprintf
(
stderr
,
"Received truncated sub-TLV on IHU.
\n
"
);
...
...
@@ -287,7 +294,8 @@ parse_ihu_subtlv(const unsigned char *a, int alen,
}
static
int
parse_other_subtlv
(
const
unsigned
char
*
a
,
int
alen
)
parse_request_subtlv
(
int
ae
,
const
unsigned
char
*
a
,
int
alen
,
unsigned
char
*
src_prefix
,
unsigned
char
*
src_plen
)
{
int
type
,
len
,
i
=
0
;
...
...
@@ -298,16 +306,107 @@ parse_other_subtlv(const unsigned char *a, int alen)
continue
;
}
if
(
i
+
1
>
alen
)
{
fprintf
(
stderr
,
"Received truncated sub-TLV.
\n
"
);
return
-
1
;
if
(
i
+
1
>
alen
)
goto
fail
;
len
=
a
[
i
+
1
];
if
(
i
+
len
>
alen
)
goto
fail
;
if
(
type
==
SUBTLV_PADN
)
{
/* Nothing to do. */
}
else
if
(
type
==
SUBTLV_SOURCE_PREFIX
)
{
int
rc
;
if
(
len
<
1
)
goto
fail
;
*
src_plen
=
a
[
i
+
2
];
rc
=
network_prefix
(
ae
,
*
src_plen
,
0
,
a
+
i
+
3
,
NULL
,
len
-
1
,
src_prefix
);
if
(
rc
<
0
)
goto
fail
;
if
(
ae
==
1
)
(
*
src_plen
)
+=
96
;
}
else
{
debugf
(
"Received unknown%s Route Request sub-TLV %d.
\n
"
,
((
type
&
0x80
)
!=
0
)
?
" mandatory"
:
""
,
type
);
if
((
type
&
0x80
)
!=
0
)
return
-
1
;
}
i
+=
len
+
2
;
}
return
1
;
fail:
fprintf
(
stderr
,
"Received truncated sub-TLV on Route Request.
\n
"
);
return
-
1
;
}
static
int
parse_seqno_request_subtlv
(
int
ae
,
const
unsigned
char
*
a
,
int
alen
,
unsigned
char
*
src_prefix
,
unsigned
char
*
src_plen
)
{
int
type
,
len
,
i
=
0
;
while
(
i
<
alen
)
{
type
=
a
[
0
];
if
(
type
==
SUBTLV_PAD1
)
{
i
++
;
continue
;
}
if
(
i
+
1
>
alen
)
goto
fail
;
len
=
a
[
i
+
1
];
if
(
i
+
len
+
2
>
alen
)
{
fprintf
(
stderr
,
"Received truncated sub-TLV.
\n
"
);
return
-
1
;
if
(
i
+
len
+
2
>
alen
)
goto
fail
;
if
(
type
==
SUBTLV_PADN
)
{
/* Nothing to do. */
}
else
if
(
type
==
SUBTLV_SOURCE_PREFIX
)
{
int
rc
;
if
(
len
<
1
)
goto
fail
;
*
src_plen
=
a
[
i
+
2
];
rc
=
network_prefix
(
ae
,
*
src_plen
,
0
,
a
+
i
+
3
,
NULL
,
len
-
1
,
src_prefix
);
if
(
rc
<
0
)
goto
fail
;
if
(
ae
==
1
)
(
*
src_plen
)
+=
96
;
}
else
{
debugf
(
"Received unknown%s Route Request sub-TLV %d.
\n
"
,
((
type
&
0x80
)
!=
0
)
?
" mandatory"
:
""
,
type
);
if
((
type
&
0x80
)
!=
0
)
return
-
1
;
}
i
+=
len
+
2
;
}
return
1
;
fail:
fprintf
(
stderr
,
"Received truncated sub-TLV on Route Request.
\n
"
);
return
-
1
;
}
static
int
parse_other_subtlv
(
const
unsigned
char
*
a
,
int
alen
)
{
int
type
,
len
,
i
=
0
;
while
(
i
<
alen
)
{
type
=
a
[
0
];
if
(
type
==
SUBTLV_PAD1
)
{
i
++
;
continue
;
}
if
(
i
+
1
>
alen
)
goto
fail
;
len
=
a
[
i
+
1
];
if
(
i
+
len
>
alen
)
goto
fail
;
if
((
type
&
0x80
)
!=
0
)
{
debugf
(
"Received unknown mandatory sub-TLV %d.
\n
"
,
type
);
return
-
1
;
...
...
@@ -316,6 +415,9 @@ parse_other_subtlv(const unsigned char *a, int alen)
i
+=
len
+
2
;
}
return
1
;
fail:
fprintf
(
stderr
,
"Received truncated sub-TLV.
\n
"
);
return
-
1
;
}
static
int
...
...
@@ -342,7 +444,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
/* Content of the RTT sub-TLV on IHU messages. */
unsigned
int
hello_send_us
=
0
,
hello_rtt_receive_time
=
0
;
if
(
ifp
->
flags
&
IF_TIMESTAMPS
)
{
if
(
ifp
->
buf
.
enable_timestamps
)
{
/* We want to track exactly when we received this packet. */
gettime
(
&
now
);
}
...
...
@@ -528,7 +630,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
unsigned
char
channels
[
MAX_CHANNEL_HOPS
];
int
channels_len
=
MAX_CHANNEL_HOPS
;
unsigned
short
interval
,
seqno
,
metric
;
int
rc
,
parsed_len
;
int
rc
,
parsed_len
,
is_ss
;
if
(
len
<
10
)
{
if
(
len
<
2
||
message
[
3
]
&
0x80
)
have_v4_prefix
=
have_v6_prefix
=
0
;
...
...
@@ -588,7 +690,6 @@ parse_packet(const unsigned char *from, struct interface *ifp,
(
message
[
3
]
&
0x40
)
?
"/id"
:
""
,
format_prefix
(
prefix
,
plen
),
format_address
(
from
),
ifp
->
name
);
if
(
message
[
2
]
==
0
)
{
rc
=
parse_other_subtlv
(
message
+
12
,
len
-
10
);
if
(
rc
<
0
)
...
...
@@ -610,10 +711,20 @@ parse_packet(const unsigned char *from, struct interface *ifp,
nh
=
neigh
->
address
;
}
rc
=
parse_update_subtlv
(
ifp
,
metric
,
message
+
2
+
parsed_len
,
len
-
parsed_len
,
channels
,
&
channels_len
);
if
(
rc
<
0
)
rc
=
parse_update_subtlv
(
ifp
,
metric
,
message
[
2
],
message
+
2
+
parsed_len
,
len
-
parsed_len
,
channels
,
&
channels_len
,
src_prefix
,
&
src_plen
);
if
(
rc
<
0
)
goto
done
;
is_ss
=
!
is_default
(
src_prefix
,
src_plen
);
debugf
(
"Received update%s%s for dst %s%s%s from %s on %s.
\n
"
,
(
message
[
3
]
&
0x80
)
?
"/prefix"
:
""
,
(
message
[
3
]
&
0x40
)
?
"/id"
:
""
,
format_prefix
(
prefix
,
plen
),
is_ss
?
" src "
:
""
,
is_ss
?
format_prefix
(
src_prefix
,
src_plen
)
:
""
,
format_address
(
from
),
ifp
->
name
);
if
(
message
[
2
]
==
1
)
{
if
(
!
ifp
->
ipv4
)
...
...
@@ -625,19 +736,33 @@ parse_packet(const unsigned char *from, struct interface *ifp,
channels
,
channels_len
);
}
else
if
(
type
==
MESSAGE_REQUEST
)
{
unsigned
char
prefix
[
16
],
src_prefix
[
16
],
plen
,
src_plen
;
int
rc
;
int
rc
,
is_ss
;
if
(
len
<
2
)
goto
fail
;
rc
=
network_prefix
(
message
[
2
],
message
[
3
],
0
,
message
+
4
,
NULL
,
len
-
2
,
prefix
);
if
(
rc
<
0
)
goto
fail
;
plen
=
message
[
3
]
+
(
message
[
2
]
==
1
?
96
:
0
);
debugf
(
"Received request for %s from %s on %s.
\n
"
,
message
[
2
]
==
0
?
"any"
:
format_prefix
(
prefix
,
plen
),
format_address
(
from
),
ifp
->
name
);
rc
=
parse_other_subtlv
(
message
+
4
+
rc
,
len
-
2
-
rc
);
if
(
message
[
2
]
==
1
)
{
v4tov6
(
src_prefix
,
zeroes
);
src_plen
=
96
;
}
else
{
memcpy
(
src_prefix
,
zeroes
,
16
);
src_plen
=
0
;
}
rc
=
parse_request_subtlv
(
message
[
2
],
message
+
4
+
rc
,
len
-
2
-
rc
,
src_prefix
,
&
src_plen
);
if
(
rc
<
0
)
goto
done
;
is_ss
=
!
is_default
(
src_prefix
,
src_plen
);
if
(
message
[
2
]
==
0
)
{
if
(
is_ss
)
{
/* Wildcard requests don't carry a source prefix. */
fprintf
(
stderr
,
"Received source-specific wildcard request.
\n
"
);
goto
done
;
}
debugf
(
"Received request for any from %s on %s.
\n
"
,
format_address
(
from
),
ifp
->
name
);
/* If a neighbour is requesting a full route dump from us,
we might as well send it an IHU. */
send_ihu
(
neigh
,
NULL
);
...
...
@@ -646,31 +771,26 @@ parse_packet(const unsigned char *from, struct interface *ifp,
update storm. Ignore a wildcard request that happens
shortly after we sent a full update. */
if
(
neigh
->
ifp
->
last_update_time
<
now
.
tv_sec
-
MAX
(
neigh
->
ifp
->
hello_interval
/
100
,
1
))
send_update
(
neigh
->
ifp
,
0
,
NULL
,
0
,
zeroes
,
0
);
}
else
{
if
(
message
[
2
]
==
1
)
{
v4tov6
(
src_prefix
,
zeroes
);
src_plen
=
96
;
}
else
{
memcpy
(
src_prefix
,
zeroes
,
16
);
src_plen
=
0
;
now
.
tv_sec
-
MAX
(
neigh
->
ifp
->
hello_interval
/
100
,
1
))
{
send_update
(
neigh
->
ifp
,
0
,
NULL
,
0
,
NULL
,
0
);
}
}
else
{
debugf
(
"Received request for dst %s%s%s from %s on %s.
\n
"
,
message
[
2
]
==
0
?
""
:
format_prefix
(
prefix
,
plen
),
is_ss
?
" src "
:
""
,
is_ss
?
format_prefix
(
src_prefix
,
src_plen
)
:
""
,
format_address
(
from
),
ifp
->
name
);
send_update
(
neigh
->
ifp
,
0
,
prefix
,
plen
,
src_prefix
,
src_plen
);
}
}
else
if
(
type
==
MESSAGE_MH_REQUEST
)
{
unsigned
char
prefix
[
16
],
src_prefix
[
16
],
plen
,
src_plen
;
unsigned
short
seqno
;
int
rc
;
int
rc
,
is_ss
;
if
(
len
<
14
)
goto
fail
;
DO_NTOHS
(
seqno
,
message
+
4
);
rc
=
network_prefix
(
message
[
2
],
message
[
3
],
0
,
message
+
16
,
NULL
,
len
-
14
,
prefix
);
if
(
rc
<
0
)
goto
fail
;
rc
=
parse_other_subtlv
(
message
+
16
+
rc
,
len
-
14
-
rc
);
if
(
rc
<
0
)
goto
done
;
plen
=
message
[
3
]
+
(
message
[
2
]
==
1
?
96
:
0
);
if
(
message
[
2
]
==
1
)
{
v4tov6
(
src_prefix
,
zeroes
);
src_plen
=
96
;
...
...
@@ -678,165 +798,23 @@ parse_packet(const unsigned char *from, struct interface *ifp,
memcpy
(
src_prefix
,
zeroes
,
16
);
src_plen
=
0
;
}
debugf
(
"Received request (%d) for %s from %s on %s (%s, %d).
\n
"
,
message
[
6
],
format_prefix
(
prefix
,
plen
),
format_address
(
from
),
ifp
->
name
,
format_eui64
(
message
+
8
),
seqno
);
handle_request
(
neigh
,
prefix
,
plen
,
src_prefix
,
src_plen
,
message
[
6
],
seqno
,
message
+
8
);
}
else
if
(
type
==
MESSAGE_UPDATE_SRC_SPECIFIC
)
{
unsigned
char
prefix
[
16
],
src_prefix
[
16
],
*
nh
;
unsigned
char
ae
,
plen
,
src_plen
,
omitted
;
unsigned
char
channels
[
MAX_CHANNEL_HOPS
];
int
channels_len
=
MAX_CHANNEL_HOPS
;
unsigned
short
interval
,
seqno
,
metric
;
const
unsigned
char
*
src_prefix_beginning
=
NULL
;
int
rc
,
parsed_len
=
0
;
if
(
len
<
10
)
goto
fail
;
ae
=
message
[
2
];
src_plen
=
message
[
3
];
plen
=
message
[
4
];
omitted
=
message
[
5
];
DO_NTOHS
(
interval
,
message
+
6
);
DO_NTOHS
(
seqno
,
message
+
8
);
DO_NTOHS
(
metric
,
message
+
10
);
if
(
omitted
==
0
||
(
ae
==
1
?
have_v4_prefix
:
have_v6_prefix
))
rc
=
network_prefix
(
ae
,
plen
,
omitted
,
message
+
12
,
ae
==
1
?
v4_prefix
:
v6_prefix
,
len
-
10
,
prefix
);
else
rc
=
-
1
;
if
(
rc
<
0
)
goto
fail
;
parsed_len
=
10
+
rc
;
src_prefix_beginning
=
message
+
2
+
parsed_len
;
rc
=
network_prefix
(
ae
,
src_plen
,
0
,
src_prefix_beginning
,
NULL
,
len
-
parsed_len
,
src_prefix
);
if
(
rc
<
0
)
goto
fail
;
parsed_len
+=
rc
;
if
(
ae
==
1
)
{
plen
+=
96
;
src_plen
+=
96
;
}
if
(
!
have_router_id
)
{
fprintf
(
stderr
,
"Received prefix with no router id.
\n
"
);
goto
fail
;
}
debugf
(
"Received ss-update for (%s from %s) from %s on %s.
\n
"
,
format_prefix
(
prefix
,
plen
),
format_prefix
(
src_prefix
,
src_plen
),
format_address
(
from
),
ifp
->
name
);
if
(
ae
==
0
)
{
debugf
(
"Received invalid Source-Specific wildcard update.
\n
"
);
rc
=
parse_other_subtlv
(
message
+
12
,
len
-
10
);
if
(
rc
<
0
)
goto
done
;
retract_neighbour_routes
(
neigh
);
goto
done
;
}
else
if
(
ae
==
1
)
{
if
(
!
have_v4_nh
)
goto
fail
;
nh
=
v4_nh
;
}
else
if
(
have_v6_nh
)
{
nh
=
v6_nh
;
}
else
{
nh
=
neigh
->
address
;
}
rc
=
parse_update_subtlv
(
ifp
,
metric
,
message
+
2
+
parsed_len
,
len
-
parsed_len
,
channels
,
&
channels_len
);
if
(
rc
<
0
)
goto
done
;
if
(
ae
==
1
)
{
if
(
!
ifp
->
ipv4
)
goto
done
;
}
update_route
(
router_id
,
prefix
,
plen
,
src_prefix
,
src_plen
,
seqno
,
metric
,
interval
,
neigh
,
nh
,
channels
,
channels_len
);
}
else
if
(
type
==
MESSAGE_REQUEST_SRC_SPECIFIC
)
{
unsigned
char
prefix
[
16
],
plen
,
ae
,
src_prefix
[
16
],
src_plen
;
int
rc
,
parsed
=
5
;
if
(
len
<
3
)
goto
fail
;
ae
=
message
[
2
];
plen
=
message
[
3
];
src_plen
=
message
[
4
];
rc
=
network_prefix
(
ae
,
plen
,
0
,
message
+
parsed
,
NULL
,
len
+
2
-
parsed
,
prefix
);
if
(
rc
<
0
)
goto
fail
;
if
(
ae
==
1
)
plen
+=
96
;
parsed
+=
rc
;
rc
=
network_prefix
(
ae
,
src_plen
,
0
,
message
+
parsed
,
NULL
,
len
+
2
-
parsed
,
src_prefix
);
if
(
rc
<
0
)
goto
fail
;
if
(
ae
==
1
)
src_plen
+=
96
;
parsed
+=
rc
;
rc
=
parse_other_subtlv
(
message
+
parsed
,
len
-
parsed
+
2
);
if
(
rc
<
0
)
goto
done
;
if
(
ae
==
0
)
{
debugf
(
"Received request for any source-specific "
"from %s on %s.
\n
"
,
format_address
(
from
),
ifp
->
name
);
/* See comments for std requests. */
send_ihu
(
neigh
,
NULL
);
if
(
neigh
->
ifp
->
last_specific_update_time
<
now
.
tv_sec
-
MAX
(
neigh
->
ifp
->
hello_interval
/
100
,
1
))
send_update
(
neigh
->
ifp
,
0
,
zeroes
,
0
,
NULL
,
0
);
}
else
{
debugf
(
"Received request for (%s from %s) from %s on %s.
\n
"
,
format_prefix
(
prefix
,
plen
),
format_prefix
(
src_prefix
,
src_plen
),
format_address
(
from
),
ifp
->
name
);
send_update
(
neigh
->
ifp
,
0
,
prefix
,
plen
,
src_prefix
,
src_plen
);
}
}
else
if
(
type
==
MESSAGE_MH_REQUEST_SRC_SPECIFIC
)
{
unsigned
char
prefix
[
16
],
plen
,
ae
,
src_prefix
[
16
],
src_plen
,
hopc
;
const
unsigned
char
*
router_id
;
unsigned
short
seqno
;
int
rc
,
parsed
=
16
;
if
(
len
<
14
)
goto
fail
;
ae
=
message
[
2
];
plen
=
message
[
3
];
DO_NTOHS
(
seqno
,
message
+
4
);
hopc
=
message
[
6
];
src_plen
=
message
[
7
];
router_id
=
message
+
8
;
rc
=
network_prefix
(
ae
,
plen
,
0
,
message
+
parsed
,
NULL
,
len
+
2
-
parsed
,
prefix
);
if
(
rc
<
0
)
goto
fail
;
if
(
ae
==
1
)
plen
+=
96
;
parsed
+=
rc
;
rc
=
network_prefix
(
ae
,
src_plen
,
0
,
message
+
parsed
,
NULL
,
len
+
2
-
parsed
,
src_prefix
);
if
(
rc
<
0
)
goto
fail
;
parsed
+=
rc
;
rc
=
parse_other_subtlv
(
message
+
parsed
,
len
-
parsed
+
2
);
rc
=
parse_seqno_request_subtlv
(
message
[
2
],
message
+
16
+
rc
,
len
-
14
-
rc
,
src_prefix
,
&
src_plen
);
if
(
rc
<
0
)
goto
done
;
i
f
(
ae
==
1
)
src_plen
+=
96
;
debugf
(
"Received request (%d) for
(%s, %s)
"
"
from %s on
%s (%s, %d).
\n
"
,
i
s_ss
=
!
is_default
(
src_prefix
,
src_plen
);
plen
=
message
[
3
]
+
(
message
[
2
]
==
1
?
96
:
0
)
;
debugf
(
"Received request (%d) for
dst %s%s%s from %s on
"
"%s (%s, %d).
\n
"
,
message
[
6
],
format_prefix
(
prefix
,
plen
),
format_prefix
(
src_prefix
,
src_plen
),
is_ss
?
" src "
:
""
,
is_ss
?
format_prefix
(
src_prefix
,
src_plen
)
:
""
,
format_address
(
from
),
ifp
->
name
,
format_eui64
(
router_id
),
seqno
);
format_eui64
(
message
+
8
),
seqno
);
handle_request
(
neigh
,
prefix
,
plen
,
src_prefix
,
src_plen
,
hopc
,
seqno
,
router_id
);
message
[
6
],
seqno
,
message
+
8
);
}
else
{
debugf
(
"Received unknown packet type %d from %s on %s.
\n
"
,
type
,
format_address
(
from
),
ifp
->
name
);
...
...
@@ -891,43 +869,18 @@ parse_packet(const unsigned char *from, struct interface *ifp,
return
;
}
/* Under normal circumstances, there are enough moderation mechanisms
elsewhere in the protocol to make sure that this last-ditch check
should never trigger. But I'm superstitious. */
static
int
check_bucket
(
struct
interface
*
ifp
)
fill_rtt_message
(
struct
buffered
*
buf
)
{
if
(
ifp
->
bucket
<=
0
)
{
int
seconds
=
now
.
tv_sec
-
ifp
->
bucket_time
;
if
(
seconds
>
0
)
{
ifp
->
bucket
=
MIN
(
BUCKET_TOKENS_MAX
,
seconds
*
BUCKET_TOKENS_PER_SEC
);
}
/* Reset bucket time unconditionally, in case clock is stepped. */
ifp
->
bucket_time
=
now
.
tv_sec
;
}
if
(
ifp
->
bucket
>
0
)
{
ifp
->
bucket
--
;
return
1
;
}
else
{
return
0
;
}
}
static
int
fill_rtt_message
(
struct
interface
*
ifp
)
{
if
((
ifp
->
flags
&
IF_TIMESTAMPS
)
&&
(
ifp
->
buffered_hello
>=
0
))
{
if
(
ifp
->
sendbuf
[
ifp
->
buffered_hello
+
8
]
==
SUBTLV_PADN
&&
ifp
->
sendbuf
[
ifp
->
buffered_hello
+
9
]
==
4
)
{
if
(
buf
->
enable_timestamps
&&
(
buf
->
hello
>=
0
))
{
if
(
buf
->
buf
[
buf
->
hello
+
8
]
==
SUBTLV_PADN
&&
buf
->
buf
[
buf
->
hello
+
9
]
==
4
)
{
unsigned
int
time
;
/* Change the type of sub-TLV. */
ifp
->
sendbuf
[
ifp
->
buffered_
hello
+
8
]
=
SUBTLV_TIMESTAMP
;
buf
->
buf
[
buf
->
hello
+
8
]
=
SUBTLV_TIMESTAMP
;
gettime
(
&
now
);
time
=
time_us
(
now
);
DO_HTONL
(
ifp
->
sendbuf
+
ifp
->
buffered_
hello
+
10
,
time
);
DO_HTONL
(
buf
->
buf
+
buf
->
hello
+
10
,
time
);
return
1
;
}
else
{
fprintf
(
stderr
,
...
...
@@ -940,214 +893,129 @@ fill_rtt_message(struct interface *ifp)
}
void
flushbuf
(
struct
interface
*
ifp
)
flushbuf
(
struct
buffered
*
buf
)
{
int
rc
;
struct
sockaddr_in6
sin6
;
assert
(
ifp
->
buffered
<=
ifp
->
buf
size
);
assert
(
buf
->
len
<=
buf
->
size
);
flushupdates
(
ifp
);
if
(
ifp
->
buffered
>
0
)
{
debugf
(
" (flushing %d buffered bytes on %s)
\n
"
,
ifp
->
buffered
,
ifp
->
name
);
if
(
check_bucket
(
ifp
))
{
memset
(
&
sin6
,
0
,
sizeof
(
sin6
));
sin6
.
sin6_family
=
AF_INET6
;
memcpy
(
&
sin6
.
sin6_addr
,
protocol_group
,
16
);
sin6
.
sin6_port
=
htons
(
protocol_port
);
sin6
.
sin6_scope_id
=
ifp
->
ifindex
;
DO_HTONS
(
packet_header
+
2
,
ifp
->
buffered
);
fill_rtt_message
(
ifp
);
rc
=
babel_send
(
protocol_socket
,
packet_header
,
sizeof
(
packet_header
),
ifp
->
sendbuf
,
ifp
->
buffered
,
(
struct
sockaddr
*
)
&
sin6
,
sizeof
(
sin6
));
if
(
rc
<
0
)
perror
(
"send"
);
}
else
{
fprintf
(
stderr
,
"Warning: bucket full, dropping packet to %s.
\n
"
,
ifp
->
name
);
}
if
(
buf
->
len
>
0
)
{
debugf
(
" (flushing %d buffered bytes)
\n
"
,
buf
->
len
);
DO_HTONS
(
packet_header
+
2
,
buf
->
len
);
fill_rtt_message
(
buf
);
rc
=
babel_send
(
protocol_socket
,
packet_header
,
sizeof
(
packet_header
),
buf
->
buf
,
buf
->
len
,
(
struct
sockaddr
*
)
&
buf
->
sin6
,
sizeof
(
buf
->
sin6
));
if
(
rc
<
0
)
perror
(
"send"
);
}
VALGRIND_MAKE_MEM_UNDEFINED
(
ifp
->
sendbuf
,
ifp
->
buf
size
);
ifp
->
buffered
=
0
;
ifp
->
buffered_
hello
=
-
1
;
ifp
->
have_buffered
_id
=
0
;
ifp
->
have_buffered
_nh
=
0
;
ifp
->
have_buffered
_prefix
=
0
;
ifp
->
flush_
timeout
.
tv_sec
=
0
;
ifp
->
flush_
timeout
.
tv_usec
=
0
;
VALGRIND_MAKE_MEM_UNDEFINED
(
buf
->
buf
,
buf
->
size
);
buf
->
len
=
0
;
buf
->
hello
=
-
1
;
buf
->
have
_id
=
0
;
buf
->
have
_nh
=
0
;
buf
->
have
_prefix
=
0
;
buf
->
timeout
.
tv_sec
=
0
;
buf
->
timeout
.
tv_usec
=
0
;
}
static
void
schedule_flush
(
struct
interface
*
ifp
)
schedule_flush
_ms
(
struct
buffered
*
buf
,
int
msecs
)
{
unsigned
msecs
=
jitter
(
ifp
,
0
);
if
(
ifp
->
flush_timeout
.
tv_sec
!=
0
&&
timeval_minus_msec
(
&
ifp
->
flush_timeout
,
&
now
)
<
msecs
)
if
(
buf
->
timeout
.
tv_sec
!=
0
&&
timeval_minus_msec
(
&
buf
->
timeout
,
&
now
)
<
msecs
)
return
;
set_timeout
(
&
ifp
->
flush_
timeout
,
msecs
);
set_timeout
(
&
buf
->
timeout
,
msecs
);
}
static
void
schedule_flush
_now
(
struct
interface
*
ifp
)
schedule_flush
(
struct
buffered
*
buf
)
{
/* Almost now */
unsigned
msecs
=
roughly
(
10
);
if
(
ifp
->
flush_timeout
.
tv_sec
!=
0
&&
timeval_minus_msec
(
&
ifp
->
flush_timeout
,
&
now
)
<
msecs
)
return
;
set_timeout
(
&
ifp
->
flush_timeout
,
msecs
);
schedule_flush_ms
(
buf
,
jitter
(
buf
,
0
));
}
static
void
schedule_
unicast_flush
(
unsigned
msecs
)
schedule_
flush_now
(
struct
buffered
*
buf
)
{
if
(
!
unicast_neighbour
)
return
;
if
(
unicast_flush_timeout
.
tv_sec
!=
0
&&
timeval_minus_msec
(
&
unicast_flush_timeout
,
&
now
)
<
msecs
)
return
;
unicast_flush_timeout
.
tv_usec
=
(
now
.
tv_usec
+
msecs
*
1000
)
%
1000000
;
unicast_flush_timeout
.
tv_sec
=
now
.
tv_sec
+
(
now
.
tv_usec
/
1000
+
msecs
)
/
1000
;
schedule_flush_ms
(
buf
,
roughly
(
10
));
}
static
void
ensure_space
(
struct
interface
*
ifp
,
int
space
)
ensure_space
(
struct
buffered
*
buf
,
int
space
)
{
if
(
ifp
->
bufsize
-
ifp
->
buffered
<
space
)
flushbuf
(
ifp
);
if
(
buf
->
size
-
buf
->
len
<
space
)
flushbuf
(
buf
);
}
static
void
start_message
(
struct
interface
*
ifp
,
int
type
,
int
len
)
start_message
(
struct
buffered
*
buf
,
int
type
,
int
len
)
{
if
(
ifp
->
bufsize
-
ifp
->
buffered
<
len
+
2
)
flushbuf
(
ifp
);
ifp
->
sendbuf
[
ifp
->
buffered
++
]
=
type
;
ifp
->
sendbuf
[
ifp
->
buffered
++
]
=
len
;
if
(
buf
->
size
-
buf
->
len
<
len
+
2
)
flushbuf
(
buf
);
buf
->
buf
[
buf
->
len
++
]
=
type
;
buf
->
buf
[
buf
->
len
++
]
=
len
;
}
static
void
end_message
(
struct
interface
*
ifp
,
int
type
,
int
bytes
)
end_message
(
struct
buffered
*
buf
,
int
type
,
int
bytes
)
{
assert
(
ifp
->
buffered
>=
bytes
+
2
&&
ifp
->
sendbuf
[
ifp
->
buffered
-
bytes
-
2
]
==
type
&&
ifp
->
sendbuf
[
ifp
->
buffered
-
bytes
-
1
]
==
bytes
);
schedule_flush
(
ifp
);
assert
(
buf
->
len
>=
bytes
+
2
&&
buf
->
buf
[
buf
->
len
-
bytes
-
2
]
==
type
&&
buf
->
buf
[
buf
->
len
-
bytes
-
1
]
==
bytes
);
schedule_flush
(
buf
);
}
static
void
accumulate_byte
(
struct
interface
*
ifp
,
unsigned
char
value
)
accumulate_byte
(
struct
buffered
*
buf
,
unsigned
char
value
)
{
ifp
->
sendbuf
[
ifp
->
buffered
++
]
=
value
;
buf
->
buf
[
buf
->
len
++
]
=
value
;
}
static
void
accumulate_short
(
struct
interface
*
ifp
,
unsigned
short
value
)
accumulate_short
(
struct
buffered
*
buf
,
unsigned
short
value
)
{
DO_HTONS
(
ifp
->
sendbuf
+
ifp
->
buffered
,
value
);
ifp
->
buffered
+=
2
;
DO_HTONS
(
buf
->
buf
+
buf
->
len
,
value
);
buf
->
len
+=
2
;
}
static
void
accumulate_int
(
struct
interface
*
ifp
,
unsigned
int
value
)
accumulate_int
(
struct
buffered
*
buf
,
unsigned
int
value
)
{
DO_HTONL
(
ifp
->
sendbuf
+
ifp
->
buffered
,
value
);
ifp
->
buffered
+=
4
;
DO_HTONL
(
buf
->
buf
+
buf
->
len
,
value
);
buf
->
len
+=
4
;
}
static
void
accumulate_bytes
(
struct
interface
*
ifp
,
accumulate_bytes
(
struct
buffered
*
buf
,
const
unsigned
char
*
value
,
unsigned
len
)
{
memcpy
(
ifp
->
sendbuf
+
ifp
->
buffered
,
value
,
len
);
ifp
->
buffered
+=
len
;
}
static
int
start_unicast_message
(
struct
neighbour
*
neigh
,
int
type
,
int
len
)
{
if
(
unicast_neighbour
)
{
if
(
neigh
!=
unicast_neighbour
||
unicast_buffered
+
len
+
2
>=
MIN
(
UNICAST_BUFSIZE
,
neigh
->
ifp
->
bufsize
))
flush_unicast
(
0
);
}
if
(
!
unicast_buffer
)
unicast_buffer
=
malloc
(
UNICAST_BUFSIZE
);
if
(
!
unicast_buffer
)
{
perror
(
"malloc(unicast_buffer)"
);
return
-
1
;
}
unicast_neighbour
=
neigh
;
unicast_buffer
[
unicast_buffered
++
]
=
type
;
unicast_buffer
[
unicast_buffered
++
]
=
len
;
return
1
;
}
static
void
end_unicast_message
(
struct
neighbour
*
neigh
,
int
type
,
int
bytes
)
{
assert
(
unicast_neighbour
==
neigh
&&
unicast_buffered
>=
bytes
+
2
&&
unicast_buffer
[
unicast_buffered
-
bytes
-
2
]
==
type
&&
unicast_buffer
[
unicast_buffered
-
bytes
-
1
]
==
bytes
);
schedule_unicast_flush
(
jitter
(
neigh
->
ifp
,
0
));
}
static
void
accumulate_unicast_byte
(
struct
neighbour
*
neigh
,
unsigned
char
value
)
{
unicast_buffer
[
unicast_buffered
++
]
=
value
;
}
static
void
accumulate_unicast_short
(
struct
neighbour
*
neigh
,
unsigned
short
value
)
{
DO_HTONS
(
unicast_buffer
+
unicast_buffered
,
value
);
unicast_buffered
+=
2
;
}
static
void
accumulate_unicast_int
(
struct
neighbour
*
neigh
,
unsigned
int
value
)
{
DO_HTONL
(
unicast_buffer
+
unicast_buffered
,
value
);
unicast_buffered
+=
4
;
}
static
void
accumulate_unicast_bytes
(
struct
neighbour
*
neigh
,
const
unsigned
char
*
value
,
unsigned
len
)
{
memcpy
(
unicast_buffer
+
unicast_buffered
,
value
,
len
);
unicast_buffered
+=
len
;
memcpy
(
buf
->
buf
+
buf
->
len
,
value
,
len
);
buf
->
len
+=
len
;
}
void
send_ack
(
struct
neighbour
*
neigh
,
unsigned
short
nonce
,
unsigned
short
interval
)
{
int
rc
;
debugf
(
"Sending ack (%04x) to %s on %s.
\n
"
,
nonce
,
format_address
(
neigh
->
address
),
neigh
->
ifp
->
name
);
rc
=
start_unicast_message
(
neigh
,
MESSAGE_ACK
,
2
);
if
(
rc
<
0
)
return
;
accumulate_
unicast_short
(
neigh
,
nonce
);
end_
unicast_message
(
neigh
,
MESSAGE_ACK
,
2
);
start_message
(
&
neigh
->
buf
,
MESSAGE_ACK
,
2
)
;
accumulate_
short
(
&
neigh
->
buf
,
nonce
);
end_
message
(
&
neigh
->
buf
,
MESSAGE_ACK
,
2
);
/* Roughly yields a value no larger than 3/2, so this meets the deadline */
schedule_
unicast_flush
(
roughly
(
interval
*
6
));
schedule_
flush_ms
(
&
neigh
->
buf
,
roughly
(
interval
*
6
));
}
void
send_hello_no
update
(
struct
interface
*
ifp
,
unsigned
interval
)
send_hello_no
ihu
(
struct
interface
*
ifp
,
unsigned
interval
)
{
/* This avoids sending multiple hellos in a single packet, which breaks
link quality estimation. */
if
(
ifp
->
buffered_hello
>=
0
)
flushbuf
(
ifp
);
if
(
ifp
->
buf
.
hello
>=
0
)
{
flushupdates
(
ifp
);
flushbuf
(
&
ifp
->
buf
);
}
ifp
->
hello_seqno
=
seqno_plus
(
ifp
->
hello_seqno
,
1
);
set_timeout
(
&
ifp
->
hello_timeout
,
ifp
->
hello_interval
);
...
...
@@ -1158,25 +1026,25 @@ send_hello_noupdate(struct interface *ifp, unsigned interval)
debugf
(
"Sending hello %d (%d) to %s.
\n
"
,
ifp
->
hello_seqno
,
interval
,
ifp
->
name
);
start_message
(
ifp
,
MESSAGE_HELLO
,
(
ifp
->
flags
&
IF_TIMESTAMPS
)
?
12
:
6
);
ifp
->
buf
fered_hello
=
ifp
->
buffered
-
2
;
accumulate_short
(
ifp
,
0
);
accumulate_short
(
ifp
,
ifp
->
hello_seqno
);
accumulate_short
(
ifp
,
interval
>
0xFFFF
?
0xFFFF
:
interval
);
if
(
ifp
->
flags
&
IF_TIMESTAMPS
)
{
start_message
(
&
ifp
->
buf
,
MESSAGE_HELLO
,
ifp
->
buf
.
enable_timestamps
?
12
:
6
);
ifp
->
buf
.
hello
=
ifp
->
buf
.
len
-
2
;
accumulate_short
(
&
ifp
->
buf
,
0
);
accumulate_short
(
&
ifp
->
buf
,
ifp
->
hello_seqno
);
accumulate_short
(
&
ifp
->
buf
,
interval
>
0xFFFF
?
0xFFFF
:
interval
);
if
(
ifp
->
buf
.
enable_timestamps
)
{
/* Sub-TLV containing the local time of emission. We use a
Pad4 sub-TLV, which we'll fill just before sending. */
accumulate_byte
(
ifp
,
SUBTLV_PADN
);
accumulate_byte
(
ifp
,
4
);
accumulate_int
(
ifp
,
0
);
accumulate_byte
(
&
ifp
->
buf
,
SUBTLV_PADN
);
accumulate_byte
(
&
ifp
->
buf
,
4
);
accumulate_int
(
&
ifp
->
buf
,
0
);
}
end_message
(
ifp
,
MESSAGE_HELLO
,
(
ifp
->
flags
&
IF_TIMESTAMPS
)
?
12
:
6
);
end_message
(
&
ifp
->
buf
,
MESSAGE_HELLO
,
ifp
->
buf
.
enable_timestamps
?
12
:
6
);
}
void
send_hello
(
struct
interface
*
ifp
)
{
send_hello_no
update
(
ifp
,
(
ifp
->
hello_interval
+
9
)
/
10
);
send_hello_no
ihu
(
ifp
,
(
ifp
->
hello_interval
+
9
)
/
10
);
/* Send full IHU every 3 hellos, and marginal IHU each time */
if
(
ifp
->
hello_seqno
%
3
==
0
)
send_ihu
(
NULL
,
ifp
);
...
...
@@ -1184,115 +1052,64 @@ send_hello(struct interface *ifp)
send_marginal_ihu
(
ifp
);
}
void
flush_unicast
(
int
dofree
)
{
struct
sockaddr_in6
sin6
;
int
rc
;
if
(
unicast_buffered
==
0
)
goto
done
;
if
(
!
if_up
(
unicast_neighbour
->
ifp
))
goto
done
;
/* Preserve ordering of messages */
flushbuf
(
unicast_neighbour
->
ifp
);
if
(
check_bucket
(
unicast_neighbour
->
ifp
))
{
memset
(
&
sin6
,
0
,
sizeof
(
sin6
));
sin6
.
sin6_family
=
AF_INET6
;
memcpy
(
&
sin6
.
sin6_addr
,
unicast_neighbour
->
address
,
16
);
sin6
.
sin6_port
=
htons
(
protocol_port
);
sin6
.
sin6_scope_id
=
unicast_neighbour
->
ifp
->
ifindex
;
DO_HTONS
(
packet_header
+
2
,
unicast_buffered
);
fill_rtt_message
(
unicast_neighbour
->
ifp
);
rc
=
babel_send
(
protocol_socket
,
packet_header
,
sizeof
(
packet_header
),
unicast_buffer
,
unicast_buffered
,
(
struct
sockaddr
*
)
&
sin6
,
sizeof
(
sin6
));
if
(
rc
<
0
)
perror
(
"send(unicast)"
);
}
else
{
fprintf
(
stderr
,
"Warning: bucket full, dropping unicast packet "
"to %s if %s.
\n
"
,
format_address
(
unicast_neighbour
->
address
),
unicast_neighbour
->
ifp
->
name
);
}
done:
VALGRIND_MAKE_MEM_UNDEFINED
(
unicast_buffer
,
UNICAST_BUFSIZE
);
unicast_buffered
=
0
;
if
(
dofree
&&
unicast_buffer
)
{
free
(
unicast_buffer
);
unicast_buffer
=
NULL
;
}
unicast_neighbour
=
NULL
;
unicast_flush_timeout
.
tv_sec
=
0
;
unicast_flush_timeout
.
tv_usec
=
0
;
}
static
void
really_
send_update
(
struct
interface
*
ifp
,
const
unsigned
char
*
id
,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
,
unsigned
short
seqno
,
unsigned
short
metric
,
unsigned
char
*
channels
,
int
channels_len
)
really_
buffer_update
(
struct
buffered
*
buf
,
struct
interface
*
ifp
,
const
unsigned
char
*
id
,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
,
unsigned
short
seqno
,
unsigned
short
metric
,
unsigned
char
*
channels
,
int
channels_len
)
{
int
add_metric
,
v4
,
real_plen
,
omit
=
0
;
const
unsigned
char
*
real_prefix
;
const
unsigned
char
*
real_src_prefix
=
NULL
;
int
real_src_plen
=
0
;
int
add_metric
,
v4
,
real_plen
,
real_src_plen
;
int
omit
,
spb
,
channels_size
,
len
;
const
unsigned
char
*
real_prefix
,
*
real_src_prefix
;
unsigned
short
flags
=
0
;
int
channels_size
;
int
is_ss
=
!
is_default
(
src_prefix
,
src_plen
);
if
(
diversity_kind
!=
DIVERSITY_CHANNEL
)
channels_len
=
-
1
;
channels_size
=
channels_len
>=
0
?
channels_len
+
2
:
0
;
if
(
!
if_up
(
ifp
))
return
;
if
(
is_ss
&&
buf
->
rfc6126_compatible
)
return
;
add_metric
=
output_filter
(
id
,
prefix
,
plen
,
src_prefix
,
src_plen
,
ifp
->
ifindex
);
if
(
add_metric
>=
INFINITY
)
return
;
metric
=
MIN
(
metric
+
add_metric
,
INFINITY
);
/* Worst case */
ensure_space
(
ifp
,
20
+
12
+
28
+
18
);
ensure_space
(
buf
,
20
+
12
+
28
+
18
);
v4
=
plen
>=
96
&&
v4mapped
(
prefix
);
if
(
v4
)
{
if
(
!
ifp
->
ipv4
)
return
;
if
(
!
ifp
->
have_buffered_nh
||
memcmp
(
ifp
->
buffered_nh
,
ifp
->
ipv4
,
4
)
!=
0
)
{
start_message
(
ifp
,
MESSAGE_NH
,
6
);
accumulate_byte
(
ifp
,
1
);
accumulate_byte
(
ifp
,
0
);
accumulate_bytes
(
ifp
,
ifp
->
ipv4
,
4
);
end_message
(
ifp
,
MESSAGE_NH
,
6
);
memcpy
(
ifp
->
buffered_nh
,
ifp
->
ipv4
,
4
);
ifp
->
have_buffered_nh
=
1
;
omit
=
0
;
if
(
!
buf
->
have_nh
||
memcmp
(
buf
->
nh
,
ifp
->
ipv4
,
4
)
!=
0
)
{
start_message
(
buf
,
MESSAGE_NH
,
6
);
accumulate_byte
(
buf
,
1
);
accumulate_byte
(
buf
,
0
);
accumulate_bytes
(
buf
,
ifp
->
ipv4
,
4
);
end_message
(
buf
,
MESSAGE_NH
,
6
);
memcpy
(
&
buf
->
nh
,
ifp
->
ipv4
,
4
);
buf
->
have_nh
=
1
;
}
real_prefix
=
prefix
+
12
;
real_plen
=
plen
-
96
;
real_src_prefix
=
src_prefix
+
12
;
real_src_plen
=
src_plen
-
96
;
}
else
{
if
(
ifp
->
have_buffered_prefix
)
{
omit
=
0
;
if
(
buf
->
have_prefix
)
{
while
(
omit
<
plen
/
8
&&
ifp
->
buffered_
prefix
[
omit
]
==
prefix
[
omit
])
buf
->
prefix
[
omit
]
==
prefix
[
omit
])
omit
++
;
}
if
(
!
is_ss
&&
(
!
ifp
->
have_buffered_prefix
||
plen
>=
48
)
)
if
(
!
buf
->
have_prefix
||
plen
>=
48
)
flags
|=
0x80
;
real_prefix
=
prefix
;
real_plen
=
plen
;
...
...
@@ -1300,57 +1117,77 @@ really_send_update(struct interface *ifp,
real_src_plen
=
src_plen
;
}
if
(
!
ifp
->
have_buffered_id
||
memcmp
(
id
,
ifp
->
buffered_id
,
8
)
!=
0
)
{
if
(
!
is_ss
&&
real_plen
==
128
&&
memcmp
(
real_prefix
+
8
,
id
,
8
)
==
0
)
{
if
(
!
buf
->
have_id
||
memcmp
(
id
,
buf
->
id
,
8
)
!=
0
)
{
if
(
real_plen
==
128
&&
memcmp
(
real_prefix
+
8
,
id
,
8
)
==
0
)
{
flags
|=
0x40
;
}
else
{
start_message
(
ifp
,
MESSAGE_ROUTER_ID
,
10
);
accumulate_short
(
ifp
,
0
);
accumulate_bytes
(
ifp
,
id
,
8
);
end_message
(
ifp
,
MESSAGE_ROUTER_ID
,
10
);
start_message
(
buf
,
MESSAGE_ROUTER_ID
,
10
);
accumulate_short
(
buf
,
0
);
accumulate_bytes
(
buf
,
id
,
8
);
end_message
(
buf
,
MESSAGE_ROUTER_ID
,
10
);
}
memcpy
(
ifp
->
buffered_
id
,
id
,
8
);
ifp
->
have_buffered
_id
=
1
;
memcpy
(
buf
->
id
,
id
,
8
);
buf
->
have
_id
=
1
;
}
if
(
!
is_ss
)
start_message
(
ifp
,
MESSAGE_UPDATE
,
10
+
(
real_plen
+
7
)
/
8
-
omit
+
channels_size
);
else
start_message
(
ifp
,
MESSAGE_UPDATE_SRC_SPECIFIC
,
10
+
(
real_plen
+
7
)
/
8
-
omit
+
(
real_src_plen
+
7
)
/
8
+
channels_size
);
accumulate_byte
(
ifp
,
v4
?
1
:
2
);
if
(
is_ss
)
accumulate_byte
(
ifp
,
real_src_plen
);
else
accumulate_byte
(
ifp
,
flags
);
accumulate_byte
(
ifp
,
real_plen
);
accumulate_byte
(
ifp
,
omit
);
accumulate_short
(
ifp
,
(
ifp
->
update_interval
+
5
)
/
10
);
accumulate_short
(
ifp
,
seqno
);
accumulate_short
(
ifp
,
metric
);
accumulate_bytes
(
ifp
,
real_prefix
+
omit
,
(
real_plen
+
7
)
/
8
-
omit
);
channels_size
=
diversity_kind
==
DIVERSITY_CHANNEL
&&
channels_len
>=
0
?
channels_len
+
2
:
0
;
len
=
10
+
(
real_plen
+
7
)
/
8
-
omit
+
channels_size
;
spb
=
(
real_src_plen
+
7
)
/
8
;
if
(
is_ss
)
accumulate_bytes
(
ifp
,
real_src_prefix
,
(
real_src_plen
+
7
)
/
8
);
len
+=
3
+
spb
;
start_message
(
buf
,
MESSAGE_UPDATE
,
len
);
accumulate_byte
(
buf
,
v4
?
1
:
2
);
accumulate_byte
(
buf
,
flags
);
accumulate_byte
(
buf
,
real_plen
);
accumulate_byte
(
buf
,
omit
);
accumulate_short
(
buf
,
(
ifp
->
update_interval
+
5
)
/
10
);
accumulate_short
(
buf
,
seqno
);
accumulate_short
(
buf
,
metric
);
accumulate_bytes
(
buf
,
real_prefix
+
omit
,
(
real_plen
+
7
)
/
8
-
omit
);
if
(
is_ss
)
{
accumulate_byte
(
buf
,
SUBTLV_SOURCE_PREFIX
);
accumulate_byte
(
buf
,
1
+
spb
);
accumulate_byte
(
buf
,
real_src_plen
);
accumulate_bytes
(
buf
,
real_src_prefix
,
spb
);
}
/* Note that an empty channels TLV is different from no such TLV. */
if
(
channels_
len
>=
0
)
{
accumulate_byte
(
ifp
,
2
);
accumulate_byte
(
ifp
,
channels_len
);
accumulate_bytes
(
ifp
,
channels
,
channels_len
);
if
(
channels_
size
>
0
)
{
accumulate_byte
(
buf
,
2
);
accumulate_byte
(
buf
,
channels_len
);
accumulate_bytes
(
buf
,
channels
,
channels_len
);
}
if
(
!
is_ss
)
end_message
(
ifp
,
MESSAGE_UPDATE
,
10
+
(
real_plen
+
7
)
/
8
-
omit
+
channels_size
);
else
end_message
(
ifp
,
MESSAGE_UPDATE_SRC_SPECIFIC
,
10
+
(
real_plen
+
7
)
/
8
-
omit
+
(
real_src_plen
+
7
)
/
8
+
channels_size
);
end_message
(
buf
,
MESSAGE_UPDATE
,
len
);
if
(
flags
&
0x80
)
{
memcpy
(
ifp
->
buffered_prefix
,
prefix
,
16
);
ifp
->
have_buffered_prefix
=
1
;
memcpy
(
buf
->
prefix
,
prefix
,
16
);
buf
->
have_prefix
=
1
;
}
}
static
void
really_send_update
(
struct
interface
*
ifp
,
const
unsigned
char
*
id
,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
,
unsigned
short
seqno
,
unsigned
short
metric
,
unsigned
char
*
channels
,
int
channels_len
)
{
if
(
!
if_up
(
ifp
))
return
;
if
((
ifp
->
flags
&
IF_UNICAST
)
!=
0
)
{
struct
neighbour
*
neigh
;
FOR_ALL_NEIGHBOURS
(
neigh
)
{
if
(
neigh
->
ifp
==
ifp
)
{
really_buffer_update
(
&
neigh
->
buf
,
ifp
,
id
,
prefix
,
plen
,
src_prefix
,
src_plen
,
seqno
,
metric
,
channels
,
channels_len
);
}
}
}
else
{
really_buffer_update
(
&
ifp
->
buf
,
ifp
,
id
,
prefix
,
plen
,
src_prefix
,
src_plen
,
seqno
,
metric
,
channels
,
channels_len
);
}
}
...
...
@@ -1512,7 +1349,8 @@ flushupdates(struct interface *ifp)
really_send_update
(
ifp
,
route
->
src
->
id
,
route
->
src
->
prefix
,
route
->
src
->
plen
,
route
->
src
->
src_prefix
,
route
->
src
->
src_plen
,
route
->
src
->
src_prefix
,
route
->
src
->
src_plen
,
seqno
,
metric
,
channels
,
chlen
);
update_source
(
route
->
src
,
seqno
,
metric
);
...
...
@@ -1523,12 +1361,23 @@ flushupdates(struct interface *ifp)
}
else
{
/* There's no route for this prefix. This can happen shortly
after an xroute has been retracted, so send a retraction. */
really_send_update
(
ifp
,
myid
,
b
[
i
].
prefix
,
b
[
i
].
plen
,
really_send_update
(
ifp
,
myid
,
b
[
i
].
prefix
,
b
[
i
].
plen
,
b
[
i
].
src_prefix
,
b
[
i
].
src_plen
,
myseqno
,
INFINITY
,
NULL
,
-
1
);
}
}
schedule_flush_now
(
ifp
);
if
((
ifp
->
flags
&
IF_UNICAST
)
!=
0
)
{
struct
neighbour
*
neigh
;
FOR_ALL_NEIGHBOURS
(
neigh
)
{
if
(
neigh
->
ifp
==
ifp
)
{
schedule_flush_now
(
&
neigh
->
buf
);
}
}
}
else
{
schedule_flush_now
(
&
ifp
->
buf
);
}
done:
free
(
b
);
}
...
...
@@ -1563,7 +1412,7 @@ buffer_update(struct interface *ifp,
number of installed routes will grow over time, make sure we
have enough space to send a full-ish frame. */
n
=
installed_routes_estimate
()
+
xroutes_estimate
()
+
4
;
n
=
MAX
(
n
,
ifp
->
bufsize
/
16
);
n
=
MAX
(
n
,
ifp
->
buf
.
size
/
16
);
again:
ifp
->
buffered_updates
=
malloc
(
n
*
sizeof
(
struct
buffered_update
));
if
(
ifp
->
buffered_updates
==
NULL
)
{
...
...
@@ -1643,10 +1492,7 @@ send_update(struct interface *ifp, int urgent,
fprintf
(
stderr
,
"Couldn't allocate route stream.
\n
"
);
}
set_timeout
(
&
ifp
->
update_timeout
,
ifp
->
update_interval
);
if
(
!
prefix
)
ifp
->
last_update_time
=
now
.
tv_sec
;
else
ifp
->
last_specific_update_time
=
now
.
tv_sec
;
ifp
->
last_update_time
=
now
.
tv_sec
;
}
else
{
send_update
(
ifp
,
urgent
,
NULL
,
0
,
zeroes
,
0
);
send_update
(
ifp
,
urgent
,
zeroes
,
0
,
NULL
,
0
);
...
...
@@ -1666,6 +1512,23 @@ send_update_resend(struct interface *ifp,
0
,
NULL
,
NULL
,
resend_delay
);
}
void
buffer_wildcard_retraction
(
struct
buffered
*
buf
)
{
start_message
(
buf
,
MESSAGE_UPDATE
,
10
);
accumulate_byte
(
buf
,
0
);
accumulate_byte
(
buf
,
0
);
accumulate_byte
(
buf
,
0
);
accumulate_byte
(
buf
,
0
);
accumulate_short
(
buf
,
0xFFFF
);
accumulate_short
(
buf
,
myseqno
);
accumulate_short
(
buf
,
0xFFFF
);
end_message
(
buf
,
MESSAGE_UPDATE
,
10
);
buf
->
have_id
=
0
;
}
void
send_wildcard_retraction
(
struct
interface
*
ifp
)
{
...
...
@@ -1679,17 +1542,16 @@ send_wildcard_retraction(struct interface *ifp)
if
(
!
if_up
(
ifp
))
return
;
start_message
(
ifp
,
MESSAGE_UPDATE
,
10
);
accumulate_byte
(
ifp
,
0
);
accumulate_byte
(
ifp
,
0
);
accumulate_byte
(
ifp
,
0
);
accumulate_byte
(
ifp
,
0
);
accumulate_short
(
ifp
,
0xFFFF
);
accumulate_short
(
ifp
,
myseqno
);
accumulate_short
(
ifp
,
0xFFFF
);
end_message
(
ifp
,
MESSAGE_UPDATE
,
10
);
ifp
->
have_buffered_id
=
0
;
if
((
ifp
->
flags
&
IF_UNICAST
)
!=
0
)
{
struct
neighbour
*
neigh
;
FOR_ALL_NEIGHBOURS
(
neigh
)
{
if
(
neigh
->
ifp
==
ifp
)
{
buffer_wildcard_retraction
(
&
neigh
->
buf
);
}
}
}
else
{
buffer_wildcard_retraction
(
&
ifp
->
buf
);
}
}
void
...
...
@@ -1728,13 +1590,40 @@ send_self_update(struct interface *ifp)
}
}
void
buffer_ihu
(
struct
buffered
*
buf
,
unsigned
short
rxcost
,
unsigned
short
interval
,
const
unsigned
char
*
address
,
int
rtt_data
,
unsigned
int
t1
,
unsigned
int
t2
)
{
int
msglen
,
ll
;
ll
=
linklocal
(
address
);
msglen
=
(
ll
?
14
:
200
)
+
(
rtt_data
?
10
:
0
);
start_message
(
buf
,
MESSAGE_IHU
,
msglen
);
accumulate_byte
(
buf
,
ll
?
3
:
2
);
accumulate_byte
(
buf
,
0
);
accumulate_short
(
buf
,
rxcost
);
accumulate_short
(
buf
,
interval
);
if
(
ll
)
accumulate_bytes
(
buf
,
address
+
8
,
8
);
else
accumulate_bytes
(
buf
,
address
,
16
);
if
(
rtt_data
)
{
accumulate_byte
(
buf
,
SUBTLV_TIMESTAMP
);
accumulate_byte
(
buf
,
8
);
accumulate_int
(
buf
,
t1
);
accumulate_int
(
buf
,
t2
);
}
end_message
(
buf
,
MESSAGE_IHU
,
msglen
);
}
void
send_ihu
(
struct
neighbour
*
neigh
,
struct
interface
*
ifp
)
{
int
rxcost
,
interval
;
int
ll
;
int
send_rtt_data
;
int
msglen
;
if
(
neigh
==
NULL
&&
ifp
==
NULL
)
{
struct
interface
*
ifp_aux
;
...
...
@@ -1765,19 +1654,12 @@ send_ihu(struct neighbour *neigh, struct interface *ifp)
rxcost
=
neighbour_rxcost
(
neigh
);
interval
=
(
ifp
->
hello_interval
*
3
+
9
)
/
10
;
/* Conceptually, an IHU is a unicast message. We usually send them as
multicast, since this allows aggregation into a single packet and
avoids an ARP exchange. If we already have a unicast message queued
for this neighbour, however, we might as well piggyback the IHU. */
debugf
(
"Sending %sihu %d on %s to %s.
\n
"
,
unicast_neighbour
==
neigh
?
"unicast "
:
""
,
debugf
(
"Sending ihu %d on %s to %s.
\n
"
,
rxcost
,
neigh
->
ifp
->
name
,
format_address
(
neigh
->
address
));
ll
=
linklocal
(
neigh
->
address
);
if
((
ifp
->
flags
&
IF_TIMESTAMPS
)
&&
neigh
->
hello_send_us
&&
if
(
ifp
->
buf
.
enable_timestamps
&&
neigh
->
hello_send_us
&&
/* Checks whether the RTT data is not too old to be sent. */
timeval_minus_msec
(
&
now
,
&
neigh
->
hello_rtt_receive_time
)
<
1000000
)
{
send_rtt_data
=
1
;
...
...
@@ -1786,48 +1668,10 @@ send_ihu(struct neighbour *neigh, struct interface *ifp)
send_rtt_data
=
0
;
}
/* The length depends on the format of the address, and then an
optional 10-bytes sub-TLV for timestamps (used to compute a RTT). */
msglen
=
(
ll
?
14
:
22
)
+
(
send_rtt_data
?
10
:
0
);
if
(
unicast_neighbour
!=
neigh
)
{
start_message
(
ifp
,
MESSAGE_IHU
,
msglen
);
accumulate_byte
(
ifp
,
ll
?
3
:
2
);
accumulate_byte
(
ifp
,
0
);
accumulate_short
(
ifp
,
rxcost
);
accumulate_short
(
ifp
,
interval
);
if
(
ll
)
accumulate_bytes
(
ifp
,
neigh
->
address
+
8
,
8
);
else
accumulate_bytes
(
ifp
,
neigh
->
address
,
16
);
if
(
send_rtt_data
)
{
accumulate_byte
(
ifp
,
SUBTLV_TIMESTAMP
);
accumulate_byte
(
ifp
,
8
);
accumulate_int
(
ifp
,
neigh
->
hello_send_us
);
accumulate_int
(
ifp
,
time_us
(
neigh
->
hello_rtt_receive_time
));
}
end_message
(
ifp
,
MESSAGE_IHU
,
msglen
);
}
else
{
int
rc
;
rc
=
start_unicast_message
(
neigh
,
MESSAGE_IHU
,
msglen
);
if
(
rc
<
0
)
return
;
accumulate_unicast_byte
(
neigh
,
ll
?
3
:
2
);
accumulate_unicast_byte
(
neigh
,
0
);
accumulate_unicast_short
(
neigh
,
rxcost
);
accumulate_unicast_short
(
neigh
,
interval
);
if
(
ll
)
accumulate_unicast_bytes
(
neigh
,
neigh
->
address
+
8
,
8
);
else
accumulate_unicast_bytes
(
neigh
,
neigh
->
address
,
16
);
if
(
send_rtt_data
)
{
accumulate_unicast_byte
(
neigh
,
SUBTLV_TIMESTAMP
);
accumulate_unicast_byte
(
neigh
,
8
);
accumulate_unicast_int
(
neigh
,
neigh
->
hello_send_us
);
accumulate_unicast_int
(
neigh
,
time_us
(
neigh
->
hello_rtt_receive_time
));
}
end_unicast_message
(
neigh
,
MESSAGE_IHU
,
msglen
);
}
buffer_ihu
(
&
ifp
->
buf
,
rxcost
,
interval
,
neigh
->
address
,
send_rtt_data
,
neigh
->
hello_send_us
,
time_us
(
neigh
->
hello_rtt_receive_time
));
}
/* Send IHUs to all marginal neighbours */
...
...
@@ -1845,83 +1689,86 @@ send_marginal_ihu(struct interface *ifp)
/* Standard wildcard request with prefix == NULL && src_prefix == zeroes,
Specific wildcard request with prefix == zeroes && src_prefix == NULL. */
void
send_request
(
struct
interface
*
ifp
,
static
void
send_request
(
struct
buffered
*
buf
,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
)
{
int
v4
,
pb
,
spb
,
len
,
is_ss
;
if
(
ifp
==
NULL
)
{
struct
interface
*
ifp_aux
;
FOR_ALL_INTERFACES
(
ifp_aux
)
{
if
(
!
if_up
(
ifp_aux
))
continue
;
send_request
(
ifp_aux
,
prefix
,
plen
,
src_prefix
,
src_plen
);
}
return
;
}
/* make sure any buffered updates go out before this request. */
flushupdates
(
ifp
);
int
v4
,
pb
,
spb
,
len
;
int
is_ss
=
!
is_default
(
src_prefix
,
src_plen
);
if
(
!
if_up
(
ifp
)
)
if
(
is_ss
&&
buf
->
rfc6126_compatible
)
return
;
if
(
prefix
&&
src_prefix
)
{
debugf
(
"sending request to %s for %s from %s.
\n
"
,
ifp
->
name
,
format_prefix
(
prefix
,
plen
),
format_prefix
(
src_prefix
,
src_plen
));
}
else
if
(
prefix
)
{
debugf
(
"sending request to %s for any specific.
\n
"
,
ifp
->
name
);
start_message
(
ifp
,
MESSAGE_REQUEST_SRC_SPECIFIC
,
3
);
accumulate_byte
(
ifp
,
0
);
accumulate_byte
(
ifp
,
0
);
accumulate_byte
(
ifp
,
0
);
end_message
(
ifp
,
MESSAGE_REQUEST_SRC_SPECIFIC
,
3
);
return
;
}
else
if
(
src_prefix
)
{
debugf
(
"sending request to %s for any.
\n
"
,
ifp
->
name
);
start_message
(
ifp
,
MESSAGE_REQUEST
,
2
);
accumulate_byte
(
ifp
,
0
);
accumulate_byte
(
ifp
,
0
);
end_message
(
ifp
,
MESSAGE_REQUEST
,
2
);
return
;
}
else
{
send_request
(
ifp
,
NULL
,
0
,
zeroes
,
0
);
send_request
(
ifp
,
zeroes
,
0
,
NULL
,
0
);
if
(
!
prefix
)
{
assert
(
!
src_prefix
);
debugf
(
"sending request for any.
\n
"
);
start_message
(
buf
,
MESSAGE_REQUEST
,
2
);
accumulate_byte
(
buf
,
0
);
accumulate_byte
(
buf
,
0
);
end_message
(
buf
,
MESSAGE_REQUEST
,
2
);
return
;
}
debugf
(
"sending request for %s from %s.
\n
"
,
format_prefix
(
prefix
,
plen
),
format_prefix
(
src_prefix
,
src_plen
));
v4
=
plen
>=
96
&&
v4mapped
(
prefix
);
pb
=
v4
?
((
plen
-
96
)
+
7
)
/
8
:
(
plen
+
7
)
/
8
;
len
=
2
+
pb
;
spb
=
v4
?
((
src_plen
-
96
)
+
7
)
/
8
:
(
src_plen
+
7
)
/
8
;
len
=
2
+
pb
+
(
is_ss
?
3
+
spb
:
0
);
is_ss
=
!
is_default
(
src_prefix
,
src_plen
);
if
(
is_ss
)
{
spb
=
v4
?
((
src_plen
-
96
)
+
7
)
/
8
:
(
src_plen
+
7
)
/
8
;
len
+=
spb
+
1
;
start_message
(
ifp
,
MESSAGE_REQUEST_SRC_SPECIFIC
,
len
);
}
else
{
spb
=
0
;
start_message
(
ifp
,
MESSAGE_REQUEST
,
len
);
}
accumulate_byte
(
ifp
,
v4
?
1
:
2
);
accumulate_byte
(
ifp
,
v4
?
plen
-
96
:
plen
);
if
(
is_ss
)
accumulate_byte
(
ifp
,
v4
?
src_plen
-
96
:
src_plen
);
start_message
(
buf
,
MESSAGE_REQUEST
,
len
);
accumulate_byte
(
buf
,
v4
?
1
:
2
);
accumulate_byte
(
buf
,
v4
?
plen
-
96
:
plen
);
if
(
v4
)
accumulate_bytes
(
ifp
,
prefix
+
12
,
pb
);
accumulate_bytes
(
buf
,
prefix
+
12
,
pb
);
else
accumulate_bytes
(
ifp
,
prefix
,
pb
);
accumulate_bytes
(
buf
,
prefix
,
pb
);
if
(
is_ss
)
{
accumulate_byte
(
buf
,
SUBTLV_SOURCE_PREFIX
);
accumulate_byte
(
buf
,
1
+
spb
);
accumulate_byte
(
buf
,
v4
?
src_plen
-
96
:
src_plen
);
if
(
v4
)
accumulate_bytes
(
ifp
,
src_prefix
+
12
,
spb
);
accumulate_bytes
(
buf
,
src_prefix
+
12
,
spb
);
else
accumulate_bytes
(
ifp
,
src_prefix
,
spb
);
end_message
(
ifp
,
MESSAGE_REQUEST_SRC_SPECIFIC
,
len
);
}
else
{
end_message
(
ifp
,
MESSAGE_REQUEST
,
len
);
accumulate_bytes
(
buf
,
src_prefix
,
spb
);
}
end_message
(
buf
,
MESSAGE_REQUEST
,
len
);
}
void
send_multicast_request
(
struct
interface
*
ifp
,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
)
{
if
(
ifp
==
NULL
)
{
struct
interface
*
ifp_auxn
;
FOR_ALL_INTERFACES
(
ifp_auxn
)
{
if
(
if_up
(
ifp_auxn
))
continue
;
send_multicast_request
(
ifp_auxn
,
prefix
,
plen
,
src_prefix
,
src_plen
);
}
return
;
}
if
(
!
if_up
(
ifp
))
return
;
/* make sure any buffered updates go out before this request. */
flushupdates
(
ifp
);
if
((
ifp
->
flags
&
IF_UNICAST
)
!=
0
)
{
struct
neighbour
*
neigh
;
FOR_ALL_NEIGHBOURS
(
neigh
)
{
if
(
neigh
->
ifp
==
ifp
)
{
send_request
(
&
neigh
->
buf
,
prefix
,
plen
,
src_prefix
,
src_plen
);
}
else
{
send_request
(
&
ifp
->
buf
,
prefix
,
plen
,
src_prefix
,
src_plen
);
}
}
}
}
...
...
@@ -1930,136 +1777,97 @@ send_unicast_request(struct neighbour *neigh,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
)
{
int
rc
,
v4
,
pb
,
spb
,
len
,
is_ss
;
if
(
!
if_up
(
neigh
->
ifp
))
return
;
/* make sure any buffered updates go out before this request. */
flushupdates
(
neigh
->
ifp
);
if
(
prefix
&&
src_prefix
)
{
debugf
(
"sending unicast request to %s for %s from %s.
\n
"
,
format_address
(
neigh
->
address
),
format_prefix
(
prefix
,
plen
),
format_prefix
(
src_prefix
,
src_plen
));
}
else
if
(
prefix
)
{
debugf
(
"sending unicast request to %s for any specific.
\n
"
,
format_address
(
neigh
->
address
));
rc
=
start_unicast_message
(
neigh
,
MESSAGE_REQUEST_SRC_SPECIFIC
,
3
);
if
(
rc
<
0
)
return
;
accumulate_unicast_byte
(
neigh
,
0
);
accumulate_unicast_byte
(
neigh
,
0
);
accumulate_unicast_byte
(
neigh
,
0
);
end_unicast_message
(
neigh
,
MESSAGE_REQUEST_SRC_SPECIFIC
,
3
);
return
;
}
else
if
(
src_prefix
)
{
debugf
(
"sending unicast request to %s for any.
\n
"
,
format_address
(
neigh
->
address
));
rc
=
start_unicast_message
(
neigh
,
MESSAGE_REQUEST
,
2
);
if
(
rc
<
0
)
return
;
accumulate_unicast_byte
(
neigh
,
0
);
accumulate_unicast_byte
(
neigh
,
0
);
end_unicast_message
(
neigh
,
MESSAGE_REQUEST
,
2
);
return
;
}
else
{
send_unicast_request
(
neigh
,
NULL
,
0
,
zeroes
,
0
);
send_unicast_request
(
neigh
,
zeroes
,
0
,
NULL
,
0
);
send_request
(
&
neigh
->
buf
,
prefix
,
plen
,
src_prefix
,
src_plen
);
}
static
void
send_multihop_request
(
struct
buffered
*
buf
,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
,
unsigned
short
seqno
,
const
unsigned
char
*
id
,
unsigned
short
hop_count
)
{
int
v4
,
pb
,
spb
,
len
;
int
is_ss
=
!
is_default
(
src_prefix
,
src_plen
);
if
(
is_ss
&&
buf
->
rfc6126_compatible
)
return
;
}
debugf
(
"Sending request (%d) for %s.
\n
"
,
hop_count
,
format_prefix
(
prefix
,
plen
));
v4
=
plen
>=
96
&&
v4mapped
(
prefix
);
pb
=
v4
?
((
plen
-
96
)
+
7
)
/
8
:
(
plen
+
7
)
/
8
;
len
=
2
+
pb
;
is_ss
=
!
is_default
(
src_prefix
,
src_plen
);
if
(
is_ss
)
{
spb
=
v4
?
((
src_plen
-
96
)
+
7
)
/
8
:
(
src_plen
+
7
)
/
8
;
len
+=
spb
+
1
;
rc
=
start_unicast_message
(
neigh
,
MESSAGE_REQUEST_SRC_SPECIFIC
,
len
);
}
else
{
spb
=
0
;
rc
=
start_unicast_message
(
neigh
,
MESSAGE_REQUEST
,
len
);
spb
=
v4
?
((
src_plen
-
96
)
+
7
)
/
8
:
(
src_plen
+
7
)
/
8
;
len
=
6
+
8
+
pb
+
(
is_ss
?
3
+
spb
:
0
);
start_message
(
buf
,
MESSAGE_MH_REQUEST
,
len
);
accumulate_byte
(
buf
,
v4
?
1
:
2
);
accumulate_byte
(
buf
,
v4
?
plen
-
96
:
plen
);
accumulate_short
(
buf
,
seqno
);
accumulate_byte
(
buf
,
hop_count
);
accumulate_byte
(
buf
,
v4
?
src_plen
-
96
:
src_plen
);
accumulate_bytes
(
buf
,
id
,
8
);
if
(
prefix
)
{
if
(
v4
)
accumulate_bytes
(
buf
,
prefix
+
12
,
pb
);
else
accumulate_bytes
(
buf
,
prefix
,
pb
);
}
if
(
rc
<
0
)
return
;
accumulate_unicast_byte
(
neigh
,
v4
?
1
:
2
);
accumulate_unicast_byte
(
neigh
,
v4
?
plen
-
96
:
plen
);
if
(
is_ss
)
accumulate_unicast_byte
(
neigh
,
v4
?
src_plen
-
96
:
src_plen
);
if
(
v4
)
accumulate_unicast_bytes
(
neigh
,
prefix
+
12
,
pb
);
else
accumulate_unicast_bytes
(
neigh
,
prefix
,
pb
);
if
(
is_ss
)
{
accumulate_byte
(
buf
,
SUBTLV_SOURCE_PREFIX
);
accumulate_byte
(
buf
,
1
+
spb
);
accumulate_byte
(
buf
,
v4
?
src_plen
-
96
:
src_plen
);
if
(
v4
)
accumulate_
unicast_bytes
(
neigh
,
src_prefix
+
12
,
spb
);
accumulate_
bytes
(
buf
,
src_prefix
+
12
,
spb
);
else
accumulate_unicast_bytes
(
neigh
,
src_prefix
,
spb
);
end_unicast_message
(
neigh
,
MESSAGE_REQUEST_SRC_SPECIFIC
,
len
);
}
else
{
end_unicast_message
(
neigh
,
MESSAGE_REQUEST
,
len
);
accumulate_bytes
(
buf
,
src_prefix
,
spb
);
}
end_message
(
buf
,
MESSAGE_MH_REQUEST
,
len
);
}
void
send_multihop_request
(
struct
interface
*
ifp
,
send_multi
cast_multi
hop_request
(
struct
interface
*
ifp
,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
,
unsigned
short
seqno
,
const
unsigned
char
*
id
,
unsigned
short
hop_count
)
{
int
v4
,
pb
,
spb
,
len
,
is_ss
;
/* Make sure any buffered updates go out before this request. */
flushupdates
(
ifp
);
if
(
ifp
==
NULL
)
{
struct
interface
*
ifp_aux
;
FOR_ALL_INTERFACES
(
ifp_aux
)
{
if
(
!
if_up
(
ifp_aux
))
continue
;
send_multihop_request
(
ifp_aux
,
prefix
,
plen
,
src_prefix
,
src_plen
,
seqno
,
id
,
hop_count
);
send_multicast_multihop_request
(
ifp_aux
,
prefix
,
plen
,
src_prefix
,
src_plen
,
seqno
,
id
,
hop_count
);
}
return
;
}
flushupdates
(
ifp
);
if
(
!
if_up
(
ifp
))
return
;
debugf
(
"Sending request (%d) on %s for %s from %s.
\n
"
,
hop_count
,
ifp
->
name
,
format_prefix
(
prefix
,
plen
),
format_prefix
(
src_prefix
,
src_plen
));
v4
=
plen
>=
96
&&
v4mapped
(
prefix
);
pb
=
v4
?
((
plen
-
96
)
+
7
)
/
8
:
(
plen
+
7
)
/
8
;
len
=
6
+
8
+
pb
;
is_ss
=
!
is_default
(
src_prefix
,
src_plen
);
if
(
is_ss
)
{
spb
=
v4
?
((
src_plen
-
96
)
+
7
)
/
8
:
(
src_plen
+
7
)
/
8
;
len
+=
spb
;
start_message
(
ifp
,
MESSAGE_MH_REQUEST_SRC_SPECIFIC
,
len
);
}
else
{
spb
=
0
;
start_message
(
ifp
,
MESSAGE_MH_REQUEST
,
len
);
}
accumulate_byte
(
ifp
,
v4
?
1
:
2
);
accumulate_byte
(
ifp
,
v4
?
plen
-
96
:
plen
);
accumulate_short
(
ifp
,
seqno
);
accumulate_byte
(
ifp
,
hop_count
);
accumulate_byte
(
ifp
,
v4
?
src_plen
-
96
:
src_plen
);
accumulate_bytes
(
ifp
,
id
,
8
);
if
(
prefix
)
{
if
(
v4
)
accumulate_bytes
(
ifp
,
prefix
+
12
,
pb
);
else
accumulate_bytes
(
ifp
,
prefix
,
pb
);
}
if
(
is_ss
)
{
if
(
v4
)
accumulate_bytes
(
ifp
,
src_prefix
+
12
,
spb
);
else
accumulate_bytes
(
ifp
,
src_prefix
,
spb
);
end_message
(
ifp
,
MESSAGE_MH_REQUEST_SRC_SPECIFIC
,
len
);
if
((
ifp
->
flags
&
IF_UNICAST
)
!=
0
)
{
struct
neighbour
*
neigh
;
FOR_ALL_NEIGHBOURS
(
neigh
)
{
if
(
neigh
->
ifp
==
ifp
)
{
send_multihop_request
(
&
neigh
->
buf
,
prefix
,
plen
,
src_prefix
,
src_plen
,
seqno
,
id
,
hop_count
);
}
}
}
else
{
end_message
(
ifp
,
MESSAGE_MH_REQUEST
,
len
);
send_multihop_request
(
&
ifp
->
buf
,
prefix
,
plen
,
src_prefix
,
src_plen
,
seqno
,
id
,
hop_count
);
}
}
...
...
@@ -2071,50 +1879,9 @@ send_unicast_multihop_request(struct neighbour *neigh,
unsigned
short
seqno
,
const
unsigned
char
*
id
,
unsigned
short
hop_count
)
{
int
rc
,
v4
,
pb
,
spb
,
len
,
is_ss
;
/* Make sure any buffered updates go out before this request. */
flushupdates
(
neigh
->
ifp
);
debugf
(
"Sending multi-hop request to %s for %s from %s (%d hops).
\n
"
,
format_address
(
neigh
->
address
),
format_prefix
(
prefix
,
plen
),
format_prefix
(
src_prefix
,
src_plen
),
hop_count
);
v4
=
plen
>=
96
&&
v4mapped
(
prefix
);
pb
=
v4
?
((
plen
-
96
)
+
7
)
/
8
:
(
plen
+
7
)
/
8
;
len
=
6
+
8
+
pb
;
is_ss
=
!
is_default
(
src_prefix
,
src_plen
);
if
(
is_ss
)
{
spb
=
v4
?
((
src_plen
-
96
)
+
7
)
/
8
:
(
src_plen
+
7
)
/
8
;
len
+=
spb
;
rc
=
start_unicast_message
(
neigh
,
MESSAGE_MH_REQUEST_SRC_SPECIFIC
,
len
);
}
else
{
spb
=
0
;
rc
=
start_unicast_message
(
neigh
,
MESSAGE_MH_REQUEST
,
len
);
}
if
(
rc
<
0
)
return
;
accumulate_unicast_byte
(
neigh
,
v4
?
1
:
2
);
accumulate_unicast_byte
(
neigh
,
v4
?
plen
-
96
:
plen
);
accumulate_unicast_short
(
neigh
,
seqno
);
accumulate_unicast_byte
(
neigh
,
hop_count
);
accumulate_unicast_byte
(
neigh
,
v4
?
src_plen
-
96
:
src_plen
);
accumulate_unicast_bytes
(
neigh
,
id
,
8
);
if
(
prefix
)
{
if
(
v4
)
accumulate_unicast_bytes
(
neigh
,
prefix
+
12
,
pb
);
else
accumulate_unicast_bytes
(
neigh
,
prefix
,
pb
);
}
if
(
is_ss
)
{
if
(
v4
)
accumulate_unicast_bytes
(
neigh
,
src_prefix
+
12
,
spb
);
else
accumulate_unicast_bytes
(
neigh
,
src_prefix
,
spb
);
end_unicast_message
(
neigh
,
MESSAGE_MH_REQUEST_SRC_SPECIFIC
,
len
);
}
else
{
end_unicast_message
(
neigh
,
MESSAGE_MH_REQUEST
,
len
);
}
send_multihop_request
(
&
neigh
->
buf
,
prefix
,
plen
,
src_prefix
,
src_plen
,
seqno
,
id
,
hop_count
);
}
/* Send a request to a well-chosen neighbour and resend. If there is no
...
...
@@ -2135,8 +1902,12 @@ send_request_resend(const unsigned char *prefix, unsigned char plen,
record_resend
(
RESEND_REQUEST
,
prefix
,
plen
,
src_prefix
,
src_plen
,
seqno
,
id
,
neigh
->
ifp
,
resend_delay
);
}
else
{
send_multihop_request
(
NULL
,
prefix
,
plen
,
src_prefix
,
src_plen
,
seqno
,
id
,
127
);
struct
interface
*
ifp
;
FOR_ALL_INTERFACES
(
ifp
)
{
if
(
!
if_up
(
ifp
))
continue
;
send_multihop_request
(
&
ifp
->
buf
,
prefix
,
plen
,
src_prefix
,
src_plen
,
seqno
,
id
,
127
);
}
}
}
...
...
message.h
View file @
5afde873
...
...
@@ -22,9 +22,6 @@ THE SOFTWARE.
#define MAX_BUFFERED_UPDATES 200
#define BUCKET_TOKENS_MAX 4000
#define BUCKET_TOKENS_PER_SEC 1000
#define MESSAGE_PAD1 0
#define MESSAGE_PADN 1
#define MESSAGE_ACK_REQ 2
...
...
@@ -37,15 +34,13 @@ THE SOFTWARE.
#define MESSAGE_REQUEST 9
#define MESSAGE_MH_REQUEST 10
/* 11 and 12 are for authentication */
#define MESSAGE_UPDATE_SRC_SPECIFIC 13
#define MESSAGE_REQUEST_SRC_SPECIFIC 14
#define MESSAGE_MH_REQUEST_SRC_SPECIFIC 15
/* Protocol extension through sub-TLVs. */
#define SUBTLV_PAD1 0
#define SUBTLV_PADN 1
#define SUBTLV_DIVERSITY 2
/* Also known as babelz. */
#define SUBTLV_TIMESTAMP 3
/* Used to compute RTT. */
#define SUBTLV_DIVERSITY 2
/* Also known as babelz. */
#define SUBTLV_TIMESTAMP 3
/* Used to compute RTT. */
#define SUBTLV_SOURCE_PREFIX 128
/* Source-specific routing. */
extern
unsigned
short
myseqno
;
extern
struct
timeval
seqno_time
;
...
...
@@ -55,16 +50,13 @@ extern int split_horizon;
extern
unsigned
char
packet_header
[
4
];
extern
struct
neighbour
*
unicast_neighbour
;
extern
struct
timeval
unicast_flush_timeout
;
void
parse_packet
(
const
unsigned
char
*
from
,
struct
interface
*
ifp
,
const
unsigned
char
*
packet
,
int
packetlen
);
void
flushbuf
(
struct
interface
*
ifp
);
void
flushbuf
(
struct
buffered
*
buf
);
void
flushupdates
(
struct
interface
*
ifp
);
void
send_ack
(
struct
neighbour
*
neigh
,
unsigned
short
nonce
,
unsigned
short
interval
);
void
send_hello_no
update
(
struct
interface
*
ifp
,
unsigned
interval
);
void
send_hello_no
ihu
(
struct
interface
*
ifp
,
unsigned
interval
);
void
send_hello
(
struct
interface
*
ifp
);
void
flush_unicast
(
int
dofree
);
void
send_update
(
struct
interface
*
ifp
,
int
urgent
,
...
...
@@ -79,19 +71,20 @@ void update_myseqno(void);
void
send_self_update
(
struct
interface
*
ifp
);
void
send_ihu
(
struct
neighbour
*
neigh
,
struct
interface
*
ifp
);
void
send_marginal_ihu
(
struct
interface
*
ifp
);
void
send_request
(
struct
interface
*
ifp
,
void
send_
multicast_
request
(
struct
interface
*
ifp
,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
);
void
send_unicast_request
(
struct
neighbour
*
neigh
,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
);
void
send_multihop_request
(
struct
interface
*
ifp
,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
,
unsigned
short
seqno
,
const
unsigned
char
*
id
,
unsigned
short
hop_count
);
void
send_multicast_multihop_request
(
struct
interface
*
ifp
,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
,
unsigned
short
seqno
,
const
unsigned
char
*
id
,
unsigned
short
hop_count
);
void
send_unicast_multihop_request
(
struct
neighbour
*
neigh
,
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
...
...
neighbour.c
View file @
5afde873
...
...
@@ -24,6 +24,8 @@ THE SOFTWARE.
#include <string.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <assert.h>
...
...
@@ -55,8 +57,6 @@ void
flush_neighbour
(
struct
neighbour
*
neigh
)
{
flush_neighbour_routes
(
neigh
);
if
(
unicast_neighbour
==
neigh
)
flush_unicast
(
1
);
flush_resends
(
neigh
);
if
(
neighs
==
neigh
)
{
...
...
@@ -68,6 +68,7 @@ flush_neighbour(struct neighbour *neigh)
previous
->
next
=
neigh
->
next
;
}
local_notify_neighbour
(
neigh
,
LOCAL_FLUSH
);
free
(
neigh
->
buf
.
buf
);
free
(
neigh
);
}
...
...
@@ -76,6 +77,7 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
{
struct
neighbour
*
neigh
;
const
struct
timeval
zero
=
{
0
,
0
};
char
*
buf
;
neigh
=
find_neighbour_nocreate
(
address
,
ifp
);
if
(
neigh
)
...
...
@@ -84,8 +86,15 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
debugf
(
"Creating neighbour %s on %s.
\n
"
,
format_address
(
address
),
ifp
->
name
);
buf
=
malloc
(
ifp
->
buf
.
size
);
if
(
buf
==
NULL
)
{
perror
(
"malloc(neighbour->buf)"
);
return
NULL
;
}
neigh
=
calloc
(
1
,
sizeof
(
struct
neighbour
));
if
(
neigh
==
NULL
)
{
free
(
buf
);
perror
(
"malloc(neighbour)"
);
return
NULL
;
}
...
...
@@ -98,6 +107,13 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
neigh
->
hello_rtt_receive_time
=
zero
;
neigh
->
rtt_time
=
zero
;
neigh
->
ifp
=
ifp
;
neigh
->
buf
.
buf
=
buf
;
neigh
->
buf
.
size
=
ifp
->
buf
.
size
;
neigh
->
buf
.
flush_interval
=
ifp
->
buf
.
flush_interval
;
neigh
->
buf
.
sin6
.
sin6_family
=
AF_INET6
;
memcpy
(
&
neigh
->
buf
.
sin6
.
sin6_addr
,
address
,
16
);
neigh
->
buf
.
sin6
.
sin6_port
=
htons
(
protocol_port
);
neigh
->
buf
.
sin6
.
sin6_scope_id
=
ifp
->
ifindex
;
neigh
->
next
=
neighs
;
neighs
=
neigh
;
local_notify_neighbour
(
neigh
,
LOCAL_ADD
);
...
...
@@ -135,6 +151,11 @@ update_neighbour(struct neighbour *neigh, struct hello_history *hist,
missed_hellos
=
0
;
rc
=
1
;
}
else
if
(
missed_hellos
<
0
)
{
/* Late hello. Probably due to the link layer buffering
packets during a link outage or a cpu overload. */
fprintf
(
stderr
,
"Late hello: bufferbloated neighbor %s
\n
"
,
format_address
(
neigh
->
address
));
hist
->
reach
<<=
-
missed_hellos
;
missed_hellos
=
0
;
rc
=
1
;
...
...
neighbour.h
View file @
5afde873
...
...
@@ -44,6 +44,7 @@ struct neighbour {
unsigned
int
rtt
;
struct
timeval
rtt_time
;
struct
interface
*
ifp
;
struct
buffered
buf
;
};
extern
struct
neighbour
*
neighs
;
...
...
resend.c
View file @
5afde873
...
...
@@ -24,13 +24,15 @@ THE SOFTWARE.
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "babeld.h"
#include "util.h"
#include "interface.h"
#include "neighbour.h"
#include "resend.h"
#include "message.h"
#include "interface.h"
#include "configuration.h"
struct
timeval
resend_time
=
{
0
,
0
};
...
...
@@ -304,10 +306,12 @@ do_resend()
if
(
timeval_compare
(
&
now
,
&
timeout
)
>=
0
)
{
switch
(
resend
->
kind
)
{
case
RESEND_REQUEST
:
send_multihop_request
(
resend
->
ifp
,
resend
->
prefix
,
resend
->
plen
,
resend
->
src_prefix
,
resend
->
src_plen
,
resend
->
seqno
,
resend
->
id
,
127
);
send_multicast_multihop_request
(
resend
->
ifp
,
resend
->
prefix
,
resend
->
plen
,
resend
->
src_prefix
,
resend
->
src_plen
,
resend
->
seqno
,
resend
->
id
,
127
);
break
;
case
RESEND_UPDATE
:
send_update
(
resend
->
ifp
,
1
,
...
...
route.c
View file @
5afde873
...
...
@@ -1139,8 +1139,8 @@ send_triggered_update(struct babel_route *route, struct source *oldsrc,
if
(
oldmetric
<
INFINITY
)
{
if
(
newmetric
>=
oldmetric
+
288
)
{
send_request
(
NULL
,
route
->
src
->
prefix
,
route
->
src
->
plen
,
route
->
src
->
src_prefix
,
route
->
src
->
src_plen
);
send_
multicast_
request
(
NULL
,
route
->
src
->
prefix
,
route
->
src
->
plen
,
route
->
src
->
src_prefix
,
route
->
src
->
src_plen
);
}
}
}
...
...
source.c
View file @
5afde873
...
...
@@ -24,6 +24,8 @@ THE SOFTWARE.
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <assert.h>
#include "babeld.h"
...
...
util.c
View file @
5afde873
...
...
@@ -302,7 +302,7 @@ format_thousands(unsigned int value)
static
char
buf
[
4
][
15
];
static
int
i
=
0
;
i
=
(
i
+
1
)
%
4
;
snprintf
(
buf
[
i
],
15
,
"%
d.%.3d
"
,
value
/
1000
,
value
%
1000
);
snprintf
(
buf
[
i
],
15
,
"%
u.%.3u
"
,
value
/
1000
,
value
%
1000
);
return
buf
[
i
];
}
...
...
util.h
View file @
5afde873
...
...
@@ -88,7 +88,7 @@ unsigned char *normalize_prefix(unsigned char *restrict ret,
const
unsigned
char
*
restrict
prefix
,
unsigned
char
plen
);
const
char
*
format_address
(
const
unsigned
char
*
address
);
const
char
*
format_prefix
(
const
unsigned
char
*
address
,
unsigned
char
prefix
);
const
char
*
format_prefix
(
const
unsigned
char
*
prefix
,
unsigned
char
plen
);
const
char
*
format_eui64
(
const
unsigned
char
*
eui
);
const
char
*
format_thousands
(
unsigned
int
value
);
int
parse_address
(
const
char
*
address
,
unsigned
char
*
addr_r
,
int
*
af_r
);
...
...
@@ -161,4 +161,3 @@ static inline void kdebugf(const char *format, ...) { return; }
#endif
#endif
xroute.c
View file @
5afde873
...
...
@@ -30,33 +30,128 @@ THE SOFTWARE.
#include "babeld.h"
#include "kernel.h"
#include "interface.h"
#include "neighbour.h"
#include "message.h"
#include "source.h"
#include "route.h"
#include "xroute.h"
#include "util.h"
#include "configuration.h"
#include "interface.h"
#include "local.h"
static
struct
xroute
*
xroutes
;
static
int
numxroutes
=
0
,
maxxroutes
=
0
;
static
int
xroute_compare
(
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
,
const
struct
xroute
*
xroute
)
{
int
rc
;
if
(
plen
<
xroute
->
plen
)
return
-
1
;
if
(
plen
>
xroute
->
plen
)
return
1
;
rc
=
memcmp
(
prefix
,
xroute
->
prefix
,
16
);
if
(
rc
!=
0
)
return
rc
;
if
(
src_plen
<
xroute
->
src_plen
)
return
-
1
;
if
(
src_plen
>
xroute
->
src_plen
)
return
1
;
rc
=
memcmp
(
src_prefix
,
xroute
->
src_prefix
,
16
);
if
(
rc
!=
0
)
return
rc
;
return
0
;
}
static
int
find_xroute_slot
(
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
,
int
*
new_return
)
{
int
p
,
m
,
g
,
c
;
if
(
numxroutes
<
1
)
{
if
(
new_return
)
*
new_return
=
0
;
return
-
1
;
}
p
=
0
;
g
=
numxroutes
-
1
;
do
{
m
=
(
p
+
g
)
/
2
;
c
=
xroute_compare
(
prefix
,
plen
,
src_prefix
,
src_plen
,
&
xroutes
[
m
]);
if
(
c
==
0
)
return
m
;
else
if
(
c
<
0
)
g
=
m
-
1
;
else
p
=
m
+
1
;
}
while
(
p
<=
g
);
if
(
new_return
)
*
new_return
=
p
;
return
-
1
;
}
struct
xroute
*
find_xroute
(
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
)
{
int
i
;
for
(
i
=
0
;
i
<
numxroutes
;
i
++
)
{
if
(
xroutes
[
i
].
plen
==
plen
&&
memcmp
(
xroutes
[
i
].
prefix
,
prefix
,
16
)
==
0
&&
xroutes
[
i
].
src_plen
==
src_plen
&&
memcmp
(
xroutes
[
i
].
src_prefix
,
src_prefix
,
16
)
==
0
)
return
&
xroutes
[
i
];
}
int
i
=
find_xroute_slot
(
prefix
,
plen
,
src_prefix
,
src_plen
,
NULL
);
if
(
i
>=
0
)
return
&
xroutes
[
i
];
return
NULL
;
}
int
add_xroute
(
unsigned
char
prefix
[
16
],
unsigned
char
plen
,
unsigned
char
src_prefix
[
16
],
unsigned
char
src_plen
,
unsigned
short
metric
,
unsigned
int
ifindex
,
int
proto
)
{
int
n
=
-
1
;
int
i
=
find_xroute_slot
(
prefix
,
plen
,
src_prefix
,
src_plen
,
&
n
);
if
(
i
>=
0
)
return
-
1
;
if
(
numxroutes
>=
maxxroutes
)
{
struct
xroute
*
new_xroutes
;
int
num
=
maxxroutes
<
1
?
8
:
2
*
maxxroutes
;
new_xroutes
=
realloc
(
xroutes
,
num
*
sizeof
(
struct
xroute
));
if
(
new_xroutes
==
NULL
)
return
-
1
;
maxxroutes
=
num
;
xroutes
=
new_xroutes
;
}
if
(
n
<
numxroutes
)
memmove
(
xroutes
+
n
+
1
,
xroutes
+
n
,
(
numxroutes
-
n
)
*
sizeof
(
struct
xroute
));
numxroutes
++
;
memcpy
(
xroutes
[
n
].
prefix
,
prefix
,
16
);
xroutes
[
n
].
plen
=
plen
;
memcpy
(
xroutes
[
n
].
src_prefix
,
src_prefix
,
16
);
xroutes
[
n
].
src_plen
=
src_plen
;
xroutes
[
n
].
metric
=
metric
;
xroutes
[
n
].
ifindex
=
ifindex
;
xroutes
[
n
].
proto
=
proto
;
local_notify_xroute
(
&
xroutes
[
n
],
LOCAL_ADD
);
return
1
;
}
void
flush_xroute
(
struct
xroute
*
xroute
)
{
...
...
@@ -68,7 +163,8 @@ flush_xroute(struct xroute *xroute)
local_notify_xroute
(
xroute
,
LOCAL_FLUSH
);
if
(
i
!=
numxroutes
-
1
)
memcpy
(
xroutes
+
i
,
xroutes
+
numxroutes
-
1
,
sizeof
(
struct
xroute
));
memmove
(
xroutes
+
i
,
xroutes
+
i
+
1
,
(
numxroutes
-
i
-
1
)
*
sizeof
(
struct
xroute
));
numxroutes
--
;
VALGRIND_MAKE_MEM_UNDEFINED
(
xroutes
+
numxroutes
,
sizeof
(
struct
xroute
));
...
...
@@ -87,42 +183,6 @@ flush_xroute(struct xroute *xroute)
}
}
int
add_xroute
(
unsigned
char
prefix
[
16
],
unsigned
char
plen
,
unsigned
char
src_prefix
[
16
],
unsigned
char
src_plen
,
unsigned
short
metric
,
unsigned
int
ifindex
,
int
proto
)
{
struct
xroute
*
xroute
=
find_xroute
(
prefix
,
plen
,
src_prefix
,
src_plen
);
if
(
xroute
)
{
if
(
xroute
->
metric
<=
metric
)
return
0
;
xroute
->
metric
=
metric
;
local_notify_xroute
(
xroute
,
LOCAL_CHANGE
);
return
1
;
}
if
(
numxroutes
>=
maxxroutes
)
{
struct
xroute
*
new_xroutes
;
int
n
=
maxxroutes
<
1
?
8
:
2
*
maxxroutes
;
new_xroutes
=
realloc
(
xroutes
,
n
*
sizeof
(
struct
xroute
));
if
(
new_xroutes
==
NULL
)
return
-
1
;
maxxroutes
=
n
;
xroutes
=
new_xroutes
;
}
memcpy
(
xroutes
[
numxroutes
].
prefix
,
prefix
,
16
);
xroutes
[
numxroutes
].
plen
=
plen
;
memcpy
(
xroutes
[
numxroutes
].
src_prefix
,
src_prefix
,
16
);
xroutes
[
numxroutes
].
src_plen
=
src_plen
;
xroutes
[
numxroutes
].
metric
=
metric
;
xroutes
[
numxroutes
].
ifindex
=
ifindex
;
xroutes
[
numxroutes
].
proto
=
proto
;
numxroutes
++
;
local_notify_xroute
(
&
xroutes
[
numxroutes
-
1
],
LOCAL_ADD
);
return
1
;
}
/* Returns an overestimate of the number of xroutes. */
int
xroutes_estimate
()
...
...
@@ -244,15 +304,44 @@ kernel_addresses(int ifindex, int ll, struct kernel_route *routes,
return
found
;
}
/* This must coincide with the ordering defined by xroute_compare above. */
static
int
kernel_route_compare
(
const
void
*
v1
,
const
void
*
v2
)
{
const
struct
kernel_route
*
route1
=
(
struct
kernel_route
*
)
v1
;
const
struct
kernel_route
*
route2
=
(
struct
kernel_route
*
)
v2
;
int
rc
;
if
(
route1
->
plen
<
route2
->
plen
)
return
-
1
;
if
(
route1
->
plen
>
route2
->
plen
)
return
1
;
rc
=
memcmp
(
route1
->
prefix
,
route2
->
prefix
,
16
);
if
(
rc
!=
0
)
return
rc
;
if
(
route1
->
src_plen
<
route2
->
src_plen
)
return
-
1
;
if
(
route1
->
src_plen
>
route2
->
src_plen
)
return
1
;
rc
=
memcmp
(
route1
->
src_prefix
,
route2
->
src_prefix
,
16
);
if
(
rc
!=
0
)
return
rc
;
return
0
;
}
int
check_xroutes
(
int
send_updates
)
{
int
i
,
j
,
metric
,
export
,
change
=
0
,
rc
;
int
i
,
j
,
change
=
0
,
rc
;
struct
kernel_route
*
routes
;
struct
filter_result
filter_result
;
int
numroutes
,
numaddresses
;
int
numroutes
;
static
int
maxroutes
=
8
;
const
int
maxmaxroutes
=
1
6
*
1024
;
const
int
maxmaxroutes
=
25
6
*
1024
;
debugf
(
"
\n
Checking kernel routes.
\n
"
);
...
...
@@ -272,8 +361,6 @@ check_xroutes(int send_updates)
if
(
numroutes
>=
maxroutes
)
goto
resize
;
numaddresses
=
numroutes
;
rc
=
kernel_routes
(
routes
+
numroutes
,
maxroutes
-
numroutes
);
if
(
rc
<
0
)
fprintf
(
stderr
,
"Couldn't get kernel routes.
\n
"
);
...
...
@@ -283,42 +370,65 @@ check_xroutes(int send_updates)
if
(
numroutes
>=
maxroutes
)
goto
resize
;
/* Apply filter to kernel routes (e.g. change the source prefix). */
for
(
i
=
numaddresses
;
i
<
numroutes
;
i
++
)
{
redistribute_filter
(
routes
[
i
].
prefix
,
routes
[
i
].
plen
,
routes
[
i
].
src_prefix
,
routes
[
i
].
src_plen
,
routes
[
i
].
ifindex
,
routes
[
i
].
proto
,
&
filter_result
);
if
(
filter_result
.
src_prefix
)
{
for
(
i
=
0
;
i
<
numroutes
;
i
++
)
{
routes
[
i
].
metric
=
redistribute_filter
(
routes
[
i
].
prefix
,
routes
[
i
].
plen
,
routes
[
i
].
src_prefix
,
routes
[
i
].
src_
plen
,
routes
[
i
].
ifindex
,
routes
[
i
].
proto
,
&
filter_result
);
if
(
filter_result
.
src_prefix
!=
NULL
)
{
memcpy
(
routes
[
i
].
src_prefix
,
filter_result
.
src_prefix
,
16
);
routes
[
i
].
src_plen
=
filter_result
.
src_plen
;
}
}
/* Check for any routes that need to be flushed */
qsort
(
routes
,
numroutes
,
sizeof
(
struct
kernel_route
),
kernel_route_compare
);
i
=
0
;
while
(
i
<
numxroutes
)
{
export
=
0
;
metric
=
redistribute_filter
(
xroutes
[
i
].
prefix
,
xroutes
[
i
].
plen
,
xroutes
[
i
].
src_prefix
,
xroutes
[
i
].
src_plen
,
xroutes
[
i
].
ifindex
,
xroutes
[
i
].
proto
,
NULL
);
if
(
metric
<
INFINITY
&&
metric
==
xroutes
[
i
].
metric
)
{
for
(
j
=
0
;
j
<
numroutes
;
j
++
)
{
if
(
xroutes
[
i
].
plen
==
routes
[
j
].
plen
&&
memcmp
(
xroutes
[
i
].
prefix
,
routes
[
j
].
prefix
,
16
)
==
0
&&
xroutes
[
i
].
ifindex
==
routes
[
j
].
ifindex
&&
xroutes
[
i
].
proto
==
routes
[
j
].
proto
)
{
export
=
1
;
break
;
}
}
j
=
0
;
while
(
i
<
numroutes
||
j
<
numxroutes
)
{
/* Ignore routes filtered out. */
if
(
i
<
numroutes
&&
routes
[
i
].
metric
>=
INFINITY
)
{
i
++
;
continue
;
}
if
(
!
export
)
{
if
(
i
>=
numroutes
)
rc
=
+
1
;
else
if
(
j
>=
numxroutes
)
rc
=
-
1
;
else
rc
=
xroute_compare
(
routes
[
i
].
prefix
,
routes
[
i
].
plen
,
routes
[
i
].
src_prefix
,
routes
[
i
].
src_plen
,
&
xroutes
[
j
]);
if
(
rc
<
0
)
{
/* Add route i. */
if
(
!
martian_prefix
(
routes
[
i
].
prefix
,
routes
[
i
].
plen
)
&&
routes
[
i
].
metric
<
INFINITY
)
{
rc
=
add_xroute
(
routes
[
i
].
prefix
,
routes
[
i
].
plen
,
routes
[
i
].
src_prefix
,
routes
[
i
].
src_plen
,
routes
[
i
].
metric
,
routes
[
i
].
ifindex
,
routes
[
i
].
proto
);
if
(
rc
>
0
)
{
struct
babel_route
*
route
;
route
=
find_installed_route
(
routes
[
i
].
prefix
,
routes
[
i
].
plen
,
routes
[
i
].
src_prefix
,
routes
[
i
].
src_plen
);
if
(
route
)
{
if
(
allow_duplicates
<
0
||
routes
[
i
].
metric
<
allow_duplicates
)
uninstall_route
(
route
);
}
if
(
send_updates
)
send_update
(
NULL
,
0
,
routes
[
i
].
prefix
,
routes
[
i
].
plen
,
routes
[
i
].
src_prefix
,
routes
[
i
].
src_plen
);
j
++
;
}
}
i
++
;
}
else
if
(
rc
>
0
)
{
/* Flush xroute j. */
unsigned
char
prefix
[
16
],
plen
;
unsigned
char
src_prefix
[
16
],
src_plen
;
struct
babel_route
*
route
;
...
...
@@ -326,47 +436,27 @@ check_xroutes(int send_updates)
plen
=
xroutes
[
i
].
plen
;
memcpy
(
src_prefix
,
xroutes
[
i
].
src_prefix
,
16
);
src_plen
=
xroutes
[
i
].
src_plen
;
flush_xroute
(
&
xroutes
[
i
]);
route
=
find_best_route
(
prefix
,
plen
,
src_prefix
,
src_plen
,
1
,
NULL
);
if
(
route
)
flush_xroute
(
&
xroutes
[
j
]);
route
=
find_best_route
(
prefix
,
plen
,
src_prefix
,
src_plen
,
1
,
NULL
);
if
(
route
!=
NULL
)
{
install_route
(
route
);
/* send_update_resend only records the prefix, so the update
will only be sent after we perform all of the changes. */
if
(
send_updates
)
send_update
(
NULL
,
0
,
prefix
,
plen
,
src_prefix
,
src_plen
);
}
else
{
send_update_resend
(
NULL
,
prefix
,
plen
,
src_prefix
,
src_plen
);
change
=
1
;
}
}
else
{
i
++
;
}
}
/* Add any new routes */
for
(
i
=
0
;
i
<
numroutes
;
i
++
)
{
if
(
martian_prefix
(
routes
[
i
].
prefix
,
routes
[
i
].
plen
))
continue
;
metric
=
redistribute_filter
(
routes
[
i
].
prefix
,
routes
[
i
].
plen
,
routes
[
i
].
src_prefix
,
routes
[
i
].
src_plen
,
routes
[
i
].
ifindex
,
routes
[
i
].
proto
,
NULL
);
if
(
metric
<
INFINITY
)
{
rc
=
add_xroute
(
routes
[
i
].
prefix
,
routes
[
i
].
plen
,
routes
[
i
].
src_prefix
,
routes
[
i
].
src_plen
,
metric
,
routes
[
i
].
ifindex
,
routes
[
i
].
proto
);
if
(
rc
>
0
)
{
struct
babel_route
*
route
;
route
=
find_installed_route
(
routes
[
i
].
prefix
,
routes
[
i
].
plen
,
routes
[
i
].
src_prefix
,
routes
[
i
].
src_plen
);
if
(
route
)
{
if
(
allow_duplicates
<
0
||
routes
[
i
].
metric
<
allow_duplicates
)
uninstall_route
(
route
);
}
change
=
1
;
if
(
routes
[
i
].
metric
!=
xroutes
[
j
].
metric
||
routes
[
i
].
proto
!=
xroutes
[
j
].
proto
)
{
xroutes
[
j
].
metric
=
routes
[
i
].
metric
;
xroutes
[
j
].
proto
=
routes
[
i
].
proto
;
local_notify_xroute
(
&
xroutes
[
j
],
LOCAL_CHANGE
);
if
(
send_updates
)
send_update
(
NULL
,
0
,
routes
[
i
].
prefix
,
routes
[
i
].
plen
,
routes
[
i
].
src_prefix
,
routes
[
i
].
src_plen
);
send_update
(
NULL
,
0
,
xroutes
[
j
].
prefix
,
xroutes
[
j
].
plen
,
xroutes
[
j
].
src_prefix
,
xroutes
[
j
].
src_plen
);
}
i
++
;
j
++
;
}
}
...
...
xroute.h
View file @
5afde873
...
...
@@ -34,10 +34,10 @@ struct xroute_stream;
struct
xroute
*
find_xroute
(
const
unsigned
char
*
prefix
,
unsigned
char
plen
,
const
unsigned
char
*
src_prefix
,
unsigned
char
src_plen
);
void
flush_xroute
(
struct
xroute
*
xroute
);
int
add_xroute
(
unsigned
char
prefix
[
16
],
unsigned
char
plen
,
unsigned
char
src_prefix
[
16
],
unsigned
char
src_plen
,
unsigned
short
metric
,
unsigned
int
ifindex
,
int
proto
);
void
flush_xroute
(
struct
xroute
*
xroute
);
int
xroutes_estimate
(
void
);
struct
xroute_stream
*
xroute_stream
();
struct
xroute
*
xroute_stream_next
(
struct
xroute_stream
*
stream
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment