version 1.1.1.1, 2012/02/21 17:26:12
|
version 1.1.1.2, 2012/10/09 09:22:28
|
Line 238 bgp_bind (struct peer *peer)
|
Line 238 bgp_bind (struct peer *peer)
|
} |
} |
|
|
static int |
static int |
bgp_bind_address (int sock, struct in_addr *addr) | bgp_update_address (struct interface *ifp, const union sockunion *dst, |
| union sockunion *addr) |
{ |
{ |
int ret; | struct prefix *p, *sel, *d; |
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 struct in_addr * | |
bgp_update_address (struct interface *ifp) | |
{ | |
struct prefix_ipv4 *p; | |
struct connected *connected; |
struct connected *connected; |
struct listnode *node; |
struct listnode *node; |
|
int common; |
|
|
|
d = sockunion2hostprefix (dst); |
|
sel = NULL; |
|
common = -1; |
|
|
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) |
for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) |
{ |
{ |
p = (struct prefix_ipv4 *) connected->address; | p = connected->address; |
| if (p->family != d->family) |
if (p->family == AF_INET) | continue; |
return &p->prefix; | 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. */ |
/* Update source selection. */ |
Line 285 static void
|
Line 275 static void
|
bgp_update_source (struct peer *peer) |
bgp_update_source (struct peer *peer) |
{ |
{ |
struct interface *ifp; |
struct interface *ifp; |
struct in_addr *addr; | union sockunion addr; |
|
|
/* Source is specified with interface name. */ |
/* Source is specified with interface name. */ |
if (peer->update_if) |
if (peer->update_if) |
Line 294 bgp_update_source (struct peer *peer)
|
Line 284 bgp_update_source (struct peer *peer)
|
if (! ifp) |
if (! ifp) |
return; |
return; |
|
|
addr = bgp_update_address (ifp); | if (bgp_update_address (ifp, &peer->su, &addr)) |
if (! addr) | |
return; |
return; |
|
|
bgp_bind_address (peer->fd, addr); | sockunion_bind (peer->fd, &addr, 0, &addr); |
} |
} |
|
|
/* Source is specified with IP address. */ |
/* Source is specified with IP address. */ |
Line 328 bgp_connect (struct peer *peer)
|
Line 317 bgp_connect (struct peer *peer)
|
sockopt_reuseport (peer->fd); |
sockopt_reuseport (peer->fd); |
|
|
#ifdef IPTOS_PREC_INTERNETCONTROL |
#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) |
if (sockunion_family (&peer->su) == AF_INET) |
setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL); |
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 |
#endif |
|
|
if (peer->password) |
if (peer->password) |
Line 386 bgp_listener (int sock, struct sockaddr *sa, socklen_t
|
Line 383 bgp_listener (int sock, struct sockaddr *sa, socklen_t
|
sockopt_reuseaddr (sock); |
sockopt_reuseaddr (sock); |
sockopt_reuseport (sock); |
sockopt_reuseport (sock); |
|
|
|
if (bgpd_privs.change (ZPRIVS_RAISE)) |
|
zlog_err ("%s: could not raise privs", __func__); |
|
|
#ifdef IPTOS_PREC_INTERNETCONTROL |
#ifdef IPTOS_PREC_INTERNETCONTROL |
if (sa->sa_family == AF_INET) |
if (sa->sa_family == AF_INET) |
setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL); |
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 |
#endif |
|
|
#ifdef IPV6_V6ONLY | sockopt_v6only (sa->sa_family, sock); |
/* 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 | |
|
|
if (bgpd_privs.change (ZPRIVS_RAISE) ) |
|
zlog_err ("bgp_socket: could not raise privs"); |
|
|
|
ret = bind (sock, sa, salen); |
ret = bind (sock, sa, salen); |
en = errno; |
en = errno; |
if (bgpd_privs.change (ZPRIVS_LOWER) ) | if (bgpd_privs.change (ZPRIVS_LOWER)) |
zlog_err ("bgp_bind_address: could not lower privs"); | zlog_err ("%s: could not lower privs", __func__); |
|
|
if (ret < 0) |
if (ret < 0) |
{ |
{ |