From 49984acc34e108c3455a9d74f1394913b6433aa1 Mon Sep 17 00:00:00 2001 From: snar Date: Fri, 16 May 2008 15:19:09 +0000 Subject: [PATCH] Initial support for ASN32 (RFC4893), Juniper only for now --- bgpq3.c | 19 +++++++++++--- bgpq3.h | 3 ++- bgpq3_printer.c | 66 +++++++++++++++++++++++++++++-------------------- bgpq_expander.c | 61 ++++++++++++++++++++++++++++++++++++--------- 4 files changed, 105 insertions(+), 44 deletions(-) diff --git a/bgpq3.c b/bgpq3.c index 8b4e1c8..2090409 100644 --- a/bgpq3.c +++ b/bgpq3.c @@ -21,14 +21,15 @@ extern int debug_expander; int usage(int ecode) { - printf("Usage: bgpq3 [-h] [-S sources] [-P|G |f ] [-6]" + printf("Usage: bgpq3 [-h] [-S sources] [-P|G |f ] [-36]" " ...\n"); - printf(" -6 : generate IPv6 access/prefix-lists\n"); + printf(" -3 : assume that your device is asn32-safe\n"); + printf(" -6 : generate IPv6 prefix-lists (IPv4 by default)\n"); printf(" -d : generate some debugging output\n"); printf(" -f number : generate input as-path access-list\n"); printf(" -G number : generate output as-path access-list\n"); printf(" -h : this help\n"); - printf(" -J : use Juniper replace formatted output\n"); + printf(" -J : generate config for JunOS (Cisco IOS by default)\n"); printf(" -l : use specified name for generated access/prefix/.." " list\n"); printf(" -P : generate prefix-list (default)\n"); @@ -56,8 +57,11 @@ main(int argc, char* argv[]) bgpq_expander_init(&expander,af); expander.sources=getenv("IRRD_SOURCES"); - while((c=getopt(argc,argv,"6dhS:Jf:l:W:PG:"))!=EOF) { + while((c=getopt(argc,argv,"36dhS:Jf:l:W:PG:"))!=EOF) { switch(c) { + case '3': + expander.asn32=1; + break; case '6': af=AF_INET6; expander.family=AF_INET6; expander.tree->family=AF_INET6; @@ -125,6 +129,13 @@ main(int argc, char* argv[]) expander.generation=T_PREFIXLIST; }; + if(expander.vendor==V_CISCO && expander.asn32 && + expander.generationname?b->name:"NN"); - if(b->asnumbers[b->asnumber/8]&(0x80>>(b->asnumber%8))) { + if(b->asn32s[0][b->asnumber/8]&(0x80>>(b->asnumber%8))) { fprintf(f,"ip as-path access-list %s permit ^%i(_%i)*$\n", b->name?b->name:"NN",b->asnumber,b->asnumber); }; - for(i=0;iasnumbers);i++) { + for(i=0;i<8192;i++) { for(j=0;j<8;j++) { - if(b->asnumbers[i]&(0x80>>j)) { + if(b->asn32s[0][i]&(0x80>>j)) { if(i*8+j==b->asnumber) continue; if(!nc) { fprintf(f,"ip as-path access-list %s permit" @@ -48,13 +48,13 @@ bgpq3_print_cisco_oaspath(FILE* f, struct bgpq_expander* b) { int nc=0, i, j; fprintf(f,"no ip as-path access-list %s\n", b->name?b->name:"NN"); - if(b->asnumbers[b->asnumber/8]&(0x80>>(b->asnumber%8))) { + if(b->asn32s[0][b->asnumber/8]&(0x80>>(b->asnumber%8))) { fprintf(f,"ip as-path access-list %s permit ^(_%i)*$\n", b->name?b->name:"NN",b->asnumber); }; - for(i=0;iasnumbers);i++) { + for(i=0;i<8192;i++) { for(j=0;j<8;j++) { - if(b->asnumbers[i]&(0x80>>j)) { + if(b->asn32s[0][i]&(0x80>>j)) { if(i*8+j==b->asnumber) continue; if(!nc) { fprintf(f,"ip as-path access-list %s permit" @@ -78,30 +78,42 @@ bgpq3_print_cisco_oaspath(FILE* f, struct bgpq_expander* b) int bgpq3_print_juniper_aspath(FILE* f, struct bgpq_expander* b) { - int nc=0, lineNo=0, i, j; + int nc=0, lineNo=0, i, j, k; fprintf(f,"policy-options {\nreplace:\n as-path-group %s {\n", b->name?b->name:"NN"); - if(b->asnumbers[b->asnumber/8]&(0x80>>(b->asnumber%8))) { + if(b->asn32s[0][b->asnumber/8]&(0x80>>(b->asnumber%8))) { fprintf(f," as-path a%i \"^%i(%i)*$\";\n", lineNo, b->asnumber, b->asnumber); lineNo++; }; - for(i=0;iasnumbers);i++) { - for(j=0;j<8;j++) { - if(b->asnumbers[i]&(0x80>>j)) { - if(i*8+j==b->asnumber) continue; - if(!nc) { - fprintf(f," as-path a%i \"^%i(.)*(%i", - lineNo,b->asnumber,i*8+j); - } else { - fprintf(f,"|%i",i*8+j); - } - nc++; - if(nc==b->aswidth) { - fprintf(f,")$\";\n"); - nc=0; - lineNo++; + for(k=0;k<65536;k++) { + if(!b->asn32s[k]) continue; + for(i=0;i<8192;i++) { + for(j=0;j<8;j++) { + if(b->asn32s[k][i]&(0x80>>j)) { + if(i*8+j==b->asnumber) continue; + if(!nc) { + if(k) { + fprintf(f," as-path a%i \"^%i(.)*(%u.%u", + lineNo,b->asnumber,k,i*8+j); + } else { + fprintf(f," as-path a%i \"^%i(.)*(%u", + lineNo,b->asnumber,i*8+j); + }; + } else { + if(k) { + fprintf(f,"|%u.%u",k,i*8+j); + } else { + fprintf(f,"|%u",i*8+j); + }; + }; + nc++; + if(nc==b->aswidth) { + fprintf(f,")$\";\n"); + nc=0; + lineNo++; + }; }; }; }; @@ -118,14 +130,14 @@ bgpq3_print_juniper_oaspath(FILE* f, struct bgpq_expander* b) fprintf(f,"policy-options {\nreplace:\n as-path-group %s {\n", b->name?b->name:"NN"); - if(b->asnumbers[b->asnumber/8]&(0x80>>(b->asnumber%8))) { + if(b->asn32s[0][b->asnumber/8]&(0x80>>(b->asnumber%8))) { fprintf(f," as-path a%i \"^%i(%i)*$\";\n", lineNo, b->asnumber, b->asnumber); lineNo++; }; - for(i=0;iasnumbers);i++) { + for(i=0;i<8192;i++) { for(j=0;j<8;j++) { - if(b->asnumbers[i]&(0x80>>j)) { + if(b->asn32s[0][i]&(0x80>>j)) { if(i*8+j==b->asnumber) continue; if(!nc) { fprintf(f," as-path a%i \"^(.)*(%i", @@ -204,7 +216,7 @@ bgpq3_print_juniper_prefixlist(FILE* f, struct bgpq_expander* b) fprintf(f,"policy-options {\nreplace:\n prefix-list %s {\n", b->name?b->name:"NN"); sx_radix_tree_foreach(b->tree,bgpq3_print_jprefix,f); - fprintf(f," }\n}\n"); + fprintf(f," }\n}\n"); return 0; }; diff --git a/bgpq_expander.c b/bgpq_expander.c index 4caef96..e98c1e7 100644 --- a/bgpq_expander.c +++ b/bgpq_expander.c @@ -35,6 +35,7 @@ bgpq_expander_init(struct bgpq_expander* b, int af) b->sources="ripe,radb,apnic"; b->name="NN"; b->aswidth=8; + b->asn32s[0]=malloc(8192); return 1; fixups: @@ -77,7 +78,31 @@ bgpq_expander_add_as(struct bgpq_expander* b, char* as) }; if(*eoa=='.') { - sx_report(SX_ERROR,"32-bit as numbers is not supported yet (%s)\n",as); + if(b->asn32 || b->generation>=T_PREFIXLIST) { + uint32_t asn1=strtoul(eoa+1,&eoa,10); + if(eoa && *eoa!=0) { + sx_report(SX_ERROR,"Invalid symbol in AS number: '%c' in %s\n", + *eoa, as); + return 0; + }; + if(asn1<1 || asn1>65535) { + sx_report(SX_ERROR,"Invalid AS number in %s\n", as); + return 0; + }; + if(!b->asn32s[asno]) { + b->asn32s[asno]=malloc(8192); + if(!b->asn32s[asno]) { + sx_report(SX_ERROR, "Unable to allocate 8192 bytes: %s." + " Unable to add asn32 %s to future expansion\n", + strerror(errno), as); + return 0; + }; + memset(b->asn32s[asno],0,8192); + }; + b->asn32s[asno][asn1/8]|=(0x80>>(asn1%8)); + } else if(!b->asn32) { + b->asn32s[0][23456/8]|=(0x80>>(23456%8)); + }; return 0; }; @@ -86,7 +111,7 @@ bgpq_expander_add_as(struct bgpq_expander* b, char* as) return 0; }; - b->asnumbers[asno/8]|=(0x80>>(asno%8)); + b->asn32s[0][asno/8]|=(0x80>>(asno%8)); return 1; }; @@ -369,16 +394,28 @@ bgpq_expand(struct bgpq_expander* b) bgpq_expand_radb(f,bgpq_expanded_macro,b,"!i%s,1\n",mc->text); }; if(b->generation>=T_PREFIXLIST) { - int i, j; - for(i=0;iasnumbers);i++) { - for(j=0;j<8;j++) { - if(b->asnumbers[i]&(0x80>>j)) { - if(b->family==AF_INET6) { - bgpq_expand_ripe(f,bgpq_expanded_v6prefix,b, - "-i origin as%i\r\n",i*8+j); - } else { - bgpq_expand_radb(f,bgpq_expanded_prefix,b,"!gas%i\n", - i*8+j); + unsigned i, j, k; + for(k=0;kasn32s)/sizeof(unsigned char*);k++) { + if(!b->asn32s[k]) continue; + for(i=0;i<8192;i++) { + for(j=0;j<8;j++) { + if(b->asn32s[k][i]&(0x80>>j)) { + if(b->family==AF_INET6) { + if(k>0) + bgpq_expand_ripe(f,bgpq_expanded_v6prefix,b, + "-i origin as%u.%u\r\n", k, i*8+j); + else + bgpq_expand_ripe(f,bgpq_expanded_v6prefix,b, + "-i origin as%u\r\n", i*8+j); + + } else { + if(k>0) + bgpq_expand_radb(f,bgpq_expanded_prefix,b, + "!gas%u.%u\n", k, i*8+j); + else + bgpq_expand_radb(f,bgpq_expanded_prefix,b, + "!gas%u\n", i*8+j); + }; }; }; };