From d787382df03378695075dc86b9cee51d83fdfc31 Mon Sep 17 00:00:00 2001 From: Alexandre Snarskii Date: Thu, 19 Feb 2015 16:41:38 +0300 Subject: [PATCH] RPSL routes now supported too. Can be found in rs-esnetcustomers. --- CHANGES | 4 + COPYRIGHT | 2 +- bgpq3.8 | 2 +- bgpq3.c | 11 +- bgpq3.h | 1 + bgpq_expander.c | 302 +++++++++++++------------- configure | 18 +- configure.in | 2 +- sx_prefix.c | 566 ++++++++++++++++++++++++++++-------------------- sx_prefix.h | 1 + 10 files changed, 509 insertions(+), 400 deletions(-) diff --git a/CHANGES b/CHANGES index 104bfe9..bb4d532 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +0.1.26 (2015-02-19) + - RPSL support, can be found in rs-esnetcustomers. + Thanks to Kris O'Connell for reporting. + 0.1.25 (2014-10-29) - JSON support extended to handle "as-paths" too. Well, actually, as there are no defined format for as-path in json, bgpq3 just creates diff --git a/COPYRIGHT b/COPYRIGHT index 0b0a6f9..256f26d 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2007-2014 Alexandre Snarskii + * Copyright (c) 2007-2015 Alexandre Snarskii * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/bgpq3.8 b/bgpq3.8 index 344a226..40a9823 100644 --- a/bgpq3.8 +++ b/bgpq3.8 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2007-2014 Alexandre Snarskii +.\" Copyright (c) 2007-2015 Alexandre Snarskii .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without diff --git a/bgpq3.c b/bgpq3.c index 411912c..e47aa37 100644 --- a/bgpq3.c +++ b/bgpq3.c @@ -351,7 +351,7 @@ main(int argc, char* argv[]) }; }; if(expander.generationname="NN"; b->aswidth=8; b->asn32s[0]=malloc(8192); - if(!b->asn32s[0]) { - sx_report(SX_FATAL,"Unable to allocate 8192 bytes: %s\n", + if(!b->asn32s[0]) { + sx_report(SX_FATAL,"Unable to allocate 8192 bytes: %s\n", strerror(errno)); exit(1); }; @@ -57,14 +57,14 @@ fixups: int bgpq_expander_add_asset(struct bgpq_expander* b, char* as) -{ +{ struct sx_slentry* le; if(!b || !as) return 0; le=sx_slentry_new(as); if(!le) return 0; - if(!b->macroses) { + if(!b->macroses) { b->macroses=le; - } else { + } else { struct sx_slentry* ln=b->macroses; while(ln->next) ln=ln->next; ln->next=le; @@ -72,16 +72,16 @@ bgpq_expander_add_asset(struct bgpq_expander* b, char* as) return 1; }; -int +int bgpq_expander_add_rset(struct bgpq_expander* b, char* rs) -{ +{ struct sx_slentry* le; if(!b || !rs) return 0; le=sx_slentry_new(rs); if(!le) return 0; - if(!b->rsets) { + if(!b->rsets) { b->rsets=le; - } else { + } else { struct sx_slentry* ln=b->rsets; while(ln->next) ln=ln->next; ln->next=le; @@ -91,55 +91,55 @@ bgpq_expander_add_rset(struct bgpq_expander* b, char* rs) int bgpq_expander_add_as(struct bgpq_expander* b, char* as) -{ +{ char* eoa; uint32_t asno; if(!b || !as) return 0; asno=strtoul(as+2,&eoa,10); - if(eoa && (*eoa!='.' && *eoa!=0)) { - sx_report(SX_ERROR,"Invalid symbol in AS number: '%c' in %s\n", + if(eoa && (*eoa!='.' && *eoa!=0)) { + sx_report(SX_ERROR,"Invalid symbol in AS number: '%c' in %s\n", *eoa, as); return 0; }; - if(*eoa=='.' || asno>65535) { - if(b->asn32 || b->generation>=T_PREFIXLIST) { + if(*eoa=='.' || asno>65535) { + if(b->asn32 || b->generation>=T_PREFIXLIST) { uint32_t asn1; - if(asno>65535) { + if(asno>65535) { asn1=asno%65536; asno/=65536; - } else + } else asn1=strtoul(eoa+1,&eoa,10); - if(eoa && *eoa!=0) { + if(eoa && *eoa!=0) { sx_report(SX_ERROR,"Invalid symbol in AS number: '%c' in %s\n", *eoa, as); return 0; }; - if(asn1>65535) { + if(asn1>65535) { sx_report(SX_ERROR,"Invalid AS number in %s\n", as); return 0; }; - if(!b->asn32s[asno]) { + if(!b->asn32s[asno]) { b->asn32s[asno]=malloc(8192); - if(!b->asn32s[asno]) { + if(!b->asn32s[asno]) { sx_report(SX_FATAL, "Unable to allocate 8192 bytes: %s." - " Unable to add asn32 %s to future expansion\n", + " 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) { + } else if(!b->asn32) { b->asn32s[0][23456/8]|=(0x80>>(23456%8)); }; return 0; }; - if(asno<1 || asno>65535) { + if(asno<1 || asno>65535) { sx_report(SX_ERROR,"Invalid AS number in %s\n", as); return 0; }; @@ -151,17 +151,17 @@ bgpq_expander_add_as(struct bgpq_expander* b, char* as) int bgpq_expander_add_prefix(struct bgpq_expander* b, char* prefix) -{ +{ struct sx_prefix p; - if(!sx_prefix_parse(&p,0,prefix)) { + if(!sx_prefix_parse(&p,0,prefix)) { sx_report(SX_ERROR,"Unable to parse prefix %s\n", prefix); return 0; - } else if(p.family!=b->family) { + } else if(p.family!=b->family) { SX_DEBUG(debug_expander,"Ignoring prefix %s with wrong address family\n" ,prefix); return 0; }; - if(b->maxlen && p.masklen>b->maxlen) { + if(b->maxlen && p.masklen>b->maxlen) { SX_DEBUG(debug_expander, "Ignoring prefix %s: masklen %i > max " "masklen %u\n", prefix, p.masklen, b->maxlen); return 0; @@ -170,9 +170,15 @@ bgpq_expander_add_prefix(struct bgpq_expander* b, char* prefix) return 1; }; +int +bgpq_expander_add_prefix_range(struct bgpq_expander* b, char* prefix) +{ + return sx_prefix_range_parse(b->tree, b->family, b->maxlen, prefix); +}; + int bgpq_expanded_macro(char* as, void* udata) -{ +{ struct bgpq_expander* ex=(struct bgpq_expander*)udata; if(!ex) return 0; bgpq_expander_add_as(ex,as); @@ -181,68 +187,72 @@ bgpq_expanded_macro(char* as, void* udata) int bgpq_expanded_prefix(char* as, void* udata) -{ +{ struct bgpq_expander* ex=(struct bgpq_expander*)udata; + char* d = strchr(as, '^'); if(!ex) return 0; - bgpq_expander_add_prefix(ex,as); + if (!d) + bgpq_expander_add_prefix(ex,as); + else + bgpq_expander_add_prefix_range(ex,as); return 1; }; int bgpq_expanded_v6prefix(char* prefix, void* udata) -{ +{ struct bgpq_expander* ex=(struct bgpq_expander*)udata; if(!ex) return 0; bgpq_expander_add_prefix(ex,prefix); return 1; }; -int +int bgpq_pipeline_dequeue_ripe(FILE* f, struct bgpq_expander* b) -{ +{ int sawNL=0; char buffer[128]; char* otype=NULL, *object=NULL; - if(!f || !b) { + if(!f || !b) { sx_report(SX_FATAL, "Invalid arguments\n"); exit(1); }; - if(!b->firstpipe) { + if(!b->firstpipe) { sx_report(SX_FATAL, "No piped requests\n"); exit(1); }; - while(fgets(buffer,sizeof(buffer),f)) { - if(buffer[0]=='\n') { + while(fgets(buffer,sizeof(buffer),f)) { + if(buffer[0]=='\n') { if(b->family==AF_INET && otype && !strcmp(otype,"route")) { SX_DEBUG(debug_expander,"dequeuer(ripe): got route %s\n", object); - if(b->firstpipe->callback) + if(b->firstpipe->callback) b->firstpipe->callback(object,b->firstpipe->udata); } else if(b->family==AF_INET6 && otype && !strcmp(otype,"route6")){ SX_DEBUG(debug_expander,"dequeuer(ripe): got route6 %s\n", object); - if(b->firstpipe->callback) + if(b->firstpipe->callback) b->firstpipe->callback(object,b->firstpipe->udata); }; if(otype) free(otype); otype=NULL; if(object) free(object); object=NULL; sawNL++; - if(sawNL==2) { + if(sawNL==2) { /* end of object */ struct bgpq_prequest* p=b->firstpipe; b->firstpipe=b->firstpipe->next; free(p); b->piped--; - if(!b->piped) { + if(!b->piped) { return 0; }; }; - } else { + } else { sawNL=0; - if(!otype) { + if(!otype) { char* c=strchr(buffer,':'); - if(c) { + if(c) { *c=0; otype=strdup(buffer); c++; @@ -254,10 +264,10 @@ bgpq_pipeline_dequeue_ripe(FILE* f, struct bgpq_expander* b) }; }; }; - if(feof(f)) { + if(feof(f)) { sx_report(SX_FATAL,"EOF from RADB (dequeue, ripe)\n"); - } else { - sx_report(SX_FATAL,"Error from RADB: %s (dequeue, ripe)\n", + } else { + sx_report(SX_FATAL,"Error from RADB: %s (dequeue, ripe)\n", strerror(errno)); }; return 0; @@ -273,7 +283,7 @@ bgpq_expand_ripe(FILE* f, int (*callback)(char*, void*), void* udata, va_list ap; struct bgpq_expander* b=(struct bgpq_expander*)udata; - if(!f) { + if(!f) { sx_report(SX_FATAL,"Invalid argments\n"); exit(1); }; @@ -287,13 +297,13 @@ bgpq_expand_ripe(FILE* f, int (*callback)(char*, void*), void* udata, fflush(f); sawNL=0; - while(fgets(request,sizeof(request),f)) { - if(request[0]=='\n') { - if(b->family==AF_INET && otype && !strcmp(otype,"route")) { + while(fgets(request,sizeof(request),f)) { + if(request[0]=='\n') { + if(b->family==AF_INET && otype && !strcmp(otype,"route")) { SX_DEBUG(debug_expander,"expander(ripe): got route: %s\n", object); callback(object,udata); - } else if(b->family==AF_INET6 && otype&&!strcmp(otype,"route6")) { + } else if(b->family==AF_INET6 && otype&&!strcmp(otype,"route6")) { SX_DEBUG(debug_expander,"expander(ripe): got route6: %s\n", object); callback(object,udata); @@ -303,16 +313,16 @@ bgpq_expand_ripe(FILE* f, int (*callback)(char*, void*), void* udata, if(origin) free(origin); origin=NULL; nObjects++; sawNL++; - if(sawNL==2) { + if(sawNL==2) { /* ok, that's end of input */ return nObjects; }; - } else { + } else { sawNL=0; - if(!otype) { + if(!otype) { /* that's the first line of object */ char* c=strchr(request,':'); - if(c) { + if(c) { *c=0; otype=strdup(request); c++; @@ -321,16 +331,16 @@ bgpq_expand_ripe(FILE* f, int (*callback)(char*, void*), void* udata, c=strchr(object,'\n'); if(c) *c=0; }; - } else if(!strncmp(request,"origin",6)) { + } else if(!strncmp(request,"origin",6)) { if(origin) free(origin); origin=strdup(request); }; }; }; - if(feof(f)) { + if(feof(f)) { sx_report(SX_FATAL,"EOF from server (expand, ripe)\n"); - } else { - sx_report(SX_FATAL,"Error reading server: %s (expand, ripe)\n", + } else { + sx_report(SX_FATAL,"Error reading server: %s (expand, ripe)\n", strerror(errno)); }; return 0; @@ -339,7 +349,7 @@ bgpq_expand_ripe(FILE* f, int (*callback)(char*, void*), void* udata, int bgpq_pipeline(FILE* f, int (*callback)(char*, void*), void* udata, char* fmt, ...) -{ +{ char request[128]; int ret; struct bgpq_prequest* bp=NULL; @@ -352,8 +362,8 @@ bgpq_pipeline(FILE* f, int (*callback)(char*, void*), void* udata, SX_DEBUG(debug_expander,"expander: sending '%s'\n", request); bp=malloc(sizeof(struct bgpq_prequest)); - if(!bp) { - sx_report(SX_FATAL,"Unable to allocate %lu bytes: %s\n", + if(!bp) { + sx_report(SX_FATAL,"Unable to allocate %lu bytes: %s\n", (unsigned long)sizeof(struct bgpq_prequest),strerror(errno)); exit(1); }; @@ -361,7 +371,7 @@ bgpq_pipeline(FILE* f, int (*callback)(char*, void*), void* udata, ret=fwrite(request,1,strlen(request),f); - if(ret!=strlen(request)) { + if(ret!=strlen(request)) { sx_report(SX_FATAL,"Partial write to radb, only %i bytes written: %s\n", ret,strerror(errno)); exit(1); @@ -371,10 +381,10 @@ bgpq_pipeline(FILE* f, int (*callback)(char*, void*), void* udata, bp->callback=callback; bp->udata=udata; - if(d->lastpipe) { + if(d->lastpipe) { d->lastpipe->next=bp; d->lastpipe=bp; - } else { + } else { d->firstpipe=d->lastpipe=bp; }; d->piped++; @@ -384,37 +394,37 @@ bgpq_pipeline(FILE* f, int (*callback)(char*, void*), void* udata, int bgpq_pipeline_dequeue(FILE* f, struct bgpq_expander* b) -{ - while(b->piped>0) { +{ + while(b->piped>0) { char request[128]; struct bgpq_prequest* pipe; memset(request,0,sizeof(request)); - if(!fgets(request,sizeof(request),f)) { - if(ferror(f)) { + if(!fgets(request,sizeof(request),f)) { + if(ferror(f)) { sx_report(SX_FATAL,"Error reading data from RADB: %s (dequeue)" "\n", strerror(errno)); - } else { + } else { sx_report(SX_FATAL,"EOF from RADB (dequeue)\n"); }; exit(1); }; - if(request[0]=='A') { + if(request[0]=='A') { char* eon, *c; unsigned long togot=strtoul(request+1,&eon,10); char recvbuffer[togot+2]; memset(recvbuffer,0,togot+2); - if(eon && *eon!='\n') { + if(eon && *eon!='\n') { sx_report(SX_ERROR,"A-code finished with wrong char '%c'(%s)\n", *eon,request); exit(1); }; - if(fgets(recvbuffer,togot+1,f)==NULL) { - if(ferror(f)) { + if(fgets(recvbuffer,togot+1,f)==NULL) { + if(ferror(f)) { sx_report(SX_FATAL,"Error reading RADB: %s (dequeue, " "result)\n", strerror(errno)); - } else { + } else { sx_report(SX_FATAL,"EOF from RADB (dequeue, result)\n"); }; exit(1); @@ -422,36 +432,36 @@ bgpq_pipeline_dequeue(FILE* f, struct bgpq_expander* b) SX_DEBUG(debug_expander>=3,"Got %s in response to %s",recvbuffer, b->firstpipe->request); - for(c=recvbuffer; cfirstpipe->callback) { + if(b->firstpipe->callback) { b->firstpipe->callback(c,b->firstpipe->udata); }; c+=spn+1; }; /* Final code */ - if(fgets(recvbuffer,togot,f)==NULL) { - if(ferror(f)) { + if(fgets(recvbuffer,togot,f)==NULL) { + if(ferror(f)) { sx_report(SX_FATAL,"Error reading RADB: %s (dequeue,final)" ")\n", strerror(errno)); - } else { + } else { sx_report(SX_FATAL,"EOF from RADB (dequeue,final)\n"); }; exit(1); }; - } else if(request[0]=='C') { + } else if(request[0]=='C') { /* No data */ - } else if(request[0]=='D') { + } else if(request[0]=='D') { /* .... */ - } else if(request[0]=='E') { + } else if(request[0]=='E') { /* XXXXX */ - } else if(request[0]=='F') { + } else if(request[0]=='F') { /* XXXXX */ - } else { - sx_report(SX_ERROR,"Wrong reply: %s to %s\n", request, + } else { + sx_report(SX_ERROR,"Wrong reply: %s to %s\n", request, b->firstpipe->request); }; @@ -467,7 +477,7 @@ bgpq_pipeline_dequeue(FILE* f, struct bgpq_expander* b) int bgpq_expand_radb(FILE* f, int (*callback)(char*, void*), void* udata, char* fmt, ...) -{ +{ char request[128]; va_list ap; int ret; @@ -479,14 +489,14 @@ bgpq_expand_radb(FILE* f, int (*callback)(char*, void*), void* udata, SX_DEBUG(debug_expander,"expander: sending '%s'\n", request); ret=fwrite(request,1,strlen(request),f); - if(ret!=strlen(request)) { + if(ret!=strlen(request)) { sx_report(SX_FATAL,"Partial write to radb, only %i bytes written: %s\n", ret,strerror(errno)); exit(1); }; memset(request,0,sizeof(request)); - if(!fgets(request,sizeof(request),f)) { - if(ferror(f)) { + if(!fgets(request,sizeof(request),f)) { + if(ferror(f)) { sx_report(SX_FATAL,"Error reading data from radb: %s (expand,radb)" "\n", strerror(errno)); exit(1); @@ -496,21 +506,21 @@ bgpq_expand_radb(FILE* f, int (*callback)(char*, void*), void* udata, }; SX_DEBUG(debug_expander>2,"expander: initially got %lu bytes, '%s'\n", (unsigned long)strlen(request),request); - if(request[0]=='A') { + if(request[0]=='A') { char* eon, *c; long togot=strtoul(request+1,&eon,10); char recvbuffer[togot+1]; - if(eon && *eon!='\n') { + if(eon && *eon!='\n') { sx_report(SX_ERROR,"A-code finised with wrong char '%c' (%s)\n", *eon,request); exit(1); }; - if(fgets(recvbuffer,togot+1,f)==NULL) { - if(feof(f)) { + if(fgets(recvbuffer,togot+1,f)==NULL) { + if(feof(f)) { sx_report(SX_FATAL,"EOF from radb (expand,radb,result)\n"); - } else { + } else { sx_report(SX_FATAL,"Error reading radb: %s (expand,radb," "result)\n", strerror(errno)); }; @@ -519,7 +529,7 @@ bgpq_expand_radb(FILE* f, int (*callback)(char*, void*), void* udata, SX_DEBUG(debug_expander>2,"expander: final reply of %lu bytes, '%s'\n", (unsigned long)strlen(recvbuffer),recvbuffer); - for(c=recvbuffer; cserver,"43",&hints,&res); - if(err) { + if(err) { sx_report(SX_ERROR,"Unable to resolve %s: %s\n", b->server, gai_strerror(err)); exit(1); }; - for(rp=res; rp; rp=rp->ai_next) { + for(rp=res; rp; rp=rp->ai_next) { fd=socket(rp->ai_family,rp->ai_socktype,0); - if(fd==-1) { + if(fd==-1) { if(errno==EPROTONOSUPPORT) continue; - sx_report(SX_ERROR,"Unable to create socket: %s\n", + sx_report(SX_ERROR,"Unable to create socket: %s\n", strerror(errno)); exit(1); }; err=connect(fd,rp->ai_addr,rp->ai_addrlen); - if(err) { + if(err) { shutdown(fd,SHUT_RDWR); close(fd); fd=-1; @@ -585,7 +595,7 @@ bgpq_expand(struct bgpq_expander* b) }; sx_maxsockbuf(fd,SO_SNDBUF); f=fdopen(fd,"a+"); - if(!f) { + if(!f) { shutdown(fd,SHUT_RDWR); close(fd); fd=-1; @@ -596,87 +606,87 @@ bgpq_expand(struct bgpq_expander* b) }; freeaddrinfo(res); - if(!f) { + if(!f) { /* all our attempts to connect failed */ sx_report(SX_ERROR,"All attempts to connect %s failed, last" " error: %s\n", b->server, strerror(errno)); exit(1); }; - if((ret=fwrite("!!\n",1,3,f))!=3) { - sx_report(SX_ERROR,"Partial fwrite to radb: %i bytes, %s\n", + if((ret=fwrite("!!\n",1,3,f))!=3) { + sx_report(SX_ERROR,"Partial fwrite to radb: %i bytes, %s\n", ret, strerror(errno)); exit(1); }; - if(b->sources && b->sources[0]!=0) { + if(b->sources && b->sources[0]!=0) { char sources[128]; snprintf(sources,sizeof(sources),"!s%s\n", b->sources); fwrite(sources,strlen(sources),1,f); fgets(sources,sizeof(sources),f); }; - if(b->identify) { + if(b->identify) { char ident[128]; snprintf(ident,sizeof(ident),"!n" PACKAGE_STRING "\n"); fwrite(ident,strlen(ident),1,f); fgets(ident,sizeof(ident),f); }; - for(mc=b->macroses;mc;mc=mc->next) { + for(mc=b->macroses;mc;mc=mc->next) { bgpq_expand_radb(f,bgpq_expanded_macro,b,"!i%s,1\n",mc->text); }; - if(b->generation>=T_PREFIXLIST) { + if(b->generation>=T_PREFIXLIST) { unsigned i, j, k; - for(mc=b->rsets;mc;mc=mc->next) { - if(b->family==AF_INET) { + for(mc=b->rsets;mc;mc=mc->next) { + if(b->family==AF_INET) { bgpq_expand_radb(f,bgpq_expanded_prefix,b,"!i%s,1\n",mc->text); - } else { - if(!pipelining) { + } else { + if(!pipelining) { bgpq_expand_ripe(f,bgpq_expanded_v6prefix,b, "-T route6 -i member-of %s\n",mc->text); - } else { + } else { bgpq_pipeline(f,bgpq_expanded_v6prefix,b, "-T route6 -i member-of %s\n", mc->text); }; }; }; - for(k=0;kasn32s)/sizeof(unsigned char*);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(!pipelining) { - if(k>0) + 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(!pipelining) { + if(k>0) bgpq_expand_ripe(f,bgpq_expanded_v6prefix,b, "-T route6 -i origin as%u.%u\r\n", k, i*8+j); - else + else bgpq_expand_ripe(f,bgpq_expanded_v6prefix,b, "-T route6 -i origin as%u\r\n", i*8+j); - } else { - if(k>0) + } else { + if(k>0) bgpq_pipeline(f,bgpq_expanded_v6prefix,b, "-T route6 -i origin as%u.%u\r\n", k, i*8+j); - else + else bgpq_pipeline(f,bgpq_expanded_v6prefix,b, "-T route6 -i origin as%u\r\n", i*8+j); }; - } else { - if(!pipelining) { - if(k>0) + } else { + if(!pipelining) { + if(k>0) bgpq_expand_radb(f,bgpq_expanded_prefix,b, "!gas%u.%u\n", k, i*8+j); - else + else bgpq_expand_radb(f,bgpq_expanded_prefix,b, "!gas%u\n", i*8+j); - } else { - if(k>0) + } else { + if(k>0) bgpq_pipeline(f,bgpq_expanded_prefix,b, "!gas%u.%u\n", k, i*8+j); - else + else bgpq_pipeline(f,bgpq_expanded_prefix,b, "!gas%u\n", i*8+j); }; @@ -685,10 +695,10 @@ bgpq_expand(struct bgpq_expander* b) }; }; }; - if(pipelining && b->firstpipe) { - if(b->family==AF_INET6) { + if(pipelining && b->firstpipe) { + if(b->family==AF_INET6) { bgpq_pipeline_dequeue_ripe(f,b); - } else { + } else { bgpq_pipeline_dequeue(f,b); }; }; diff --git a/configure b/configure index a8aa192..b7befe3 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for bgpq3 0.1.25. +# Generated by GNU Autoconf 2.69 for bgpq3 0.1.26. # # Report bugs to . # @@ -579,8 +579,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='bgpq3' PACKAGE_TARNAME='bgpq3' -PACKAGE_VERSION='0.1.25' -PACKAGE_STRING='bgpq3 0.1.25' +PACKAGE_VERSION='0.1.26' +PACKAGE_STRING='bgpq3 0.1.26' PACKAGE_BUGREPORT='snar@snar.spb.ru' PACKAGE_URL='' @@ -1187,7 +1187,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures bgpq3 0.1.25 to adapt to many kinds of systems. +\`configure' configures bgpq3 0.1.26 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1248,7 +1248,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of bgpq3 0.1.25:";; + short | recursive ) echo "Configuration of bgpq3 0.1.26:";; esac cat <<\_ACEOF @@ -1327,7 +1327,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -bgpq3 configure 0.1.25 +bgpq3 configure 0.1.26 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1495,7 +1495,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by bgpq3 $as_me 0.1.25, which was +It was created by bgpq3 $as_me 0.1.26, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3413,7 +3413,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by bgpq3 $as_me 0.1.25, which was +This file was extended by bgpq3 $as_me 0.1.26, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -3475,7 +3475,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -bgpq3 config.status 0.1.25 +bgpq3 config.status 0.1.26 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.in b/configure.in index ee57921..2baba9a 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -AC_INIT(bgpq3,0.1.25,snar@snar.spb.ru) +AC_INIT(bgpq3,0.1.26,snar@snar.spb.ru) AC_CONFIG_HEADER(config.h) AC_PROG_CC AC_PROG_INSTALL diff --git a/sx_prefix.c b/sx_prefix.c index a403f0b..07d4e9b 100644 --- a/sx_prefix.c +++ b/sx_prefix.c @@ -13,103 +13,106 @@ #include "sx_report.h" int debug_aggregation=0; +extern int debug_expander; -struct sx_prefix* +struct sx_prefix* sx_prefix_alloc(struct sx_prefix* p) -{ +{ struct sx_prefix* sp=malloc(sizeof(struct sx_prefix)); if(!sp) return NULL; - if(p) { + if(p) { *sp=*p; - } else { + } else { memset(sp,0,sizeof(struct sx_prefix)); }; return sp; }; void sx_prefix_destroy(struct sx_prefix* p) -{ +{ if(p) free(p); }; void sx_prefix_adjust_masklen(struct sx_prefix* p) -{ +{ int nbytes=(p->family==AF_INET?4:16); int i; if(p->masklen==nbytes*8) return ; /* mask is all ones */ - for(i=nbytes-1;i>p->masklen/8;i--) { + for(i=nbytes-1;i>p->masklen/8;i--) { p->addr.addrs[i]=0; }; - for(i=1;i<=8-p->masklen%8;i++) { + for(i=1;i<=8-p->masklen%8;i++) { p->addr.addrs[p->masklen/8]&=(0xff<addr)!=1) { + if(inet_pton(af,text,&p->addr)!=1) { int aparts[4]; - /* contrary to documentation (man inet_ntop on FreeBSD), + /* contrary to documentation (man inet_ntop on FreeBSD), addresses with leading zeros are not parsed correctly. Try to workaround this issue manually */ - if (af==AF_INET && sscanf(text, "%i.%i.%i.%i", aparts, + if (af==AF_INET && sscanf(text, "%i.%i.%i.%i", aparts, aparts+1, aparts+2, aparts+3) == 4 && aparts[0]>=0 && - aparts[0]<256 && aparts[1]>=0 && aparts[1]<256 && - aparts[2]>=0 && aparts[2]<256 && aparts[3]>=0 && - aparts[3]<256) { - p->addr.addr.s_addr = htonl((aparts[0]<<24) + + aparts[0]<256 && aparts[1]>=0 && aparts[1]<256 && + aparts[2]>=0 && aparts[2]<256 && aparts[3]>=0 && + aparts[3]<256) { + p->addr.addr.s_addr = htonl((aparts[0]<<24) + (aparts[1]<<16) + (aparts[2]<<8) + aparts[3]); - } else { + } else { if(c) *c='/'; sx_report(SX_ERROR,"Unable to parse prefix %s, af=%i\n",text,af); goto fixups; }; }; - if(af==AF_INET) { + if(af==AF_INET) { if(masklen==-1) p->masklen=32; - else { - if(masklen<0 || masklen>32) { + else { + if(masklen<0 || masklen>32) { p->masklen=32; - } else { + } else { p->masklen=masklen; }; }; - } else if(af==AF_INET6) { + } else if(af==AF_INET6) { if(masklen==-1) p->masklen=128; - else { - if(masklen<0 || masklen>128) { + else { + if(masklen<0 || masklen>128) { p->masklen=128; - } else { + } else { p->masklen=masklen; }; }; - } else { + } else { sx_report(SX_ERROR,"Invalid address family %i\n", af); goto fixups; }; @@ -123,10 +126,104 @@ fixups: return 0; }; +int +sx_prefix_isbitset(struct sx_prefix* p, int n) +{ + unsigned char s; + /* bits outside the prefix considered unset */ + if(p->family==AF_INET && (n<0 || n>32)) return 0; + else if(p->family==AF_INET6 && (n<0 || n>128)) return 0; + s=p->addr.addrs[(n-1)/8]; + return (s&(0x80>>((n-1)%8)))?1:0; +}; + +void +sx_prefix_setbit(struct sx_prefix* p, int n) +{ + unsigned char* s; + if (p->family == AF_INET && (n<0 || n>32)) return; + else if (p->family == AF_INET6 && (n<0 || n>128)) return; + s=p->addr.addrs+(n-1)/8; + (*s)|=0x80>>((n-1)%8); +}; + + +int +sx_radix_tree_insert_specifics(struct sx_radix_tree* t, struct sx_prefix p, + unsigned min, unsigned max) +{ + if (p.masklen >= min) + sx_radix_tree_insert(t, &p); + if (p.masklen+1 > max) + return 1; + p.masklen+=1; + sx_radix_tree_insert_specifics(t, p, min, max); + sx_prefix_setbit(&p, p.masklen); + sx_radix_tree_insert_specifics(t, p, min, max); + return 1; +}; + +int +sx_prefix_range_parse(struct sx_radix_tree* tree, int af, int maxlen, + char* text) +{ + char* d=strchr(text, '^'); + struct sx_prefix p; + unsigned long min, max; + + if (!d || !d[1]) return 0; + *d = 0; + + if (!sx_prefix_parse(&p, 0, text)) { + sx_report(SX_ERROR, "Unable to parse prefix %s^%s\n", text, d+1); + return 0; + }; + *d = '^'; + if (af && p.family != af) { + sx_report(SX_ERROR, "Ignoring prefix %s, wrong af %i\n", text, + p.family); + return 0; + }; + if (maxlen && p.masklen > maxlen) { + SX_DEBUG(debug_expander, "Ignoring prefix %s, masklen %i > max " + "masklen %u\n", text, p.masklen, maxlen); + return 0; + }; + if (d[1] == '-') { + min=p.masklen+1; + max=maxlen; + } else if (d[1] == '+') { + min=p.masklen; + max=maxlen; + } else if (isnumber(d[1])) { + char* dm = NULL; + min = strtoul(d+1, &dm, 10); + if (dm && *dm == '-' && isnumber(dm[1])) { + max = strtoul(dm+1, NULL, 10); + } else if (dm && *dm) { + sx_report(SX_ERROR, "Unable to parse prefix-range %s\n", text); + return 0; + }; + } else { + sx_report(SX_ERROR, "Invalid prefix-range %s\n", text); + return 0; + }; + if (min < p.masklen) { + sx_report(SX_ERROR, "Invalid prefix-range %s: min %lu < masklen %u\n", + text, min, p.masklen); + return 0; + }; + SX_DEBUG(debug_expander, "parsed prefix-range %s as %lu-%lu\n", + text, min, max); + if (max > maxlen) + max = maxlen; + sx_radix_tree_insert_specifics(tree, p, min, max); + return 1; +}; struct sx_prefix* sx_prefix_new(int af, char* text) -{ +{ struct sx_prefix* p=NULL; if(!text) return NULL; @@ -134,7 +231,7 @@ sx_prefix_new(int af, char* text) p=sx_prefix_alloc(NULL); if(!p) return NULL; - if(!sx_prefix_parse(p,af,text)) { + if(!sx_prefix_parse(p,af,text)) { sx_prefix_destroy(p); return NULL; }; @@ -143,11 +240,11 @@ sx_prefix_new(int af, char* text) int sx_prefix_fprint(FILE* f, struct sx_prefix* p) -{ +{ char buffer[128]; - if(!p) { - fprintf(f?f:stdout,"(null)"); - return 0; + if(!p) { + fprintf(f?f:stdout,"(null)"); + return 0; }; inet_ntop(p->family,&p->addr,buffer,sizeof(buffer)); return fprintf(f?f:stdout,"%s/%i",buffer,p->masklen); @@ -155,11 +252,11 @@ sx_prefix_fprint(FILE* f, struct sx_prefix* p) int sx_prefix_snprintf(struct sx_prefix* p, char* rbuffer, int srb) -{ +{ char buffer[128]; - if(!p) { - snprintf(rbuffer,srb,"(null)"); - return 0; + if(!p) { + snprintf(rbuffer,srb,"(null)"); + return 0; }; inet_ntop(p->family,&p->addr,buffer,sizeof(buffer)); return snprintf(rbuffer,srb,"%s/%i",buffer,p->masklen); @@ -167,21 +264,21 @@ sx_prefix_snprintf(struct sx_prefix* p, char* rbuffer, int srb) int sx_prefix_jsnprintf(struct sx_prefix* p, char* rbuffer, int srb) -{ +{ char buffer[128]; - if(!p) { - snprintf(rbuffer,srb,"(null)"); - return 0; + if(!p) { + snprintf(rbuffer,srb,"(null)"); + return 0; }; inet_ntop(p->family,&p->addr,buffer,sizeof(buffer)); return snprintf(rbuffer,srb,"%s\\/%i",buffer,p->masklen); }; -struct sx_radix_tree* +struct sx_radix_tree* sx_radix_tree_new(int af) -{ +{ struct sx_radix_tree* rt=malloc(sizeof(struct sx_radix_tree)); - if(!rt) { + if(!rt) { return NULL; }; memset(rt,0,sizeof(struct sx_radix_tree)); @@ -191,17 +288,17 @@ sx_radix_tree_new(int af) int sx_radix_tree_empty(struct sx_radix_tree* t) -{ +{ return t->head == NULL; }; struct sx_radix_node* sx_radix_node_new(struct sx_prefix* prefix) -{ +{ struct sx_radix_node* rn=malloc(sizeof(struct sx_radix_node)); if(!rn) return NULL; memset(rn,0,sizeof(struct sx_radix_node)); - if(prefix) { + if(prefix) { rn->prefix=*prefix; /* structure copy */ }; return rn; @@ -209,14 +306,14 @@ sx_radix_node_new(struct sx_prefix* prefix) int sx_prefix_eqbits(struct sx_prefix* a, struct sx_prefix* b) -{ +{ int i; int nbytes=(a->family==AF_INET?4:16); - for(i=0;iaddr.addrs[i]==b->addr.addrs[i]) continue; - else { + else { int j; - for(j=0;j<8 && i*8+j<=a->masklen && i*8+j<=b->masklen;j++) { + for(j=0;j<8 && i*8+j<=a->masklen && i*8+j<=b->masklen;j++) { if((a->addr.addrs[i]&(0x80>>j))!=(b->addr.addrs[i]&(0x80>>j))) return i*8+j; }; @@ -226,20 +323,9 @@ sx_prefix_eqbits(struct sx_prefix* a, struct sx_prefix* b) return b->masklen; }; -int -sx_prefix_isbitset(struct sx_prefix* p, int n) -{ - unsigned char s; - /* bits outside the prefix considered unset */ - if(p->family==AF_INET && (n<0 || n>32)) return 0; - else if(p->family==AF_INET6 && (n<0 || n>128)) return 0; - s=p->addr.addrs[(n-1)/8]; - return (s&(0x80>>((n-1)%8)))?1:0; -}; - -struct sx_prefix* +struct sx_prefix* sx_prefix_overlay(struct sx_prefix* p, int n) -{ +{ struct sx_prefix* sp=sx_prefix_alloc(p); sp->masklen=n; sx_prefix_adjust_masklen(sp); @@ -248,65 +334,65 @@ sx_prefix_overlay(struct sx_prefix* p, int n) void sx_radix_tree_unlink(struct sx_radix_tree* tree, struct sx_radix_node* node) -{ +{ next: - if(node->r && node->l) { + if(node->r && node->l) { node->isGlue=1; - } else if(node->r) { - if(node->parent) { - if(node->parent->r==node) { + } else if(node->r) { + if(node->parent) { + if(node->parent->r==node) { node->parent->r=node->r; node->r->parent=node->parent; - } else if(node->parent->l==node) { + } else if(node->parent->l==node) { node->parent->l=node->r; node->r->parent=node->parent; - } else { + } else { sx_report(SX_ERROR,"Unlinking node which is not descendant " "of its parent\n"); }; - } else if(tree->head==node) { + } else if(tree->head==node) { /* only one case, really */ tree->head=node->r; node->r->parent=NULL; - } else { + } else { sx_report(SX_ERROR,"Unlinking node with no parent and not root\n"); }; return; - } else if(node->l) { - if(node->parent) { - if(node->parent->r==node) { + } else if(node->l) { + if(node->parent) { + if(node->parent->r==node) { node->parent->r=node->l; node->l->parent=node->parent; - } else if(node->parent->l==node) { + } else if(node->parent->l==node) { node->parent->l=node->l; node->l->parent=node->parent; - } else { + } else { sx_report(SX_ERROR,"Unlinking node which is not descendant " "of its parent\n"); }; - } else if(tree->head==node) { + } else if(tree->head==node) { tree->head=node->l; node->l->parent=NULL; - } else { + } else { sx_report(SX_ERROR,"Unlinking node with no parent and not root\n"); }; return; - } else { + } else { /* the only case - node does not have descendants */ - if(node->parent) { + if(node->parent) { if(node->parent->l==node) node->parent->l=NULL; else if(node->parent->r==node) node->parent->r=NULL; - else { + else { sx_report(SX_ERROR,"Unlinking node which is not descendant " "of its parent\n"); }; - if(node->parent->isGlue) { + if(node->parent->isGlue) { node=node->parent; goto next; }; - } else if(tree->head==node) { + } else if(tree->head==node) { tree->head=NULL; - } else { + } else { sx_report(SX_ERROR,"Unlinking node with no parent and not root\n"); }; return; @@ -314,9 +400,9 @@ next: }; -struct sx_radix_node* +struct sx_radix_node* sx_radix_tree_lookup(struct sx_radix_tree* tree, struct sx_prefix* prefix) -{ +{ int eb; struct sx_radix_node* candidate=NULL, *chead; @@ -328,38 +414,38 @@ sx_radix_tree_lookup(struct sx_radix_tree* tree, struct sx_prefix* prefix) next: eb=sx_prefix_eqbits(&chead->prefix,prefix); - if(eb==chead->prefix.masklen && eb==prefix->masklen) { + if(eb==chead->prefix.masklen && eb==prefix->masklen) { /* they are equal */ if(chead->isGlue) return candidate; return chead; - } else if(ebprefix.masklen) { + } else if(ebprefix.masklen) { return candidate; - } else if(ebmasklen) { + } else if(ebmasklen) { /* it equals chead->masklen */ - if(sx_prefix_isbitset(prefix,eb+1)) { - if(chead->r) { - if(!chead->isGlue) { + if(sx_prefix_isbitset(prefix,eb+1)) { + if(chead->r) { + if(!chead->isGlue) { candidate=chead; }; chead=chead->r; goto next; - } else { + } else { if(chead->isGlue) return candidate; return chead; }; - } else { - if(chead->l) { - if(!chead->isGlue) { + } else { + if(chead->l) { + if(!chead->isGlue) { candidate=chead; }; chead=chead->l; goto next; - } else { + } else { if(chead->isGlue) return candidate; return chead; }; }; - } else { + } else { char pbuffer[128], cbuffer[128]; sx_prefix_snprintf(prefix,pbuffer,sizeof(pbuffer)); sx_prefix_snprintf(&chead->prefix,cbuffer,sizeof(cbuffer)); @@ -372,7 +458,7 @@ next: struct sx_radix_node* sx_radix_tree_insert(struct sx_radix_tree* tree, struct sx_prefix* prefix) -{ +{ int eb; struct sx_radix_node** candidate=NULL, *chead; @@ -380,7 +466,7 @@ sx_radix_tree_insert(struct sx_radix_tree* tree, struct sx_prefix* prefix) if(tree->family!=prefix->family) { return NULL; }; - if(!tree->head) { + if(!tree->head) { tree->head=sx_radix_node_new(prefix); return tree->head; }; @@ -389,20 +475,20 @@ sx_radix_tree_insert(struct sx_radix_tree* tree, struct sx_prefix* prefix) next: eb=sx_prefix_eqbits(prefix,&chead->prefix); - if(ebmasklen && ebprefix.masklen) { + if(ebmasklen && ebprefix.masklen) { struct sx_prefix neoRoot=*prefix; struct sx_radix_node* rn, *ret=sx_radix_node_new(prefix); neoRoot.masklen=eb; sx_prefix_adjust_masklen(&neoRoot); rn=sx_radix_node_new(&neoRoot); - if(!rn) { + if(!rn) { sx_report(SX_ERROR,"Unable to create node: %s\n", strerror(errno)); return NULL; }; - if(sx_prefix_isbitset(prefix,eb+1)) { + if(sx_prefix_isbitset(prefix,eb+1)) { rn->l=chead; rn->r=ret; - } else { + } else { rn->l=ret; rn->r=chead; }; @@ -412,46 +498,46 @@ next: rn->isGlue=1; *candidate=rn; return ret; - } else if(eb==prefix->masklen && ebprefix.masklen) { + } else if(eb==prefix->masklen && ebprefix.masklen) { struct sx_radix_node* ret=sx_radix_node_new(prefix); - if(sx_prefix_isbitset(&chead->prefix,eb+1)) { + if(sx_prefix_isbitset(&chead->prefix,eb+1)) { ret->r=chead; - } else { + } else { ret->l=chead; }; ret->parent=chead->parent; chead->parent=ret; *candidate=ret; return ret; - } else if(eb==chead->prefix.masklen && ebmasklen) { - if(sx_prefix_isbitset(prefix,eb+1)) { - if(chead->r) { + } else if(eb==chead->prefix.masklen && ebmasklen) { + if(sx_prefix_isbitset(prefix,eb+1)) { + if(chead->r) { candidate=&chead->r; chead=chead->r; goto next; - } else { + } else { chead->r=sx_radix_node_new(prefix); chead->r->parent=chead; return chead->r; }; - } else { - if(chead->l) { + } else { + if(chead->l) { candidate=&chead->l; chead=chead->l; goto next; - } else { + } else { chead->l=sx_radix_node_new(prefix); chead->l->parent=chead; return chead->l; }; }; - } else if(eb==chead->prefix.masklen && eb==prefix->masklen) { + } else if(eb==chead->prefix.masklen && eb==prefix->masklen) { /* equal routes... */ - if(chead->isGlue) { + if(chead->isGlue) { chead->isGlue=0; }; return chead; - } else { + } else { char pbuffer[128], cbuffer[128]; sx_prefix_snprintf(prefix,pbuffer,sizeof(pbuffer)); sx_prefix_snprintf(&chead->prefix,cbuffer,sizeof(cbuffer)); @@ -463,21 +549,21 @@ next: void sx_radix_node_fprintf(struct sx_radix_node* node, void* udata) -{ +{ FILE* out=(udata?udata:stdout); char buffer[128]; - if(!node) { + if(!node) { fprintf(out,"(null)\n"); - } else { + } else { sx_prefix_snprintf(&node->prefix,buffer,sizeof(buffer)); fprintf(out,"%s %s\n", buffer, node->isGlue?"(glue)":""); }; }; -int -sx_radix_node_foreach(struct sx_radix_node* node, +int +sx_radix_node_foreach(struct sx_radix_node* node, void (*func)(struct sx_radix_node*, void*), void* udata) -{ +{ func(node,udata); if(node->l) sx_radix_node_foreach(node->l,func,udata); if(node->r) sx_radix_node_foreach(node->r,func,udata); @@ -485,9 +571,9 @@ sx_radix_node_foreach(struct sx_radix_node* node, }; int -sx_radix_tree_foreach(struct sx_radix_tree* tree, +sx_radix_tree_foreach(struct sx_radix_tree* tree, void (*func)(struct sx_radix_node*, void*), void* udata) -{ +{ if(!func || !tree || !tree->head) return 0; sx_radix_node_foreach(tree->head,func,udata); return 0; @@ -495,71 +581,71 @@ sx_radix_tree_foreach(struct sx_radix_tree* tree, int sx_radix_node_aggregate(struct sx_radix_node* node) -{ - if(node->l) +{ + if(node->l) sx_radix_node_aggregate(node->l); - if(node->r) + if(node->r) sx_radix_node_aggregate(node->r); - if(debug_aggregation) { + if(debug_aggregation) { printf("Aggregating on node: "); sx_prefix_fprint(stdout,&node->prefix); - printf(" %s%s%u,%u\n", node->isGlue?"Glue ":"", + printf(" %s%s%u,%u\n", node->isGlue?"Glue ":"", node->isAggregate?"Aggregate ":"",node->aggregateLow, node->aggregateHi); - if(node->r) { + if(node->r) { printf("R-Tree: "); sx_prefix_fprint(stdout,&node->r->prefix); - printf(" %s%s%u,%u\n", (node->r->isGlue)?"Glue ":"", - (node->r->isAggregate)?"Aggregate ":"", + printf(" %s%s%u,%u\n", (node->r->isGlue)?"Glue ":"", + (node->r->isAggregate)?"Aggregate ":"", node->r->aggregateLow,node->r->aggregateHi); - if(node->r->son) { + if(node->r->son) { printf("R-Son: "); sx_prefix_fprint(stdout,&node->r->son->prefix); - printf(" %s%s%u,%u\n",node->r->son->isGlue?"Glue ":"", - node->r->son->isAggregate?"Aggregate ":"", + printf(" %s%s%u,%u\n",node->r->son->isGlue?"Glue ":"", + node->r->son->isAggregate?"Aggregate ":"", node->r->son->aggregateLow,node->r->son->aggregateHi); }; }; - if(node->l) { + if(node->l) { printf("L-Tree: "); sx_prefix_fprint(stdout,&node->l->prefix); - printf(" %s%s%u,%u\n",node->l->isGlue?"Glue ":"", - node->l->isAggregate?"Aggregate ":"", + printf(" %s%s%u,%u\n",node->l->isGlue?"Glue ":"", + node->l->isAggregate?"Aggregate ":"", node->l->aggregateLow,node->l->aggregateHi); - if(node->l->son) { + if(node->l->son) { printf("L-Son: "); sx_prefix_fprint(stdout,&node->l->son->prefix); - printf(" %s%s%u,%u\n",node->l->son->isGlue?"Glue ":"", - node->l->son->isAggregate?"Aggregate ":"", + printf(" %s%s%u,%u\n",node->l->son->isGlue?"Glue ":"", + node->l->son->isAggregate?"Aggregate ":"", node->l->son->aggregateLow,node->l->son->aggregateHi); }; }; }; - if(node->r && node->l) { - if(!node->r->isAggregate && !node->l->isAggregate && - !node->r->isGlue && !node->l->isGlue && - node->r->prefix.masklen==node->l->prefix.masklen) { - if(node->r->prefix.masklen==node->prefix.masklen+1) { + if(node->r && node->l) { + if(!node->r->isAggregate && !node->l->isAggregate && + !node->r->isGlue && !node->l->isGlue && + node->r->prefix.masklen==node->l->prefix.masklen) { + if(node->r->prefix.masklen==node->prefix.masklen+1) { node->isAggregate=1; node->r->isGlue=1; node->l->isGlue=1; node->aggregateHi=node->r->prefix.masklen; - if(node->isGlue) { + if(node->isGlue) { node->isGlue=0; node->aggregateLow=node->r->prefix.masklen; - } else { + } else { node->aggregateLow=node->prefix.masklen; }; }; - if(node->r->son && node->l->son && - node->r->son->isAggregate && node->l->son->isAggregate && + if(node->r->son && node->l->son && + node->r->son->isAggregate && node->l->son->isAggregate && node->r->son->aggregateHi==node->l->son->aggregateHi && node->r->son->aggregateLow==node->l->son->aggregateLow && - node->r->prefix.masklen==node->prefix.masklen+1 && + node->r->prefix.masklen==node->prefix.masklen+1 && node->l->prefix.masklen==node->prefix.masklen+1) - { + { node->son=sx_radix_node_new(&node->prefix); node->son->isGlue=0; node->son->isAggregate=1; @@ -568,25 +654,25 @@ sx_radix_node_aggregate(struct sx_radix_node* node) node->r->son->isGlue=1; node->l->son->isGlue=1; }; - } else if(node->r->isAggregate && node->l->isAggregate && - node->r->aggregateHi==node->l->aggregateHi && - node->r->aggregateLow==node->l->aggregateLow) { + } else if(node->r->isAggregate && node->l->isAggregate && + node->r->aggregateHi==node->l->aggregateHi && + node->r->aggregateLow==node->l->aggregateLow) { if(node->r->prefix.masklen==node->prefix.masklen+1 && - node->l->prefix.masklen==node->prefix.masklen+1) { - if(node->isGlue) { + node->l->prefix.masklen==node->prefix.masklen+1) { + if(node->isGlue) { node->r->isGlue=1; node->l->isGlue=1; node->isAggregate=1; node->isGlue=0; node->aggregateHi=node->r->aggregateHi; node->aggregateLow=node->r->aggregateLow; - } else if(node->r->prefix.masklen==node->r->aggregateLow) { + } else if(node->r->prefix.masklen==node->r->aggregateLow) { node->r->isGlue=1; node->l->isGlue=1; node->isAggregate=1; node->aggregateHi=node->r->aggregateHi; node->aggregateLow=node->prefix.masklen; - } else { + } else { node->son=sx_radix_node_new(&node->prefix); node->son->isGlue=0; node->son->isAggregate=1; @@ -594,10 +680,10 @@ sx_radix_node_aggregate(struct sx_radix_node* node) node->son->aggregateLow=node->r->aggregateLow; node->r->isGlue=1; node->l->isGlue=1; - if(node->r->son && node->l->son && + if(node->r->son && node->l->son && node->r->son->aggregateHi==node->l->son->aggregateHi && node->r->son->aggregateLow==node->l->son->aggregateLow) - { + { node->son->son=sx_radix_node_new(&node->prefix); node->son->son->isGlue=0; node->son->son->isAggregate=1; @@ -608,20 +694,20 @@ sx_radix_node_aggregate(struct sx_radix_node* node) }; }; }; - } else if(node->l->son && - node->r->isAggregate && node->l->son->isAggregate && - node->r->aggregateHi==node->l->son->aggregateHi && - node->r->aggregateLow==node->l->son->aggregateLow) { + } else if(node->l->son && + node->r->isAggregate && node->l->son->isAggregate && + node->r->aggregateHi==node->l->son->aggregateHi && + node->r->aggregateLow==node->l->son->aggregateLow) { if(node->r->prefix.masklen==node->prefix.masklen+1 && - node->l->prefix.masklen==node->prefix.masklen+1) { - if(node->isGlue) { + node->l->prefix.masklen==node->prefix.masklen+1) { + if(node->isGlue) { node->r->isGlue=1; node->l->son->isGlue=1; node->isAggregate=1; node->isGlue=0; node->aggregateHi=node->r->aggregateHi; node->aggregateLow=node->r->aggregateLow; - } else { + } else { node->son=sx_radix_node_new(&node->prefix); node->son->isGlue=0; node->son->isAggregate=1; @@ -631,20 +717,20 @@ sx_radix_node_aggregate(struct sx_radix_node* node) node->l->son->isGlue=1; }; }; - } else if(node->r->son && - node->l->isAggregate && node->r->son->isAggregate && - node->l->aggregateHi==node->r->son->aggregateHi && - node->l->aggregateLow==node->r->son->aggregateLow) { + } else if(node->r->son && + node->l->isAggregate && node->r->son->isAggregate && + node->l->aggregateHi==node->r->son->aggregateHi && + node->l->aggregateLow==node->r->son->aggregateLow) { if(node->l->prefix.masklen==node->prefix.masklen+1 && - node->r->prefix.masklen==node->prefix.masklen+1) { - if(node->isGlue) { + node->r->prefix.masklen==node->prefix.masklen+1) { + if(node->isGlue) { node->l->isGlue=1; node->r->son->isGlue=1; node->isAggregate=1; node->isGlue=0; node->aggregateHi=node->l->aggregateHi; node->aggregateLow=node->l->aggregateLow; - } else { + } else { node->son=sx_radix_node_new(&node->prefix); node->son->isGlue=0; node->son->isAggregate=1; @@ -661,46 +747,46 @@ sx_radix_node_aggregate(struct sx_radix_node* node) int sx_radix_tree_aggregate(struct sx_radix_tree* tree) -{ +{ if(tree && tree->head) return sx_radix_node_aggregate(tree->head); return 0; }; -static void +static void setGlueUpTo(struct sx_radix_node* node, void* udata) -{ +{ unsigned refine=*(unsigned*)udata; if(node && node->prefix.masklen <= refine) { node->isGlue=1; }; }; -int +int sx_radix_node_refine(struct sx_radix_node* node, unsigned refine) -{ - if(!node->isGlue && node->prefix.masklenisGlue && node->prefix.masklenisAggregate=1; node->aggregateLow=node->prefix.masklen; node->aggregateHi=refine; - if(node->l) { + if(node->l) { sx_radix_node_foreach(node->l, setGlueUpTo, &refine); sx_radix_node_refine(node->l, refine); }; - if(node->r) { + if(node->r) { sx_radix_node_foreach(node->r, setGlueUpTo, &refine); sx_radix_node_refine(node->r, refine); }; - } else if(!node->isGlue && node->prefix.masklen==refine) { + } else if(!node->isGlue && node->prefix.masklen==refine) { /* not setting aggregate in this case */ if(node->l) sx_radix_node_refine(node->l, refine); if(node->r) sx_radix_node_refine(node->r, refine); - } else if(node->isGlue) { + } else if(node->isGlue) { if(node->r) sx_radix_node_refine(node->r, refine); if(node->l) sx_radix_node_refine(node->l, refine); - } else { + } else { /* node->prefix.masklen > refine */ /* do nothing, should pass specifics 'as is'. Also, do not - process any embedded routes, their masklen is bigger, too... + process any embedded routes, their masklen is bigger, too... node->isGlue=1; if(node->l) sx_radix_node_foreach(node->l, setGlue, NULL); if(node->r) sx_radix_node_foreach(node->r, setGlue, NULL); @@ -711,54 +797,54 @@ sx_radix_node_refine(struct sx_radix_node* node, unsigned refine) int sx_radix_tree_refine(struct sx_radix_tree* tree, unsigned refine) -{ +{ if(tree && tree->head) return sx_radix_node_refine(tree->head, refine); return 0; }; -static void +static void setGlueFrom(struct sx_radix_node* node, void* udata) -{ +{ unsigned refine=*(unsigned*)udata; if(node && node->prefix.masklen <= refine) { node->isGlue=1; }; }; -static int +static int sx_radix_node_refineLow(struct sx_radix_node* node, unsigned refineLow) -{ - if(!node->isGlue && node->prefix.masklen<=refineLow) { - if(!node->isAggregate) { +{ + if(!node->isGlue && node->prefix.masklen<=refineLow) { + if(!node->isAggregate) { node->isAggregate=1; node->aggregateLow=refineLow; - if(node->prefix.family == AF_INET) { + if(node->prefix.family == AF_INET) { node->aggregateHi=32; - } else { + } else { node->aggregateHi=128; } - } else { + } else { node->aggregateLow=refineLow; }; - if(node->l) { + if(node->l) { sx_radix_node_foreach(node->l, setGlueFrom, &refineLow); sx_radix_node_refineLow(node->l, refineLow); }; - if(node->r) { + if(node->r) { sx_radix_node_foreach(node->r, setGlueFrom, &refineLow); sx_radix_node_refineLow(node->r, refineLow); }; - } else if(!node->isGlue && node->prefix.masklen==refineLow) { + } else if(!node->isGlue && node->prefix.masklen==refineLow) { /* not setting aggregate in this case */ if(node->l) sx_radix_node_refineLow(node->l, refineLow); if(node->r) sx_radix_node_refineLow(node->r, refineLow); - } else if(node->isGlue) { + } else if(node->isGlue) { if(node->r) sx_radix_node_refineLow(node->r, refineLow); if(node->l) sx_radix_node_refineLow(node->l, refineLow); - } else { + } else { /* node->prefix.masklen > refine */ /* do nothing, should pass specifics 'as is'. Also, do not - process any embedded routes, their masklen is bigger, too... + process any embedded routes, their masklen is bigger, too... node->isGlue=1; if(node->l) sx_radix_node_foreach(node->l, setGlue, NULL); if(node->r) sx_radix_node_foreach(node->r, setGlue, NULL); @@ -770,73 +856,73 @@ sx_radix_node_refineLow(struct sx_radix_node* node, unsigned refineLow) int sx_radix_tree_refineLow(struct sx_radix_tree* tree, unsigned refineLow) -{ - if(tree && tree->head) +{ + if(tree && tree->head) return sx_radix_node_refineLow(tree->head, refineLow); return 0; }; #if SX_PTREE_TEST -int +int main() { struct sx_prefix* p; int n; struct sx_radix_tree* tree; struct sx_radix_node* node; - p=sx_prefix_new(0,strdup("10.11.12.13/24")); + p=sx_prefix_new(0,"10.11.12.13/24"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(0,strdup("10.11.12.13/33")); + p=sx_prefix_new(0,"10.11.12.13/33"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(0,strdup("10.11.12.13/-133")); + p=sx_prefix_new(0,"10.11.12.13/-133"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(AF_INET,strdup("10.11.12.14/24")); + p=sx_prefix_new(AF_INET,"10.11.12.14/24"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(AF_INET,strdup("10.11.12.14/33")); + p=sx_prefix_new(AF_INET,"10.11.12.14/33"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(AF_INET,strdup("10.11.12.14/-133")); + p=sx_prefix_new(AF_INET,"10.11.12.14/-133"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(AF_INET6,strdup("10.11.12.15/24")); + p=sx_prefix_new(AF_INET6,"10.11.12.15/24"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(AF_INET6,strdup("10.11.12.15/33")); + p=sx_prefix_new(AF_INET6,"10.11.12.15/33"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(AF_INET6,strdup("10.11.12.15/-133")); + p=sx_prefix_new(AF_INET6,"10.11.12.15/-133"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(0,strdup("2001:1b00::/24")); + p=sx_prefix_new(0,"2001:1b00::/24"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(0,strdup("2001:1b00::/33")); + p=sx_prefix_new(0,"2001:1b00::/33"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(0,strdup("2001:1b00::/-133")); + p=sx_prefix_new(0,"2001:1b00::/-133"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(AF_INET6,strdup("2001:1b01::/24")); + p=sx_prefix_new(AF_INET6,"2001:1b01::/24"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(AF_INET6,strdup("2001:1b01::/33")); + p=sx_prefix_new(AF_INET6,"2001:1b01::/33"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(AF_INET6,strdup("2001:1b01::/-133")); + p=sx_prefix_new(AF_INET6,"2001:1b01::/-133"); sx_prefix_fprint(stdout,p); printf("\n"); -#define SX_TEST_EBITS(a,b,susp) n=sx_prefix_eqbits(sx_prefix_new(0,strdup(a)),\ - sx_prefix_new(0,strdup(b))); \ +#define SX_TEST_EBITS(a,b,susp) n=sx_prefix_eqbits(sx_prefix_new(0,a)),\ + sx_prefix_new(0,b))); \ if(n!=susp) printf("FAILED: %s eqbits %s=%i, not %i\n", a, b, n, susp);\ else printf("OK, %s eqbits %s=%i, as suspected\n", a, b, n); SX_TEST_EBITS("192.168.0.0/24","192.168.1.0/24",23); @@ -845,35 +931,35 @@ main() { SX_TEST_EBITS("2001:1b00::/32","2001:1b01::/32",31); #endif - p=sx_prefix_new(0,strdup("10.11.12.255/32")); + p=sx_prefix_new(0,"10.11.12.255/32"); sx_prefix_fprint(stdout,p); printf("\n31'th bit is %i\n",sx_prefix_isbitset(p,31)); printf("32'th bit is %i\n",sx_prefix_isbitset(p,32)); printf("33'th bit is %i\n",sx_prefix_isbitset(p,33)); - p=sx_prefix_new(0,strdup("10.11.12.255/31")); + p=sx_prefix_new(0,"10.11.12.255/31"); sx_prefix_fprint(stdout,p); printf("\n31'th bit is %i\n",sx_prefix_isbitset(p,31)); printf("32'th bit is %i\n",sx_prefix_isbitset(p,32)); printf("33'th bit is %i\n",sx_prefix_isbitset(p,33)); - p=sx_prefix_new(0,strdup("10.11.12.255/30")); + p=sx_prefix_new(0,"10.11.12.255/30"); sx_prefix_fprint(stdout,p); printf("\n31'th bit is %i\n",sx_prefix_isbitset(p,31)); - p=sx_prefix_new(0,strdup("10.11.12.255/29")); + p=sx_prefix_new(0,"10.11.12.255/29"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(0,strdup("10.11.12.255/28")); + p=sx_prefix_new(0,"10.11.12.255/28"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(0,strdup("10.11.12.255/27")); + p=sx_prefix_new(0,"10.11.12.255/27"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(0,strdup("10.11.12.255/26")); + p=sx_prefix_new(0,"10.11.12.255/26"); sx_prefix_fprint(stdout,p); printf("\n"); - p=sx_prefix_new(0,strdup("10.11.12.255/25")); + p=sx_prefix_new(0,"10.11.12.255/25"); sx_prefix_fprint(stdout,p); printf("\n25'th bit is %i\n",sx_prefix_isbitset(p,25)); - p=sx_prefix_new(0,strdup("10.11.12.255/24")); + p=sx_prefix_new(0,"10.11.12.255/24"); sx_prefix_fprint(stdout,p); printf("\n25'th bit is %i\n",sx_prefix_isbitset(p,25)); diff --git a/sx_prefix.h b/sx_prefix.h index ace7b24..291bf42 100644 --- a/sx_prefix.h +++ b/sx_prefix.h @@ -46,6 +46,7 @@ void sx_prefix_destroy(struct sx_prefix* p); void sx_prefix_adjust_masklen(struct sx_prefix* p); struct sx_prefix* sx_prefix_new(int af, char* text); int sx_prefix_parse(struct sx_prefix* p, int af, char* text); +int sx_prefix_range_parse(struct sx_radix_tree* t, int af, int ml, char* text); int sx_prefix_fprint(FILE* f, struct sx_prefix* p); int sx_prefix_snprintf(struct sx_prefix* p, char* rbuffer, int srb); int sx_prefix_jsnprintf(struct sx_prefix* p, char* rbuffer, int srb);