From 6d0732c8abad7ace509d033a41814ea03a3a1b16 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 28 Sep 2011 14:23:35 +0400 Subject: IPv6 transport class suppport IPv6 supports the same concept of differentiated service for routing protocols as IPv4, but like too many things, the standards committee decided that having two names for the same thing wasn't good enough and introduced a third more generic term transport class. The socket option to set transport class works the same as IPv4, but the arguments are different. * lib/sockopt.[ch] * setsockopt_ipv6_tclass(): new function * bgpd/bgp_network.c * bgp_connect(): set socket option * bgp_listener(): set socket option * ospf6d/ospf6_network.c * ospf6_set_transport_class(): new function * ospf6_serv_sock(): set socket option * ripngd/ripngd.c * ripng_make_socket(): set socket option --- bgpd/bgp_network.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'bgpd/bgp_network.c') diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 570cc3b7..c8ff87a6 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -330,6 +330,10 @@ bgp_connect (struct peer *peer) #ifdef IPTOS_PREC_INTERNETCONTROL if (sockunion_family (&peer->su) == AF_INET) setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL); +# ifdef HAVE_IPV6 + else if (sockunion_family (&peer->su) == AF_INET6) + setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL); +# endif #endif if (peer->password) @@ -389,6 +393,10 @@ bgp_listener (int sock, struct sockaddr *sa, socklen_t salen) #ifdef IPTOS_PREC_INTERNETCONTROL if (sa->sa_family == AF_INET) setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL); +# ifdef HAVE_IPV6 + else if (sa->sa_family == AF_INET6) + setsockopt_ipv6_tclass (sock, IPTOS_PREC_INTERNETCONTROL); +# endif #endif #ifdef IPV6_V6ONLY -- cgit v1.2.1 From 5c88f19d5b166c6afa8a9b8501badb785afa553b Mon Sep 17 00:00:00 2001 From: Chris Luke Date: Tue, 18 Oct 2011 17:26:51 +0400 Subject: bgpd: justify capabilities for TOS setting To set the TOS bits on TCP connections, platforms that restrict capabilities need the priv level to be raised before the sockopt is set, and this requires the ZCAP_NET_ADMIN priv. * bgp_main.c: update _caps_p to include ZCAP_NET_ADMIN * bgp_network.c * bgp_connect(): request ZPRIVS_RAISE/ZPRIVS_LOWER * bgp_listener(): request ZPRIVS_RAISE earlier --- bgpd/bgp_network.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'bgpd/bgp_network.c') diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index c8ff87a6..52c72b67 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -328,12 +328,16 @@ bgp_connect (struct peer *peer) sockopt_reuseport (peer->fd); #ifdef IPTOS_PREC_INTERNETCONTROL + if (bgpd_privs.change (ZPRIVS_RAISE)) + zlog_err ("%s: could not raise privs", __func__); if (sockunion_family (&peer->su) == AF_INET) setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL); # ifdef HAVE_IPV6 else if (sockunion_family (&peer->su) == AF_INET6) setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL); # endif + if (bgpd_privs.change (ZPRIVS_LOWER)) + zlog_err ("%s: could not lower privs", __func__); #endif if (peer->password) @@ -390,6 +394,9 @@ bgp_listener (int sock, struct sockaddr *sa, socklen_t salen) sockopt_reuseaddr (sock); sockopt_reuseport (sock); + if (bgpd_privs.change (ZPRIVS_RAISE)) + zlog_err ("%s: could not raise privs", __func__); + #ifdef IPTOS_PREC_INTERNETCONTROL if (sa->sa_family == AF_INET) setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL); @@ -408,13 +415,10 @@ bgp_listener (int sock, struct sockaddr *sa, socklen_t salen) } #endif - if (bgpd_privs.change (ZPRIVS_RAISE) ) - zlog_err ("bgp_socket: could not raise privs"); - ret = bind (sock, sa, salen); en = errno; - if (bgpd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("bgp_bind_address: could not lower privs"); + if (bgpd_privs.change (ZPRIVS_LOWER)) + zlog_err ("%s: could not lower privs", __func__); if (ret < 0) { -- cgit v1.2.1 From 1727d2e2b939c8670d0f0e0d1a0e5eb0a8be2135 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 2 Feb 2010 20:18:23 +0100 Subject: bgpd: fix update-source for IPv6 (BZ#548) if update-source was given as interface name, bgpd was unconditionally trying to bind to an IPv4 address from that interface. change function to find the best-matching (number of address bits) same-family address on the interface. --- bgpd/bgp_network.c | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) (limited to 'bgpd/bgp_network.c') diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 52c72b67..b9cb6223 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -263,21 +263,37 @@ bgp_bind_address (int sock, struct in_addr *addr) return 0; } -static struct in_addr * -bgp_update_address (struct interface *ifp) +static int +bgp_update_address (struct interface *ifp, const union sockunion *dst, + union sockunion *addr) { - struct prefix_ipv4 *p; + struct prefix *p, *sel, *d; struct connected *connected; struct listnode *node; + int common; + + d = sockunion2hostprefix (dst); + sel = NULL; + common = -1; for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) { - p = (struct prefix_ipv4 *) connected->address; - - if (p->family == AF_INET) - return &p->prefix; + p = connected->address; + if (p->family != d->family) + continue; + if (prefix_common_bits (p, d) > common) + { + sel = p; + common = prefix_common_bits (sel, d); + } } - return NULL; + + prefix_free (d); + if (!sel) + return 1; + + prefix2sockunion (sel, addr); + return 0; } /* Update source selection. */ @@ -285,7 +301,7 @@ static void bgp_update_source (struct peer *peer) { struct interface *ifp; - struct in_addr *addr; + union sockunion addr; /* Source is specified with interface name. */ if (peer->update_if) @@ -294,11 +310,10 @@ bgp_update_source (struct peer *peer) if (! ifp) return; - addr = bgp_update_address (ifp); - if (! addr) + if (bgp_update_address (ifp, &peer->su, &addr)) return; - bgp_bind_address (peer->fd, addr); + sockunion_bind (peer->fd, &addr, 0, &addr); } /* Source is specified with IP address. */ -- cgit v1.2.1 From 2fbd6f5a62f654c59aec5e1707c859d6ed79c6b0 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Tue, 2 Feb 2010 20:20:35 +0100 Subject: bgpd: remove unused function bgp_bind_address bgp_bind_address is replaced with sockunion_bind. --- bgpd/bgp_network.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'bgpd/bgp_network.c') diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index b9cb6223..274a989d 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -237,32 +237,6 @@ bgp_bind (struct peer *peer) return 0; } -static int -bgp_bind_address (int sock, struct in_addr *addr) -{ - int ret; - struct sockaddr_in local; - - memset (&local, 0, sizeof (struct sockaddr_in)); - local.sin_family = AF_INET; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - local.sin_len = sizeof(struct sockaddr_in); -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - memcpy (&local.sin_addr, addr, sizeof (struct in_addr)); - - if ( bgpd_privs.change (ZPRIVS_RAISE) ) - zlog_err ("bgp_bind_address: could not raise privs"); - - ret = bind (sock, (struct sockaddr *)&local, sizeof (struct sockaddr_in)); - if (ret < 0) - ; - - if (bgpd_privs.change (ZPRIVS_LOWER) ) - zlog_err ("bgp_bind_address: could not lower privs"); - - return 0; -} - static int bgp_update_address (struct interface *ifp, const union sockunion *dst, union sockunion *addr) -- cgit v1.2.1 From ca0512692156d5bbb902523d2f123fc89dbec1ab Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 4 Oct 2009 16:21:49 +0200 Subject: lib: add sockopt helper for setting IPV6_V6ONLY and use it getaddrinfo returns a list of socket parameters for listening. it will contain both IPv4 and IPv6 listening sockets. unless we use IPV6_V6ONLY on the IPv6 ones, only the socket listed first will work. if the IPv4 one came first, the IPv6 one would get an "Address in use" error. this functionality was already present for bgpd and its listening sockets. as it is needed for vtys as well, make it a common helper. Conflicts: lib/sockunion.c --- bgpd/bgp_network.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'bgpd/bgp_network.c') diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 274a989d..a7dca531 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -395,14 +395,7 @@ bgp_listener (int sock, struct sockaddr *sa, socklen_t salen) # endif #endif -#ifdef IPV6_V6ONLY - /* Want only IPV6 on ipv6 socket (not mapped addresses) */ - if (sa->sa_family == AF_INET6) { - int on = 1; - setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, - (void *) &on, sizeof (on)); - } -#endif + sockopt_v6only (sa->sa_family, sock); ret = bind (sock, sa, salen); en = errno; -- cgit v1.2.1