From b36141c0c739177e1ebb0e09024ca2fc736eb160 Mon Sep 17 00:00:00 2001 From: Benjamin Cama Date: Fri, 22 Jul 2011 02:11:33 +0200 Subject: [PATCH] Add an option to set source address for a BGP session. When adding a BGP neighbour, one can set "update-source" (quagga syntax) to the source IP address that will be used for that session. Signed-off-by: Benjamin Cama --- bgp.c | 17 ++++++++++++++++- bgp.h | 3 ++- cli.c | 30 ++++++++++++++++++++++++++++++ l2tpns.c | 3 ++- l2tpns.h | 1 + 5 files changed, 51 insertions(+), 3 deletions(-) diff --git a/bgp.c b/bgp.c index 6a868fa..4b7f949 100644 --- a/bgp.c +++ b/bgp.c @@ -95,7 +95,7 @@ int bgp_setup(int as) /* start connection with a peer */ int bgp_start(struct bgp_peer *peer, char *name, int as, int keepalive, - int hold, int enable) + int hold, struct in_addr update_source, int enable) { struct hostent *h; int ibgp; @@ -124,6 +124,7 @@ int bgp_start(struct bgp_peer *peer, char *name, int as, int keepalive, } memcpy(&peer->addr, h->h_addr, sizeof(peer->addr)); + peer->source_addr = update_source.s_addr; peer->as = as > 0 ? as : our_as; ibgp = peer->as == our_as; @@ -696,6 +697,7 @@ static int bgp_connect(struct bgp_peer *peer) { static int bgp_port = 0; struct sockaddr_in addr; + struct sockaddr_in source_addr; struct epoll_event ev; if (!bgp_port) @@ -727,6 +729,19 @@ static int bgp_connect(struct bgp_peer *peer) /* set to non-blocking */ fcntl(peer->sock, F_SETFL, fcntl(peer->sock, F_GETFL, 0) | O_NONBLOCK); + /* set source address */ + memset(&source_addr, 0, sizeof(source_addr)); + source_addr.sin_family = AF_INET; + source_addr.sin_addr.s_addr = peer->source_addr; /* defaults to INADDR_ANY */ + if (bind(peer->sock, (struct sockaddr *) &source_addr, sizeof(source_addr)) < 0) + { + LOG(1, 0, 0, "Can't set source address to %s: %s\n", + inet_ntoa(source_addr.sin_addr), strerror(errno)); + + bgp_set_retry(peer); + return 0; + } + /* try connect */ memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; diff --git a/bgp.h b/bgp.h index 0a2e59c..1dbee29 100644 --- a/bgp.h +++ b/bgp.h @@ -152,6 +152,7 @@ struct bgp_buf { struct bgp_peer { char name[32]; /* peer name */ in_addr_t addr; /* peer address */ + in_addr_t source_addr; /* our source address */ int as; /* AS number */ int sock; enum bgp_state state; /* FSM state */ @@ -188,7 +189,7 @@ extern int bgp_configured; /* actions */ int bgp_setup(int as); int bgp_start(struct bgp_peer *peer, char *name, int as, int keepalive, - int hold, int enable); + int hold, struct in_addr update_source, int enable); void bgp_stop(struct bgp_peer *peer); void bgp_halt(struct bgp_peer *peer); diff --git a/cli.c b/cli.c index e182e8b..8377339 100644 --- a/cli.c +++ b/cli.c @@ -1038,6 +1038,11 @@ static int cmd_show_run(struct cli_def *cli, char *command, char **argv, int arg h = BGP_HOLD_TIME; cli_print(cli, " neighbour %s timers %d %d", config->neighbour[i].name, k, h); + + if (config->neighbour[i].update_source.s_addr != INADDR_ANY) + cli_print(cli, " neighbour %s update-source %s", + config->neighbour[i].name, + inet_ntoa(config->neighbour[i].update_source)); } } #endif @@ -2064,6 +2069,7 @@ static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **a return cli_arg_help(cli, 0, "remote-as", "Set remote autonomous system number", "timers", "Set timers", + "update-source", "Set source address to use for the BGP session", NULL); default: @@ -2082,6 +2088,9 @@ static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **a return cli_arg_help(cli, 1, NULL); } + if (MATCH("update-source", argv[1])) + return cli_arg_help(cli, argc > 3, "A.B.C.D", "Source IP address", NULL); + return CLI_OK; } } @@ -2118,12 +2127,33 @@ static int cmd_router_bgp_neighbour(struct cli_def *cli, char *command, char **a snprintf(config->neighbour[i].name, sizeof(config->neighbour[i].name), "%s", argv[0]); config->neighbour[i].keepalive = -1; config->neighbour[i].hold = -1; + config->neighbour[i].update_source.s_addr = INADDR_ANY; } config->neighbour[i].as = as; return CLI_OK; } + if (MATCH("update-source", argv[1])) + { + struct in_addr addr; + + if (!config->neighbour[i].name[0]) + { + cli_error(cli, "Specify remote-as first"); + return CLI_OK; + } + + if (!inet_aton(argv[2], &addr)) + { + cli_error(cli, "Cannot parse IP \"%s\"", argv[2]); + return CLI_OK; + } + + config->neighbour[i].update_source = addr; + return CLI_OK; + } + if (argc != 4 || !MATCH("timers", argv[1])) { cli_error(cli, "Invalid arguments"); diff --git a/l2tpns.c b/l2tpns.c index 19289b0..7f94d24 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -3564,7 +3564,8 @@ static void mainloop(void) if (config->neighbour[i].name[0]) bgp_start(&bgp_peers[i], config->neighbour[i].name, config->neighbour[i].as, config->neighbour[i].keepalive, - config->neighbour[i].hold, 0); /* 0 = routing disabled */ + config->neighbour[i].hold, config->neighbour[i].update_source, + 0); /* 0 = routing disabled */ } #endif /* BGP */ diff --git a/l2tpns.h b/l2tpns.h index 6849be9..032c237 100644 --- a/l2tpns.h +++ b/l2tpns.h @@ -723,6 +723,7 @@ typedef struct uint16_t as; int keepalive; int hold; + struct in_addr update_source; } neighbour[BGP_NUM_PEERS]; #endif } configt; -- 2.20.1