mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00
[bgpd] TCP-MD5: password vty configuration and initial Linux support
2008-07-21 Paul Jakma <paul.jakma@sun.com> * bgp_packet.c: (bgp_open_receive) fix warning in a zlog call * bgp_vty.c: (bgp_vty_return) add return code * bgpd.c: (bgp_master_init) setup the socket list. * bgp_network.c: Remove the dual IPv4/6 socket thing for now, which was implemented by Michael, until such time as its clear its required for Linux (see sockopt comments). IPv6 support, including IPv4 sessions on AF_INET6 sockets, therefore is broken, and the '-l 0.0.0.0' arguments would need to be given to bgpd to make things work here. 2008-07-21 Michael H. Warfield <mhw@wittsend.com> YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Tomohiko Kusuda <kusuda@inetcore.com> Leigh Brown <leigh@solinno.co.uk> * bgp_network.c: (bgp_md5_set_one) shim between libzebra tcp-md5 sockopt and bgpd. (bgp_md5_set_socket) Helper for bgp_connect (bgp_md5_set) setup TCP-MD5SIG for the given peer. (bgp_connect) call out to bgp_md5_set_socket for the outgoing connect socket. (bgp_socket) save references to the listen sockets, needed if TCP-MD5SIG is applied later or changed. * bgp_vty.c: (*neighbor_password_cmd) New 'neighbor ... password' commands. * bgpd.c: (peer_{new,delete) manage TCP-MD5 password (peer_group2peer_config_copy) inherit TCP-MD5 password (peer_password_{un,}set) orchestrate the whole add/remove of TCP-MD5 passwords: applying checks, stopping peers, and trying to return errors to UI, etc. (bgp_config_write_peer) save password. Fix missing newline in writeout of neighbor ... port. 2008-07-21 Paul Jakma <paul.jakma@sun.com> * sockunion.c: ifdef out various places that converted v4mapped sockets to pure v4. Doesn't seem necessary at all, presumably a workaround for now historical inet_ntop bugs (?) 2008-07-21 Michael H. Warfield <mhw@wittsend.com> YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> * sockopt.{c,h}: (sockopt_tcp_signature) Add TCP-MD5SIG support.
This commit is contained in:
parent
f04b0e6bb8
commit
0df7c91f04
|
@ -1,3 +1,39 @@
|
|||
2008-07-21 Paul Jakma <paul.jakma@sun.com>
|
||||
|
||||
|
||||
* bgp_packet.c: (bgp_open_receive) fix warning in a zlog call
|
||||
* bgp_vty.c: (bgp_vty_return) add return code
|
||||
* bgpd.c: (bgp_master_init) setup the socket list.
|
||||
* bgp_network.c: Remove the dual IPv4/6 socket thing for now, which
|
||||
was implemented by Michael, until such time as its clear its
|
||||
required for Linux (see sockopt comments). IPv6 support, including
|
||||
IPv4 sessions on AF_INET6 sockets, therefore is broken, and the
|
||||
'-l 0.0.0.0' arguments would need to be given to bgpd to make
|
||||
things work here.
|
||||
|
||||
2008-07-21 Michael H. Warfield <mhw@wittsend.com>
|
||||
YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
|
||||
Tomohiko Kusuda <kusuda@inetcore.com>
|
||||
Leigh Brown <leigh@solinno.co.uk>
|
||||
|
||||
* bgp_network.c: (bgp_md5_set_one) shim between libzebra tcp-md5
|
||||
sockopt and bgpd.
|
||||
(bgp_md5_set_socket) Helper for bgp_connect
|
||||
(bgp_md5_set) setup TCP-MD5SIG for the given peer.
|
||||
(bgp_connect) call out to bgp_md5_set_socket for the outgoing
|
||||
connect socket.
|
||||
(bgp_socket) save references to the listen sockets, needed if
|
||||
TCP-MD5SIG is applied later or changed.
|
||||
* bgp_vty.c: (*neighbor_password_cmd) New 'neighbor ... password'
|
||||
commands.
|
||||
* bgpd.c: (peer_{new,delete) manage TCP-MD5 password
|
||||
(peer_group2peer_config_copy) inherit TCP-MD5 password
|
||||
(peer_password_{un,}set) orchestrate the whole add/remove of TCP-MD5
|
||||
passwords: applying checks, stopping peers, and trying to return
|
||||
errors to UI, etc.
|
||||
(bgp_config_write_peer) save password.
|
||||
Fix missing newline in writeout of neighbor ... port.
|
||||
|
||||
2008-07-02 MIYAJIMA Mitsuharu <miyajima.mitsuharu@anchor.jp>
|
||||
|
||||
* *.c: CMD_AS_RANGE was being used inside command strings, and thus
|
||||
|
|
|
@ -22,12 +22,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||
|
||||
#include "thread.h"
|
||||
#include "sockunion.h"
|
||||
#include "sockopt.h"
|
||||
#include "memory.h"
|
||||
#include "log.h"
|
||||
#include "if.h"
|
||||
#include "prefix.h"
|
||||
#include "command.h"
|
||||
#include "privs.h"
|
||||
#include "linklist.h"
|
||||
|
||||
#include "bgpd/bgpd.h"
|
||||
#include "bgpd/bgp_fsm.h"
|
||||
|
@ -37,6 +39,80 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|||
|
||||
extern struct zebra_privs_t bgpd_privs;
|
||||
|
||||
|
||||
/*
|
||||
* Set MD5 key for the socket, for the given IPv4 peer address.
|
||||
* If the password is NULL or zero-length, the option will be disabled.
|
||||
*/
|
||||
static int
|
||||
bgp_md5_set_socket (int socket, union sockunion *su, const char *password)
|
||||
{
|
||||
int ret = -1;
|
||||
int en = ENOSYS;
|
||||
|
||||
assert (socket >= 0);
|
||||
|
||||
#if HAVE_DECL_TCP_MD5SIG
|
||||
ret = sockopt_tcp_signature (socket, su, password);
|
||||
en = errno;
|
||||
#endif /* HAVE_TCP_MD5SIG */
|
||||
|
||||
if (ret < 0)
|
||||
zlog (NULL, LOG_WARNING, "can't set TCP_MD5SIG option on socket %d: %s",
|
||||
socket, safe_strerror (en));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Helper for bgp_connect */
|
||||
static int
|
||||
bgp_md5_set_connect (int socket, union sockunion *su, const char *password)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
#if HAVE_DECL_TCP_MD5SIG
|
||||
if ( bgpd_privs.change (ZPRIVS_RAISE) )
|
||||
{
|
||||
zlog_err ("%s: could not raise privs", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = bgp_md5_set_socket (socket, su, password);
|
||||
|
||||
if (bgpd_privs.change (ZPRIVS_LOWER) )
|
||||
zlog_err ("%s: could not lower privs", __func__);
|
||||
#endif /* HAVE_TCP_MD5SIG */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
bgp_md5_set (struct peer *peer)
|
||||
{
|
||||
struct listnode *node;
|
||||
int fret = 0, ret;
|
||||
int *socket;
|
||||
|
||||
if ( bgpd_privs.change (ZPRIVS_RAISE) )
|
||||
{
|
||||
zlog_err ("%s: could not raise privs", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Just set the password on the listen socket(s). Outbound connections
|
||||
* are taken care of in bgp_connect() below.
|
||||
*/
|
||||
for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, socket))
|
||||
{
|
||||
ret = bgp_md5_set_socket ((int )socket, &peer->su, peer->password);
|
||||
if (ret < 0)
|
||||
fret = ret;
|
||||
}
|
||||
if (bgpd_privs.change (ZPRIVS_LOWER) )
|
||||
zlog_err ("%s: could not lower privs", __func__);
|
||||
|
||||
return fret;
|
||||
}
|
||||
|
||||
/* Accept bgp connection. */
|
||||
static int
|
||||
|
@ -237,6 +313,9 @@ bgp_connect (struct peer *peer)
|
|||
|
||||
sockopt_reuseaddr (peer->fd);
|
||||
sockopt_reuseport (peer->fd);
|
||||
|
||||
if (peer->password)
|
||||
bgp_md5_set_connect (peer->fd, &peer->su, peer->password);
|
||||
|
||||
/* Bind socket. */
|
||||
bgp_bind (peer);
|
||||
|
@ -345,7 +424,8 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address)
|
|||
close (sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
listnode_add (bm->listen_sockets, (void *)sock);
|
||||
thread_add_read (master, bgp_accept, bgp, sock);
|
||||
}
|
||||
while ((ainfo = ainfo->ai_next) != NULL);
|
||||
|
|
|
@ -25,4 +25,6 @@ extern int bgp_socket (struct bgp *, unsigned short, char *);
|
|||
extern int bgp_connect (struct peer *);
|
||||
extern void bgp_getsockname (struct peer *);
|
||||
|
||||
extern int bgp_md5_set (struct peer *);
|
||||
|
||||
#endif /* _QUAGGA_BGP_NETWORK_H */
|
||||
|
|
|
@ -1235,7 +1235,7 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
|
|||
zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
|
||||
" Odd, but proceeding.", peer->host);
|
||||
else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
|
||||
zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 fits "
|
||||
zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
|
||||
"in 2-bytes, very odd peer.", peer->host, as4);
|
||||
if (as4)
|
||||
remote_as = as4;
|
||||
|
|
|
@ -210,6 +210,9 @@ bgp_vty_return (struct vty *vty, int ret)
|
|||
case BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS:
|
||||
str = "Cannot have local-as same as BGP AS number";
|
||||
break;
|
||||
case BGP_ERR_TCPSIG_FAILED:
|
||||
str = "Error while applying TCP-Sig to session(s)";
|
||||
break;
|
||||
}
|
||||
if (str)
|
||||
{
|
||||
|
@ -1479,6 +1482,44 @@ ALIAS (no_neighbor_local_as,
|
|||
"AS number used as local AS\n"
|
||||
"Do not prepend local-as to updates from ebgp peers\n")
|
||||
|
||||
DEFUN (neighbor_password,
|
||||
neighbor_password_cmd,
|
||||
NEIGHBOR_CMD2 "password LINE",
|
||||
NEIGHBOR_STR
|
||||
NEIGHBOR_ADDR_STR2
|
||||
"Set a password\n"
|
||||
"The password\n")
|
||||
{
|
||||
struct peer *peer;
|
||||
int ret;
|
||||
|
||||
peer = peer_and_group_lookup_vty (vty, argv[0]);
|
||||
if (! peer)
|
||||
return CMD_WARNING;
|
||||
|
||||
ret = peer_password_set (peer, argv[1]);
|
||||
return bgp_vty_return (vty, ret);
|
||||
}
|
||||
|
||||
DEFUN (no_neighbor_password,
|
||||
no_neighbor_password_cmd,
|
||||
NO_NEIGHBOR_CMD2 "password",
|
||||
NO_STR
|
||||
NEIGHBOR_STR
|
||||
NEIGHBOR_ADDR_STR2
|
||||
"Set a password\n")
|
||||
{
|
||||
struct peer *peer;
|
||||
int ret;
|
||||
|
||||
peer = peer_and_group_lookup_vty (vty, argv[0]);
|
||||
if (! peer)
|
||||
return CMD_WARNING;
|
||||
|
||||
ret = peer_password_unset (peer);
|
||||
return bgp_vty_return (vty, ret);
|
||||
}
|
||||
|
||||
DEFUN (neighbor_activate,
|
||||
neighbor_activate_cmd,
|
||||
NEIGHBOR_CMD2 "activate",
|
||||
|
@ -8897,6 +8938,10 @@ bgp_vty_init (void)
|
|||
install_element (BGP_NODE, &no_neighbor_local_as_val_cmd);
|
||||
install_element (BGP_NODE, &no_neighbor_local_as_val2_cmd);
|
||||
|
||||
/* "neighbor password" commands. */
|
||||
install_element (BGP_NODE, &neighbor_password_cmd);
|
||||
install_element (BGP_NODE, &no_neighbor_password_cmd);
|
||||
|
||||
/* "neighbor activate" commands. */
|
||||
install_element (BGP_NODE, &neighbor_activate_cmd);
|
||||
install_element (BGP_IPV4_NODE, &neighbor_activate_cmd);
|
||||
|
|
139
bgpd/bgpd.c
139
bgpd/bgpd.c
|
@ -788,6 +788,7 @@ peer_new (struct bgp *bgp)
|
|||
peer->status = Idle;
|
||||
peer->ostatus = Idle;
|
||||
peer->weight = 0;
|
||||
peer->password = NULL;
|
||||
peer->bgp = bgp;
|
||||
peer = peer_lock (peer); /* initial reference */
|
||||
|
||||
|
@ -1202,6 +1203,17 @@ peer_delete (struct peer *peer)
|
|||
peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
|
||||
bgp_stop (peer);
|
||||
bgp_fsm_change_status (peer, Deleted);
|
||||
|
||||
/* Password configuration */
|
||||
if (peer->password)
|
||||
{
|
||||
XFREE (MTYPE_PEER_PASSWORD, peer->password);
|
||||
peer->password = NULL;
|
||||
|
||||
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
|
||||
bgp_md5_set (peer);
|
||||
}
|
||||
|
||||
bgp_timer_set (peer); /* stops all timers for Deleted */
|
||||
|
||||
/* Delete from all peer list. */
|
||||
|
@ -1417,6 +1429,17 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
|
|||
else
|
||||
peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
|
||||
|
||||
/* password apply */
|
||||
if (peer->password)
|
||||
XFREE (MTYPE_PEER_PASSWORD, peer->password);
|
||||
|
||||
if (conf->password)
|
||||
peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
|
||||
else
|
||||
peer->password = NULL;
|
||||
|
||||
bgp_md5_set (peer);
|
||||
|
||||
/* maximum-prefix */
|
||||
peer->pmax[afi][safi] = conf->pmax[afi][safi];
|
||||
peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
|
||||
|
@ -3379,6 +3402,111 @@ peer_local_as_unset (struct peer *peer)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Set password for authenticating with the peer. */
|
||||
int
|
||||
peer_password_set (struct peer *peer, const char *password)
|
||||
{
|
||||
struct listnode *nn, *nnode;
|
||||
int len = password ? strlen(password) : 0;
|
||||
int ret = BGP_SUCCESS;
|
||||
|
||||
if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
|
||||
return BGP_ERR_INVALID_VALUE;
|
||||
|
||||
if (peer->password && strcmp (peer->password, password) == 0
|
||||
&& ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
|
||||
return 0;
|
||||
|
||||
if (peer->password)
|
||||
XFREE (MTYPE_PEER_PASSWORD, peer->password);
|
||||
|
||||
peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
|
||||
|
||||
if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
|
||||
{
|
||||
if (peer->status == Established)
|
||||
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
|
||||
else
|
||||
BGP_EVENT_ADD (peer, BGP_Stop);
|
||||
|
||||
return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
|
||||
{
|
||||
if (peer->password && strcmp (peer->password, password) == 0)
|
||||
continue;
|
||||
|
||||
if (peer->password)
|
||||
XFREE (MTYPE_PEER_PASSWORD, peer->password);
|
||||
|
||||
peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
|
||||
|
||||
if (peer->status == Established)
|
||||
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
|
||||
else
|
||||
BGP_EVENT_ADD (peer, BGP_Stop);
|
||||
|
||||
if (bgp_md5_set (peer) < 0)
|
||||
ret = BGP_ERR_TCPSIG_FAILED;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
peer_password_unset (struct peer *peer)
|
||||
{
|
||||
struct listnode *nn, *nnode;
|
||||
|
||||
if (!peer->password
|
||||
&& !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
|
||||
return 0;
|
||||
|
||||
if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
|
||||
{
|
||||
if (peer_group_active (peer)
|
||||
&& peer->group->conf->password
|
||||
&& strcmp (peer->group->conf->password, peer->password) == 0)
|
||||
return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
|
||||
|
||||
if (peer->status == Established)
|
||||
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
|
||||
else
|
||||
BGP_EVENT_ADD (peer, BGP_Stop);
|
||||
|
||||
if (peer->password)
|
||||
XFREE (MTYPE_PEER_PASSWORD, peer->password);
|
||||
|
||||
peer->password = NULL;
|
||||
|
||||
bgp_md5_set (peer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
XFREE (MTYPE_PEER_PASSWORD, peer->password);
|
||||
peer->password = NULL;
|
||||
|
||||
for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
|
||||
{
|
||||
if (!peer->password)
|
||||
continue;
|
||||
|
||||
if (peer->status == Established)
|
||||
bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
|
||||
else
|
||||
BGP_EVENT_ADD (peer, BGP_Stop);
|
||||
|
||||
XFREE (MTYPE_PEER_PASSWORD, peer->password);
|
||||
peer->password = NULL;
|
||||
|
||||
bgp_md5_set (peer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set distribute list to the peer. */
|
||||
int
|
||||
peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
|
||||
|
@ -4416,9 +4544,17 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
|
|||
! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
|
||||
vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
|
||||
|
||||
/* Password. */
|
||||
if (peer->password)
|
||||
if (!peer_group_active (peer)
|
||||
|| ! g_peer->password
|
||||
|| strcmp (peer->password, g_peer->password) != 0)
|
||||
vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
|
||||
VTY_NEWLINE);
|
||||
|
||||
/* BGP port. */
|
||||
if (peer->port != BGP_PORT_DEFAULT)
|
||||
vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
|
||||
vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
|
||||
VTY_NEWLINE);
|
||||
|
||||
/* Local interface name. */
|
||||
|
@ -4948,6 +5084,7 @@ bgp_master_init (void)
|
|||
|
||||
bm = &bgp_master;
|
||||
bm->bgp = list_new ();
|
||||
bm->listen_sockets = list_new ();
|
||||
bm->port = BGP_PORT_DEFAULT;
|
||||
bm->master = thread_master_create ();
|
||||
bm->start_time = time (NULL);
|
||||
|
|
18
bgpd/bgpd.h
18
bgpd/bgpd.h
|
@ -42,6 +42,9 @@ struct bgp_master
|
|||
struct work_queue *process_main_queue;
|
||||
struct work_queue *process_rsclient_queue;
|
||||
|
||||
/* Listening sockets */
|
||||
struct list *listen_sockets;
|
||||
|
||||
/* BGP port number. */
|
||||
u_int16_t port;
|
||||
|
||||
|
@ -377,7 +380,10 @@ struct peer
|
|||
#define PEER_FLAG_ORF_PREFIX_RM (1 << 13) /* orf capability receive-mode */
|
||||
#define PEER_FLAG_MAX_PREFIX (1 << 14) /* maximum prefix */
|
||||
#define PEER_FLAG_MAX_PREFIX_WARNING (1 << 15) /* maximum prefix warning-only */
|
||||
#define PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED (1 << 16) /* leave link-local nexthop unchanged */
|
||||
#define PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED (1 << 16) /* leave link-local nexthop unchanged */
|
||||
|
||||
/* MD5 password */
|
||||
char *password;
|
||||
|
||||
/* default-originate route-map. */
|
||||
struct
|
||||
|
@ -534,6 +540,9 @@ struct peer
|
|||
#define PEER_RMAP_TYPE_EXPORT (1 << 7) /* neighbor route-map export */
|
||||
};
|
||||
|
||||
#define PEER_PASSWORD_MINLEN (1)
|
||||
#define PEER_PASSWORD_MAXLEN (80)
|
||||
|
||||
/* This structure's member directly points incoming packet data
|
||||
stream. */
|
||||
struct bgp_nlri
|
||||
|
@ -787,7 +796,8 @@ enum bgp_clear_type
|
|||
#define BGP_ERR_INSTANCE_MISMATCH -26
|
||||
#define BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP -27
|
||||
#define BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS -28
|
||||
#define BGP_ERR_MAX -29
|
||||
#define BGP_ERR_TCPSIG_FAILED -29
|
||||
#define BGP_ERR_MAX -30
|
||||
|
||||
extern struct bgp_master *bm;
|
||||
|
||||
|
@ -924,6 +934,10 @@ extern int peer_route_map_set (struct peer *, afi_t, safi_t, int, const char *);
|
|||
extern int peer_route_map_unset (struct peer *, afi_t, safi_t, int);
|
||||
|
||||
extern int peer_unsuppress_map_set (struct peer *, afi_t, safi_t, const char *);
|
||||
|
||||
extern int peer_password_set (struct peer *, const char *);
|
||||
extern int peer_password_unset (struct peer *);
|
||||
|
||||
extern int peer_unsuppress_map_unset (struct peer *, afi_t, safi_t);
|
||||
|
||||
extern int peer_maximum_prefix_set (struct peer *, afi_t, safi_t, u_int32_t, u_char, int, u_int16_t);
|
||||
|
|
21
configure.ac
21
configure.ac
|
@ -906,6 +906,27 @@ AC_CHECK_HEADER([net/if.h],
|
|||
QUAGGA_INCLUDES)],
|
||||
[], QUAGGA_INCLUDES )
|
||||
|
||||
dnl ------------------------
|
||||
dnl TCP_MD5SIG socket option
|
||||
dnl ------------------------
|
||||
|
||||
AC_CHECK_HEADER([netinet/tcp.h],
|
||||
[m4_define([MD5_INCLUDES],
|
||||
QUAGGA_INCLUDES
|
||||
[#include <netinet/tcp.h>
|
||||
])
|
||||
AC_CHECK_DECLS([TCP_MD5SIG], [], [], MD5_INCLUDES)],
|
||||
[],
|
||||
QUAGGA_INCLUDES)
|
||||
if test $ac_cv_have_decl_TCP_MD5SIG = no; then
|
||||
AC_CHECK_HEADER([linux/tcp.h],
|
||||
[m4_define([MD5_INCLUDES],
|
||||
QUAGGA_INCLUDES
|
||||
[#include <linux/tcp.h>
|
||||
])
|
||||
AC_CHECK_DECLS([TCP_MD5SIG], [], [], MD5_INCLUDES)])
|
||||
fi
|
||||
|
||||
dnl -----------------------
|
||||
dnl check proc file system.
|
||||
dnl -----------------------
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
2008-07-21 Paul Jakma <paul.jakma@sun.com>
|
||||
|
||||
* sockunion.c: ifdef out various places that converted
|
||||
v4mapped sockets to pure v4. Doesn't seem necessary at all,
|
||||
presumably a workaround for now historical inet_ntop bugs (?)
|
||||
|
||||
2008-07-21 Michael H. Warfield <mhw@wittsend.com>
|
||||
YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
|
||||
|
||||
* sockopt.{c,h}: (sockopt_tcp_signature) Add TCP-MD5SIG support.
|
||||
|
||||
2008-06-07 Paul Jakma <paul@jakma.org>
|
||||
|
||||
* stream.{c,h}: (stream_{put,write}) add const qualifier to source
|
||||
|
|
|
@ -95,6 +95,7 @@ struct memory_list memory_list_bgp[] =
|
|||
{ MTYPE_BGP_PEER_HOST, "BGP peer hostname" },
|
||||
{ MTYPE_PEER_GROUP, "Peer group" },
|
||||
{ MTYPE_PEER_DESC, "Peer description" },
|
||||
{ MTYPE_PEER_PASSWORD, "Peer password string" },
|
||||
{ MTYPE_ATTR, "BGP attribute" },
|
||||
{ MTYPE_ATTR_EXTRA, "BGP extra attributes" },
|
||||
{ MTYPE_AS_PATH, "BGP aspath" },
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <zebra.h>
|
||||
#include "log.h"
|
||||
#include "sockopt.h"
|
||||
#include "sockunion.h"
|
||||
|
||||
int
|
||||
setsockopt_so_recvbuf (int sock, int size)
|
||||
|
@ -480,3 +481,70 @@ sockopt_iphdrincl_swab_systoh (struct ip *iph)
|
|||
|
||||
iph->ip_id = ntohs(iph->ip_id);
|
||||
}
|
||||
|
||||
int
|
||||
sockopt_tcp_signature (int sock, union sockunion *su, const char *password)
|
||||
{
|
||||
#if HAVE_DECL_TCP_MD5SIG
|
||||
#ifndef GNU_LINUX
|
||||
/*
|
||||
* XXX Need to do PF_KEY operation here to add/remove an SA entry,
|
||||
* and add/remove an SP entry for this peer's packet flows also.
|
||||
*/
|
||||
int md5sig = password && *password ? 1 : 0;
|
||||
#else
|
||||
int keylen = password ? strlen (password) : 0;
|
||||
struct tcp_md5sig md5sig;
|
||||
union sockunion *su2, *susock;
|
||||
int ret;
|
||||
|
||||
/* Figure out whether the socket and the sockunion are the same family..
|
||||
* adding AF_INET to AF_INET6 needs to be v4 mapped, you'd think..
|
||||
*/
|
||||
if (!(susock = sockunion_getsockname (sock)))
|
||||
return -1;
|
||||
|
||||
if (susock->sa.sa_family == su->sa.sa_family)
|
||||
su2 = su;
|
||||
else
|
||||
{
|
||||
/* oops.. */
|
||||
su2 = susock;
|
||||
|
||||
if (su2->sa.sa_family == AF_INET)
|
||||
{
|
||||
sockunion_free (susock);
|
||||
return -1;
|
||||
};
|
||||
|
||||
/* If this does not work, then all users of this sockopt will need to
|
||||
* differentiate between IPv4 and IPv6, and keep seperate sockets for
|
||||
* each.
|
||||
*
|
||||
* Sadly, it doesn't seem to work at present. It's unknown whether
|
||||
* this is a bug or not.
|
||||
*/
|
||||
if (su2->sa.sa_family == AF_INET6
|
||||
&& su->sa.sa_family == AF_INET)
|
||||
{
|
||||
su2->sin6.sin6_family = AF_INET6;
|
||||
/* V4Map the address */
|
||||
memset (&su2->sin6.sin6_addr, 0, sizeof (struct in6_addr));
|
||||
su2->sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
|
||||
memcpy (&su2->sin6.sin6_addr.s6_addr32[3], &su->sin.sin_addr, 4);
|
||||
}
|
||||
}
|
||||
|
||||
memset (&md5sig, 0, sizeof (md5sig));
|
||||
memcpy (&md5sig.tcpm_addr, su2, sizeof (*su2));
|
||||
md5sig.tcpm_keylen = keylen;
|
||||
if (keylen)
|
||||
memcpy (md5sig.tcpm_key, password, keylen);
|
||||
#endif /* GNU_LINUX */
|
||||
ret = setsockopt (sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof md5sig);
|
||||
sockunion_free (susock);
|
||||
return ret;
|
||||
#else /* HAVE_TCP_MD5SIG */
|
||||
return -2;
|
||||
#endif /* HAVE_TCP_MD5SIG */
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#ifndef _ZEBRA_SOCKOPT_H
|
||||
#define _ZEBRA_SOCKOPT_H
|
||||
|
||||
#include "sockunion.h"
|
||||
|
||||
extern int setsockopt_so_recvbuf (int sock, int size);
|
||||
extern int setsockopt_so_sendbuf (const int sock, int size);
|
||||
extern int getsockopt_so_sendbuf (const int sock);
|
||||
|
@ -98,4 +100,6 @@ extern int getsockopt_ifindex (int, struct msghdr *);
|
|||
extern void sockopt_iphdrincl_swab_htosys (struct ip *iph);
|
||||
extern void sockopt_iphdrincl_swab_systoh (struct ip *iph);
|
||||
|
||||
extern int sockopt_tcp_signature(int sock, union sockunion *su,
|
||||
const char *password);
|
||||
#endif /*_ZEBRA_SOCKOPT_H */
|
||||
|
|
|
@ -254,6 +254,7 @@ sockunion_accept (int sock, union sockunion *su)
|
|||
client_sock = accept (sock, (struct sockaddr *) su, &len);
|
||||
|
||||
/* Convert IPv4 compatible IPv6 address to IPv4 address. */
|
||||
#if 0
|
||||
#ifdef HAVE_IPV6
|
||||
if (su->sa.sa_family == AF_INET6)
|
||||
{
|
||||
|
@ -268,7 +269,7 @@ sockunion_accept (int sock, union sockunion *su)
|
|||
}
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
||||
#endif
|
||||
return client_sock;
|
||||
}
|
||||
|
||||
|
@ -592,6 +593,7 @@ sockunion_getsockname (int fd)
|
|||
su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
|
||||
memcpy (su, &name, sizeof (struct sockaddr_in6));
|
||||
|
||||
#if 0
|
||||
if (IN6_IS_ADDR_V4MAPPED (&su->sin6.sin6_addr))
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
|
@ -601,6 +603,7 @@ sockunion_getsockname (int fd)
|
|||
sin.sin_port = su->sin6.sin6_port;
|
||||
memcpy (su, &sin, sizeof (struct sockaddr_in));
|
||||
}
|
||||
#endif
|
||||
return su;
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
@ -645,7 +648,7 @@ sockunion_getpeername (int fd)
|
|||
{
|
||||
su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion));
|
||||
memcpy (su, &name, sizeof (struct sockaddr_in6));
|
||||
|
||||
#if 0
|
||||
if (IN6_IS_ADDR_V4MAPPED (&su->sin6.sin6_addr))
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
|
@ -655,6 +658,7 @@ sockunion_getpeername (int fd)
|
|||
sin.sin_port = su->sin6.sin6_port;
|
||||
memcpy (su, &sin, sizeof (struct sockaddr_in));
|
||||
}
|
||||
#endif
|
||||
return su;
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
||||
|
|
Loading…
Reference in a new issue