[-]
[+]
|
Changed |
bird.changes
|
|
[-]
[+]
|
Changed |
bird.spec
^
|
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/ChangeLog
^
|
@@ -1,3 +1,139 @@
+commit 7c00551749005ad951845eb924f76e1fd28e62a2
+Author: Ondrej Filip <feela@network.cz>
+Date: Wed Jul 9 23:46:02 2014 +0200
+
+ Version 1.4.4.
+
+commit 06c4b6ac9da204453049fa56a204474486a9c9e9
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Wed Jul 9 18:42:59 2014 +0200
+
+ NEWS and version update.
+
+commit 029ec22d0acedb79e03394b60ea99bb46c479d79
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Wed Jul 9 18:34:42 2014 +0200
+
+ Fixes a bug in BSD kernel interfacing code.
+
+ The bug was introduced in 05476c4d04a24bdb26fa64e05ab31bc36118f34e.
+
+commit 751482899c190194b4958bc54ded428f98f565e9
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Jul 7 22:56:21 2014 +0200
+
+ Implements default router preference (RFC 4191) for RAdv.
+
+ Thanks to Baptiste Jonglez for the patch.
+
+commit 6285793f18817091060c7257f7d4af0db010a67a
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Jul 7 22:23:37 2014 +0200
+
+ Replaces function name in test.conf as it collided with new keyword.
+
+commit 20e8d040b09f1e01c431c686f1ced5a12ba7bc68
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Jun 30 11:55:22 2014 +0200
+
+ Fixes integer overflow in show memory command.
+
+ Thanks to Job Snijders for the bugreport.
+
+commit 8945f73d946a9323daf8dfc1bf5b3884cf6d7664
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Thu Jun 26 13:30:27 2014 +0200
+
+ Ensures that msg_controllen includes last padding.
+
+ Although RFC 3542 allows both cases, Theo de Raadt thinks
+ he knows better, and msg_controllen without last padding
+ fails on OpenBSD.
+
+ Thanks to Job Snijders for the bugreport.
+
+commit 9d5960cfa5b4c15ddd48dbab599f864a6aa1e025
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Tue Jun 10 12:16:01 2014 +0200
+
+ Fixes max include depth in documentation.
+
+ Thanks to Artyom Gavrichenkov for the patch.
+
+commit 9eceab33f97724be148f9f05614d7551940e85f1
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Thu May 29 23:05:03 2014 +0200
+
+ String constants could be used for string option values.
+
+ Thanks to Frederik Kriewitz for the patch.
+
+commit 05476c4d04a24bdb26fa64e05ab31bc36118f34e
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun May 18 11:42:26 2014 +0200
+
+ IPv4/IPv6 integrated socket code.
+
+commit 1149aa977d906a6400f998d5f6600871584395d0
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon May 5 11:05:12 2014 +0200
+
+ Fixes a problem with undoing of deconfiguring of protocol.
+
+ Thanks to Sergey Popovich for the original patch.
+
+commit 5a3905fe905ab1cc1a58fe9e6a4284f7d5057d13
+Merge: 66370ea 7d9ab86
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun May 4 11:59:50 2014 +0200
+
+ Merge commit 'origin/master'
+
+commit 66370eac1f88ec74b3017f1c39038d7b8b776de6
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun May 4 00:01:06 2014 +0200
+
+ Fixes BGP crash when update with some attributes and empty NLRI is received.
+
+ Thanks to Charlie Allom for the bugreport.
+
+commit 7d9ab86b7ac7d1f039af92a58eb749a24811b5c9
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun May 4 00:01:06 2014 +0200
+
+ Fixes BGP crash when update with some attributes and empty NLRI is received.
+
+commit c865cae3eb327d1e0a745352c483bc7cb00f9323
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Apr 28 17:31:03 2014 +0200
+
+ Fixes 'show route export' w.r.t. protocols with different RA_* types.
+
+commit 984d734944a39b70a59f74e57f0e6fc3f720dd48
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Sun Apr 27 00:46:32 2014 +0200
+
+ Fixes limit verification during reconfiguration.
+
+commit 145368f5474436ad7c48fa26f5bde8108ae5ef4a
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Wed Apr 23 13:54:28 2014 +0200
+
+ Extends multipath support for OSPF.
+
+ Fixes cases where the same network or external route are propagated by
+ several OSPF routes and some other corner cases in next hop construction
+ and ECMP. Allows to specify whether external routes should be merged.
+
+ Thanks to Peter Christensen for the original patch.
+
+commit 4dd24f05f384ac14546d4bebbfcb0ecf9a976ec6
+Merge: 1cb0f83 6c6ebd6
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Wed Apr 23 13:52:15 2014 +0200
+
+ Merge commit 'origin/master'
+
commit 6c6ebd64c3e44a2658a7ae8729159f1653c00a89
Author: Ondrej Zajicek <santiago@crfreenet.org>
Date: Mon Apr 14 14:47:20 2014 +0200
@@ -23,6 +159,12 @@
Thanks to Peter Andreev for reporting it and Alexander V. Chernikov for
resolving it.
+commit 1cb0f83d291d9bb3da06067bc2ea838238d5c487
+Author: Ondrej Zajicek <santiago@crfreenet.org>
+Date: Mon Apr 7 11:48:25 2014 +0200
+
+ Fixes some asserts.
+
commit 538fec7b1b7dd729eadf1c933e27f59080cd3576
Author: Ondrej Zajicek <santiago@crfreenet.org>
Date: Wed Apr 2 23:00:10 2014 +0200
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/NEWS
^
|
@@ -1,3 +1,10 @@
+Version 1.4.4 (2014-07-09)
+ o Extended OSPF multipath support.
+ o Default router preference for RAdv.
+ o Significant changes in socket layer.
+ o Important bugfix in BGP.
+ o Several minor bugfixes.
+
Version 1.4.3 (2014-04-14)
o Important bugfix in IPv6 BGP.
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/client/birdc.c
^
|
@@ -19,7 +19,6 @@
#include "lib/resource.h"
#include "lib/string.h"
#include "client/client.h"
-#include "sysdep/unix/unix.h"
static int input_hidden_end;
static int prompt_active;
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/conf/confbase.Y
^
|
@@ -77,6 +77,7 @@
%type <time> datetime
%type <a> ipa
%type <px> prefix prefix_or_ipa
+%type <t> text
%type <t> text_or_none
%nonassoc PREFIX_DUMMY
@@ -191,6 +192,14 @@
}
;
+text:
+ TEXT
+ | SYM {
+ if ($1->class != (SYM_CONSTANT | T_STRING)) cf_error("String expected");
+ $$ = SYM_VAL($1).s;
+ }
+ ;
+
text_or_none:
TEXT { $$ = $1; }
| { $$ = NULL; }
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/doc/bird-3.html
^
|
@@ -66,7 +66,7 @@
<P>
<DL>
<DT><CODE>include "<I>filename</I>"</CODE><DD><P>This statement causes inclusion of a new file. <I>Filename</I> could also
-be a wildcard. The maximal depth is 5. Note that this statement could be
+be a wildcard. The maximal depth is 8. Note that this statement could be
used anywhere in the config file, not just as a top-level option.
<P>
<DT><CODE>
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/doc/bird-6.html
^
|
@@ -932,6 +932,7 @@
stub router <switch>;
tick <num>;
ecmp <switch> [limit <num>];
+ merge external <switch>;
area <id> {
stub;
nssa;
@@ -1036,6 +1037,13 @@
nexthops in one route. By default, ECMP is disabled. If enabled,
default value of the limit is 16.
<P>
+<DT><CODE>merge external <I>switch</I></CODE><DD><P>This option specifies whether OSPF should merge external routes from
+different routers/LSAs for the same destination. When enabled together
+with <CODE>ecmp</CODE>, equal-cost external routes will be combined to multipath
+routes in the same way as regular routes. When disabled, external routes
+from different LSAs are treated as separate even if they represents the
+same destination. Default value is no.
+<P>
<DT><CODE>area <I>id</I></CODE><DD><P>This defines an OSPF area with given area ID (an integer or an IPv4
address, similarly to a router ID). The most important area is the
backbone (ID 0) to which every other area must be connected.
@@ -1595,6 +1603,9 @@
<A HREF="#dsc-trigger">trigger</A>.
Default: 3 * <CODE>max ra interval</CODE>, <CODE>sensitive</CODE> yes.
<P>
+<DT><CODE>default preference low|medium|high</CODE><DD><P>This option specifies the Default Router Preference value to advertise
+to hosts. Default: medium.
+<P>
<DT><CODE>rdnss local <I>switch</I></CODE><DD><P>Use only local (interface-specific) RDNSS definitions for this
interface. Otherwise, both global and local definitions are used. Could
also be used to disable RDNSS for given interface if no local definitons
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/doc/bird.sgml
^
|
@@ -318,7 +318,7 @@
<p><descrip>
<tag>include "<m/filename/"</tag>
This statement causes inclusion of a new file. <m/Filename/ could also
- be a wildcard. The maximal depth is 5. Note that this statement could be
+ be a wildcard. The maximal depth is 8. Note that this statement could be
used anywhere in the config file, not just as a top-level option.
<tag><label id="dsc-log">log "<m/filename/"|syslog [name <m/name/]|stderr all|{ <m/list of classes/ }</tag>
@@ -2291,6 +2291,7 @@
stub router <switch>;
tick <num>;
ecmp <switch> [limit <num>];
+ merge external <switch>;
area <id> {
stub;
nssa;
@@ -2396,6 +2397,14 @@
nexthops in one route. By default, ECMP is disabled. If enabled,
default value of the limit is 16.
+ <tag>merge external <M>switch</M></tag>
+ This option specifies whether OSPF should merge external routes from
+ different routers/LSAs for the same destination. When enabled together
+ with <cf/ecmp/, equal-cost external routes will be combined to multipath
+ routes in the same way as regular routes. When disabled, external routes
+ from different LSAs are treated as separate even if they represents the
+ same destination. Default value is no.
+
<tag>area <M>id</M></tag>
This defines an OSPF area with given area ID (an integer or an IPv4
address, similarly to a router ID). The most important area is the
@@ -3004,6 +3013,10 @@
as a default router. For <cf/sensitive/ option, see <ref id="dsc-trigger" name="trigger">.
Default: 3 * <cf/max ra interval/, <cf/sensitive/ yes.
+ <tag>default preference low|medium|high</tag>
+ This option specifies the Default Router Preference value to advertise
+ to hosts. Default: medium.
+
<tag>rdnss local <m/switch/</tag>
Use only local (interface-specific) RDNSS definitions for this
interface. Otherwise, both global and local definitions are used. Could
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/doc/prog-5.html
^
|
@@ -1033,6 +1033,7 @@
<P>Supported standards:
- RFC 4861 - main RA standard
- RFC 6106 - DNS extensions (RDDNS, DNSSL)
+- RFC 4191 (partial) - Default Router Preference
<P>
<P>
<H2><A NAME="ss5.7">5.7</A> <A HREF="prog.html#toc5.7">Static</A>
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/doc/prog-8.html
^
|
@@ -638,27 +638,80 @@
<P>Freeing of sockets from inside socket hooks is perfectly safe.
<P>
<P><HR><H3>Function</H3>
-<P><I>sock *</I>
-<B>sock_new</B>
-(<I>pool *</I> <B>p</B>) -- create a socket
+<P><I>int</I>
+<B>sk_setup_multicast</B>
+(<I>sock *</I> <B>s</B>) -- enable multicast for given socket
<P>
<H3>Arguments</H3>
<P>
<DL>
-<DT><I>pool *</I> <B>p</B><DD><P>pool
+<DT><I>sock *</I> <B>s</B><DD><P>socket
</DL>
<H3>Description</H3>
-<P>This function creates a new socket resource. If you want to use it,
-you need to fill in all the required fields of the structure and
-call <B>sk_open()</B> to do the actual opening of the socket.
-<P>The real function name is <B>sock_new()</B>, <B>sk_new()</B> is a macro wrapper
-to avoid collision with OpenSSL.
+<P>Prepare transmission of multicast packets for given datagram socket.
+The socket must have defined <B>iface</B>.
+<H3>Result</H3>
+<P>0 for success, -1 for an error.
+
+
+<HR><H3>Function</H3>
+<P><I>int</I>
+<B>sk_join_group</B>
+(<I>sock *</I> <B>s</B>, <I>ip_addr</I> <B>maddr</B>) -- join multicast group for given socket
+<P>
+<H3>Arguments</H3>
+<P>
+<DL>
+<DT><I>sock *</I> <B>s</B><DD><P>socket
+<DT><I>ip_addr</I> <B>maddr</B><DD><P>multicast address
+</DL>
+<H3>Description</H3>
+<P>Join multicast group for given datagram socket and associated interface.
+The socket must have defined <B>iface</B>.
+<H3>Result</H3>
+<P>0 for success, -1 for an error.
+
+
+<HR><H3>Function</H3>
+<P><I>int</I>
+<B>sk_leave_group</B>
+(<I>sock *</I> <B>s</B>, <I>ip_addr</I> <B>maddr</B>) -- leave multicast group for given socket
+<P>
+<H3>Arguments</H3>
+<P>
+<DL>
+<DT><I>sock *</I> <B>s</B><DD><P>socket
+<DT><I>ip_addr</I> <B>maddr</B><DD><P>multicast address
+</DL>
+<H3>Description</H3>
+<P>Leave multicast group for given datagram socket and associated interface.
+The socket must have defined <B>iface</B>.
+<H3>Result</H3>
+<P>0 for success, -1 for an error.
+
+
+<HR><H3>Function</H3>
+<P><I>int</I>
+<B>sk_setup_broadcast</B>
+(<I>sock *</I> <B>s</B>) -- enable broadcast for given socket
+<P>
+<H3>Arguments</H3>
+<P>
+<DL>
+<DT><I>sock *</I> <B>s</B><DD><P>socket
+</DL>
+<H3>Description</H3>
+<P>Allow reception and transmission of broadcast packets for given datagram
+socket. The socket must have defined <B>iface</B>. For transmission, packets should
+be send to <B>brd</B> address of <B>iface</B>.
+<H3>Result</H3>
+<P>0 for success, -1 for an error.
<HR><H3>Function</H3>
<P><I>int</I>
<B>sk_set_ttl</B>
-(<I>sock *</I> <B>s</B>, <I>int</I> <B>ttl</B>) -- set transmit TTL for given socket.
+(<I>sock *</I> <B>s</B>, <I>int</I> <B>ttl</B>) -- set transmit TTL for given socket
<P>
<H3>Arguments</H3>
<P>
@@ -667,9 +720,8 @@
<DT><I>int</I> <B>ttl</B><DD><P>TTL value
</DL>
<H3>Description</H3>
-<P>Set TTL for already opened connections when TTL was not set before.
-Useful for accepted connections when different ones should have
-different TTL.
+<P>Set TTL for already opened connections when TTL was not set before. Useful
+for accepted connections when different ones should have different TTL.
<H3>Result</H3>
<P>0 for success, -1 for an error.
@@ -677,7 +729,7 @@
<HR><H3>Function</H3>
<P><I>int</I>
<B>sk_set_min_ttl</B>
-(<I>sock *</I> <B>s</B>, <I>int</I> <B>ttl</B>) -- set minimal accepted TTL for given socket.
+(<I>sock *</I> <B>s</B>, <I>int</I> <B>ttl</B>) -- set minimal accepted TTL for given socket
<P>
<H3>Arguments</H3>
<P>
@@ -686,7 +738,8 @@
<DT><I>int</I> <B>ttl</B><DD><P>TTL value
</DL>
<H3>Description</H3>
-<P>Can be used in TTL security implementation
+<P>Set minimal accepted TTL for given socket. Can be used for TTL security.
+implementations.
<H3>Result</H3>
<P>0 for success, -1 for an error.
@@ -694,7 +747,7 @@
<HR><H3>Function</H3>
<P><I>int</I>
<B>sk_set_md5_auth</B>
-(<I>sock *</I> <B>s</B>, <I>ip_addr</I> <B>a</B>, <I>struct iface *</I> <B>ifa</B>, <I>char *</I> <B>passwd</B>) -- add / remove MD5 security association for given socket.
+(<I>sock *</I> <B>s</B>, <I>ip_addr</I> <B>a</B>, <I>struct iface *</I> <B>ifa</B>, <I>char *</I> <B>passwd</B>) -- add / remove MD5 security association for given socket
<P>
<H3>Arguments</H3>
<P>
@@ -705,11 +758,10 @@
<DT><I>char *</I> <B>passwd</B><DD><P>password used for MD5 authentication
</DL>
<H3>Description</H3>
-<P>In TCP MD5 handling code in kernel, there is a set of pairs
-(address, password) used to choose password according to
-address of the other side. This function is useful for
-listening socket, for active sockets it is enough to set
-s->password field.
+<P>In TCP MD5 handling code in kernel, there is a set of pairs (address,
+password) used to choose password according to address of the other side.
+This function is useful for listening socket, for active sockets it is enough
+to set s->password field.
<P>When called with passwd != NULL, the new pair is added,
When called with passwd == NULL, the existing pair is removed.
<H3>Result</H3>
@@ -717,6 +769,44 @@
<HR><H3>Function</H3>
+<P><I>int</I>
+<B>sk_set_ipv6_checksum</B>
+(<I>sock *</I> <B>s</B>, <I>int</I> <B>offset</B>) -- specify IPv6 checksum offset for given socket
+<P>
+<H3>Arguments</H3>
+<P>
+<DL>
+<DT><I>sock *</I> <B>s</B><DD><P>socket
+<DT><I>int</I> <B>offset</B><DD><P>offset
+</DL>
+<H3>Description</H3>
+<P>Specify IPv6 checksum field offset for given raw IPv6 socket. After that, the
+kernel will automatically fill it for outgoing packets and check it for
+incoming packets. Should not be used on ICMPv6 sockets, where the position is
+known to the kernel.
+<H3>Result</H3>
+<P>0 for success, -1 for an error.
+
+
+<HR><H3>Function</H3>
+<P><I>sock *</I>
+<B>sock_new</B>
+(<I>pool *</I> <B>p</B>) -- create a socket
+<P>
+<H3>Arguments</H3>
+<P>
+<DL>
+<DT><I>pool *</I> <B>p</B><DD><P>pool
+</DL>
+<H3>Description</H3>
+<P>This function creates a new socket resource. If you want to use it,
+you need to fill in all the required fields of the structure and
+call <B>sk_open()</B> to do the actual opening of the socket.
+<P>The real function name is <B>sock_new()</B>, <B>sk_new()</B> is a macro wrapper
+to avoid collision with OpenSSL.
+
+
+<HR><H3>Function</H3>
<P><I>int</I>
<B>sk_open</B>
(<I>sock *</I> <B>s</B>) -- open a socket
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/filter/test.conf
^
|
@@ -78,7 +78,7 @@
" ", roa_check(rl, 10.130.130.0/24, 3000) = ROA_VALID;
}
-function paths()
+function path_test()
bgpmask pm1;
bgpmask pm2;
bgppath p2;
@@ -389,7 +389,7 @@
i = fifteen();
print "Testing function calls: 15 = ", i;
- paths();
+ path_test();
print "1.2.3.4 = ", onetwo;
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/lib/printf.c
^
|
@@ -221,6 +221,16 @@
continue;
case 'm':
+ if (flags & SPECIAL) {
+ if (!errno)
+ continue;
+ if (size < 2)
+ return -1;
+ *str++ = ':';
+ *str++ = ' ';
+ start += 2;
+ size -= 2;
+ }
s = strerror(errno);
goto str;
case 'M':
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/lib/slab.c
^
|
@@ -123,7 +123,7 @@
slab_memsize(resource *r)
{
slab *s = (slab *) r;
- int cnt = 0;
+ size_t cnt = 0;
struct sl_obj *o;
WALK_LIST(o, s->objs)
@@ -346,7 +346,7 @@
slab_memsize(resource *r)
{
slab *s = (slab *) r;
- int heads = 0;
+ size_t heads = 0;
struct sl_head *h;
WALK_LIST(h, s->empty_heads)
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/lib/socket.h
^
|
@@ -10,6 +10,7 @@
#define _BIRD_SOCKET_H_
#include <errno.h>
+// #include <sys/socket.h>
#include "lib/resource.h"
@@ -43,17 +44,21 @@
unsigned lifindex; /* local interface that received the datagram */
/* laddr and lifindex are valid only if SKF_LADDR_RX flag is set to request it */
+ int af; /* Address family (AF_INET, AF_INET6 or 0 for non-IP) of fd */
int fd; /* System-dependent data */
int index; /* Index in poll buffer */
+ int rcv_ttl; /* TTL of last received datagram */
node n;
void *rbuf_alloc, *tbuf_alloc;
- char *password; /* Password for MD5 authentication */
+ char *password; /* Password for MD5 authentication */
+ char *err; /* Error message */
} sock;
sock *sock_new(pool *); /* Allocate new socket */
#define sk_new(X) sock_new(X) /* Wrapper to avoid name collision with OpenSSL */
int sk_open(sock *); /* Open socket */
+int sk_rx_ready(sock *s);
int sk_send(sock *, unsigned len); /* Send data, <0=err, >0=ok, 0=sleep */
int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */
void sk_reallocate(sock *); /* Free and allocate tbuf & rbuf */
@@ -61,39 +66,41 @@
void sk_set_tbsize(sock *s, uint val); /* Resize TX buffer, keeping content */
void sk_set_tbuf(sock *s, void *tbuf); /* Switch TX buffer, NULL-> return to internal */
void sk_dump_all(void);
-int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
-int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
-/* Add or remove security associations for given passive socket */
-int sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd);
-int sk_rx_ready(sock *s);
+static inline int sk_send_buffer_empty(sock *sk)
+{ return sk->tbuf == sk->tpos; }
-/* Prepare UDP or IP socket to multicasting. s->iface and s->ttl must be set */
-int sk_setup_multicast(sock *s);
-int sk_join_group(sock *s, ip_addr maddr);
-int sk_leave_group(sock *s, ip_addr maddr);
#ifdef IPV6
-int sk_set_ipv6_checksum(sock *s, int offset);
-int sk_set_icmp_filter(sock *s, int p1, int p2);
+#define sk_is_ipv4(X) 0
+#define sk_is_ipv6(X) 1
+#else
+#define sk_is_ipv4(X) 1
+#define sk_is_ipv6(X) 0
#endif
-int sk_set_broadcast(sock *s, int enable);
-static inline int
-sk_send_buffer_empty(sock *sk)
-{
- return sk->tbuf == sk->tpos;
-}
+int sk_setup_multicast(sock *s); /* Prepare UDP or IP socket for multicasting */
+int sk_join_group(sock *s, ip_addr maddr); /* Join multicast group on sk iface */
+int sk_leave_group(sock *s, ip_addr maddr); /* Leave multicast group on sk iface */
+int sk_setup_broadcast(sock *s);
+int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
+int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
+int sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd);
+int sk_set_ipv6_checksum(sock *s, int offset);
+int sk_set_icmp6_filter(sock *s, int p1, int p2);
+void sk_log_error(sock *s, const char *p);
+
+extern int sk_priority_control; /* Suggested priority for control traffic, should be sysdep define */
-extern int sk_priority_control; /* Suggested priority for control traffic, should be sysdep define */
/* Socket flags */
-#define SKF_V6ONLY 1 /* Use IPV6_V6ONLY socket option */
-#define SKF_LADDR_RX 2 /* Report local address for RX packets */
-#define SKF_TTL_RX 4 /* Report TTL / Hop Limit for RX packets */
-#define SKF_BIND 8 /* Bind datagram socket to given source address */
+#define SKF_V4ONLY 0x01 /* Use IPv4 for IP sockets */
+#define SKF_V6ONLY 0x02 /* Use IPV6_V6ONLY socket option */
+#define SKF_LADDR_RX 0x04 /* Report local address for RX packets */
+#define SKF_TTL_RX 0x08 /* Report TTL / Hop Limit for RX packets */
+#define SKF_BIND 0x10 /* Bind datagram socket to given source address */
#define SKF_THREAD 0x100 /* Socked used in thread, Do not add to main loop */
#define SKF_TRUNCATED 0x200 /* Received packet was truncated, set by IO layer */
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/nest/config.Y
^
|
@@ -208,7 +208,7 @@
| IMPORT KEEP FILTERED bool { this_proto->in_keep_filtered = $4; }
| TABLE rtable { this_proto->table = $2; }
| ROUTER ID idval { this_proto->router_id = $3; }
- | DESCRIPTION TEXT { this_proto->dsc = $2; }
+ | DESCRIPTION text { this_proto->dsc = $2; }
;
imexport:
@@ -388,7 +388,7 @@
;
password_item_begin:
- PASSWORD TEXT {
+ PASSWORD text {
if (!this_p_list) {
this_p_list = cfg_alloc(sizeof(list));
init_list(this_p_list);
@@ -498,7 +498,6 @@
if ($$->export_mode) cf_error("Protocol specified twice");
if ($3->class != SYM_PROTO || !c->proto) cf_error("%s is not a protocol", $3->name);
$$->export_mode = $2;
- $$->primary_only = 1;
$$->export_protocol = c->proto;
$$->running_on_config = c->proto->cf->global;
}
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/nest/proto.c
^
|
@@ -403,7 +403,6 @@
static int
proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config *nc, int type)
{
- struct announce_hook *ah = p->main_ahook;
/* If the protocol is DOWN, we just restart it */
if (p->proto_state == PS_DOWN)
return 0;
@@ -435,31 +434,16 @@
/* Update filters and limits in the main announce hook
Note that this also resets limit state */
- if (ah)
- {
+ if (p->main_ahook)
+ {
+ struct announce_hook *ah = p->main_ahook;
ah->in_filter = nc->in_filter;
ah->out_filter = nc->out_filter;
ah->rx_limit = nc->rx_limit;
ah->in_limit = nc->in_limit;
ah->out_limit = nc->out_limit;
ah->in_keep_filtered = nc->in_keep_filtered;
-
- if (p->proto_state == PS_UP) /* Recheck export/import/receive limit */
- {
- struct proto_stats *stats = ah->stats;
- struct proto_limit *l = ah->in_limit;
- u32 all_routes = stats->imp_routes + stats->filt_routes;
-
- if (l && (stats->imp_routes >= l->limit)) proto_notify_limit(ah, l, PLD_IN, stats->imp_routes);
-
- l = ah->rx_limit;
-
- if (l && ( all_routes >= l->limit)) proto_notify_limit(ah, l, PLD_RX, all_routes );
-
- l = ah->out_limit;
-
- if (l && ( stats->exp_routes >= l->limit)) proto_notify_limit(ah, l, PLD_OUT, stats->exp_routes);
- }
+ proto_verify_limits(ah);
}
/* Update routes when filters changed. If the protocol in not UP,
@@ -621,6 +605,7 @@
{
struct proto_config *nc = p->cf_new;
DBG("%s has shut down for reconfiguration\n", p->name);
+ p->cf->proto = NULL;
config_del_obstacle(p->cf->global);
rem_node(&p->n);
rem_node(&p->glob_node);
@@ -1198,11 +1183,32 @@
case PLA_RESTART:
case PLA_DISABLE:
l->state = PLS_BLOCKED;
- proto_schedule_down(p, l->action == PLA_RESTART, dir_down[dir]);
+ if (p->proto_state == PS_UP)
+ proto_schedule_down(p, l->action == PLA_RESTART, dir_down[dir]);
break;
}
}
+void
+proto_verify_limits(struct announce_hook *ah)
+{
+ struct proto_limit *l;
+ struct proto_stats *stats = ah->stats;
+ u32 all_routes = stats->imp_routes + stats->filt_routes;
+
+ l = ah->rx_limit;
+ if (l && (all_routes > l->limit))
+ proto_notify_limit(ah, l, PLD_RX, all_routes);
+
+ l = ah->in_limit;
+ if (l && (stats->imp_routes > l->limit))
+ proto_notify_limit(ah, l, PLD_IN, stats->imp_routes);
+
+ l = ah->out_limit;
+ if (l && (stats->exp_routes > l->limit))
+ proto_notify_limit(ah, l, PLD_OUT, stats->exp_routes);
+}
+
static void
proto_want_core_up(struct proto *p)
@@ -1235,7 +1241,7 @@
static void
proto_want_export_up(struct proto *p)
{
- ASSERT(p->core_state == CS_HAPPY);
+ ASSERT(p->core_state == FS_HAPPY);
ASSERT(p->export_state == ES_DOWN);
proto_link_ahooks(p);
@@ -1258,7 +1264,7 @@
static void
proto_want_core_down(struct proto *p)
{
- ASSERT(p->core_state == CS_HAPPY);
+ ASSERT(p->core_state == FS_HAPPY);
ASSERT(p->export_state == ES_DOWN);
p->core_state = FS_FLUSHING;
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/nest/protocol.h
^
|
@@ -423,6 +423,7 @@
};
void proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, int dir, u32 rt_count);
+void proto_verify_limits(struct announce_hook *ah);
static inline void
proto_reset_limit(struct proto_limit *l)
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/nest/rt-table.c
^
|
@@ -2246,59 +2246,82 @@
{
rte *e, *ee;
byte ia[STD_ADDRESS_P_LENGTH+8];
- struct announce_hook *a;
- int ok;
+ struct ea_list *tmpa;
+ struct announce_hook *a = NULL;
+ int first = 1;
+ int pass = 0;
bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
- for(e=n->routes; e; e=e->next)
+ if (d->export_mode)
+ {
+ a = proto_find_announce_hook(d->export_protocol, d->table);
+ if (!a)
+ return;
+ }
+
+ for (e = n->routes; e; e = e->next)
{
if (rte_is_filtered(e) != d->filtered)
continue;
- struct ea_list *tmpa;
- struct rte_src *src = e->attrs->src;
- struct proto *p1 = d->export_protocol;
- struct proto *p2 = d->show_protocol;
-
- if (ia[0])
- d->net_counter++;
d->rt_counter++;
+ d->net_counter += first;
+ first = 0;
+
+ if (pass)
+ continue;
+
ee = e;
rte_update_lock(); /* We use the update buffer for filtering */
tmpa = make_tmp_attrs(e, rte_update_pool);
- ok = f_run(d->filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) <= F_ACCEPT;
- if (p2 && p2 != src->proto) ok = 0;
- if (ok && d->export_mode)
+
+ if (d->export_mode)
{
- int ic;
- if ((ic = p1->import_control ? p1->import_control(p1, &e, &tmpa, rte_update_pool) : 0) < 0)
- ok = 0;
- else if (!ic && d->export_mode > 1)
+ struct proto *ep = d->export_protocol;
+ int ic = ep->import_control ? ep->import_control(ep, &e, &tmpa, rte_update_pool) : 0;
+
+ if (ep->accept_ra_types == RA_OPTIMAL)
+ pass = 1;
+
+ if (ic < 0)
+ goto skip;
+
+ if (d->export_mode > 1)
{
- /* FIXME - this shows what should be exported according
- to current filters, but not what was really exported.
- 'configure soft' command may change the export filter
- and do not update routes */
-
- if ((a = proto_find_announce_hook(p1, d->table)) &&
- (f_run(a->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
- ok = 0;
+ /*
+ * FIXME - This shows what should be exported according to current
+ * filters, but not what was really exported. 'configure soft'
+ * command may change the export filter and do not update routes.
+ */
+
+ if (!ic && (f_run(a->out_filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT))
+ goto skip;
+
+ if (ep->accept_ra_types == RA_ACCEPTED)
+ pass = 1;
}
}
- if (ok)
- {
- d->show_counter++;
- if (d->stats < 2)
- rt_show_rte(c, ia, e, d, tmpa);
- ia[0] = 0;
- }
+
+ if (d->show_protocol && (d->show_protocol != e->attrs->src->proto))
+ goto skip;
+
+ if (f_run(d->filter, &e, &tmpa, rte_update_pool, FF_FORCE_TMPATTR) > F_ACCEPT)
+ goto skip;
+
+ d->show_counter++;
+ if (d->stats < 2)
+ rt_show_rte(c, ia, e, d, tmpa);
+ ia[0] = 0;
+
+ skip:
if (e != ee)
{
rte_free(e);
e = ee;
}
rte_update_unlock();
+
if (d->primary_only)
break;
}
@@ -2360,10 +2383,14 @@
net *n;
/* Default is either a master table or a table related to a respective protocol */
- if ((!d->table) && d->export_protocol) d->table = d->export_protocol->table;
- if ((!d->table) && d->show_protocol) d->table = d->show_protocol->table;
+ if (!d->table && d->export_protocol) d->table = d->export_protocol->table;
+ if (!d->table && d->show_protocol) d->table = d->show_protocol->table;
if (!d->table) d->table = config->master_rtc->table;
+ /* Filtered routes are neither exported nor have sensible ordering */
+ if (d->filtered && (d->export_mode || d->primary_only))
+ cli_msg(0, "");
+
if (d->pxlen == 256)
{
FIB_ITERATE_INIT(&d->fit, &d->table->fib);
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/bfd/config.Y
^
|
@@ -99,7 +99,7 @@
bfd_neigh_iface:
/* empty */ { $$ = NULL; }
| '%' SYM { $$ = if_get_by_name($2->name); }
- | DEV TEXT { $$ = if_get_by_name($2); }
+ | DEV text { $$ = if_get_by_name($2); }
;
bfd_neigh_local:
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/bfd/packets.c
^
|
@@ -101,8 +101,8 @@
uint err_val = 0;
char fb[8];
- if ((sk->sport == BFD_CONTROL_PORT) && (sk->ttl < 255))
- DROP("wrong TTL", sk->ttl);
+ if ((sk->sport == BFD_CONTROL_PORT) && (sk->rcv_ttl < 255))
+ DROP("wrong TTL", sk->rcv_ttl);
if (len < BFD_BASE_LEN)
DROP("too short", len);
@@ -209,6 +209,7 @@
return sk;
err:
+ sk_log_error(sk, p->p.name);
rfree(sk);
return NULL;
}
@@ -243,6 +244,7 @@
return sk;
err:
+ sk_log_error(sk, p->p.name);
rfree(sk);
return NULL;
}
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/bgp/bgp.c
^
|
@@ -106,14 +106,11 @@
struct config *cfg = p->cf->c.global;
int errcode;
- bgp_counter++;
-
if (!bgp_listen_sk)
bgp_listen_sk = bgp_setup_listen_sk(cfg->listen_bgp_addr, cfg->listen_bgp_port, cfg->listen_bgp_flags);
if (!bgp_listen_sk)
{
- bgp_counter--;
errcode = BEM_NO_SOCKET;
goto err;
}
@@ -121,16 +118,16 @@
if (!bgp_linpool)
bgp_linpool = lp_new(&root_pool, 4080);
+ bgp_counter++;
+
if (p->cf->password)
- {
- int rv = sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, p->cf->password);
- if (rv < 0)
- {
- bgp_close(p, 0);
- errcode = BEM_INVALID_MD5;
- goto err;
- }
- }
+ if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, p->cf->password) < 0)
+ {
+ sk_log_error(bgp_listen_sk, p->p.name);
+ bgp_close(p, 0);
+ errcode = BEM_INVALID_MD5;
+ goto err;
+ }
return 0;
@@ -194,7 +191,8 @@
bgp_counter--;
if (p->cf->password && apply_md5)
- sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, NULL);
+ if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, NULL) < 0)
+ sk_log_error(bgp_listen_sk, p->p.name);
if (!bgp_counter)
{
@@ -697,25 +695,21 @@
bgp_conn_set_state(conn, BS_CONNECT);
if (sk_open(s) < 0)
- {
- bgp_sock_err(s, 0);
- return;
- }
+ goto err;
/* Set minimal receive TTL if needed */
if (p->cf->ttl_security)
- {
- DBG("Setting minimum received TTL to %d", 256 - hops);
if (sk_set_min_ttl(s, 256 - hops) < 0)
- {
- log(L_ERR "TTL security configuration failed, closing session");
- bgp_sock_err(s, 0);
- return;
- }
- }
+ goto err;
DBG("BGP: Waiting for connect success\n");
bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time);
+ return;
+
+ err:
+ sk_log_error(s, p->p.name);
+ bgp_sock_err(s, 0);
+ return;
}
/**
@@ -760,32 +754,33 @@
sk->dport, acc ? "accepted" : "rejected");
if (!acc)
- goto err;
+ goto reject;
int hops = p->cf->multihop ? : 1;
+
+ if (sk_set_ttl(sk, p->cf->ttl_security ? 255 : hops) < 0)
+ goto err;
+
if (p->cf->ttl_security)
- {
- /* TTL security support */
- if ((sk_set_ttl(sk, 255) < 0) ||
- (sk_set_min_ttl(sk, 256 - hops) < 0))
- {
- log(L_ERR "TTL security configuration failed, closing session");
+ if (sk_set_min_ttl(sk, 256 - hops) < 0)
goto err;
- }
- }
- else
- sk_set_ttl(sk, hops);
bgp_setup_conn(p, &p->incoming_conn);
bgp_setup_sk(&p->incoming_conn, sk);
bgp_send_open(&p->incoming_conn);
return 0;
+
+ err:
+ sk_log_error(sk, p->p.name);
+ log(L_ERR "%s: Incoming connection aborted", p->p.name);
+ rfree(sk);
+ return 0;
}
}
log(L_WARN "BGP: Unexpected connect from unknown address %I%J (port %d)",
sk->daddr, ipa_has_link_scope(sk->daddr) ? sk->iface : NULL, sk->dport);
- err:
+ reject:
rfree(sk);
return 0;
}
@@ -816,13 +811,15 @@
s->err_hook = bgp_listen_sock_err;
if (sk_open(s) < 0)
- {
- log(L_ERR "BGP: Unable to open listening socket");
- rfree(s);
- return NULL;
- }
+ goto err;
return s;
+
+ err:
+ sk_log_error(s, "BGP");
+ log(L_ERR "BGP: Cannot open listening socket");
+ rfree(s);
+ return NULL;
}
static void
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/bgp/config.Y
^
|
@@ -103,7 +103,7 @@
| bgp_proto ENABLE AS4 bool ';' { BGP_CFG->enable_as4 = $4; }
| bgp_proto CAPABILITIES bool ';' { BGP_CFG->capabilities = $3; }
| bgp_proto ADVERTISE IPV4 bool ';' { BGP_CFG->advertise_ipv4 = $4; }
- | bgp_proto PASSWORD TEXT ';' { BGP_CFG->password = $3; }
+ | bgp_proto PASSWORD text ';' { BGP_CFG->password = $3; }
| bgp_proto ROUTE LIMIT expr ';' {
this_proto->in_limit = cfg_allocz(sizeof(struct proto_limit));
this_proto->in_limit->limit = $4;
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/bgp/packets.c
^
|
@@ -1112,7 +1112,7 @@
if (conn->state != BS_ESTABLISHED) /* fatal error during decoding */
return;
- if (a0 && ! bgp_set_next_hop(p, a0))
+ if (a0 && nlri_len && !bgp_set_next_hop(p, a0))
a0 = NULL;
last_id = 0;
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/ospf/config.Y
^
|
@@ -132,7 +132,7 @@
CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL)
CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY)
CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY, LENGTH)
-CF_KEYWORDS(SECONDARY)
+CF_KEYWORDS(SECONDARY, MERGE)
%type <t> opttext
%type <ld> lsadb_args
@@ -162,6 +162,7 @@
| STUB ROUTER bool { OSPF_CFG->stub_router = $3; }
| ECMP bool { OSPF_CFG->ecmp = $2 ? DEFAULT_ECMP_LIMIT : 0; }
| ECMP bool LIMIT expr { OSPF_CFG->ecmp = $2 ? $4 : 0; if ($4 < 0) cf_error("ECMP limit cannot be negative"); }
+ | MERGE EXTERNAL bool { OSPF_CFG->merge_external = $3; }
| TICK expr { OSPF_CFG->tick = $2; if($2<=0) cf_error("Tick must be greater than zero"); }
| ospf_area
;
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/ospf/iface.c
^
|
@@ -90,6 +90,8 @@
static int
ospf_sk_open(struct ospf_iface *ifa)
{
+ struct proto_ospf *po = ifa->oa->po;
+
sock *sk = sk_new(ifa->pool);
sk->type = SK_IP;
sk->dport = OSPF_PROTO;
@@ -121,7 +123,7 @@
{
ifa->all_routers = ifa->addr->brd;
- if (sk_set_broadcast(sk, 1) < 0)
+ if (sk_setup_broadcast(sk) < 0)
goto err;
}
else
@@ -141,6 +143,7 @@
return 1;
err:
+ sk_log_error(sk, po->proto.name);
rfree(sk);
return 0;
}
@@ -151,7 +154,9 @@
if (ifa->sk_dr)
return;
- sk_join_group(ifa->sk, AllDRouters);
+ if (sk_join_group(ifa->sk, AllDRouters) < 0)
+ sk_log_error(ifa->sk, ifa->oa->po->proto.name);
+
ifa->sk_dr = 1;
}
@@ -161,15 +166,15 @@
if (!ifa->sk_dr)
return;
- sk_leave_group(ifa->sk, AllDRouters);
+ if (sk_leave_group(ifa->sk, AllDRouters) < 0)
+ sk_log_error(ifa->sk, ifa->oa->po->proto.name);
+
ifa->sk_dr = 0;
}
void
ospf_open_vlink_sk(struct proto_ospf *po)
{
- struct proto *p = &po->proto;
-
sock *sk = sk_new(po->proto.pool);
sk->type = SK_IP;
sk->dport = OSPF_PROTO;
@@ -197,8 +202,9 @@
return;
err:
+ sk_log_error(sk, po->proto.name);
+ log(L_ERR "%s: Cannot open virtual link socket", po->proto.name);
rfree(sk);
- log(L_ERR "%s: Cannot open virtual link socket", p->name);
}
static void
@@ -463,7 +469,7 @@
/* Open socket if interface is not stub */
if (! ifa->stub && ! ospf_sk_open(ifa))
{
- log(L_ERR "%s: Socket open failed on interface %s, declaring as stub", p->name, ifa->ifname);
+ log(L_ERR "%s: Cannot open socket for %s, declaring as stub", p->name, ifa->ifname);
ifa->ioprob = OSPF_I_SK;
ifa->stub = 1;
}
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/ospf/ospf.c
^
|
@@ -234,6 +234,7 @@
po->router_id = proto_get_router_id(p->cf);
po->rfc1583 = c->rfc1583;
po->stub_router = c->stub_router;
+ po->merge_external = c->merge_external;
po->ebit = 0;
po->ecmp = c->ecmp;
po->tick = c->tick;
@@ -742,6 +743,7 @@
return 0;
po->stub_router = new->stub_router;
+ po->merge_external = new->merge_external;
po->ecmp = new->ecmp;
po->tick = new->tick;
po->disp_timer->recurrent = po->tick;
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/ospf/ospf.h
^
|
@@ -81,6 +81,7 @@
unsigned tick;
byte rfc1583;
byte stub_router;
+ byte merge_external;
byte abr;
int ecmp;
list area_list; /* list of struct ospf_area_config */
@@ -777,6 +778,7 @@
struct fib rtf; /* Routing table */
byte rfc1583; /* RFC1583 compatibility */
byte stub_router; /* Do not forward transit traffic */
+ byte merge_external; /* Should i merge external routes? */
byte ebit; /* Did I originate any ext lsa? */
byte ecmp; /* Maximal number of nexthops in ECMP route, or 0 */
struct ospf_area *backbone; /* If exists */
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/ospf/packet.c
^
|
@@ -308,9 +308,9 @@
return 1;
}
- if (ifa->check_ttl && (sk->ttl < 255))
+ if (ifa->check_ttl && (sk->rcv_ttl < 255))
{
- log(L_ERR "%s%I - TTL %d (< 255)", mesg, sk->faddr, sk->ttl);
+ log(L_ERR "%s%I - TTL %d (< 255)", mesg, sk->faddr, sk->rcv_ttl);
return 1;
}
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/ospf/rt.c
^
|
@@ -37,9 +37,15 @@
}
static inline int
-unresolved_vlink(struct mpnh *nhs)
+nh_is_vlink(struct mpnh *nhs)
{
- return nhs && !nhs->iface;
+ return !nhs->iface;
+}
+
+static inline int
+unresolved_vlink(ort *ort)
+{
+ return ort->n.nhs && nh_is_vlink(ort->n.nhs);
}
static inline struct mpnh *
@@ -54,7 +60,7 @@
}
static inline struct mpnh *
-copy_nexthop(struct proto_ospf *po, struct mpnh *src)
+copy_nexthop(struct proto_ospf *po, const struct mpnh *src)
{
struct mpnh *nh = lp_alloc(po->nhpool, sizeof(struct mpnh));
nh->gw = src->gw;
@@ -64,72 +70,138 @@
return nh;
}
-
-/* If new is better return 1 */
+/* Compare nexthops during merge.
+ We need to maintain nhs sorted to eliminate duplicities */
static int
-ri_better(struct proto_ospf *po, orta *new, orta *old)
+cmp_nhs(struct mpnh *s1, struct mpnh *s2)
{
- if (old->type == RTS_DUMMY)
- return 1;
+ int r;
- if (new->type < old->type)
+ if (!s1)
return 1;
- if (new->type > old->type)
- return 0;
+ if (!s2)
+ return -1;
- if (new->metric1 < old->metric1)
- return 1;
+ r = ((int) s2->weight) - ((int) s1->weight);
+ if (r)
+ return r;
- if (new->metric1 > old->metric1)
- return 0;
+ r = ipa_compare(s1->gw, s2->gw);
+ if (r)
+ return r;
- return 0;
+ return ((int) s1->iface->index) - ((int) s2->iface->index);
}
+static struct mpnh *
+merge_nexthops(struct proto_ospf *po, struct mpnh *s1, struct mpnh *s2, int r1, int r2)
+{
+ struct mpnh *root = NULL;
+ struct mpnh **n = &root;
+ int count = po->ecmp;
-/* Whether the ASBR or the forward address destination is preferred
- in AS external route selection according to 16.4.1. */
+ /*
+ * r1, r2 signalize whether we can reuse nexthops from s1, s2.
+ * New nexthops (s2, new) can be reused if they are not inherited
+ * from the parent (i.e. it is allocated in calc_next_hop()).
+ * Current nexthops (s1, en->nhs) can be reused if they weren't
+ * inherited in previous steps (that is stored in nhs_reuse,
+ * i.e. created by merging or allocalted in calc_next_hop()).
+ *
+ * Generally, a node first inherits shared nexthops from its
+ * parent and later possibly gets reusable copy during merging.
+ */
+
+ while ((s1 || s2) && count--)
+ {
+ int cmp = cmp_nhs(s1, s2);
+ if (cmp < 0)
+ {
+ *n = r1 ? s1 : copy_nexthop(po, s1);
+ s1 = s1->next;
+ }
+ else if (cmp > 0)
+ {
+ *n = r2 ? s2 : copy_nexthop(po, s2);
+ s2 = s2->next;
+ }
+ else
+ {
+ *n = r1 ? s1 : (r2 ? s2 : copy_nexthop(po, s1));
+ s1 = s1->next;
+ s2 = s2->next;
+ }
+ n = &((*n)->next);
+ }
+ *n = NULL;
+
+ return root;
+}
+
+/* Returns true if there are device nexthops in n */
static inline int
-epath_preferred(orta *ep)
+has_device_nexthops(const struct mpnh *n)
{
- return (ep->type == RTS_OSPF) && (ep->oa->areaid != 0);
+ for (; n; n = n->next)
+ if (ipa_zero(n->gw))
+ return 1;
+
+ return 0;
}
-/* 16.4. (3), return 1 if new is better */
-static int
-ri_better_asbr(struct proto_ospf *po, orta *new, orta *old)
+/* Replace device nexthops with nexthops to gw */
+static struct mpnh *
+fix_device_nexthops(struct proto_ospf *po, const struct mpnh *n, ip_addr gw)
{
- if (old->type == RTS_DUMMY)
- return 1;
+ struct mpnh *root1 = NULL;
+ struct mpnh *root2 = NULL;
+ struct mpnh **nn1 = &root1;
+ struct mpnh **nn2 = &root2;
- if (!po->rfc1583)
- {
- int new_pref = epath_preferred(new);
- int old_pref = epath_preferred(old);
+ /* This is a bit tricky. We cannot just copy the list and update n->gw,
+ because the list should stay sorted, so we create two lists, one with new
+ gateways and one with old ones, and then merge them. */
- if (new_pref > old_pref)
- return 1;
+ for (; n; n = n->next)
+ {
+ struct mpnh *nn = new_nexthop(po, ipa_zero(n->gw) ? gw : n->gw, n->iface, n->weight);
- if (new_pref < old_pref)
- return 0;
+ if (ipa_zero(n->gw))
+ {
+ *nn1 = nn;
+ nn1 = &(nn->next);
+ }
+ else
+ {
+ *nn2 = nn;
+ nn2 = &(nn->next);
+ }
}
- if (new->metric1 < old->metric1)
- return 1;
+ return merge_nexthops(po, root1, root2, 1, 1);
+}
- if (new->metric1 > old->metric1)
- return 0;
- /* Larger area ID is preferred */
- if (new->oa->areaid > old->oa->areaid)
- return 1;
+/* Whether the ASBR or the forward address destination is preferred
+ in AS external route selection according to 16.4.1. */
+static inline int
+epath_preferred(const orta *ep)
+{
+ return (ep->type == RTS_OSPF) && (ep->oa->areaid != 0);
+}
- return 0;
+/* Whether the ext route has ASBR/next_hop marked as preferred. */
+static inline int
+orta_pref(const orta *nf)
+{
+ return !!(nf->options & ORTA_PREF);
}
+/* Classify orta entries according to RFC 3101 2.5 (6e) priorities:
+ Type-7 LSA with P-bit, Type-5 LSA, Type-7 LSA without P-bit */
static int
-orta_prio(orta *nf)
+orta_prio(const orta *nf)
{
/* RFC 3103 2.5 (6e) priorities */
u32 opts = nf->options & (ORTA_NSSA | ORTA_PROP);
@@ -145,98 +217,246 @@
return 0;
}
-/* 16.4. (6), return 1 if new is better */
+/* Whether the route is better according to RFC 3101 2.5 (6e):
+ Prioritize Type-7 LSA with P-bit, then Type-5 LSA, then higher router ID */
static int
-ri_better_ext(struct proto_ospf *po, orta *new, orta *old)
+orta_prefer_lsa(const orta *new, const orta *old)
{
+ int pn = orta_prio(new);
+ int po = orta_prio(old);
+
+ return (pn > po) || ((pn == po) && (new->en->lsa.rt > old->en->lsa.rt));
+}
+
+/*
+ * Compare an existing routing table entry with a new one. Applicable for
+ * intra-area routes, inter-area routes and router entries. Returns integer
+ * <, = or > than 0 if the new orta is less, equal or more preferred than
+ * the old orta.
+ */
+static int
+orta_compare(const struct proto_ospf *po, const orta *new, const orta *old)
+{
+ int r;
+
if (old->type == RTS_DUMMY)
return 1;
- /* 16.4. (6a) */
- if (new->type < old->type)
+ /* Prefer intra-area to inter-area to externals */
+ r = ((int) old->type) - ((int) new->type);
+ if (r) return r;
+
+ /* Prefer lowest type 1 metric */
+ r = ((int) old->metric1) - ((int) new->metric1);
+ if (r) return r;
+
+
+ /* Rest is BIRD-specific */
+
+ /* Area-wide routes should not mix next-hops from different areas.
+ This generally should not happen unless there is some misconfiguration. */
+ if (new->oa->areaid != old->oa->areaid)
+ return (new->oa->areaid > old->oa->areaid) ? 1 : -1;
+
+ /* Prefer routes for configured stubnets (!nhs) to regular routes to dummy
+ vlink nexthops. We intentionally return -1 if both are stubnets or vlinks. */
+ if (!old->nhs)
+ return -1;
+ if (!new->nhs)
+ return 1;
+ if (nh_is_vlink(new->nhs))
+ return -1;
+ if (nh_is_vlink(old->nhs))
return 1;
- if (new->type > old->type)
+
+ if (po->ecmp)
return 0;
- /* 16.4. (6b), same type */
- if (new->type == RTS_OSPF_EXT2)
- {
- if (new->metric2 < old->metric2)
- return 1;
+ /* Prefer routes with higher Router ID, just to be more deterministic */
+ if (new->rid > old->rid)
+ return 1;
+
+ return -1;
+}
- if (new->metric2 > old->metric2)
- return 0;
- }
+/*
+ * Compare ASBR routing table entry with a new one, used for precompute ASBRs
+ * for AS external route selection (RFC 2328 16.4 (3)), Returns integer < or >
+ * than 0 if the new ASBR is less or more preferred than the old ASBR.
+ */
+static int
+orta_compare_asbr(const struct proto_ospf *po, const orta *new, const orta *old)
+{
+ int r;
+
+ if (old->type == RTS_DUMMY)
+ return 1;
- /* 16.4. (6c) */
if (!po->rfc1583)
{
- u32 new_pref = new->options & ORTA_PREF;
- u32 old_pref = old->options & ORTA_PREF;
-
- if (new_pref > old_pref)
- return 1;
-
- if (new_pref < old_pref)
- return 0;
+ r = epath_preferred(new) - epath_preferred(old);
+ if (r) return r;
}
- /* 16.4. (6d) */
- if (new->metric1 < old->metric1)
+ r = ((int) old->metric1) - ((int) new->metric1);
+ if (r) return r;
+
+ /* Larger area ID is preferred */
+ if (new->oa->areaid > old->oa->areaid)
return 1;
- if (new->metric1 > old->metric1)
- return 0;
+ /* There is just one ASBR of that RID per area, so tie is not possible */
+ return -1;
+}
- /* RFC 3103, 2.5. (6e) */
- int new_prio = orta_prio(new);
- int old_prio = orta_prio(old);
+/*
+ * Compare a routing table entry with a new one, for AS external routes
+ * (RFC 2328 16.4) and NSSA routes (RFC 3103 2.5), Returns integer <, = or >
+ * than 0 if the new orta is less, equal or more preferred than the old orta.
+ */
+static int
+orta_compare_ext(const struct proto_ospf *po, const orta *new, const orta *old)
+{
+ int r;
- if (new_prio > old_prio)
+ if (old->type == RTS_DUMMY)
return 1;
- if (old_prio > new_prio)
+ /* 16.4 (6a) - prefer routes with lower type */
+ r = ((int) old->type) - ((int) new->type);
+ if (r) return r;
+
+ /* 16.4 (6b) - prefer routes with lower type 2 metric */
+ if (new->type == RTS_OSPF_EXT2)
+ {
+ r = ((int) old->metric2) - ((int) new->metric2);
+ if (r) return r;
+ }
+
+ /* 16.4 (6c) - if not RFC1583, prefer routes with preferred ASBR/next_hop */
+ if (!po->rfc1583)
+ {
+ r = orta_pref(new) - orta_pref(old);
+ if (r) return r;
+ }
+
+ /* 16.4 (6d) - prefer routes with lower type 1 metric */
+ r = ((int) old->metric1) - ((int) new->metric1);
+ if (r) return r;
+
+
+ if (po->ecmp && po->merge_external)
return 0;
- /* make it more deterministic */
- if (new->rid > old->rid)
+ /*
+ * RFC 3101 2.5 (6e) - prioritize Type-7 LSA with P-bit, then Type-5 LSA, then
+ * LSA with higher router ID. Although this should apply just to functionally
+ * equivalent LSAs (i.e. ones with the same non-zero forwarding address), we
+ * use it also to disambiguate otherwise equally preferred nexthops.
+ */
+ if (orta_prefer_lsa(new, old))
return 1;
- return 0;
+ return -1;
}
+
static inline void
-ri_install_net(struct proto_ospf *po, ip_addr prefix, int pxlen, orta *new)
+ort_replace(ort *o, const orta *new)
+{
+ memcpy(&o->n, new, sizeof(orta));
+}
+
+static void
+ort_merge(struct proto_ospf *po, ort *o, const orta *new)
+{
+ orta *old = &o->n;
+
+ if (old->nhs != new->nhs)
+ {
+ old->nhs = merge_nexthops(po, old->nhs, new->nhs, old->nhs_reuse, new->nhs_reuse);
+ old->nhs_reuse = 1;
+ }
+
+ if (old->rid < new->rid)
+ old->rid = new->rid;
+}
+
+static void
+ort_merge_ext(struct proto_ospf *po, ort *o, const orta *new)
+{
+ orta *old = &o->n;
+
+ if (old->nhs != new->nhs)
+ {
+ old->nhs = merge_nexthops(po, old->nhs, new->nhs, old->nhs_reuse, new->nhs_reuse);
+ old->nhs_reuse = 1;
+ }
+
+ if (old->tag != new->tag)
+ old->tag = 0;
+
+ /*
+ * Even with multipath, we store only one LSA in orta.en for the purpose of
+ * NSSA/ext translation. Therefore, we apply procedures from RFC 3101 2.5 (6e)
+ * to all chosen LSAs for given network, not just to functionally equivalent
+ * ones (i.e. ones with the same non-zero forwarding address).
+ */
+ if (orta_prefer_lsa(new, old))
+ {
+ old->options = new->options;
+ old->rid = new->rid;
+ old->oa = new->oa;
+ old->en = new->en;
+ }
+}
+
+
+
+static inline void
+ri_install_net(struct proto_ospf *po, ip_addr prefix, int pxlen, const orta *new)
{
ort *old = (ort *) fib_get(&po->rtf, &prefix, pxlen);
- if (ri_better(po, new, &old->n))
- memcpy(&old->n, new, sizeof(orta));
+ int cmp = orta_compare(po, new, &old->n);
+
+ if (cmp > 0)
+ ort_replace(old, new);
+ else if (cmp == 0)
+ ort_merge(po, old, new);
}
static inline void
-ri_install_rt(struct ospf_area *oa, u32 rid, orta *new)
+ri_install_rt(struct ospf_area *oa, u32 rid, const orta *new)
{
ip_addr addr = ipa_from_rid(rid);
ort *old = (ort *) fib_get(&oa->rtr, &addr, MAX_PREFIX_LENGTH);
- if (ri_better(oa->po, new, &old->n))
- memcpy(&old->n, new, sizeof(orta));
+ int cmp = orta_compare(oa->po, new, &old->n);
+
+ if (cmp > 0)
+ ort_replace(old, new);
+ else if (cmp == 0)
+ ort_merge(oa->po, old, new);
}
static inline void
-ri_install_asbr(struct proto_ospf *po, ip_addr *addr, orta *new)
+ri_install_asbr(struct proto_ospf *po, ip_addr *addr, const orta *new)
{
ort *old = (ort *) fib_get(&po->backbone->rtr, addr, MAX_PREFIX_LENGTH);
- if (ri_better_asbr(po, new, &old->n))
- memcpy(&old->n, new, sizeof(orta));
+ if (orta_compare_asbr(po, new, &old->n) > 0)
+ ort_replace(old, new);
}
static inline void
-ri_install_ext(struct proto_ospf *po, ip_addr prefix, int pxlen, orta *new)
+ri_install_ext(struct proto_ospf *po, ip_addr prefix, int pxlen, const orta *new)
{
ort *old = (ort *) fib_get(&po->rtf, &prefix, pxlen);
- if (ri_better_ext(po, new, &old->n))
- memcpy(&old->n, new, sizeof(orta));
+ int cmp = orta_compare_ext(po, new, &old->n);
+
+ if (cmp > 0)
+ ort_replace(old, new);
+ else if (cmp == 0)
+ ort_merge_ext(po, old, new);
}
static inline struct ospf_iface *
@@ -842,7 +1062,7 @@
/* 16.3. (5) */
if ((metric < re->n.metric1) ||
- ((metric == re->n.metric1) && unresolved_vlink(re->n.nhs)))
+ ((metric == re->n.metric1) && unresolved_vlink(re)))
{
/* We want to replace the next-hop even if the metric is equal
to replace a virtual next-hop through vlink with a real one.
@@ -1129,13 +1349,24 @@
struct area_net *anet;
ort *nf, *default_nf;
+ /* RFC 2328 G.3 - incomplete resolution of virtual next hops - routers */
+ FIB_WALK(&po->backbone->rtr, nftmp)
+ {
+ nf = (ort *) nftmp;
+
+ if (nf->n.type && unresolved_vlink(nf))
+ reset_ri(nf);
+ }
+ FIB_WALK_END;
+
+
FIB_WALK(&po->rtf, nftmp)
{
nf = (ort *) nftmp;
- /* RFC 2328 G.3 - incomplete resolution of virtual next hops */
- if (nf->n.type && unresolved_vlink(nf->n.nhs))
+ /* RFC 2328 G.3 - incomplete resolution of virtual next hops - networks */
+ if (nf->n.type && unresolved_vlink(nf))
reset_ri(nf);
@@ -1361,7 +1592,7 @@
ospf_ext_spf(struct proto_ospf *po)
{
ort *nf1, *nf2;
- orta nfa;
+ orta nfa = {};
struct top_hash_entry *en;
struct proto *p = &po->proto;
struct ospf_lsa_ext *le;
@@ -1369,7 +1600,6 @@
ip_addr ip, rtid, rt_fwaddr;
u32 br_metric, rt_metric, rt_tag;
struct ospf_area *atmp;
- struct mpnh* nhs = NULL;
OSPF_TRACE(D_EVENTS, "Starting routing table calculation for ext routes");
@@ -1465,7 +1695,7 @@
if (!rt_fwaddr_valid)
{
nf2 = nf1;
- nhs = nf1->n.nhs;
+ nfa.nhs = nf1->n.nhs;
br_metric = nf1->n.metric1;
}
else
@@ -1491,11 +1721,15 @@
if (!nf2->n.nhs)
continue;
- nhs = nf2->n.nhs;
- /* If gw is zero, it is a device route */
- if (ipa_zero(nhs->gw))
- nhs = new_nexthop(po, rt_fwaddr, nhs->iface, nhs->weight);
+ nfa.nhs = nf2->n.nhs;
br_metric = nf2->n.metric1;
+
+ /* Replace device nexthops with nexthops to forwarding address from LSA */
+ if (has_device_nexthops(nfa.nhs))
+ {
+ nfa.nhs = fix_device_nexthops(po, nfa.nhs, rt_fwaddr);
+ nfa.nhs_reuse = 1;
+ }
}
if (ebit)
@@ -1526,8 +1760,6 @@
nfa.tag = rt_tag;
nfa.rid = en->lsa.rt;
nfa.oa = atmp; /* undefined in RFC 2328 */
- nfa.voa = NULL;
- nfa.nhs = nhs;
nfa.en = en; /* store LSA for later (NSSA processing) */
ri_install_ext(po, ip, pxlen, &nfa);
@@ -1745,81 +1977,6 @@
return NULL;
}
-/* Compare nexthops during merge.
- We need to maintain nhs sorted to eliminate duplicities */
-static int
-cmp_nhs(struct mpnh *s1, struct mpnh *s2)
-{
- int r;
-
- if (!s1)
- return 1;
-
- if (!s2)
- return -1;
-
- r = ((int) s2->weight) - ((int) s1->weight);
- if (r)
- return r;
-
- r = ipa_compare(s1->gw, s2->gw);
- if (r)
- return r;
-
- return ((int) s1->iface->index) - ((int) s2->iface->index);
-}
-
-static void
-merge_nexthops(struct proto_ospf *po, struct top_hash_entry *en,
- struct top_hash_entry *par, struct mpnh *new)
-{
- if (en->nhs == new)
- return;
-
- int r1 = en->nhs_reuse;
- int r2 = (par->nhs != new);
- int count = po->ecmp;
- struct mpnh *s1 = en->nhs;
- struct mpnh *s2 = new;
- struct mpnh **n = &(en->nhs);
-
- /*
- * r1, r2 signalize whether we can reuse nexthops from s1, s2.
- * New nexthops (s2, new) can be reused if they are not inherited
- * from the parent (i.e. it is allocated in calc_next_hop()).
- * Current nexthops (s1, en->nhs) can be reused if they weren't
- * inherited in previous steps (that is stored in nhs_reuse,
- * i.e. created by merging or allocalted in calc_next_hop()).
- *
- * Generally, a node first inherits shared nexthops from its
- * parent and later possibly gets reusable copy during merging.
- */
-
- while ((s1 || s2) && count--)
- {
- int cmp = cmp_nhs(s1, s2);
- if (cmp < 0)
- {
- *n = r1 ? s1 : copy_nexthop(po, s1);
- s1 = s1->next;
- }
- else if (cmp > 0)
- {
- *n = r2 ? s2 : copy_nexthop(po, s2);
- s2 = s2->next;
- }
- else
- {
- *n = r1 ? s1 : (r2 ? s2 : copy_nexthop(po, s1));
- s1 = s1->next;
- s2 = s2->next;
- }
- n = &((*n)->next);
- }
- *n = NULL;
-
- en->nhs_reuse=1;
-}
/* Add LSA into list of candidates in Dijkstra's algorithm */
static void
@@ -1866,31 +2023,33 @@
return;
}
- if (dist == en->dist)
+ /* We know that en->color == CANDIDATE and en->nhs is defined. */
+
+ if ((dist == en->dist) && !nh_is_vlink(en->nhs))
{
/*
- * For multipath, we should merge nexthops. We do not mix dummy
- * vlink nexthops, device nexthops and gateway nexthops. We merge
- * gateway nexthops only. We prefer device nexthops over gateway
- * nexthops and gateway nexthops over vlink nexthops. We either
- * keep old nexthops, merge old and new, or replace old with new.
- *
- * We know that en->color == CANDIDATE and en->nhs is defined.
+ * For multipath, we should merge nexthops. We merge regular nexthops only.
+ * Dummy vlink nexthops are less preferred and handled as a special case.
+ *
+ * During merging, new nexthops (nhs) can be reused if they are not
+ * inherited from the parent (i.e. they are allocated in calc_next_hop()).
+ * Current nexthops (en->nhs) can be reused if they weren't inherited in
+ * previous steps (that is stored in nhs_reuse, i.e. created by merging or
+ * allocated in calc_next_hop()).
+ *
+ * Generally, a node first inherits shared nexthops from its parent and
+ * later possibly gets reusable copy during merging.
*/
- struct mpnh *onhs = en->nhs;
/* Keep old ones */
- if (!po->ecmp || !nhs->iface || (onhs->iface && ipa_zero(onhs->gw)))
+ if (!po->ecmp || nh_is_vlink(nhs) || (nhs == en->nhs))
return;
/* Merge old and new */
- if (ipa_nonzero(nhs->gw) && ipa_nonzero(onhs->gw))
- {
- merge_nexthops(po, en, par, nhs);
- return;
- }
-
- /* Fallback to replace old ones */
+ int new_reuse = (par->nhs != nhs);
+ en->nhs = merge_nexthops(po, en->nhs, nhs, en->nhs_reuse, new_reuse);
+ en->nhs_reuse = 1;
+ return;
}
DBG(" Adding candidate: rt: %R, id: %R, type: %u\n",
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/ospf/rt.h
^
|
@@ -16,7 +16,8 @@
typedef struct orta
{
- int type;
+ u8 type; /* RTS_OSPF_* */
+ u8 nhs_reuse; /* Whether nhs nodes can be reused during merging */
u32 options;
/*
* For ORT_ROUTER routes, options field are router-LSA style
@@ -93,16 +94,24 @@
* - n.metric1 may be at most a small multiple of LSINFINITY,
* therefore sums do not overflow
* - n.oa is always non-NULL
- * - n.nhs is always non-NULL with one exception - configured stubnet
- * nodes (in po->rtf).
+ * - n.nhs is always non-NULL unless it is configured stubnet
+ * - n.en is non-NULL for external routes, NULL for intra/inter area routes.
* - oa->rtr does not contain calculating router itself
*
- * There are three types of nexthops in nhs fields:
+ * There are four types of nexthops in nhs fields:
* - gateway nexthops (non-NULL iface, gw != IPA_NONE)
* - device nexthops (non-NULL iface, gw == IPA_NONE)
* - dummy vlink nexthops (NULL iface, gw == IPA_NONE)
- * These three types don't mix, nhs field contains either
- * one device, one vlink node, or one/more gateway nodes.
+ * - configured stubnets (nhs is NULL, only RTS_OSPF orta nodes in po->rtf)
+ *
+ * Dummy vlink nexthops and configured stubnets cannot be mixed with
+ * regular ones, nhs field contains either list of gateway+device nodes,
+ * one vlink node, or NULL for configured stubnet.
+ *
+ * Dummy vlink nexthops can appear in both network (rtf) and backbone area router
+ * (rtr) tables for regular and inter-area routes, but only if areano > 1. They are
+ * replaced in ospf_rt_sum_tr() and removed in ospf_rt_abr1(), therefore cannot
+ * appear in ASBR pre-selection and external routes processing.
*/
void ospf_rt_spf(struct proto_ospf *po);
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/pipe/pipe.c
^
|
@@ -235,12 +235,14 @@
{
P->main_ahook->out_filter = new->out_filter;
P->main_ahook->in_limit = new->in_limit;
+ proto_verify_limits(P->main_ahook);
}
if (p->peer_ahook)
{
p->peer_ahook->out_filter = new->in_filter;
p->peer_ahook->in_limit = new->out_limit;
+ proto_verify_limits(p->peer_ahook);
}
if ((P->proto_state != PS_UP) || (proto_reconfig_type == RECONFIG_SOFT))
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/radv/config.Y
^
|
@@ -30,9 +30,9 @@
MANAGED, OTHER, CONFIG, LINK, MTU, REACHABLE, TIME, RETRANS,
TIMER, CURRENT, HOP, LIMIT, DEFAULT, VALID, PREFERRED, MULT,
LIFETIME, SKIP, ONLINK, AUTONOMOUS, RDNSS, DNSSL, NS, DOMAIN,
- LOCAL, TRIGGER, SENSITIVE)
+ LOCAL, TRIGGER, SENSITIVE, PREFERENCE, LOW, MEDIUM, HIGH)
-%type<i> radv_mult radv_sensitive
+%type<i> radv_mult radv_sensitive radv_preference
CF_GRAMMAR
@@ -84,6 +84,7 @@
RADV_IFACE->current_hop_limit = DEFAULT_CURRENT_HOP_LIMIT;
RADV_IFACE->default_lifetime = -1;
RADV_IFACE->default_lifetime_sensitive = 1;
+ RADV_IFACE->default_preference = RA_PREF_MEDIUM;
};
radv_iface_item:
@@ -101,6 +102,7 @@
if (($3 < 0) || ($3 > 9000)) cf_error("Default lifetime must be in range 0-9000");
if ($4 != -1) RADV_IFACE->default_lifetime_sensitive = $4;
}
+ | DEFAULT PREFERENCE radv_preference { RADV_IFACE->default_preference = $3; }
| PREFIX radv_prefix { add_tail(&RADV_IFACE->pref_list, NODE this_radv_prefix); }
| RDNSS { init_list(&radv_dns_list); } radv_rdnss { add_tail_list(&RADV_IFACE->rdnss_list, &radv_dns_list); }
| DNSSL { init_list(&radv_dns_list); } radv_dnssl { add_tail_list(&RADV_IFACE->dnssl_list, &radv_dns_list); }
@@ -108,6 +110,11 @@
| DNSSL LOCAL bool { RADV_IFACE->dnssl_local = $3; }
;
+radv_preference:
+ LOW { $$ = RA_PREF_LOW; }
+ | MEDIUM { $$ = RA_PREF_MEDIUM; }
+ | HIGH { $$ = RA_PREF_HIGH; }
+
radv_iface_finish:
{
struct radv_iface_config *ic = RADV_IFACE;
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/radv/packets.c
^
|
@@ -251,10 +251,11 @@
pkt->code = 0;
pkt->checksum = 0;
pkt->current_hop_limit = ic->current_hop_limit;
- pkt->flags = (ic->managed ? OPT_RA_MANAGED : 0) |
- (ic->other_config ? OPT_RA_OTHER_CFG : 0);
pkt->router_lifetime = (ra->active || !ic->default_lifetime_sensitive) ?
htons(ic->default_lifetime) : 0;
+ pkt->flags = (ic->managed ? OPT_RA_MANAGED : 0) |
+ (ic->other_config ? OPT_RA_OTHER_CFG : 0) |
+ (pkt->router_lifetime ? ic->default_preference : 0);
pkt->reachable_time = htonl(ic->reachable_time);
pkt->retrans_timer = htonl(ic->retrans_timer);
buf += sizeof(*pkt);
@@ -330,10 +331,15 @@
if (shutdown)
{
- /* Modify router lifetime to 0, it is not restored because
- we suppose that the iface will be removed */
+ /*
+ * Modify router lifetime to 0, it is not restored because we suppose that
+ * the iface will be removed. The preference value also has to be zeroed.
+ * (RFC 4191 2.2: If router lifetime is 0, the preference value must be 0.)
+ */
+
struct radv_ra_packet *pkt = (void *) ifa->sk->tbuf;
pkt->router_lifetime = 0;
+ pkt->flags &= ~RA_PREF_MASK;
}
RADV_TRACE(D_PACKETS, "Sending RA via %s", ifa->iface->name);
@@ -416,11 +422,11 @@
sk->data = ifa;
sk->flags = SKF_LADDR_RX;
- if (sk_open(sk) != 0)
+ if (sk_open(sk) < 0)
goto err;
/* We want listen just to ICMPv6 messages of type RS and RA */
- if (sk_set_icmp_filter(sk, ICMPV6_RS, ICMPV6_RA) < 0)
+ if (sk_set_icmp6_filter(sk, ICMPV6_RS, ICMPV6_RA) < 0)
goto err;
if (sk_setup_multicast(sk) < 0)
@@ -433,6 +439,7 @@
return 1;
err:
+ sk_log_error(sk, ifa->ra->p.name);
rfree(sk);
return 0;
}
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/radv/radv.c
^
|
@@ -40,6 +40,7 @@
* Supported standards:
* - RFC 4861 - main RA standard
* - RFC 6106 - DNS extensions (RDDNS, DNSSL)
+ * - RFC 4191 (partial) - Default Router Preference
*/
static void
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/radv/radv.h
^
|
@@ -80,6 +80,7 @@
u32 current_hop_limit;
u32 default_lifetime;
u8 default_lifetime_sensitive; /* Whether default_lifetime depends on trigger */
+ u8 default_preference; /* Default Router Preference (RFC 4191) */
};
struct radv_prefix_config
@@ -144,6 +145,11 @@
#define RA_EV_CHANGE 2 /* Change of options or prefixes */
#define RA_EV_RS 3 /* Received RS */
+/* Default Router Preferences (RFC 4191) */
+#define RA_PREF_LOW 0x18
+#define RA_PREF_MEDIUM 0x00
+#define RA_PREF_HIGH 0x08
+#define RA_PREF_MASK 0x18
#ifdef LOCAL_DEBUG
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/proto/rip/rip.c
^
|
@@ -483,10 +483,10 @@
iface = i->iface;
#endif
- if (i->check_ttl && (s->ttl < 255))
+ if (i->check_ttl && (s->rcv_ttl < 255))
{
log( L_REMOTE "%s: Discarding packet with TTL %d (< 255) from %I on %s",
- p->name, s->ttl, s->faddr, i->iface->name);
+ p->name, s->rcv_ttl, s->faddr, i->iface->name);
return 1;
}
@@ -733,7 +733,7 @@
log( L_WARN "%s: interface %s is too strange for me", p->name, rif->iface->name );
} else {
- if (sk_open(rif->sock)<0)
+ if (sk_open(rif->sock) < 0)
goto err;
if (rif->multicast)
@@ -745,7 +745,7 @@
}
else
{
- if (sk_set_broadcast(rif->sock, 1) < 0)
+ if (sk_setup_broadcast(rif->sock) < 0)
goto err;
}
}
@@ -755,7 +755,8 @@
return rif;
err:
- log( L_ERR "%s: could not create socket for %s", p->name, rif->iface ? rif->iface->name : "(dummy)" );
+ sk_log_error(rif->sock, p->name);
+ log(L_ERR "%s: Cannot open socket for %s", p->name, rif->iface ? rif->iface->name : "(dummy)" );
if (rif->iface) {
rfree(rif->sock);
mb_free(rif);
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/sysdep/bsd/krt-sock.c
^
|
@@ -251,9 +251,9 @@
_I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
#endif
- fill_in_sockaddr(&dst, net->n.prefix, NULL, 0);
- fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), NULL, 0);
- fill_in_sockaddr(&gate, gw, NULL, 0);
+ sockaddr_fill(&dst, BIRD_AF, net->n.prefix, NULL, 0);
+ sockaddr_fill(&mask, BIRD_AF, ipa_mkmask(net->n.pxlen), NULL, 0);
+ sockaddr_fill(&gate, BIRD_AF, gw, NULL, 0);
switch (a->dest)
{
@@ -261,6 +261,7 @@
msg.rtm.rtm_flags |= RTF_GATEWAY;
msg.rtm.rtm_addrs |= RTA_GATEWAY;
break;
+
#ifdef RTF_REJECT
case RTD_UNREACHABLE:
#endif
@@ -280,7 +281,7 @@
return -1;
}
- fill_in_sockaddr(&gate, i->addr->ip, NULL, 0);
+ sockaddr_fill(&gate, BIRD_AF, i->addr->ip, NULL, 0);
msg.rtm.rtm_addrs |= RTA_GATEWAY;
}
break;
@@ -366,20 +367,16 @@
GETADDR(&gate, RTA_GATEWAY);
GETADDR(&mask, RTA_NETMASK);
- if (sa_family_check(&dst))
- get_sockaddr(&dst, &idst, NULL, NULL, 0);
- else
+ if (dst.sa.sa_family != BIRD_AF)
SKIP("invalid DST");
- /* We will check later whether we have valid gateway addr */
- if (sa_family_check(&gate))
- get_sockaddr(&gate, &igate, NULL, NULL, 0);
- else
- igate = IPA_NONE;
+ idst = ipa_from_sa(&dst);
+ imask = ipa_from_sa(&mask);
+ igate = (gate.sa.sa_family == BIRD_AF) ? ipa_from_sa(&gate) : IPA_NONE;
/* We do not test family for RTA_NETMASK, because BSD sends us
some strange values, but interpreting them as IPv4/IPv6 works */
- get_sockaddr(&mask, &imask, NULL, NULL, 0);
+
int c = ipa_classify_net(idst);
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
@@ -648,12 +645,13 @@
GETADDR (&brd, RTA_BRD);
/* Some other family address */
- if (!sa_family_check(&addr))
+ if (addr.sa.sa_family != BIRD_AF)
return;
- get_sockaddr(&addr, &iaddr, NULL, NULL, 0);
- get_sockaddr(&mask, &imask, NULL, NULL, 0);
- get_sockaddr(&brd, &ibrd, NULL, NULL, 0);
+ iaddr = ipa_from_sa(&addr);
+ imask = ipa_from_sa(&mask);
+ ibrd = ipa_from_sa(&brd);
+
if ((masklen = ipa_mklen(imask)) < 0)
{
@@ -806,7 +804,7 @@
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
- mib[3] = BIRD_PF;
+ mib[3] = BIRD_AF;
mib[4] = cmd;
mib[5] = 0;
mcnt = 6;
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/sysdep/bsd/sysio.h
^
|
@@ -1,11 +1,16 @@
/*
- * BIRD Internet Routing Daemon -- NetBSD Multicasting and Network Includes
+ * BIRD Internet Routing Daemon -- BSD Multicasting and Network Includes
*
* (c) 2004 Ondrej Filip <feela@network.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
+#include <net/if_dl.h>
+#include <netinet/in_systm.h> // Workaround for some BSDs
+#include <netinet/ip.h>
+
+
#ifdef __NetBSD__
#ifndef IP_RECVTTL
@@ -22,176 +27,121 @@
#define TCP_MD5SIG TCP_SIGNATURE_ENABLE
#endif
-#ifdef IPV6
-
-static inline void
-set_inaddr(struct in6_addr * ia, ip_addr a)
-{
- ipa_hton(a);
- memcpy(ia, &a, sizeof(a));
-}
-
-static inline void
-get_inaddr(ip_addr *a, struct in6_addr *ia)
-{
- memcpy(a, ia, sizeof(*a));
- ipa_ntoh(*a);
-}
-
-
-#else
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <netinet/in_systm.h> // Workaround for some BSDs
-#include <netinet/ip.h>
-
-static inline void
-set_inaddr(struct in_addr * ia, ip_addr a)
-{
- ipa_hton(a);
- memcpy(&ia->s_addr, &a, sizeof(a));
-}
+#define SA_LEN(x) (x).sa.sa_len
-static inline void
-get_inaddr(ip_addr *a, struct in_addr *ia)
-{
- memcpy(a, &ia->s_addr, sizeof(*a));
- ipa_ntoh(*a);
-}
+/*
+ * BSD IPv4 multicast syscalls
+ */
-/* BSD Multicast handling for IPv4 */
+#define INIT_MREQ4(maddr,ifa) \
+ { .imr_multiaddr = ipa_to_in4(maddr), .imr_interface = ipa_to_in4(ifa->addr->ip) }
-static inline char *
-sysio_setup_multicast(sock *s)
+static inline int
+sk_setup_multicast4(sock *s)
{
- struct in_addr m;
- u8 zero = 0;
- u8 ttl = s->ttl;
+ struct in_addr ifa = ipa_to_in4(s->iface->addr->ip);
+ u8 ttl = s->ttl;
+ u8 n = 0;
- if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
- return "IP_MULTICAST_LOOP";
+ /* This defines where should we send _outgoing_ multicasts */
+ if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &ifa, sizeof(ifa)) < 0)
+ ERR("IP_MULTICAST_IF");
- if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
- return "IP_MULTICAST_TTL";
+ if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
+ ERR("IP_MULTICAST_TTL");
- /* This defines where should we send _outgoing_ multicasts */
- set_inaddr(&m, s->iface->addr->ip);
- if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
- return "IP_MULTICAST_IF";
+ if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &n, sizeof(n)) < 0)
+ ERR("IP_MULTICAST_LOOP");
- return NULL;
+ return 0;
}
-
-static inline char *
-sysio_join_group(sock *s, ip_addr maddr)
+static inline int
+sk_join_group4(sock *s, ip_addr maddr)
{
- struct ip_mreq mreq;
-
- bzero(&mreq, sizeof(mreq));
- set_inaddr(&mreq.imr_interface, s->iface->addr->ip);
- set_inaddr(&mreq.imr_multiaddr, maddr);
+ struct ip_mreq mr = INIT_MREQ4(maddr, s->iface);
- /* And this one sets interface for _receiving_ multicasts from */
- if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
- return "IP_ADD_MEMBERSHIP";
+ if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0)
+ ERR("IP_ADD_MEMBERSHIP");
- return NULL;
+ return 0;
}
-static inline char *
-sysio_leave_group(sock *s, ip_addr maddr)
+static inline int
+sk_leave_group4(sock *s, ip_addr maddr)
{
- struct ip_mreq mreq;
-
- bzero(&mreq, sizeof(mreq));
- set_inaddr(&mreq.imr_interface, s->iface->addr->ip);
- set_inaddr(&mreq.imr_multiaddr, maddr);
+ struct ip_mreq mr = INIT_MREQ4(maddr, s->iface);
- /* And this one sets interface for _receiving_ multicasts from */
- if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
- return "IP_DROP_MEMBERSHIP";
+ if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)) < 0)
+ ERR("IP_ADD_MEMBERSHIP");
- return NULL;
+ return 0;
}
-/* BSD RX/TX packet info handling for IPv4 */
-/* it uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */
+/*
+ * BSD IPv4 packet control messages
+ */
+
+/* It uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */
-#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in_addr)) + \
- CMSG_SPACE(sizeof(struct sockaddr_dl)) + \
- CMSG_SPACE(sizeof(char)))
-#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_addr))
+#define CMSG4_SPACE_PKTINFO (CMSG_SPACE(sizeof(struct in_addr)) + \
+ CMSG_SPACE(sizeof(struct sockaddr_dl)))
+#define CMSG4_SPACE_TTL CMSG_SPACE(sizeof(char))
-static char *
-sysio_register_cmsgs(sock *s)
+static inline int
+sk_request_cmsg4_pktinfo(sock *s)
{
- int ok = 1;
- if (s->flags & SKF_LADDR_RX)
- {
- if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &ok, sizeof(ok)) < 0)
- return "IP_RECVDSTADDR";
+ int y = 1;
- if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &ok, sizeof(ok)) < 0)
- return "IP_RECVIF";
- }
+ if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &y, sizeof(y)) < 0)
+ ERR("IP_RECVDSTADDR");
- if ((s->flags & SKF_TTL_RX) &&
- (setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &ok, sizeof(ok)) < 0))
- return "IP_RECVTTL";
+ if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &y, sizeof(y)) < 0)
+ ERR("IP_RECVIF");
-
- return NULL;
+ return 0;
}
-static inline void
-sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
+static inline int
+sk_request_cmsg4_ttl(sock *s)
{
- struct cmsghdr *cm;
- struct in_addr *ra = NULL;
- struct sockaddr_dl *ri = NULL;
- unsigned char *ttl = NULL;
-
- for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
- {
- if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR)
- ra = (struct in_addr *) CMSG_DATA(cm);
-
- if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVIF)
- ri = (struct sockaddr_dl *) CMSG_DATA(cm);
+ int y = 1;
- if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVTTL)
- ttl = (unsigned char *) CMSG_DATA(cm);
- }
-
- if (s->flags & SKF_LADDR_RX)
- {
- s->laddr = IPA_NONE;
- s->lifindex = 0;
+ if (setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &y, sizeof(y)) < 0)
+ ERR("IP_RECVTTL");
- if (ra)
- get_inaddr(&s->laddr, ra);
- if (ri)
- s->lifindex = ri->sdl_index;
- }
+ return 0;
+}
- if (s->flags & SKF_TTL_RX)
- s->ttl = ttl ? *ttl : -1;
+static inline void
+sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
+{
+ if (cm->cmsg_type == IP_RECVDSTADDR)
+ s->laddr = ipa_from_in4(* (struct in_addr *) CMSG_DATA(cm));
- // log(L_WARN "RX %I %d", s->laddr, s->lifindex);
+ if (cm->cmsg_type == IP_RECVIF)
+ s->lifindex = ((struct sockaddr_dl *) CMSG_DATA(cm))->sdl_index;
}
-/* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
+static inline void
+sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
+{
+ if (cm->cmsg_type == IP_RECVTTL)
+ s->rcv_ttl = * (unsigned char *) CMSG_DATA(cm);
+}
static inline void
-sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
+sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
{
+ /* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
+
#ifdef IP_SENDSRCADDR
struct cmsghdr *cm;
struct in_addr *sa;
+ int controllen = 0;
msg->msg_control = cbuf;
msg->msg_controllen = cbuflen;
@@ -200,17 +150,17 @@
cm->cmsg_level = IPPROTO_IP;
cm->cmsg_type = IP_SENDSRCADDR;
cm->cmsg_len = CMSG_LEN(sizeof(*sa));
+ controllen += CMSG_SPACE(sizeof(*sa));
sa = (struct in_addr *) CMSG_DATA(cm);
- set_inaddr(sa, s->saddr);
+ *sa = ipa_to_in4(s->saddr);
- msg->msg_controllen = cm->cmsg_len;
+ msg->msg_controllen = controllen;
#endif
}
-
static void
-fill_ip_header(sock *s, void *hdr, int dlen)
+sk_prepare_ip_header(sock *s, void *hdr, int dlen)
{
struct ip *ip = hdr;
@@ -222,8 +172,8 @@
ip->ip_len = 20 + dlen;
ip->ip_ttl = (s->ttl < 0) ? 64 : s->ttl;
ip->ip_p = s->dport;
- set_inaddr(&ip->ip_src, s->saddr);
- set_inaddr(&ip->ip_dst, s->daddr);
+ ip->ip_src = ipa_to_in4(s->saddr);
+ ip->ip_dst = ipa_to_in4(s->daddr);
#ifdef __OpenBSD__
/* OpenBSD expects ip_len in network order, other BSDs expect host order */
@@ -231,10 +181,11 @@
#endif
}
-#endif
+/*
+ * Miscellaneous BSD socket syscalls
+ */
-#include <netinet/tcp.h>
#ifndef TCP_KEYLEN_MAX
#define TCP_KEYLEN_MAX 80
#endif
@@ -248,72 +199,69 @@
* management.
*/
-static int
-sk_set_md5_auth_int(sock *s, sockaddr *sa, char *passwd)
+int
+sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
{
int enable = 0;
- if (passwd)
- {
- int len = strlen(passwd);
-
- enable = len ? TCP_SIG_SPI : 0;
- if (len > TCP_KEYLEN_MAX)
- {
- log(L_ERR "MD5 password too long");
- return -1;
- }
- }
+ if (passwd && *passwd)
+ {
+ int len = strlen(passwd);
+ enable = TCP_SIG_SPI;
- int rv = setsockopt(s->fd, IPPROTO_TCP, TCP_MD5SIG, &enable, sizeof(enable));
+ if (len > TCP_KEYLEN_MAX)
+ ERR_MSG("MD5 password too long");
+ }
- if (rv < 0)
- {
- if (errno == ENOPROTOOPT)
- log(L_ERR "Kernel does not support TCP MD5 signatures");
- else
- log(L_ERR "sk_set_md5_auth_int: setsockopt: %m");
- }
+ if (setsockopt(s->fd, IPPROTO_TCP, TCP_MD5SIG, &enable, sizeof(enable)) < 0)
+ {
+ if (errno == ENOPROTOOPT)
+ ERR_MSG("Kernel does not support TCP MD5 signatures");
+ else
+ ERR("TCP_MD5SIG");
+ }
- return rv;
+ return 0;
}
-
-#ifndef IPV6
-
-static int
+static inline int
sk_set_min_ttl4(sock *s, int ttl)
{
if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
{
if (errno == ENOPROTOOPT)
- log(L_ERR "Kernel does not support IPv4 TTL security");
+ ERR_MSG("Kernel does not support IPv4 TTL security");
else
- log(L_ERR "sk_set_min_ttl4: setsockopt: %m");
-
- return -1;
+ ERR("IP_MINTTL");
}
return 0;
}
-#else /* IPv6 */
-
-static int
+static inline int
sk_set_min_ttl6(sock *s, int ttl)
{
- log(L_ERR "IPv6 TTL security not supported");
- return -1;
+ ERR_MSG("Kernel does not support IPv6 TTL security");
}
-#endif
+static inline int
+sk_disable_mtu_disc4(sock *s)
+{
+ /* TODO: Set IP_DONTFRAG to 0 ? */
+ return 0;
+}
+static inline int
+sk_disable_mtu_disc6(sock *s)
+{
+ /* TODO: Set IPV6_DONTFRAG to 0 ? */
+ return 0;
+}
int sk_priority_control = -1;
-static int
+static inline int
sk_set_priority(sock *s, int prio UNUSED)
{
- log(L_WARN "Socket priority not supported");
- return -1;
+ ERR_MSG("Socket priority not supported");
}
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/sysdep/config.h
^
|
@@ -7,7 +7,7 @@
#define _BIRD_CONFIG_H_
/* BIRD version */
-#define BIRD_VERSION "1.4.3"
+#define BIRD_VERSION "1.4.4"
/* Include parameters determined by configure script */
#include "sysdep/autoconf.h"
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/sysdep/linux/netlink.c
^
|
@@ -104,9 +104,9 @@
req.nh.nlmsg_type = cmd;
req.nh.nlmsg_len = sizeof(req);
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
- /* Is it important which PF_* is used for link-level interface scan?
- It seems that some information is available only when PF_INET is used. */
- req.g.rtgen_family = (cmd == RTM_GETLINK) ? PF_INET : BIRD_PF;
+ /* Is it important which AF_* is used for link-level interface scan?
+ It seems that some information is available only when AF_INET is used. */
+ req.g.rtgen_family = (cmd == RTM_GETLINK) ? AF_INET : BIRD_AF;
nl_send(&nl_scan, &req.nh);
}
@@ -1069,7 +1069,7 @@
sk->type = SK_MAGIC;
sk->rx_hook = nl_async_hook;
sk->fd = fd;
- if (sk_open(sk))
+ if (sk_open(sk) < 0)
bug("Netlink: sk_open failed");
}
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/sysdep/linux/sysio.h
^
|
@@ -6,235 +6,155 @@
* Can be freely distributed and used under the terms of the GNU GPL.
*/
-#include <net/if.h>
-
-#ifdef IPV6
-
-#ifndef IPV6_UNICAST_HOPS
-/* Needed on glibc 2.0 systems */
-#include <linux/in6.h>
-#define CONFIG_IPV6_GLIBC_20
-#endif
-
-static inline void
-set_inaddr(struct in6_addr *ia, ip_addr a)
-{
- ipa_hton(a);
- memcpy(ia, &a, sizeof(a));
-}
-
-static inline void
-get_inaddr(ip_addr *a, struct in6_addr *ia)
-{
- memcpy(a, ia, sizeof(*a));
- ipa_ntoh(*a);
-}
-
-#else
-
-static inline void
-set_inaddr(struct in_addr *ia, ip_addr a)
-{
- ipa_hton(a);
- memcpy(&ia->s_addr, &a, sizeof(a));
-}
-
-static inline void
-get_inaddr(ip_addr *a, struct in_addr *ia)
-{
- memcpy(a, &ia->s_addr, sizeof(*a));
- ipa_ntoh(*a);
-}
-
#ifndef HAVE_STRUCT_IP_MREQN
/* Several versions of glibc don't define this structure, so we have to do it ourselves */
struct ip_mreqn
{
- struct in_addr imr_multiaddr; /* IP multicast address of group */
- struct in_addr imr_address; /* local IP address of interface */
- int imr_ifindex; /* Interface index */
+ struct in_addr imr_multiaddr; /* IP multicast address of group */
+ struct in_addr imr_address; /* local IP address of interface */
+ int imr_ifindex; /* Interface index */
};
#endif
+#ifndef IP_MINTTL
+#define IP_MINTTL 21
+#endif
-static inline void fill_mreqn(struct ip_mreqn *m, ip_addr maddr, struct iface *ifa)
-{
- bzero(m, sizeof(*m));
- m->imr_ifindex = ifa->index;
- set_inaddr(&m->imr_multiaddr, maddr);
-}
-
-static inline char *
-sysio_setup_multicast(sock *s)
-{
- struct ip_mreqn m;
- int zero = 0;
-
- if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
- return "IP_MULTICAST_LOOP";
-
- if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_TTL, &s->ttl, sizeof(s->ttl)) < 0)
- return "IP_MULTICAST_TTL";
-
- /* This defines where should we send _outgoing_ multicasts */
- fill_mreqn(&m, IPA_NONE, s->iface);
- if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
- return "IP_MULTICAST_IF";
-
- return NULL;
-}
-
-static inline char *
-sysio_join_group(sock *s, ip_addr maddr)
-{
- struct ip_mreqn m;
-
- /* And this one sets interface for _receiving_ multicasts from */
- fill_mreqn(&m, maddr, s->iface);
- if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &m, sizeof(m)) < 0)
- return "IP_ADD_MEMBERSHIP";
-
- return NULL;
-}
-
-static inline char *
-sysio_leave_group(sock *s, ip_addr maddr)
-{
- struct ip_mreqn m;
-
- /* And this one sets interface for _receiving_ multicasts from */
- fill_mreqn(&m, maddr, s->iface);
- if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &m, sizeof(m)) < 0)
- return "IP_DROP_MEMBERSHIP";
-
- return NULL;
-}
-
+#ifndef IPV6_TCLASS
+#define IPV6_TCLASS 67
#endif
+#ifndef IPV6_MINHOPCOUNT
+#define IPV6_MINHOPCOUNT 73
+#endif
-/* For the case that we have older libc headers */
-/* Copied from Linux kernel file include/linux/tcp.h */
#ifndef TCP_MD5SIG
#define TCP_MD5SIG 14
#define TCP_MD5SIG_MAXKEYLEN 80
-#include <linux/types.h>
-
struct tcp_md5sig {
struct sockaddr_storage tcpm_addr; /* address associated */
- __u16 __tcpm_pad1; /* zero */
- __u16 tcpm_keylen; /* key length */
- __u32 __tcpm_pad2; /* zero */
- __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
+ u16 __tcpm_pad1; /* zero */
+ u16 tcpm_keylen; /* key length */
+ u32 __tcpm_pad2; /* zero */
+ u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
};
#endif
-static int
-sk_set_md5_auth_int(sock *s, sockaddr *sa, char *passwd)
+
+/* Linux does not care if sa_len is larger than needed */
+#define SA_LEN(x) sizeof(sockaddr)
+
+
+/*
+ * Linux IPv4 multicast syscalls
+ */
+
+#define INIT_MREQ4(maddr,ifa) \
+ { .imr_multiaddr = ipa_to_in4(maddr), .imr_ifindex = ifa->index }
+
+static inline int
+sk_setup_multicast4(sock *s)
{
- struct tcp_md5sig md5;
+ struct ip_mreqn mr = { .imr_ifindex = s->iface->index };
+ int ttl = s->ttl;
+ int n = 0;
- memset(&md5, 0, sizeof(md5));
- memcpy(&md5.tcpm_addr, (struct sockaddr *) sa, sizeof(*sa));
+ /* This defines where should we send _outgoing_ multicasts */
+ if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &mr, sizeof(mr)) < 0)
+ ERR("IP_MULTICAST_IF");
- if (passwd)
- {
- int len = strlen(passwd);
+ if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
+ ERR("IP_MULTICAST_TTL");
+
+ if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &n, sizeof(n)) < 0)
+ ERR("IP_MULTICAST_LOOP");
+
+ return 0;
+}
+
+static inline int
+sk_join_group4(sock *s, ip_addr maddr)
+{
+ struct ip_mreqn mr = INIT_MREQ4(maddr, s->iface);
- if (len > TCP_MD5SIG_MAXKEYLEN)
- {
- log(L_ERR "MD5 password too long");
- return -1;
- }
+ if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0)
+ ERR("IP_ADD_MEMBERSHIP");
- md5.tcpm_keylen = len;
- memcpy(&md5.tcpm_key, passwd, len);
- }
+ return 0;
+}
- int rv = setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5));
+static inline int
+sk_leave_group4(sock *s, ip_addr maddr)
+{
+ struct ip_mreqn mr = INIT_MREQ4(maddr, s->iface);
- if (rv < 0)
- {
- if (errno == ENOPROTOOPT)
- log(L_ERR "Kernel does not support TCP MD5 signatures");
- else
- log(L_ERR "sk_set_md5_auth_int: setsockopt: %m");
- }
+ if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)) < 0)
+ ERR("IP_DROP_MEMBERSHIP");
- return rv;
+ return 0;
}
-#ifndef IPV6
+/*
+ * Linux IPv4 packet control messages
+ */
-/* RX/TX packet info handling for IPv4 */
/* Mostly similar to standardized IPv6 code */
-#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in_pktinfo)) + CMSG_SPACE(sizeof(int)))
-#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_pktinfo))
+#define CMSG4_SPACE_PKTINFO CMSG_SPACE(sizeof(struct in_pktinfo))
+#define CMSG4_SPACE_TTL CMSG_SPACE(sizeof(int))
-static char *
-sysio_register_cmsgs(sock *s)
+static inline int
+sk_request_cmsg4_pktinfo(sock *s)
{
- int ok = 1;
+ int y = 1;
- if ((s->flags & SKF_LADDR_RX) &&
- (setsockopt(s->fd, SOL_IP, IP_PKTINFO, &ok, sizeof(ok)) < 0))
- return "IP_PKTINFO";
+ if (setsockopt(s->fd, SOL_IP, IP_PKTINFO, &y, sizeof(y)) < 0)
+ ERR("IP_PKTINFO");
- if ((s->flags & SKF_TTL_RX) &&
- (setsockopt(s->fd, SOL_IP, IP_RECVTTL, &ok, sizeof(ok)) < 0))
- return "IP_RECVTTL";
-
- return NULL;
+ return 0;
}
-static void
-sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
+static inline int
+sk_request_cmsg4_ttl(sock *s)
{
- struct cmsghdr *cm;
- struct in_pktinfo *pi = NULL;
- int *ttl = NULL;
+ int y = 1;
- for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
- {
- if (cm->cmsg_level == SOL_IP && cm->cmsg_type == IP_PKTINFO)
- pi = (struct in_pktinfo *) CMSG_DATA(cm);
+ if (setsockopt(s->fd, SOL_IP, IP_RECVTTL, &y, sizeof(y)) < 0)
+ ERR("IP_RECVTTL");
- if (cm->cmsg_level == SOL_IP && cm->cmsg_type == IP_TTL)
- ttl = (int *) CMSG_DATA(cm);
- }
+ return 0;
+}
- if (s->flags & SKF_LADDR_RX)
+static inline void
+sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
+{
+ if (cm->cmsg_type == IP_PKTINFO)
{
- if (pi)
- {
- get_inaddr(&s->laddr, &pi->ipi_addr);
- s->lifindex = pi->ipi_ifindex;
- }
- else
- {
- s->laddr = IPA_NONE;
- s->lifindex = 0;
- }
+ struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cm);
+ s->laddr = ipa_from_in4(pi->ipi_addr);
+ s->lifindex = pi->ipi_ifindex;
}
+}
- if (s->flags & SKF_TTL_RX)
- s->ttl = ttl ? *ttl : -1;
-
- return;
+static inline void
+sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
+{
+ if (cm->cmsg_type == IP_TTL)
+ s->rcv_ttl = * (int *) CMSG_DATA(cm);
}
-static void
-sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
+static inline void
+sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
{
struct cmsghdr *cm;
struct in_pktinfo *pi;
+ int controllen = 0;
msg->msg_control = cbuf;
msg->msg_controllen = cbuflen;
@@ -243,81 +163,109 @@
cm->cmsg_level = SOL_IP;
cm->cmsg_type = IP_PKTINFO;
cm->cmsg_len = CMSG_LEN(sizeof(*pi));
+ controllen += CMSG_SPACE(sizeof(*pi));
pi = (struct in_pktinfo *) CMSG_DATA(cm);
pi->ipi_ifindex = s->iface ? s->iface->index : 0;
- set_inaddr(&pi->ipi_spec_dst, s->saddr);
- set_inaddr(&pi->ipi_addr, IPA_NONE);
+ pi->ipi_spec_dst = ipa_to_in4(s->saddr);
+ pi->ipi_addr = ipa_to_in4(IPA_NONE);
- msg->msg_controllen = cm->cmsg_len;
+ msg->msg_controllen = controllen;
}
-#endif
+/*
+ * Miscellaneous Linux socket syscalls
+ */
+int
+sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
+{
+ struct tcp_md5sig md5;
-#ifndef IP_MINTTL
-#define IP_MINTTL 21
-#endif
+ memset(&md5, 0, sizeof(md5));
+ sockaddr_fill((sockaddr *) &md5.tcpm_addr, s->af, a, ifa, 0);
-#ifndef IPV6_MINHOPCOUNT
-#define IPV6_MINHOPCOUNT 73
-#endif
+ if (passwd)
+ {
+ int len = strlen(passwd);
+ if (len > TCP_MD5SIG_MAXKEYLEN)
+ ERR_MSG("MD5 password too long");
+
+ md5.tcpm_keylen = len;
+ memcpy(&md5.tcpm_key, passwd, len);
+ }
+
+ if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0)
+ {
+ if (errno == ENOPROTOOPT)
+ ERR_MSG("Kernel does not support TCP MD5 signatures");
+ else
+ ERR("TCP_MD5SIG");
+ }
-#ifndef IPV6
+ return 0;
+}
-static int
+static inline int
sk_set_min_ttl4(sock *s, int ttl)
{
if (setsockopt(s->fd, SOL_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
{
if (errno == ENOPROTOOPT)
- log(L_ERR "Kernel does not support IPv4 TTL security");
+ ERR_MSG("Kernel does not support IPv4 TTL security");
else
- log(L_ERR "sk_set_min_ttl4: setsockopt: %m");
-
- return -1;
+ ERR("IP_MINTTL");
}
return 0;
}
-#else
-
-static int
+static inline int
sk_set_min_ttl6(sock *s, int ttl)
{
if (setsockopt(s->fd, SOL_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0)
{
if (errno == ENOPROTOOPT)
- log(L_ERR "Kernel does not support IPv6 TTL security");
+ ERR_MSG("Kernel does not support IPv6 TTL security");
else
- log(L_ERR "sk_set_min_ttl6: setsockopt: %m");
-
- return -1;
+ ERR("IPV6_MINHOPCOUNT");
}
return 0;
}
-#endif
+static inline int
+sk_disable_mtu_disc4(sock *s)
+{
+ int dont = IP_PMTUDISC_DONT;
+ if (setsockopt(s->fd, SOL_IP, IP_MTU_DISCOVER, &dont, sizeof(dont)) < 0)
+ ERR("IP_MTU_DISCOVER");
-#ifndef IPV6_TCLASS
-#define IPV6_TCLASS 67
-#endif
+ return 0;
+}
+
+static inline int
+sk_disable_mtu_disc6(sock *s)
+{
+ int dont = IPV6_PMTUDISC_DONT;
+
+ if (setsockopt(s->fd, SOL_IPV6, IPV6_MTU_DISCOVER, &dont, sizeof(dont)) < 0)
+ ERR("IPV6_MTU_DISCOVER");
+
+ return 0;
+}
int sk_priority_control = 7;
-static int
+static inline int
sk_set_priority(sock *s, int prio)
{
if (setsockopt(s->fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)) < 0)
- {
- log(L_WARN "sk_set_priority: setsockopt: %m");
- return -1;
- }
+ ERR("SO_PRIORITY");
return 0;
}
+
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/sysdep/unix/config.Y
^
|
@@ -35,12 +35,12 @@
;
syslog_name:
- NAME TEXT { $$ = $2; }
+ NAME text { $$ = $2; }
| { $$ = bird_name; }
;
log_file:
- TEXT {
+ text {
FILE *f = tracked_fopen(new_config->pool, $1, "a");
if (!f) cf_error("Unable to open log file `%s': %m", $1);
$$ = f;
@@ -76,7 +76,7 @@
mrtdump_base:
MRTDUMP PROTOCOLS mrtdump_mask ';' { new_config->proto_default_mrtdump = $3; }
- | MRTDUMP TEXT ';' {
+ | MRTDUMP text ';' {
FILE *f = tracked_fopen(new_config->pool, $2, "a");
if (!f) cf_error("Unable to open MRTDump file '%s': %m", $2);
new_config->mrtdump_file = fileno(f);
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/sysdep/unix/io.c
^
|
@@ -22,6 +22,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
+#include <net/if.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
@@ -470,6 +471,7 @@
strcpy(x, "<too-long>");
}
+
/**
* DOC: Sockets
*
@@ -496,234 +498,147 @@
#endif
-static list sock_list;
-static struct birdsock *current_sock;
-static struct birdsock *stored_sock;
-static int sock_recalc_fdsets_p;
+/*
+ * Sockaddr helper functions
+ */
-static inline sock *
-sk_next(sock *s)
+static inline int sockaddr_length(int af)
+{ return (af == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); }
+
+static inline void
+sockaddr_fill4(struct sockaddr_in *sa, ip_addr a, struct iface *ifa, uint port)
{
- if (!s->n.next->next)
- return NULL;
- else
- return SKIP_BACK(sock, n, s->n.next);
+ memset(sa, 0, sizeof(struct sockaddr_in));
+#ifdef HAVE_SIN_LEN
+ sa->sin_len = sizeof(struct sockaddr_in);
+#endif
+ sa->sin_family = AF_INET;
+ sa->sin_port = htons(port);
+ sa->sin_addr = ipa_to_in4(a);
}
-static void
-sk_alloc_bufs(sock *s)
+static inline void
+sockaddr_fill6(struct sockaddr_in6 *sa, ip_addr a, struct iface *ifa, uint port)
{
- if (!s->rbuf && s->rbsize)
- s->rbuf = s->rbuf_alloc = xmalloc(s->rbsize);
- s->rpos = s->rbuf;
- if (!s->tbuf && s->tbsize)
- s->tbuf = s->tbuf_alloc = xmalloc(s->tbsize);
- s->tpos = s->ttx = s->tbuf;
+ memset(sa, 0, sizeof(struct sockaddr_in6));
+#ifdef SIN6_LEN
+ sa->sin6_len = sizeof(struct sockaddr_in6);
+#endif
+ sa->sin6_family = AF_INET6;
+ sa->sin6_port = htons(port);
+ sa->sin6_flowinfo = 0;
+ sa->sin6_addr = ipa_to_in6(a);
+
+ if (ifa && ipa_is_link_local(a))
+ sa->sin6_scope_id = ifa->index;
}
-static void
-sk_free_bufs(sock *s)
+void
+sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port)
{
- if (s->rbuf_alloc)
- {
- xfree(s->rbuf_alloc);
- s->rbuf = s->rbuf_alloc = NULL;
- }
- if (s->tbuf_alloc)
- {
- xfree(s->tbuf_alloc);
- s->tbuf = s->tbuf_alloc = NULL;
- }
+ if (af == AF_INET)
+ sockaddr_fill4((struct sockaddr_in *) sa, a, ifa, port);
+ else if (af == AF_INET6)
+ sockaddr_fill6((struct sockaddr_in6 *) sa, a, ifa, port);
+ else
+ bug("Unknown AF");
}
-static void
-sk_free(resource *r)
+static inline void
+sockaddr_read4(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, uint *port)
{
- sock *s = (sock *) r;
-
- sk_free_bufs(s);
- if (s->fd >= 0)
- {
- close(s->fd);
-
- /* FIXME: we should call sk_stop() for SKF_THREAD sockets */
- if (s->flags & SKF_THREAD)
- return;
-
- if (s == current_sock)
- current_sock = sk_next(s);
- if (s == stored_sock)
- stored_sock = sk_next(s);
- rem_node(&s->n);
- sock_recalc_fdsets_p = 1;
- }
+ *port = ntohs(sa->sin_port);
+ *a = ipa_from_in4(sa->sin_addr);
}
-void
-sk_set_rbsize(sock *s, uint val)
+static inline void
+sockaddr_read6(struct sockaddr_in6 *sa, ip_addr *a, struct iface **ifa, uint *port)
{
- ASSERT(s->rbuf_alloc == s->rbuf);
-
- if (s->rbsize == val)
- return;
+ *port = ntohs(sa->sin6_port);
+ *a = ipa_from_in6(sa->sin6_addr);
- s->rbsize = val;
- xfree(s->rbuf_alloc);
- s->rbuf_alloc = xmalloc(val);
- s->rpos = s->rbuf = s->rbuf_alloc;
+ if (ifa && ipa_is_link_local(*a))
+ *ifa = if_find_by_index(sa->sin6_scope_id);
}
-void
-sk_set_tbsize(sock *s, uint val)
+int
+sockaddr_read(sockaddr *sa, int af, ip_addr *a, struct iface **ifa, uint *port)
{
- ASSERT(s->tbuf_alloc == s->tbuf);
+ if (sa->sa.sa_family != af)
+ goto fail;
- if (s->tbsize == val)
- return;
+ if (af == AF_INET)
+ sockaddr_read4((struct sockaddr_in *) sa, a, ifa, port);
+ else if (af == AF_INET6)
+ sockaddr_read6((struct sockaddr_in6 *) sa, a, ifa, port);
+ else
+ goto fail;
- byte *old_tbuf = s->tbuf;
+ return 0;
- s->tbsize = val;
- s->tbuf = s->tbuf_alloc = xrealloc(s->tbuf_alloc, val);
- s->tpos = s->tbuf + (s->tpos - old_tbuf);
- s->ttx = s->tbuf + (s->ttx - old_tbuf);
+ fail:
+ *a = IPA_NONE;
+ *port = 0;
+ return -1;
}
-void
-sk_set_tbuf(sock *s, void *tbuf)
-{
- s->tbuf = tbuf ?: s->tbuf_alloc;
- s->ttx = s->tpos = s->tbuf;
-}
-void
-sk_reallocate(sock *s)
-{
- sk_free_bufs(s);
- sk_alloc_bufs(s);
-}
+/*
+ * IPv6 multicast syscalls
+ */
-static void
-sk_dump(resource *r)
-{
- sock *s = (sock *) r;
- static char *sk_type_names[] = { "TCP<", "TCP>", "TCP", "UDP", "UDP/MC", "IP", "IP/MC", "MAGIC", "UNIX<", "UNIX", "DEL!" };
+/* Fortunately standardized in RFC 3493 */
- debug("(%s, ud=%p, sa=%08x, sp=%d, da=%08x, dp=%d, tos=%d, ttl=%d, if=%s)\n",
- sk_type_names[s->type],
- s->data,
- s->saddr,
- s->sport,
- s->daddr,
- s->dport,
- s->tos,
- s->ttl,
- s->iface ? s->iface->name : "none");
-}
+#define INIT_MREQ6(maddr,ifa) \
+ { .ipv6mr_multiaddr = ipa_to_in6(maddr), .ipv6mr_interface = ifa->index }
-static struct resclass sk_class = {
- "Socket",
- sizeof(sock),
- sk_free,
- sk_dump,
- NULL,
- NULL
-};
-
-/**
- * sk_new - create a socket
- * @p: pool
- *
- * This function creates a new socket resource. If you want to use it,
- * you need to fill in all the required fields of the structure and
- * call sk_open() to do the actual opening of the socket.
- *
- * The real function name is sock_new(), sk_new() is a macro wrapper
- * to avoid collision with OpenSSL.
- */
-sock *
-sock_new(pool *p)
+static inline int
+sk_setup_multicast6(sock *s)
{
- sock *s = ralloc(p, &sk_class);
- s->pool = p;
- // s->saddr = s->daddr = IPA_NONE;
- s->tos = s->priority = s->ttl = -1;
- s->fd = -1;
- return s;
-}
+ int index = s->iface->index;
+ int ttl = s->ttl;
+ int n = 0;
-static void
-sk_insert(sock *s)
-{
- add_tail(&sock_list, &s->n);
- sock_recalc_fdsets_p = 1;
-}
+ if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index)) < 0)
+ ERR("IPV6_MULTICAST_IF");
-#ifdef IPV6
+ if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) < 0)
+ ERR("IPV6_MULTICAST_HOPS");
-void
-fill_in_sockaddr(struct sockaddr_in6 *sa, ip_addr a, struct iface *ifa, unsigned port)
-{
- memset(sa, 0, sizeof (struct sockaddr_in6));
- sa->sin6_family = AF_INET6;
- sa->sin6_port = htons(port);
- sa->sin6_flowinfo = 0;
-#ifdef HAVE_SIN_LEN
- sa->sin6_len = sizeof(struct sockaddr_in6);
-#endif
- set_inaddr(&sa->sin6_addr, a);
+ if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &n, sizeof(n)) < 0)
+ ERR("IPV6_MULTICAST_LOOP");
- if (ifa && ipa_has_link_scope(a))
- sa->sin6_scope_id = ifa->index;
+ return 0;
}
-void
-get_sockaddr(struct sockaddr_in6 *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check)
+static inline int
+sk_join_group6(sock *s, ip_addr maddr)
{
- if (check && sa->sin6_family != AF_INET6)
- bug("get_sockaddr called for wrong address family (%d)", sa->sin6_family);
- if (port)
- *port = ntohs(sa->sin6_port);
- memcpy(a, &sa->sin6_addr, sizeof(*a));
- ipa_ntoh(*a);
+ struct ipv6_mreq mr = INIT_MREQ6(maddr, s->iface);
- if (ifa && ipa_has_link_scope(*a))
- *ifa = if_find_by_index(sa->sin6_scope_id);
-}
-
-#else
+ if (setsockopt(s->fd, SOL_IPV6, IPV6_JOIN_GROUP, &mr, sizeof(mr)) < 0)
+ ERR("IPV6_JOIN_GROUP");
-void
-fill_in_sockaddr(struct sockaddr_in *sa, ip_addr a, struct iface *ifa, unsigned port)
-{
- memset (sa, 0, sizeof (struct sockaddr_in));
- sa->sin_family = AF_INET;
- sa->sin_port = htons(port);
-#ifdef HAVE_SIN_LEN
- sa->sin_len = sizeof(struct sockaddr_in);
-#endif
- set_inaddr(&sa->sin_addr, a);
+ return 0;
}
-void
-get_sockaddr(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check)
+static inline int
+sk_leave_group6(sock *s, ip_addr maddr)
{
- if (check && sa->sin_family != AF_INET)
- bug("get_sockaddr called for wrong address family (%d)", sa->sin_family);
- if (port)
- *port = ntohs(sa->sin_port);
- memcpy(a, &sa->sin_addr.s_addr, sizeof(*a));
- ipa_ntoh(*a);
-}
+ struct ipv6_mreq mr = INIT_MREQ6(maddr, s->iface);
-#endif
+ if (setsockopt(s->fd, SOL_IPV6, IPV6_LEAVE_GROUP, &mr, sizeof(mr)) < 0)
+ ERR("IPV6_LEAVE_GROUP");
+ return 0;
+}
-#ifdef IPV6
-/* PKTINFO handling is also standardized in IPv6 */
-#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)))
-#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in6_pktinfo))
+/*
+ * IPv6 packet control messages
+ */
+
+/* Also standardized, in RFC 3542 */
/*
* RFC 2292 uses IPV6_PKTINFO for both the socket option and the cmsg
@@ -741,63 +656,56 @@
#define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
#endif
-static char *
-sysio_register_cmsgs(sock *s)
-{
- int ok = 1;
- if ((s->flags & SKF_LADDR_RX) &&
- (setsockopt(s->fd, SOL_IPV6, IPV6_RECVPKTINFO, &ok, sizeof(ok)) < 0))
- return "IPV6_RECVPKTINFO";
+#define CMSG6_SPACE_PKTINFO CMSG_SPACE(sizeof(struct in6_pktinfo))
+#define CMSG6_SPACE_TTL CMSG_SPACE(sizeof(int))
- if ((s->flags & SKF_TTL_RX) &&
- (setsockopt(s->fd, SOL_IPV6, IPV6_RECVHOPLIMIT, &ok, sizeof(ok)) < 0))
- return "IPV6_RECVHOPLIMIT";
+static inline int
+sk_request_cmsg6_pktinfo(sock *s)
+{
+ int y = 1;
+
+ if (setsockopt(s->fd, SOL_IPV6, IPV6_RECVPKTINFO, &y, sizeof(y)) < 0)
+ ERR("IPV6_RECVPKTINFO");
- return NULL;
+ return 0;
}
-static void
-sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
+static inline int
+sk_request_cmsg6_ttl(sock *s)
{
- struct cmsghdr *cm;
- struct in6_pktinfo *pi = NULL;
- int *hlim = NULL;
+ int y = 1;
- for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
- {
- if (cm->cmsg_level == SOL_IPV6 && cm->cmsg_type == IPV6_PKTINFO)
- pi = (struct in6_pktinfo *) CMSG_DATA(cm);
+ if (setsockopt(s->fd, SOL_IPV6, IPV6_RECVHOPLIMIT, &y, sizeof(y)) < 0)
+ ERR("IPV6_RECVHOPLIMIT");
- if (cm->cmsg_level == SOL_IPV6 && cm->cmsg_type == IPV6_HOPLIMIT)
- hlim = (int *) CMSG_DATA(cm);
- }
+ return 0;
+}
- if (s->flags & SKF_LADDR_RX)
+static inline void
+sk_process_cmsg6_pktinfo(sock *s, struct cmsghdr *cm)
+{
+ if (cm->cmsg_type == IPV6_PKTINFO)
{
- if (pi)
- {
- get_inaddr(&s->laddr, &pi->ipi6_addr);
- s->lifindex = pi->ipi6_ifindex;
- }
- else
- {
- s->laddr = IPA_NONE;
- s->lifindex = 0;
- }
+ struct in6_pktinfo *pi = (struct in6_pktinfo *) CMSG_DATA(cm);
+ s->laddr = ipa_from_in6(pi->ipi6_addr);
+ s->lifindex = pi->ipi6_ifindex;
}
+}
- if (s->flags & SKF_TTL_RX)
- s->ttl = hlim ? *hlim : -1;
-
- return;
+static inline void
+sk_process_cmsg6_ttl(sock *s, struct cmsghdr *cm)
+{
+ if (cm->cmsg_type == IPV6_HOPLIMIT)
+ s->rcv_ttl = * (int *) CMSG_DATA(cm);
}
-static void
-sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
+static inline void
+sk_prepare_cmsgs6(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
{
struct cmsghdr *cm;
struct in6_pktinfo *pi;
+ int controllen = 0;
msg->msg_control = cbuf;
msg->msg_controllen = cbuflen;
@@ -806,107 +714,151 @@
cm->cmsg_level = SOL_IPV6;
cm->cmsg_type = IPV6_PKTINFO;
cm->cmsg_len = CMSG_LEN(sizeof(*pi));
+ controllen += CMSG_SPACE(sizeof(*pi));
pi = (struct in6_pktinfo *) CMSG_DATA(cm);
pi->ipi6_ifindex = s->iface ? s->iface->index : 0;
- set_inaddr(&pi->ipi6_addr, s->saddr);
+ pi->ipi6_addr = ipa_to_in6(s->saddr);
- msg->msg_controllen = cm->cmsg_len;
+ msg->msg_controllen = controllen;
}
-#endif
-static char *
-sk_set_ttl_int(sock *s)
+/*
+ * Miscellaneous socket syscalls
+ */
+
+static inline int
+sk_set_ttl4(sock *s, int ttl)
{
-#ifdef IPV6
- if (setsockopt(s->fd, SOL_IPV6, IPV6_UNICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
- return "IPV6_UNICAST_HOPS";
-#else
- if (setsockopt(s->fd, SOL_IP, IP_TTL, &s->ttl, sizeof(s->ttl)) < 0)
- return "IP_TTL";
-#endif
- return NULL;
+ if (setsockopt(s->fd, SOL_IP, IP_TTL, &ttl, sizeof(ttl)) < 0)
+ ERR("IP_TTL");
+
+ return 0;
}
-#define ERR(x) do { err = x; goto bad; } while(0)
-#define WARN(x) log(L_WARN "sk_setup: %s: %m", x)
+static inline int
+sk_set_ttl6(sock *s, int ttl)
+{
+ if (setsockopt(s->fd, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)) < 0)
+ ERR("IPV6_UNICAST_HOPS");
-static char *
-sk_setup(sock *s)
+ return 0;
+}
+
+static inline int
+sk_set_tos4(sock *s, int tos)
{
- int one = 1;
- int fd = s->fd;
- char *err = NULL;
+ if (setsockopt(s->fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0)
+ ERR("IP_TOS");
- if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
- ERR("fcntl(O_NONBLOCK)");
- if (s->type == SK_UNIX)
- return NULL;
+ return 0;
+}
- if (ipa_nonzero(s->saddr) && !(s->flags & SKF_BIND))
- s->flags |= SKF_PKTINFO;
+static inline int
+sk_set_tos6(sock *s, int tos)
+{
+ if (setsockopt(s->fd, SOL_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0)
+ ERR("IPV6_TCLASS");
-#ifdef CONFIG_USE_HDRINCL
- if ((s->type == SK_IP) && (s->flags & SKF_PKTINFO))
- {
- s->flags &= ~SKF_PKTINFO;
- s->flags |= SKF_HDRINCL;
- if (setsockopt(fd, SOL_IP, IP_HDRINCL, &one, sizeof(one)) < 0)
- ERR("IP_HDRINCL");
- }
-#endif
+ return 0;
+}
- if (s->iface)
- {
-#ifdef SO_BINDTODEVICE
- struct ifreq ifr;
- strcpy(ifr.ifr_name, s->iface->name);
- if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
- ERR("SO_BINDTODEVICE");
-#endif
-#ifdef CONFIG_UNIX_DONTROUTE
- if (setsockopt(s->fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
- ERR("SO_DONTROUTE");
-#endif
- }
+/*
+ * Public socket functions
+ */
- if ((s->ttl >= 0) && (err = sk_set_ttl_int(s)))
- goto bad;
+/**
+ * sk_setup_multicast - enable multicast for given socket
+ * @s: socket
+ *
+ * Prepare transmission of multicast packets for given datagram socket.
+ * The socket must have defined @iface.
+ *
+ * Result: 0 for success, -1 for an error.
+ */
- if (err = sysio_register_cmsgs(s))
- goto bad;
+int
+sk_setup_multicast(sock *s)
+{
+ ASSERT(s->iface);
+ if (sk_is_ipv4(s))
+ return sk_setup_multicast4(s);
+ else
+ return sk_setup_multicast6(s);
+}
-#ifdef IPV6
- if ((s->tos >= 0) && setsockopt(fd, SOL_IPV6, IPV6_TCLASS, &s->tos, sizeof(s->tos)) < 0)
- WARN("IPV6_TCLASS");
-#else
- if ((s->tos >= 0) && setsockopt(fd, SOL_IP, IP_TOS, &s->tos, sizeof(s->tos)) < 0)
- WARN("IP_TOS");
-#endif
+/**
+ * sk_join_group - join multicast group for given socket
+ * @s: socket
+ * @maddr: multicast address
+ *
+ * Join multicast group for given datagram socket and associated interface.
+ * The socket must have defined @iface.
+ *
+ * Result: 0 for success, -1 for an error.
+ */
- if (s->priority >= 0)
- sk_set_priority(s, s->priority);
+int
+sk_join_group(sock *s, ip_addr maddr)
+{
+ if (sk_is_ipv4(s))
+ return sk_join_group4(s, maddr);
+ else
+ return sk_join_group6(s, maddr);
+}
-#ifdef IPV6
- if ((s->flags & SKF_V6ONLY) && setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &one, sizeof(one)) < 0)
- WARN("IPV6_V6ONLY");
-#endif
+/**
+ * sk_leave_group - leave multicast group for given socket
+ * @s: socket
+ * @maddr: multicast address
+ *
+ * Leave multicast group for given datagram socket and associated interface.
+ * The socket must have defined @iface.
+ *
+ * Result: 0 for success, -1 for an error.
+ */
-bad:
- return err;
+int
+sk_leave_group(sock *s, ip_addr maddr)
+{
+ if (sk_is_ipv4(s))
+ return sk_leave_group4(s, maddr);
+ else
+ return sk_leave_group6(s, maddr);
+}
+
+/**
+ * sk_setup_broadcast - enable broadcast for given socket
+ * @s: socket
+ *
+ * Allow reception and transmission of broadcast packets for given datagram
+ * socket. The socket must have defined @iface. For transmission, packets should
+ * be send to @brd address of @iface.
+ *
+ * Result: 0 for success, -1 for an error.
+ */
+
+int
+sk_setup_broadcast(sock *s)
+{
+ int y = 1;
+
+ if (setsockopt(s->fd, SOL_SOCKET, SO_BROADCAST, &y, sizeof(y)) < 0)
+ ERR("SO_BROADCAST");
+
+ return 0;
}
/**
- * sk_set_ttl - set transmit TTL for given socket.
+ * sk_set_ttl - set transmit TTL for given socket
* @s: socket
* @ttl: TTL value
*
- * Set TTL for already opened connections when TTL was not set before.
- * Useful for accepted connections when different ones should have
- * different TTL.
+ * Set TTL for already opened connections when TTL was not set before. Useful
+ * for accepted connections when different ones should have different TTL.
*
* Result: 0 for success, -1 for an error.
*/
@@ -914,21 +866,21 @@
int
sk_set_ttl(sock *s, int ttl)
{
- char *err;
-
s->ttl = ttl;
- if (err = sk_set_ttl_int(s))
- log(L_ERR "sk_set_ttl: %s: %m", err);
- return (err ? -1 : 0);
+ if (sk_is_ipv4(s))
+ return sk_set_ttl4(s, ttl);
+ else
+ return sk_set_ttl6(s, ttl);
}
/**
- * sk_set_min_ttl - set minimal accepted TTL for given socket.
+ * sk_set_min_ttl - set minimal accepted TTL for given socket
* @s: socket
* @ttl: TTL value
*
- * Can be used in TTL security implementation
+ * Set minimal accepted TTL for given socket. Can be used for TTL security.
+ * implementations.
*
* Result: 0 for success, -1 for an error.
*/
@@ -936,28 +888,24 @@
int
sk_set_min_ttl(sock *s, int ttl)
{
- int err;
-#ifdef IPV6
- err = sk_set_min_ttl6(s, ttl);
-#else
- err = sk_set_min_ttl4(s, ttl);
-#endif
-
- return err;
+ if (sk_is_ipv4(s))
+ return sk_set_min_ttl4(s, ttl);
+ else
+ return sk_set_min_ttl6(s, ttl);
}
+#if 0
/**
- * sk_set_md5_auth - add / remove MD5 security association for given socket.
+ * sk_set_md5_auth - add / remove MD5 security association for given socket
* @s: socket
* @a: IP address of the other side
* @ifa: Interface for link-local IP address
* @passwd: password used for MD5 authentication
*
- * In TCP MD5 handling code in kernel, there is a set of pairs
- * (address, password) used to choose password according to
- * address of the other side. This function is useful for
- * listening socket, for active sockets it is enough to set
- * s->password field.
+ * In TCP MD5 handling code in kernel, there is a set of pairs (address,
+ * password) used to choose password according to address of the other side.
+ * This function is useful for listening socket, for active sockets it is enough
+ * to set s->password field.
*
* When called with passwd != NULL, the new pair is added,
* When called with passwd == NULL, the existing pair is removed.
@@ -967,41 +915,33 @@
int
sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
-{
- sockaddr sa;
- fill_in_sockaddr(&sa, a, ifa, 0);
- return sk_set_md5_auth_int(s, &sa, passwd);
-}
-
-int
-sk_set_broadcast(sock *s, int enable)
-{
- if (setsockopt(s->fd, SOL_SOCKET, SO_BROADCAST, &enable, sizeof(enable)) < 0)
- {
- log(L_ERR "sk_set_broadcast: SO_BROADCAST: %m");
- return -1;
- }
-
- return 0;
-}
-
+{ DUMMY; }
+#endif
-#ifdef IPV6
+/**
+ * sk_set_ipv6_checksum - specify IPv6 checksum offset for given socket
+ * @s: socket
+ * @offset: offset
+ *
+ * Specify IPv6 checksum field offset for given raw IPv6 socket. After that, the
+ * kernel will automatically fill it for outgoing packets and check it for
+ * incoming packets. Should not be used on ICMPv6 sockets, where the position is
+ * known to the kernel.
+ *
+ * Result: 0 for success, -1 for an error.
+ */
int
sk_set_ipv6_checksum(sock *s, int offset)
{
if (setsockopt(s->fd, SOL_IPV6, IPV6_CHECKSUM, &offset, sizeof(offset)) < 0)
- {
- log(L_ERR "sk_set_ipv6_checksum: IPV6_CHECKSUM: %m");
- return -1;
- }
+ ERR("IPV6_CHECKSUM");
return 0;
}
int
-sk_set_icmp_filter(sock *s, int p1, int p2)
+sk_set_icmp6_filter(sock *s, int p1, int p2)
{
/* a bit of lame interface, but it is here only for Radv */
struct icmp6_filter f;
@@ -1011,132 +951,291 @@
ICMP6_FILTER_SETPASS(p2, &f);
if (setsockopt(s->fd, SOL_ICMPV6, ICMP6_FILTER, &f, sizeof(f)) < 0)
- {
- log(L_ERR "sk_setup_icmp_filter: ICMP6_FILTER: %m");
- return -1;
- }
+ ERR("ICMP6_FILTER");
return 0;
}
-int
-sk_setup_multicast(sock *s)
+void
+sk_log_error(sock *s, const char *p)
{
- char *err;
- int zero = 0;
- int index;
+ log(L_ERR "%s: Socket error: %s%#m", p, s->err);
+}
- ASSERT(s->iface);
- index = s->iface->index;
- if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
- ERR("IPV6_MULTICAST_HOPS");
- if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
- ERR("IPV6_MULTICAST_LOOP");
- if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index)) < 0)
- ERR("IPV6_MULTICAST_IF");
+/*
+ * Actual struct birdsock code
+ */
- return 0;
+static list sock_list;
+static struct birdsock *current_sock;
+static struct birdsock *stored_sock;
+static int sock_recalc_fdsets_p;
-bad:
- log(L_ERR "sk_setup_multicast: %s: %m", err);
- return -1;
+static inline sock *
+sk_next(sock *s)
+{
+ if (!s->n.next->next)
+ return NULL;
+ else
+ return SKIP_BACK(sock, n, s->n.next);
}
-#ifdef CONFIG_IPV6_GLIBC_20
-#define ipv6mr_interface ipv6mr_ifindex
-#endif
+static void
+sk_alloc_bufs(sock *s)
+{
+ if (!s->rbuf && s->rbsize)
+ s->rbuf = s->rbuf_alloc = xmalloc(s->rbsize);
+ s->rpos = s->rbuf;
+ if (!s->tbuf && s->tbsize)
+ s->tbuf = s->tbuf_alloc = xmalloc(s->tbsize);
+ s->tpos = s->ttx = s->tbuf;
+}
+
+static void
+sk_free_bufs(sock *s)
+{
+ if (s->rbuf_alloc)
+ {
+ xfree(s->rbuf_alloc);
+ s->rbuf = s->rbuf_alloc = NULL;
+ }
+ if (s->tbuf_alloc)
+ {
+ xfree(s->tbuf_alloc);
+ s->tbuf = s->tbuf_alloc = NULL;
+ }
+}
+
+static void
+sk_free(resource *r)
+{
+ sock *s = (sock *) r;
+
+ sk_free_bufs(s);
+ if (s->fd >= 0)
+ {
+ close(s->fd);
+
+ /* FIXME: we should call sk_stop() for SKF_THREAD sockets */
+ if (s->flags & SKF_THREAD)
+ return;
+
+ if (s == current_sock)
+ current_sock = sk_next(s);
+ if (s == stored_sock)
+ stored_sock = sk_next(s);
+ rem_node(&s->n);
+ sock_recalc_fdsets_p = 1;
+ }
+}
+
+void
+sk_set_rbsize(sock *s, uint val)
+{
+ ASSERT(s->rbuf_alloc == s->rbuf);
+
+ if (s->rbsize == val)
+ return;
+
+ s->rbsize = val;
+ xfree(s->rbuf_alloc);
+ s->rbuf_alloc = xmalloc(val);
+ s->rpos = s->rbuf = s->rbuf_alloc;
+}
+
+void
+sk_set_tbsize(sock *s, uint val)
+{
+ ASSERT(s->tbuf_alloc == s->tbuf);
+
+ if (s->tbsize == val)
+ return;
+
+ byte *old_tbuf = s->tbuf;
+
+ s->tbsize = val;
+ s->tbuf = s->tbuf_alloc = xrealloc(s->tbuf_alloc, val);
+ s->tpos = s->tbuf + (s->tpos - old_tbuf);
+ s->ttx = s->tbuf + (s->ttx - old_tbuf);
+}
+
+void
+sk_set_tbuf(sock *s, void *tbuf)
+{
+ s->tbuf = tbuf ?: s->tbuf_alloc;
+ s->ttx = s->tpos = s->tbuf;
+}
+
+void
+sk_reallocate(sock *s)
+{
+ sk_free_bufs(s);
+ sk_alloc_bufs(s);
+}
+
+static void
+sk_dump(resource *r)
+{
+ sock *s = (sock *) r;
+ static char *sk_type_names[] = { "TCP<", "TCP>", "TCP", "UDP", NULL, "IP", NULL, "MAGIC", "UNIX<", "UNIX", "DEL!" };
+
+ debug("(%s, ud=%p, sa=%08x, sp=%d, da=%08x, dp=%d, tos=%d, ttl=%d, if=%s)\n",
+ sk_type_names[s->type],
+ s->data,
+ s->saddr,
+ s->sport,
+ s->daddr,
+ s->dport,
+ s->tos,
+ s->ttl,
+ s->iface ? s->iface->name : "none");
+}
+
+static struct resclass sk_class = {
+ "Socket",
+ sizeof(sock),
+ sk_free,
+ sk_dump,
+ NULL,
+ NULL
+};
-int
-sk_join_group(sock *s, ip_addr maddr)
+/**
+ * sk_new - create a socket
+ * @p: pool
+ *
+ * This function creates a new socket resource. If you want to use it,
+ * you need to fill in all the required fields of the structure and
+ * call sk_open() to do the actual opening of the socket.
+ *
+ * The real function name is sock_new(), sk_new() is a macro wrapper
+ * to avoid collision with OpenSSL.
+ */
+sock *
+sock_new(pool *p)
{
- struct ipv6_mreq mreq;
-
- set_inaddr(&mreq.ipv6mr_multiaddr, maddr);
- mreq.ipv6mr_interface = s->iface->index;
-
- if (setsockopt(s->fd, SOL_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) < 0)
- {
- log(L_ERR "sk_join_group: IPV6_JOIN_GROUP: %m");
- return -1;
- }
-
- return 0;
+ sock *s = ralloc(p, &sk_class);
+ s->pool = p;
+ // s->saddr = s->daddr = IPA_NONE;
+ s->tos = s->priority = s->ttl = -1;
+ s->fd = -1;
+ return s;
}
-int
-sk_leave_group(sock *s, ip_addr maddr)
+static int
+sk_setup(sock *s)
{
- struct ipv6_mreq mreq;
-
- set_inaddr(&mreq.ipv6mr_multiaddr, maddr);
- mreq.ipv6mr_interface = s->iface->index;
+ int y = 1;
+ int fd = s->fd;
- if (setsockopt(s->fd, SOL_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)) < 0)
- {
- log(L_ERR "sk_leave_group: IPV6_LEAVE_GROUP: %m");
- return -1;
- }
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
+ ERR("O_NONBLOCK");
- return 0;
-}
+ if (!s->af)
+ return 0;
-#else /* IPV4 */
+ if (ipa_nonzero(s->saddr) && !(s->flags & SKF_BIND))
+ s->flags |= SKF_PKTINFO;
-int
-sk_setup_multicast(sock *s)
-{
- char *err;
+#ifdef CONFIG_USE_HDRINCL
+ if (sk_is_ipv4(s) && (s->type == SK_IP) && (s->flags & SKF_PKTINFO))
+ {
+ s->flags &= ~SKF_PKTINFO;
+ s->flags |= SKF_HDRINCL;
+ if (setsockopt(fd, SOL_IP, IP_HDRINCL, &y, sizeof(y)) < 0)
+ ERR("IP_HDRINCL");
+ }
+#endif
- ASSERT(s->iface);
+ if (s->iface)
+ {
+#ifdef SO_BINDTODEVICE
+ struct ifreq ifr;
+ strcpy(ifr.ifr_name, s->iface->name);
+ if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
+ ERR("SO_BINDTODEVICE");
+#endif
- if (err = sysio_setup_multicast(s))
- {
- log(L_ERR "sk_setup_multicast: %s: %m", err);
- return -1;
- }
+#ifdef CONFIG_UNIX_DONTROUTE
+ if (setsockopt(s->fd, SOL_SOCKET, SO_DONTROUTE, &y, sizeof(y)) < 0)
+ ERR("SO_DONTROUTE");
+#endif
+ }
- return 0;
-}
+ if (s->priority >= 0)
+ if (sk_set_priority(s, s->priority) < 0)
+ return -1;
-int
-sk_join_group(sock *s, ip_addr maddr)
-{
- char *err;
+ if (sk_is_ipv4(s))
+ {
+ if (s->flags & SKF_LADDR_RX)
+ if (sk_request_cmsg4_pktinfo(s) < 0)
+ return -1;
+
+ if (s->flags & SKF_TTL_RX)
+ if (sk_request_cmsg4_ttl(s) < 0)
+ return -1;
+
+ if ((s->type == SK_UDP) || (s->type == SK_IP))
+ if (sk_disable_mtu_disc4(s) < 0)
+ return -1;
+
+ if (s->ttl >= 0)
+ if (sk_set_ttl4(s, s->ttl) < 0)
+ return -1;
+
+ if (s->tos >= 0)
+ if (sk_set_tos4(s, s->tos) < 0)
+ return -1;
+ }
- if (err = sysio_join_group(s, maddr))
- {
- log(L_ERR "sk_join_group: %s: %m", err);
- return -1;
- }
+ if (sk_is_ipv6(s))
+ {
+ if (s->flags & SKF_V6ONLY)
+ if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &y, sizeof(y)) < 0)
+ ERR("IPV6_V6ONLY");
+
+ if (s->flags & SKF_LADDR_RX)
+ if (sk_request_cmsg6_pktinfo(s) < 0)
+ return -1;
+
+ if (s->flags & SKF_TTL_RX)
+ if (sk_request_cmsg6_ttl(s) < 0)
+ return -1;
+
+ if ((s->type == SK_UDP) || (s->type == SK_IP))
+ if (sk_disable_mtu_disc6(s) < 0)
+ return -1;
+
+ if (s->ttl >= 0)
+ if (sk_set_ttl6(s, s->ttl) < 0)
+ return -1;
+
+ if (s->tos >= 0)
+ if (sk_set_tos6(s, s->tos) < 0)
+ return -1;
+ }
return 0;
}
-int
-sk_leave_group(sock *s, ip_addr maddr)
+static void
+sk_insert(sock *s)
{
- char *err;
-
- if (err = sysio_leave_group(s, maddr))
- {
- log(L_ERR "sk_leave_group: %s: %m", err);
- return -1;
- }
-
- return 0;
+ add_tail(&sock_list, &s->n);
+ sock_recalc_fdsets_p = 1;
}
-#endif
-
-
static void
sk_tcp_connected(sock *s)
{
- sockaddr lsa;
- int lsa_len = sizeof(lsa);
- if (getsockname(s->fd, (struct sockaddr *) &lsa, &lsa_len) == 0)
- get_sockaddr(&lsa, &s->saddr, &s->iface, &s->sport, 1);
+ sockaddr sa;
+ int sa_len = sizeof(sa);
+
+ if ((getsockname(s->fd, &sa.sa, &sa_len) < 0) ||
+ (sockaddr_read(&sa, s->af, &s->saddr, &s->iface, &s->sport) < 0))
+ log(L_WARN "SOCK: Cannot get local IP address for TCP>");
s->type = SK_TCP;
sk_alloc_bufs(s);
@@ -1144,44 +1243,55 @@
}
static int
-sk_passive_connected(sock *s, struct sockaddr *sa, int al, int type)
+sk_passive_connected(sock *s, int type)
{
- int fd = accept(s->fd, sa, &al);
- if (fd >= 0)
- {
- sock *t = sk_new(s->pool);
- char *err;
- t->type = type;
- t->fd = fd;
- t->ttl = s->ttl;
- t->tos = s->tos;
- t->rbsize = s->rbsize;
- t->tbsize = s->tbsize;
- if (type == SK_TCP)
- {
- sockaddr lsa;
- int lsa_len = sizeof(lsa);
- if (getsockname(fd, (struct sockaddr *) &lsa, &lsa_len) == 0)
- get_sockaddr(&lsa, &t->saddr, &t->iface, &t->sport, 1);
+ sockaddr loc_sa, rem_sa;
+ int loc_sa_len = sizeof(loc_sa);
+ int rem_sa_len = sizeof(rem_sa);
- get_sockaddr((sockaddr *) sa, &t->daddr, &t->iface, &t->dport, 1);
- }
- sk_insert(t);
- if (err = sk_setup(t))
- {
- log(L_ERR "Incoming connection: %s: %m", err);
- rfree(t);
- return 1;
- }
- sk_alloc_bufs(t);
- s->rx_hook(t, 0);
- return 1;
- }
- else if (errno != EINTR && errno != EAGAIN)
- {
+ int fd = accept(s->fd, ((type == SK_TCP) ? &rem_sa.sa : NULL), &rem_sa_len);
+ if (fd < 0)
+ {
+ if ((errno != EINTR) && (errno != EAGAIN))
s->err_hook(s, errno);
- }
- return 0;
+ return 0;
+ }
+
+ sock *t = sk_new(s->pool);
+ t->type = type;
+ t->fd = fd;
+ t->af = s->af;
+ t->ttl = s->ttl;
+ t->tos = s->tos;
+ t->rbsize = s->rbsize;
+ t->tbsize = s->tbsize;
+
+ if (type == SK_TCP)
+ {
+ if ((getsockname(fd, &loc_sa.sa, &loc_sa_len) < 0) ||
+ (sockaddr_read(&loc_sa, s->af, &t->saddr, &t->iface, &t->sport) < 0))
+ log(L_WARN "SOCK: Cannot get local IP address for TCP<");
+
+ if (sockaddr_read(&rem_sa, s->af, &t->daddr, &t->iface, &t->dport) < 0)
+ log(L_WARN "SOCK: Cannot get remote IP address for TCP<");
+ }
+
+ if (sk_setup(t) < 0)
+ {
+ /* FIXME: Call err_hook instead ? */
+ log(L_ERR "SOCK: Incoming connection: %s%#m", t->err);
+
+ /* FIXME: handle it better in rfree() */
+ close(t->fd);
+ t->fd = -1;
+ rfree(t);
+ return 1;
+ }
+
+ sk_insert(t);
+ sk_alloc_bufs(t);
+ s->rx_hook(t, 0);
+ return 1;
}
/**
@@ -1197,161 +1307,185 @@
int
sk_open(sock *s)
{
- int fd;
- int one = 1;
+ int af = BIRD_AF;
+ int fd = -1;
int do_bind = 0;
int bind_port = 0;
ip_addr bind_addr = IPA_NONE;
sockaddr sa;
- char *err;
switch (s->type)
- {
- case SK_TCP_ACTIVE:
- s->ttx = ""; /* Force s->ttx != s->tpos */
- /* Fall thru */
- case SK_TCP_PASSIVE:
- fd = socket(BIRD_PF, SOCK_STREAM, IPPROTO_TCP);
- bind_port = s->sport;
- bind_addr = s->saddr;
- do_bind = bind_port || ipa_nonzero(bind_addr);
- break;
-
- case SK_UDP:
- fd = socket(BIRD_PF, SOCK_DGRAM, IPPROTO_UDP);
- bind_port = s->sport;
- bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
- do_bind = 1;
- break;
-
- case SK_IP:
- fd = socket(BIRD_PF, SOCK_RAW, s->dport);
- bind_port = 0;
- bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
- do_bind = ipa_nonzero(bind_addr);
- break;
-
- case SK_MAGIC:
- fd = s->fd;
- break;
+ {
+ case SK_TCP_ACTIVE:
+ s->ttx = ""; /* Force s->ttx != s->tpos */
+ /* Fall thru */
+ case SK_TCP_PASSIVE:
+ fd = socket(af, SOCK_STREAM, IPPROTO_TCP);
+ bind_port = s->sport;
+ bind_addr = s->saddr;
+ do_bind = bind_port || ipa_nonzero(bind_addr);
+ break;
+
+ case SK_UDP:
+ fd = socket(af, SOCK_DGRAM, IPPROTO_UDP);
+ bind_port = s->sport;
+ bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
+ do_bind = 1;
+ break;
+
+ case SK_IP:
+ fd = socket(af, SOCK_RAW, s->dport);
+ bind_port = 0;
+ bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
+ do_bind = ipa_nonzero(bind_addr);
+ break;
+
+ case SK_MAGIC:
+ af = 0;
+ fd = s->fd;
+ break;
+
+ default:
+ bug("sk_open() called for invalid sock type %d", s->type);
+ }
- default:
- bug("sk_open() called for invalid sock type %d", s->type);
- }
if (fd < 0)
- die("sk_open: socket: %m");
+ ERR("socket");
+
+ s->af = af;
s->fd = fd;
- if (err = sk_setup(s))
- goto bad;
+ if (sk_setup(s) < 0)
+ goto err;
if (do_bind)
+ {
+ if (bind_port)
{
- if (bind_port)
- {
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
- ERR("SO_REUSEADDR");
+ int y = 1;
+
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(y)) < 0)
+ ERR2("SO_REUSEADDR");
#ifdef CONFIG_NO_IFACE_BIND
- /* Workaround missing ability to bind to an iface */
- if ((s->type == SK_UDP) && s->iface && ipa_zero(bind_addr))
- {
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0)
- ERR("SO_REUSEPORT");
- }
+ /* Workaround missing ability to bind to an iface */
+ if ((s->type == SK_UDP) && s->iface && ipa_zero(bind_addr))
+ {
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &y, sizeof(y)) < 0)
+ ERR2("SO_REUSEPORT");
+ }
#endif
- }
-
- fill_in_sockaddr(&sa, bind_addr, s->iface, bind_port);
- if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
- ERR("bind");
}
- fill_in_sockaddr(&sa, s->daddr, s->iface, s->dport);
+ sockaddr_fill(&sa, af, bind_addr, s->iface, bind_port);
+ if (bind(fd, &sa.sa, SA_LEN(sa)) < 0)
+ ERR2("bind");
+ }
if (s->password)
- {
- int rv = sk_set_md5_auth_int(s, &sa, s->password);
- if (rv < 0)
- goto bad_no_log;
- }
+ if (sk_set_md5_auth(s, s->daddr, s->iface, s->password) < 0)
+ goto err;
switch (s->type)
- {
- case SK_TCP_ACTIVE:
- if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0)
- sk_tcp_connected(s);
- else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS &&
- errno != ECONNREFUSED && errno != EHOSTUNREACH && errno != ENETUNREACH)
- ERR("connect");
- break;
- case SK_TCP_PASSIVE:
- if (listen(fd, 8))
- ERR("listen");
- break;
- case SK_MAGIC:
- break;
- default:
- sk_alloc_bufs(s);
-#ifdef IPV6
-#ifdef IPV6_MTU_DISCOVER
- {
- int dont = IPV6_PMTUDISC_DONT;
- if (setsockopt(fd, SOL_IPV6, IPV6_MTU_DISCOVER, &dont, sizeof(dont)) < 0)
- ERR("IPV6_MTU_DISCOVER");
- }
-#endif
-#else
-#ifdef IP_PMTUDISC
- {
- int dont = IP_PMTUDISC_DONT;
- if (setsockopt(fd, SOL_IP, IP_PMTUDISC, &dont, sizeof(dont)) < 0)
- ERR("IP_PMTUDISC");
- }
-#endif
-#endif
- }
+ {
+ case SK_TCP_ACTIVE:
+ sockaddr_fill(&sa, af, s->daddr, s->iface, s->dport);
+ if (connect(fd, &sa.sa, SA_LEN(sa)) >= 0)
+ sk_tcp_connected(s);
+ else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS &&
+ errno != ECONNREFUSED && errno != EHOSTUNREACH && errno != ENETUNREACH)
+ ERR2("connect");
+ break;
+
+ case SK_TCP_PASSIVE:
+ if (listen(fd, 8) < 0)
+ ERR2("listen");
+ break;
+
+ case SK_MAGIC:
+ break;
+
+ default:
+ sk_alloc_bufs(s);
+ }
if (!(s->flags & SKF_THREAD))
sk_insert(s);
return 0;
-bad:
- log(L_ERR "sk_open: %s: %m", err);
-bad_no_log:
+err:
close(fd);
s->fd = -1;
return -1;
}
-void
+int
sk_open_unix(sock *s, char *name)
{
- int fd;
struct sockaddr_un sa;
- char *err;
+ int fd;
+
+ /* We are sloppy during error (leak fd and not set s->err), but we die anyway */
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0)
- ERR("socket");
- s->fd = fd;
- if (err = sk_setup(s))
- goto bad;
- unlink(name);
+ return -1;
+
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
+ return -1;
/* Path length checked in test_old_bird() */
sa.sun_family = AF_UNIX;
strcpy(sa.sun_path, name);
+
if (bind(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) < 0)
- ERR("bind");
- if (listen(fd, 8))
- ERR("listen");
+ return -1;
+
+ if (listen(fd, 8) < 0)
+ return -1;
+
+ s->fd = fd;
sk_insert(s);
- return;
+ return 0;
+}
+
+
+#define CMSG_RX_SPACE MAX(CMSG4_SPACE_PKTINFO+CMSG4_SPACE_TTL, \
+ CMSG6_SPACE_PKTINFO+CMSG6_SPACE_TTL)
+#define CMSG_TX_SPACE MAX(CMSG4_SPACE_PKTINFO,CMSG6_SPACE_PKTINFO)
+
+static void
+sk_prepare_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
+{
+ if (sk_is_ipv4(s))
+ sk_prepare_cmsgs4(s, msg, cbuf, cbuflen);
+ else
+ sk_prepare_cmsgs6(s, msg, cbuf, cbuflen);
+}
+
+static void
+sk_process_cmsgs(sock *s, struct msghdr *msg)
+{
+ struct cmsghdr *cm;
+
+ s->laddr = IPA_NONE;
+ s->lifindex = 0;
+ s->rcv_ttl = -1;
+
+ for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
+ {
+ if ((cm->cmsg_level == SOL_IP) && sk_is_ipv4(s))
+ {
+ sk_process_cmsg4_pktinfo(s, cm);
+ sk_process_cmsg4_ttl(s, cm);
+ }
- bad:
- log(L_ERR "sk_open_unix: %s: %m", err);
- die("Unable to create control socket %s", name);
+ if ((cm->cmsg_level == SOL_IPV6) && sk_is_ipv6(s))
+ {
+ sk_process_cmsg6_pktinfo(s, cm);
+ sk_process_cmsg6_ttl(s, cm);
+ }
+ }
}
@@ -1362,11 +1496,11 @@
byte cmsg_buf[CMSG_TX_SPACE];
sockaddr dst;
- fill_in_sockaddr(&dst, s->daddr, s->iface, s->dport);
+ sockaddr_fill(&dst, s->af, s->daddr, s->iface, s->dport);
struct msghdr msg = {
- .msg_name = &dst,
- .msg_namelen = sizeof(dst),
+ .msg_name = &dst.sa,
+ .msg_namelen = SA_LEN(dst),
.msg_iov = &iov,
.msg_iovlen = 1
};
@@ -1377,14 +1511,14 @@
if (s->flags & SKF_HDRINCL)
{
- fill_ip_header(s, hdr, iov.iov_len);
+ sk_prepare_ip_header(s, hdr, iov.iov_len);
msg.msg_iov = iov2;
msg.msg_iovlen = 2;
}
#endif
if (s->flags & SKF_PKTINFO)
- sysio_prepare_tx_cmsgs(s, &msg, cmsg_buf, sizeof(cmsg_buf));
+ sk_prepare_cmsgs(s, &msg, cmsg_buf, sizeof(cmsg_buf));
return sendmsg(s->fd, &msg, 0);
}
@@ -1397,8 +1531,8 @@
sockaddr src;
struct msghdr msg = {
- .msg_name = &src,
- .msg_namelen = sizeof(src),
+ .msg_name = &src.sa,
+ .msg_namelen = sizeof(src), // XXXX ??
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = cmsg_buf,
@@ -1415,8 +1549,8 @@
// rv = ipv4_skip_header(pbuf, rv);
//endif
- get_sockaddr(&src, &s->faddr, NULL, &s->fport, 1);
- sysio_process_rx_cmsgs(s, &msg);
+ sockaddr_read(&src, s->af, &s->faddr, NULL, &s->fport);
+ sk_process_cmsgs(s, &msg);
if (msg.msg_flags & MSG_TRUNC)
s->flags |= SKF_TRUNCATED;
@@ -1435,55 +1569,57 @@
int e;
switch (s->type)
+ {
+ case SK_TCP:
+ case SK_MAGIC:
+ case SK_UNIX:
+ while (s->ttx != s->tpos)
{
- case SK_TCP:
- case SK_MAGIC:
- case SK_UNIX:
- while (s->ttx != s->tpos)
+ e = write(s->fd, s->ttx, s->tpos - s->ttx);
+
+ if (e < 0)
+ {
+ if (errno != EINTR && errno != EAGAIN)
{
- e = write(s->fd, s->ttx, s->tpos - s->ttx);
- if (e < 0)
- {
- if (errno != EINTR && errno != EAGAIN)
- {
- reset_tx_buffer(s);
- /* EPIPE is just a connection close notification during TX */
- s->err_hook(s, (errno != EPIPE) ? errno : 0);
- return -1;
- }
- return 0;
- }
- s->ttx += e;
+ reset_tx_buffer(s);
+ /* EPIPE is just a connection close notification during TX */
+ s->err_hook(s, (errno != EPIPE) ? errno : 0);
+ return -1;
}
- reset_tx_buffer(s);
- return 1;
- case SK_UDP:
- case SK_IP:
- {
- if (s->tbuf == s->tpos)
- return 1;
-
- e = sk_sendmsg(s);
+ return 0;
+ }
+ s->ttx += e;
+ }
+ reset_tx_buffer(s);
+ return 1;
- if (e < 0)
- {
- if (errno != EINTR && errno != EAGAIN)
- {
- reset_tx_buffer(s);
- s->err_hook(s, errno);
- return -1;
- }
-
- if (!s->tx_hook)
- reset_tx_buffer(s);
- return 0;
- }
- reset_tx_buffer(s);
+ case SK_UDP:
+ case SK_IP:
+ {
+ if (s->tbuf == s->tpos)
return 1;
+
+ e = sk_sendmsg(s);
+
+ if (e < 0)
+ {
+ if (errno != EINTR && errno != EAGAIN)
+ {
+ reset_tx_buffer(s);
+ s->err_hook(s, errno);
+ return -1;
+ }
+
+ if (!s->tx_hook)
+ reset_tx_buffer(s);
+ return 0;
}
- default:
- bug("sk_maybe_write: unknown socket type %d", s->type);
+ reset_tx_buffer(s);
+ return 1;
}
+ default:
+ bug("sk_maybe_write: unknown socket type %d", s->type);
+ }
}
int
@@ -1573,88 +1709,86 @@
sk_read(sock *s)
{
switch (s->type)
+ {
+ case SK_TCP_PASSIVE:
+ return sk_passive_connected(s, SK_TCP);
+
+ case SK_UNIX_PASSIVE:
+ return sk_passive_connected(s, SK_UNIX);
+
+ case SK_TCP:
+ case SK_UNIX:
{
- case SK_TCP_PASSIVE:
- {
- sockaddr sa;
- return sk_passive_connected(s, (struct sockaddr *) &sa, sizeof(sa), SK_TCP);
- }
- case SK_UNIX_PASSIVE:
+ int c = read(s->fd, s->rpos, s->rbuf + s->rbsize - s->rpos);
+
+ if (c < 0)
{
- struct sockaddr_un sa;
- return sk_passive_connected(s, (struct sockaddr *) &sa, sizeof(sa), SK_UNIX);
+ if (errno != EINTR && errno != EAGAIN)
+ s->err_hook(s, errno);
}
- case SK_TCP:
- case SK_UNIX:
+ else if (!c)
+ s->err_hook(s, 0);
+ else
{
- int c = read(s->fd, s->rpos, s->rbuf + s->rbsize - s->rpos);
-
- if (c < 0)
- {
- if (errno != EINTR && errno != EAGAIN)
- s->err_hook(s, errno);
- }
- else if (!c)
- s->err_hook(s, 0);
- else
- {
- s->rpos += c;
- if (s->rx_hook(s, s->rpos - s->rbuf))
- {
- /* We need to be careful since the socket could have been deleted by the hook */
- if (current_sock == s)
- s->rpos = s->rbuf;
- }
- return 1;
- }
- return 0;
+ s->rpos += c;
+ if (s->rx_hook(s, s->rpos - s->rbuf))
+ {
+ /* We need to be careful since the socket could have been deleted by the hook */
+ if (current_sock == s)
+ s->rpos = s->rbuf;
+ }
+ return 1;
}
- case SK_MAGIC:
- return s->rx_hook(s, 0);
- default:
- {
- int e;
+ return 0;
+ }
- e = sk_recvmsg(s);
+ case SK_MAGIC:
+ return s->rx_hook(s, 0);
- if (e < 0)
- {
- if (errno != EINTR && errno != EAGAIN)
- s->err_hook(s, errno);
- return 0;
- }
+ default:
+ {
+ int e = sk_recvmsg(s);
- s->rpos = s->rbuf + e;
- s->rx_hook(s, e);
- return 1;
+ if (e < 0)
+ {
+ if (errno != EINTR && errno != EAGAIN)
+ s->err_hook(s, errno);
+ return 0;
}
+
+ s->rpos = s->rbuf + e;
+ s->rx_hook(s, e);
+ return 1;
}
+ }
}
int
sk_write(sock *s)
{
switch (s->type)
+ {
+ case SK_TCP_ACTIVE:
{
- case SK_TCP_ACTIVE:
- {
- sockaddr sa;
- fill_in_sockaddr(&sa, s->daddr, s->iface, s->dport);
- if (connect(s->fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0 || errno == EISCONN)
- sk_tcp_connected(s);
- else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS)
- s->err_hook(s, errno);
- return 0;
- }
- default:
- if (s->ttx != s->tpos && sk_maybe_write(s) > 0)
- {
- if (s->tx_hook)
- s->tx_hook(s);
- return 1;
- }
+ sockaddr sa;
+ sockaddr_fill(&sa, s->af, s->daddr, s->iface, s->dport);
+
+ if (connect(s->fd, &sa.sa, SA_LEN(sa)) >= 0 || errno == EISCONN)
+ sk_tcp_connected(s);
+ else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS)
+ s->err_hook(s, errno);
return 0;
}
+
+ default:
+ if (s->ttx != s->tpos && sk_maybe_write(s) > 0)
+ {
+ if (s->tx_hook)
+ s->tx_hook(s);
+ return 1;
+ }
+ return 0;
+ }
}
void
@@ -1665,16 +1799,14 @@
debug("Open sockets:\n");
WALK_LIST(n, sock_list)
- {
- s = SKIP_BACK(sock, n, n);
- debug("%p ", s);
- sk_dump(&s->r);
- }
+ {
+ s = SKIP_BACK(sock, n, n);
+ debug("%p ", s);
+ sk_dump(&s->r);
+ }
debug("\n");
}
-#undef ERR
-#undef WARN
/*
* Main I/O Loop
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/sysdep/unix/main.c
^
|
@@ -463,7 +463,12 @@
s->type = SK_UNIX_PASSIVE;
s->rx_hook = cli_connect;
s->rbsize = 1024;
- sk_open_unix(s, path_control_socket);
+
+ /* Return value intentionally ignored */
+ unlink(path_control_socket);
+
+ if (sk_open_unix(s, path_control_socket) < 0)
+ die("Cannot create control socket %s: %m", path_control_socket);
if (use_uid || use_gid)
if (chown(path_control_socket, use_uid, use_gid) < 0)
|
[-]
[+]
|
Changed |
bird-1.4.4.tar.bz2/sysdep/unix/unix.h
^
|
@@ -12,6 +12,8 @@
#include <sys/socket.h>
struct pool;
+struct iface;
+struct birdsock;
/* main.c */
@@ -27,36 +29,81 @@
#define UNIX_DEFAULT_CONFIGURE_TIMEOUT 300
+
/* io.c */
-volatile int async_config_flag;
-volatile int async_dump_flag;
-volatile int async_shutdown_flag;
+#define ERR(c) do { s->err = c; return -1; } while (0)
+#define ERR2(c) do { s->err = c; goto err; } while (0)
+#define ERR_MSG(c) do { errno = 0; s->err = c; return -1; } while (0)
+
+
+#define SOCKADDR_SIZE 32
+
+typedef struct sockaddr_bird {
+ struct sockaddr sa;
+ char padding[SOCKADDR_SIZE - sizeof(struct sockaddr)];
+} sockaddr;
+
#ifdef IPV6
-#define BIRD_PF PF_INET6
#define BIRD_AF AF_INET6
-typedef struct sockaddr_in6 sockaddr;
-static inline int sa_family_check(sockaddr *sa) { return sa->sin6_family == AF_INET6; }
+#define _MI6(x1,x2,x3,x4) _MI(x1, x2, x3, x4)
+#define ipa_is_link_local(x) ipa_has_link_scope(x)
+#define ipa_from_sa(x) ipa_from_sa6(x)
+#define ipa_from_u32(x) _MI6(0,0,0xffff,x)
+#define ipa_to_u32(x) _I3(x)
#else
-#define BIRD_PF PF_INET
#define BIRD_AF AF_INET
-typedef struct sockaddr_in sockaddr;
-static inline int sa_family_check(sockaddr *sa) { return sa->sin_family == AF_INET; }
+#define _I0(X) 0
+#define _I1(X) 0
+#define _I2(X) 0
+#define _I3(X) 0
+#define _MI6(x1,x2,x3,x4) IPA_NONE
+#define ipa_is_link_local(x) 0
+#define ipa_from_sa(x) ipa_from_sa4(x)
#endif
+
+/* This is sloppy hack, it should be detected by configure script */
+/* Linux systems have it defined so this is definition for BSD systems */
+#ifndef s6_addr32
+#define s6_addr32 __u6_addr.__u6_addr32
+#endif
+
+
+static inline ip_addr ipa_from_in4(struct in_addr a)
+{ return ipa_from_u32(ntohl(a.s_addr)); }
+
+static inline ip_addr ipa_from_in6(struct in6_addr a)
+{ return _MI6(ntohl(a.s6_addr32[0]), ntohl(a.s6_addr32[1]), ntohl(a.s6_addr32[2]), ntohl(a.s6_addr32[3])); }
+
+static inline ip_addr ipa_from_sa4(sockaddr *sa)
+{ return ipa_from_in4(((struct sockaddr_in *) sa)->sin_addr); }
+
+static inline ip_addr ipa_from_sa6(sockaddr *sa)
+{ return ipa_from_in6(((struct sockaddr_in6 *) sa)->sin6_addr); }
+
+static inline struct in_addr ipa_to_in4(ip_addr a)
+{ return (struct in_addr) { htonl(ipa_to_u32(a)) }; }
+
+static inline struct in6_addr ipa_to_in6(ip_addr a)
+{ return (struct in6_addr) { .s6_addr32 = { htonl(_I0(a)), htonl(_I1(a)), htonl(_I2(a)), htonl(_I3(a)) } }; }
+
+void sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port);
+int sockaddr_read(sockaddr *sa, int af, ip_addr *a, struct iface **ifa, uint *port);
+
+
#ifndef SUN_LEN
#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen ((ptr)->sun_path))
#endif
-struct birdsock;
-struct iface;
+volatile int async_config_flag;
+volatile int async_dump_flag;
+volatile int async_shutdown_flag;
void io_init(void);
void io_loop(void);
-void fill_in_sockaddr(sockaddr *sa, ip_addr a, struct iface *ifa, unsigned port);
-void get_sockaddr(sockaddr *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check);
-void sk_open_unix(struct birdsock *s, char *name);
+int sk_open_unix(struct birdsock *s, char *name);
void *tracked_fopen(struct pool *, char *name, char *mode);
void test_old_bird(char *path);
|