diff --git a/bgpq3.8 b/bgpq3.8 index db60c4c..b7b47cc 100644 --- a/bgpq3.8 +++ b/bgpq3.8 @@ -31,6 +31,7 @@ .Sh SYNOPSIS .Nm .Op Fl h Ar host[:port] +.Op Fl I Ar laddr .Op Fl S Ar sources .Op Fl EPz .Oo @@ -90,6 +91,8 @@ generate output in user-defined format. generate output as-path access-list. .It Fl h Ar host[:port] host running IRRD database (default: whois.radb.net). +.It Fl H Ar laddr +local host source address used to connect to servers .It Fl J generate config for Juniper (default: Cisco). .It Fl j diff --git a/bgpq3.c b/bgpq3.c index 6b1ad90..dd35b30 100644 --- a/bgpq3.c +++ b/bgpq3.c @@ -52,6 +52,7 @@ usage(int ecode) printf(" -h host : host running IRRD software (whois.radb.net by " "default)\n" " (use host:port to specify alternate port)\n"); + printf(" -I laddr : bind to local address\n"); printf(" -J : generate config for JunOS (Cisco IOS by default)\n"); printf(" -j : generate JSON output (Cisco IOS by default)\n"); printf(" -M match : extra match conditions for JunOS route-filters\n"); @@ -155,7 +156,7 @@ main(int argc, char* argv[]) if (getenv("IRRD_SOURCES")) expander.sources=getenv("IRRD_SOURCES"); - while((c=getopt(argc,argv,"2346a:AbBdDEF:HS:jJf:l:L:m:M:NnW:Ppr:R:G:tTh:UwXxsz")) + while((c=getopt(argc,argv,"2346a:AbBdDEF:HS:jJf:l:L:m:M:NnW:Ppr:R:G:tTh:I:UwXxsz")) !=EOF) { switch(c) { case '2': @@ -238,6 +239,9 @@ main(int argc, char* argv[]) }; break; }; + case 'I': + expander.laddr=optarg; + break; case 'J': if(expander.vendor) vendor_exclusive(); expander.vendor=V_JUNIPER; break; diff --git a/bgpq3.h b/bgpq3.h index 686c454..e033d7b 100644 --- a/bgpq3.h +++ b/bgpq3.h @@ -66,6 +66,7 @@ struct bgpq_expander { char* match; char* server; char* port; + char* laddr; char* format; unsigned maxlen; STAILQ_HEAD(bgpq_requests, bgpq_request) wq, rq; diff --git a/bgpq_expander.c b/bgpq_expander.c index 843d835..da62102 100644 --- a/bgpq_expander.c +++ b/bgpq_expander.c @@ -794,7 +794,7 @@ static int bgpq_connect(struct bgpq_expander *b) { int fd, err, ret; - struct addrinfo hints, *res=NULL, *rp; + struct addrinfo hints, *res=NULL, *rp, *bres=NULL; struct linger sl; if (!b->connect) @@ -804,8 +804,20 @@ bgpq_connect(struct bgpq_expander *b) sl.l_linger = 5; memset(&hints,0,sizeof(struct addrinfo)); - hints.ai_socktype=SOCK_STREAM; + if(b->laddr) { + hints.ai_socktype=SOCK_STREAM; + hints.ai_flags=AI_NUMERICHOST|AI_ADDRCONFIG; + err=getaddrinfo(b->laddr,NULL,&hints,&bres); + if(err) { + sx_report(SX_ERROR,"Unable to parse local address %s: %s\n", + b->laddr, gai_strerror(err)); + exit(1); + }; + memset(&hints,0,sizeof(struct addrinfo)); + hints.ai_family = bres->ai_family; + } + hints.ai_socktype=SOCK_STREAM; err=getaddrinfo(b->server,b->port,&hints,&res); if(err) { sx_report(SX_ERROR,"Unable to resolve %s: %s\n", @@ -821,6 +833,14 @@ bgpq_connect(struct bgpq_expander *b) strerror(errno)); exit(1); }; + if(b->laddr && bres) { + err=bind(fd,bres->ai_addr,bres->ai_addrlen); + if(err==-1) { + sx_report(SX_ERROR,"Unable to bind local address %s to socket: %s\n", + b->laddr,strerror(errno)); + exit(1); + } + } if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &sl, sizeof(struct linger))) { sx_report(SX_ERROR,"Unable to set linger on socket: %s\n", strerror(errno)); @@ -846,6 +866,8 @@ bgpq_connect(struct bgpq_expander *b) }; break; }; + if(bres) + freeaddrinfo(bres); freeaddrinfo(res); if(fd == -1) {