/* 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;
}
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;
{
static int bgp_port = 0;
struct sockaddr_in addr;
+ struct sockaddr_in source_addr;
struct epoll_event ev;
if (!bgp_port)
/* 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;
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 */
/* 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);
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
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:
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;
}
}
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");
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 */
uint16_t as;
int keepalive;
int hold;
+ struct in_addr update_source;
} neighbour[BGP_NUM_PEERS];
#endif
} configt;