1
0
mirror of https://github.com/bgp/bgpq4.git synced 2024-05-11 05:55:05 +00:00
bgp-bgpq4/bgpq3.c

445 lines
12 KiB
C
Raw Normal View History

2007-03-22 18:12:32 +00:00
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include "bgpq3.h"
#include "sx_report.h"
extern int debug_expander;
2008-05-20 13:12:44 +00:00
extern int debug_aggregation;
2008-05-19 13:33:32 +00:00
extern int pipelining;
2007-03-22 18:12:32 +00:00
int
usage(int ecode)
{
2008-12-19 17:39:15 +00:00
printf("\nUsage: bgpq3 [-h host] [-S sources] [-P|E|G <num>|f <num>]"
" [-346AbDJjXd] [-R len] <OBJECTS>...\n");
printf(" -3 : assume that your device is asn32-safe\n");
printf(" -4 : generate IPv4 prefix-lists (default)\n");
printf(" -6 : generate IPv6 prefix-lists (IPv4 by default)\n");
2008-12-25 17:17:05 +00:00
printf(" -A : try to aggregate Cisco prefix-lists or Juniper "
"route-filters\n as much as possible\n");
printf(" -b : generate BIRD output (Cisco IOS by default)\n");
printf(" -d : generate some debugging output\n");
2008-12-25 17:17:05 +00:00
printf(" -D : use asdot notation in as-path\n");
2008-06-02 11:32:25 +00:00
printf(" -E : generate extended access-list(Cisco) or "
"route-filter(Juniper)\n");
2007-04-04 13:15:20 +00:00
printf(" -f number : generate input as-path access-list\n");
printf(" -G number : generate output as-path access-list\n");
2008-12-19 17:39:15 +00:00
printf(" -h host : host running IRRD software (whois.radb.net by "
"default)\n");
printf(" -J : generate config for JunOS (Cisco IOS by default)\n");
2013-01-08 12:21:14 +00:00
printf(" -j : generate JSON output (Cisco IOS by default)\n");
2008-08-08 09:29:53 +00:00
printf(" -M match : extra match conditions for JunOS route-filters\n");
printf(" -m len : maximum prefix length (default: 32 for IPv4, "
"128 for IPv6)\n");
2008-08-08 09:29:53 +00:00
printf(" -l name : use specified name for generated access/prefix/.."
2007-04-04 13:15:20 +00:00
" list\n");
2008-08-08 09:29:53 +00:00
printf(" -P : generate prefix-list (default, just for backward"
" compatibility)\n");
printf(" -r len : allow more specific routes from masklen specified\n");
printf(" -R len : allow more specific routes up to specified masklen\n");
2007-03-22 18:12:32 +00:00
printf(" -S sources: use only specified sources (default:"
" RADB,RIPE,APNIC)\n");
printf(" -T : disable pipelining (experimental, faster mode)\n");
2011-07-15 11:48:34 +00:00
printf(" -X : generate config for IOS XR (Cisco IOS by default)\n");
2008-05-16 16:59:56 +00:00
printf("\n" PACKAGE_NAME " version: " PACKAGE_VERSION "\n");
printf("Copyright(c) Alexandre Snarskii <snar@snar.spb.ru> 2007-2014\n\n");
2007-03-22 18:12:32 +00:00
exit(ecode);
};
2007-04-04 13:15:20 +00:00
void
exclusive()
{
2008-06-02 11:32:25 +00:00
fprintf(stderr,"-E, -f <asnum>, -G <asnum> and -P are mutually "
"exclusive\n");
2007-04-04 13:15:20 +00:00
exit(1);
};
2011-07-15 11:48:34 +00:00
void
vendor_exclusive()
{
fprintf(stderr, "-b (BIRD), -J (JunOS), -j (JSON) and -X (IOS XR) options are "
"mutually exclusive\n");
2011-07-15 11:48:34 +00:00
exit(1);
};
int
parseasnumber(struct bgpq_expander* expander, char* optarg)
{
char* eon=NULL;
expander->asnumber=strtoul(optarg,&eon,10);
if(expander->asnumber<1 || expander->asnumber>(65535ul*65535)) {
sx_report(SX_FATAL,"Invalid AS number: %s\n", optarg);
exit(1);
};
if(eon && *eon=='.') {
/* -f 3.3, for example */
uint32_t loas=strtoul(eon+1,&eon,10);
if(expander->asnumber>65535) {
/* should prevent incorrect numbers like 65537.1 */
sx_report(SX_FATAL,"Invalid AS number: %s\n", optarg);
exit(1);
};
if(loas<1 || loas>65535) {
sx_report(SX_FATAL,"Invalid AS number: %s\n", optarg);
exit(1);
};
if(eon && *eon) {
sx_report(SX_FATAL,"Invalid symbol in AS number: %c (%s)\n",
*eon, optarg);
exit(1);
};
expander->asnumber=(expander->asnumber<<16)+loas;
} else if(eon && *eon) {
sx_report(SX_FATAL,"Invalid symbol in AS number: %c (%s)\n",
*eon, optarg);
exit(1);
};
return 0;
};
2007-03-22 18:12:32 +00:00
int
main(int argc, char* argv[])
{
int c;
struct bgpq_expander expander;
int af=AF_INET, selectedipv4 = 0;
int widthSet=0, aggregate=0, refine=0, refineLow=0;
unsigned long maxlen=0;
2007-03-22 18:12:32 +00:00
bgpq_expander_init(&expander,af);
expander.sources=getenv("IRRD_SOURCES");
while((c=getopt(argc,argv,"346AbdDES:jJf:l:m:M:W:Pr:R:G:Th:X"))!=EOF) {
2007-03-22 18:12:32 +00:00
switch(c) {
case '3':
expander.asn32=1;
break;
case '4':
/* do nothing, expander already configured for IPv4 */
if (expander.family == AF_INET6) {
sx_report(SX_FATAL, "-4 and -6 are mutually exclusive\n");
exit(1);
};
selectedipv4=1;
break;
case '6':
if (selectedipv4) {
sx_report(SX_FATAL, "-4 and -6 are mutually exclusive\n");
exit(1);
};
af=AF_INET6;
2007-03-22 18:12:32 +00:00
expander.family=AF_INET6;
expander.tree->family=AF_INET6;
break;
2008-05-20 13:12:44 +00:00
case 'A':
if(aggregate) debug_aggregation++;
aggregate=1;
break;
case 'b':
if(expander.vendor) vendor_exclusive();
expander.vendor=V_BIRD;
break;
case 'd': debug_expander++;
2007-03-22 18:12:32 +00:00
break;
2008-12-25 17:17:05 +00:00
case 'D': expander.asdot=1;
break;
2008-06-02 11:32:25 +00:00
case 'E': if(expander.generation) exclusive();
expander.generation=T_EACL;
break;
2008-12-19 17:39:15 +00:00
case 'h': expander.server=optarg;
break;
2011-07-15 11:48:34 +00:00
case 'J': if(expander.vendor) vendor_exclusive();
expander.vendor=V_JUNIPER;
2007-03-22 18:12:32 +00:00
break;
2013-01-08 12:21:14 +00:00
case 'j': if(expander.vendor) vendor_exclusive();
expander.vendor=V_JSON;
break;
case 'f':
2007-04-04 13:15:20 +00:00
if(expander.generation) exclusive();
2007-03-22 18:12:32 +00:00
expander.generation=T_ASPATH;
parseasnumber(&expander,optarg);
2007-03-22 18:12:32 +00:00
break;
case 'G':
2007-04-04 13:15:20 +00:00
if(expander.generation) exclusive();
expander.generation=T_OASPATH;
parseasnumber(&expander,optarg);
2007-04-04 13:15:20 +00:00
break;
case 'P':
if(expander.generation) exclusive();
expander.generation=T_PREFIXLIST;
2007-03-22 18:12:32 +00:00
break;
case 'r':
refineLow=strtoul(optarg,NULL,10);
if(!refineLow) {
sx_report(SX_FATAL,"Invalid refineLow value: %s\n", optarg);
exit(1);
};
break;
case 'R':
refine=strtoul(optarg,NULL,10);
if(!refine) {
sx_report(SX_FATAL,"Invalid refine length: %s\n", optarg);
exit(1);
};
break;
2007-03-22 18:12:32 +00:00
case 'l': expander.name=optarg;
break;
case 'm': maxlen=strtoul(optarg, NULL, 10);
if (!maxlen) {
sx_report(SX_FATAL, "Invalid maxlen (-m): %s\n", optarg);
exit(1);
};
break;
2008-08-08 09:29:53 +00:00
case 'M': {
char* c, *d;
expander.match=strdup(optarg);
c=d=expander.match;
while(*c) {
if(*c=='\\') {
if(*(c+1)=='n') {
*d='\n';
d++;
c+=2;
} else if(*(c+1)=='r') {
*d='\r';
d++;
c+=2;
} else if(*(c+1)=='\\') {
*d='\\';
d++;
c+=2;
};
} else {
if(c!=d) {
*d=*c;
};
d++;
c++;
};
};
*d=0;
};
break;
case 'T': pipelining=0;
2008-05-19 13:33:32 +00:00
break;
2007-03-22 18:12:32 +00:00
case 'S': expander.sources=optarg;
break;
case 'W': expander.aswidth=atoi(optarg);
if(expander.aswidth<1) {
sx_report(SX_FATAL,"Invalid as-width: %s\n", optarg);
exit(1);
};
widthSet=1;
break;
2011-07-15 11:48:34 +00:00
case 'X': if(expander.vendor) vendor_exclusive();
expander.vendor=V_CISCO_XR;
break;
2007-03-22 18:12:32 +00:00
default : usage(1);
};
};
argc-=optind;
argv+=optind;
if(!widthSet) {
if(expander.generation==T_ASPATH) {
if(expander.vendor==V_CISCO) {
expander.aswidth=4;
} else if(expander.vendor==V_JUNIPER) {
expander.aswidth=8;
};
} else if(expander.generation==T_OASPATH) {
if(expander.vendor==V_CISCO) {
expander.aswidth=5;
} else if(expander.vendor==V_JUNIPER) {
expander.aswidth=8;
};
};
};
2007-04-04 13:15:20 +00:00
if(!expander.generation) {
expander.generation=T_PREFIXLIST;
};
if(expander.vendor==V_CISCO_XR && expander.generation!=T_PREFIXLIST) {
2011-07-15 11:48:34 +00:00
sx_report(SX_FATAL, "Sorry, only prefix-sets supported for IOS XR\n");
};
if(expander.vendor==V_BIRD && expander.generation!=T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, only prefix-lists supported for BIRD "
"output\n");
};
2013-01-08 12:21:14 +00:00
if(expander.vendor==V_JSON && expander.generation!=T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, only prefix-lists supported for JSON "
"output\n");
};
2008-12-25 17:17:05 +00:00
if(expander.asdot && expander.vendor!=V_CISCO) {
sx_report(SX_FATAL,"asdot notation supported only for Cisco, Juniper"
2011-07-15 11:48:34 +00:00
" uses asplain only\n");
2008-12-25 17:17:05 +00:00
};
if(!expander.asn32 && expander.asnumber>65535) {
expander.asnumber=23456;
};
2008-06-02 11:32:25 +00:00
if(aggregate && expander.vendor==V_JUNIPER &&
expander.generation==T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, aggregation (-A) does not work in"
" Juniper prefix-lists\nYou can try route-filters (-E) instead"
" of prefix-lists (-P, default)\n");
2008-05-20 13:12:44 +00:00
exit(1);
};
2013-01-08 12:21:14 +00:00
if(aggregate && expander.generation<T_PREFIXLIST) {
sx_report(SX_FATAL, "Sorry, aggregation (-A) used only for prefix-"
2008-06-02 11:32:25 +00:00
"lists, extended access-lists and route-filters\n");
exit(1);
};
if(refineLow && !refine) {
if(expander.family == AF_INET)
refine = 32;
else
refine = 128;
};
if (refineLow && refineLow > refine) {
sx_report(SX_FATAL, "Incompatible values for -r %u and -R %u\n",
refineLow, refine);
};
if(refine || refineLow) {
if(expander.family==AF_INET6 && refine>128) {
sx_report(SX_FATAL, "Invalid value for refine(-R): %u (1-128 for"
" IPv6)\n", refine);
} else if(expander.family==AF_INET6 && refineLow>128) {
sx_report(SX_FATAL, "Invalid value for refineLow(-r): %u (1-128 for"
" IPv6)\n", refineLow);
} else if(expander.family==AF_INET && refine>32) {
sx_report(SX_FATAL, "Invalid value for refine(-R): %u (1-32 for"
" IPv4)\n", refine);
} else if(expander.family==AF_INET && refineLow>32) {
sx_report(SX_FATAL, "Invalid value for refineLow(-r): %u (1-32 for"
" IPv4)\n", refineLow);
};
2008-06-02 11:32:25 +00:00
if(expander.vendor==V_JUNIPER && expander.generation==T_PREFIXLIST) {
if(refine) {
sx_report(SX_FATAL, "Sorry, more-specific filters (-R %u) "
"is not supported for Juniper prefix-lists.\n"
"Use router-filters (-E) instead\n", refine);
} else {
sx_report(SX_FATAL, "Sorry, more-specific filters (-r %u) "
"is not supported for Juniper prefix-lists.\n"
"Use route-filters (-E) instead\n", refineLow);
};
};
if(expander.generation<T_PREFIXLIST) {
if(refine) {
sx_report(SX_FATAL, "Sorry, more-specific filter (-R %u) "
"supported only with prefix-list generation\n", refine);
} else {
sx_report(SX_FATAL, "Sorry, more-specific filter (-r %u) "
"supported only with prefix-list generation\n", refineLow);
};
};
};
2013-01-08 12:21:14 +00:00
if(maxlen) {
if((expander.family==AF_INET6 && maxlen>128) ||
(expander.family==AF_INET && maxlen>32)) {
sx_report(SX_FATAL, "Invalid value for max-prefixlen: %lu (1-128 "
"for IPv6, 1-32 for IPv4)\n", maxlen);
exit(1);
} else if((expander.family==AF_INET6 && maxlen<128) ||
(expander.family==AF_INET && maxlen<32)) {
/* inet6/128 and inet4/32 does not make sense - all routes will
* be accepted, so save some CPU cycles :) */
expander.maxlen = maxlen;
};
};
if(expander.generation==T_EACL && expander.vendor==V_CISCO &&
expander.family==AF_INET6) {
sx_report(SX_FATAL,"Sorry, ipv6 access-lists not supported for Cisco"
" yet.\n");
};
if(expander.match != NULL && (expander.vendor != V_JUNIPER ||
expander.generation != T_EACL)) {
sx_report(SX_FATAL, "Sorry, extra match conditions (-M) can be used only with Juniper route-filters\n");
};
2007-03-22 18:12:32 +00:00
if(!argv[0]) usage(1);
while(argv[0]) {
if(!strncasecmp(argv[0],"AS-",3)) {
bgpq_expander_add_asset(&expander,argv[0]);
} else if(!strncasecmp(argv[0],"RS-",3)) {
bgpq_expander_add_rset(&expander,argv[0]);
2007-03-22 18:12:32 +00:00
} else if(!strncasecmp(argv[0],"AS",2)) {
2008-06-02 11:32:25 +00:00
char* c;
if((c=strchr(argv[0],':'))) {
if(!strncasecmp(c+1,"AS-",3)) {
bgpq_expander_add_asset(&expander,argv[0]);
} else if(!strncasecmp(c+1,"RS-",3)) {
bgpq_expander_add_rset(&expander,argv[0]);
} else {
SX_DEBUG(debug_expander,"Unknown sub-as object %s\n",
argv[0]);
};
} else {
bgpq_expander_add_as(&expander,argv[0]);
};
2007-03-22 18:12:32 +00:00
} else {
if(!bgpq_expander_add_prefix(&expander,argv[0]))
exit(1);
};
argv++;
argc--;
};
if(!bgpq_expand(&expander)) {
exit(1);
};
if(refine)
sx_radix_tree_refine(expander.tree,refine);
if(refineLow)
sx_radix_tree_refineLow(expander.tree, refineLow);
2008-08-08 09:29:53 +00:00
if(aggregate)
sx_radix_tree_aggregate(expander.tree);
2007-03-22 18:12:32 +00:00
switch(expander.generation) {
2008-06-02 11:32:25 +00:00
default :
2007-04-04 13:15:20 +00:00
case T_NONE: sx_report(SX_FATAL,"Unreachable point... call snar\n");
exit(1);
2007-03-22 18:12:32 +00:00
case T_ASPATH: bgpq3_print_aspath(stdout,&expander);
break;
2007-04-04 13:15:20 +00:00
case T_OASPATH: bgpq3_print_oaspath(stdout,&expander);
2007-03-22 18:12:32 +00:00
break;
2007-04-04 13:15:20 +00:00
case T_PREFIXLIST: bgpq3_print_prefixlist(stdout,&expander);
2008-06-02 11:32:25 +00:00
break;
case T_EACL: bgpq3_print_eacl(stdout,&expander);
break;
2007-03-22 18:12:32 +00:00
};
return 0;
};