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

761 lines
17 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>
2007-03-30 14:05:54 +00:00
#include <ctype.h>
2007-03-22 18:12:32 +00:00
#include <errno.h>
#include <netdb.h>
#include <string.h>
#include <strings.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "bgpq3.h"
#include "sx_report.h"
#include "sx_maxsockbuf.h"
2007-03-22 18:12:32 +00:00
int debug_expander=0;
int pipelining=1;
int expand_as23456=0;
int expand_special_asn=0;
2007-03-22 18:12:32 +00:00
int
bgpq_expander_init(struct bgpq_expander* b, int af)
{
2007-03-22 18:12:32 +00:00
if(!af) af=AF_INET;
if(!b) return 0;
memset(b,0,sizeof(struct bgpq_expander));
2015-06-23 14:56:05 +03:00
2007-03-22 18:12:32 +00:00
b->tree=sx_radix_tree_new(af);
if(!b->tree) goto fixups;
b->family=af;
b->sources="ripe,radb,apnic";
2007-04-04 13:15:20 +00:00
b->name="NN";
2007-03-22 18:12:32 +00:00
b->aswidth=8;
b->asn32s[0]=malloc(8192);
if(!b->asn32s[0]) {
sx_report(SX_FATAL,"Unable to allocate 8192 bytes: %s\n",
2008-05-20 15:57:22 +00:00
strerror(errno));
exit(1);
};
memset(b->asn32s[0],0,8192);
2008-08-08 09:29:53 +00:00
b->identify=1;
2008-12-19 17:39:15 +00:00
b->server="whois.radb.net";
2007-03-22 18:12:32 +00:00
return 1;
fixups:
/* if(b->tree) XXXXXXXXXXXXX sx_radix_tree_destroy(b->tree); */
b->tree=NULL;
free(b);
return 0;
};
int
bgpq_expander_add_asset(struct bgpq_expander* b, char* as)
{
2007-03-22 18:12:32 +00:00
struct sx_slentry* le;
if(!b || !as) return 0;
le=sx_slentry_new(as);
if(!le) return 0;
if(!b->macroses) {
2007-03-22 18:12:32 +00:00
b->macroses=le;
} else {
2007-03-22 18:12:32 +00:00
struct sx_slentry* ln=b->macroses;
while(ln->next) ln=ln->next;
ln->next=le;
};
return 1;
};
int
2008-06-02 11:32:25 +00:00
bgpq_expander_add_rset(struct bgpq_expander* b, char* rs)
{
2008-06-02 11:32:25 +00:00
struct sx_slentry* le;
if(!b || !rs) return 0;
le=sx_slentry_new(rs);
if(!le) return 0;
if(!b->rsets) {
2008-06-02 11:32:25 +00:00
b->rsets=le;
} else {
2008-06-02 11:32:25 +00:00
struct sx_slentry* ln=b->rsets;
while(ln->next) ln=ln->next;
ln->next=le;
};
return 1;
};
2007-03-22 18:12:32 +00:00
int
bgpq_expander_add_as(struct bgpq_expander* b, char* as)
{
2007-03-22 18:12:32 +00:00
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",
2007-03-22 18:12:32 +00:00
*eoa, as);
return 0;
};
if(*eoa=='.' || asno>65535) {
if(b->asn32 || b->generation>=T_PREFIXLIST) {
uint32_t asn1;
if(asno>65535) {
asn1=asno%65536;
asno/=65536;
} else if(eoa && *(eoa+1)) {
asn1=strtoul(eoa+1,&eoa,10);
} else {
sx_report(SX_ERROR, "Invalid AS number: '%s'\n", as);
return 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) {
sx_report(SX_ERROR,"Invalid AS number in %s\n", as);
return 0;
};
if(!expand_special_asn && (((asno*65536+asn1)>=4200000000) ||
((asno*65536+asn1)>=64496 && (asno*65536+asn1) <= 65551))) {
return 0;
};
if(!b->asn32s[asno]) {
b->asn32s[asno]=malloc(8192);
if(!b->asn32s[asno]) {
sx_report(SX_FATAL, "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));
};
2007-03-22 18:12:32 +00:00
return 0;
};
if(asno<1 || asno>65535) {
2007-03-22 18:12:32 +00:00
sx_report(SX_ERROR,"Invalid AS number in %s\n", as);
return 0;
};
if(asno==23456 && !expand_as23456)
return 0;
if(!expand_special_asn && (asno>=64496 && asno <= 65536))
return 0;
b->asn32s[0][asno/8]|=(0x80>>(asno%8));
2007-03-22 18:12:32 +00:00
return 1;
};
int
bgpq_expander_add_prefix(struct bgpq_expander* b, char* prefix)
{
2007-03-22 18:12:32 +00:00
struct sx_prefix p;
if(!sx_prefix_parse(&p,0,prefix)) {
2007-03-22 18:12:32 +00:00
sx_report(SX_ERROR,"Unable to parse prefix %s\n", prefix);
return 0;
} else if(p.family!=b->family) {
2008-06-02 11:32:25 +00:00
SX_DEBUG(debug_expander,"Ignoring prefix %s with wrong address family\n"
,prefix);
return 0;
2007-03-22 18:12:32 +00:00
};
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;
};
2007-03-22 18:12:32 +00:00
sx_radix_tree_insert(b->tree,&p);
return 1;
2007-03-22 18:12:32 +00:00
};
int
bgpq_expander_add_prefix_range(struct bgpq_expander* b, char* prefix)
{
return sx_prefix_range_parse(b->tree, b->family, b->maxlen, prefix);
};
2007-03-22 18:12:32 +00:00
int
bgpq_expanded_macro(char* as, void* udata)
{
2007-04-04 14:31:25 +00:00
struct bgpq_expander* ex=(struct bgpq_expander*)udata;
2007-03-22 18:12:32 +00:00
if(!ex) return 0;
bgpq_expander_add_as(ex,as);
return 1;
};
int
bgpq_expanded_prefix(char* as, void* udata)
{
2007-04-04 14:31:25 +00:00
struct bgpq_expander* ex=(struct bgpq_expander*)udata;
char* d = strchr(as, '^');
2007-03-22 18:12:32 +00:00
if(!ex) return 0;
if (!d)
bgpq_expander_add_prefix(ex,as);
else
bgpq_expander_add_prefix_range(ex,as);
2007-03-22 18:12:32 +00:00
return 1;
};
2007-03-30 14:05:54 +00:00
int
bgpq_expanded_v6prefix(char* prefix, void* udata)
{
2007-04-04 14:31:25 +00:00
struct bgpq_expander* ex=(struct bgpq_expander*)udata;
2007-03-30 14:05:54 +00:00
if(!ex) return 0;
bgpq_expander_add_prefix(ex,prefix);
return 1;
};
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) {
sx_report(SX_FATAL, "Invalid arguments\n");
exit(1);
};
if(!b->firstpipe) {
sx_report(SX_FATAL, "No piped requests\n");
exit(1);
};
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)
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)
b->firstpipe->callback(object,b->firstpipe->udata);
};
if(otype) free(otype); otype=NULL;
if(object) free(object); object=NULL;
sawNL++;
if(sawNL==2) {
/* end of object */
struct bgpq_prequest* p=b->firstpipe;
b->firstpipe=b->firstpipe->next;
2015-06-23 14:56:05 +03:00
b->qsize-=p->size;
free(p);
b->piped--;
if(!b->piped) {
2015-06-23 14:56:05 +03:00
b->lastpipe=NULL;
return 0;
};
};
} else {
sawNL=0;
if(!otype) {
char* c=strchr(buffer,':');
if(c) {
*c=0;
otype=strdup(buffer);
c++;
while(isspace((int)*c)) c++;
object=strdup(c);
c=strchr(object,'\n');
if(c) *c=0;
};
};
};
};
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",
strerror(errno));
};
return 0;
};
2007-03-30 14:05:54 +00:00
int
bgpq_expand_ripe(FILE* f, int (*callback)(char*, void*), void* udata,
char* fmt, ...)
{
char request[128];
char* otype=NULL, *object=NULL, *origin=NULL;
2007-03-30 14:05:54 +00:00
int sawNL=0, nObjects=0;
va_list ap;
struct bgpq_expander* b=(struct bgpq_expander*)udata;
if(!f) {
2007-03-30 14:05:54 +00:00
sx_report(SX_FATAL,"Invalid argments\n");
exit(1);
};
va_start(ap,fmt);
vsnprintf(request,sizeof(request),fmt,ap);
va_end(ap);
SX_DEBUG(debug_expander,"expander(ripe): sending '%s'\n", request);
fwrite(request,1,strlen(request),f);
fflush(f);
sawNL=0;
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")) {
SX_DEBUG(debug_expander,"expander(ripe): got route6: %s\n",
object);
callback(object,udata);
};
2007-03-30 14:05:54 +00:00
if(otype) free(otype); otype=NULL;
if(object) free(object); object=NULL;
if(origin) free(origin); origin=NULL;
2007-03-30 14:05:54 +00:00
nObjects++;
sawNL++;
if(sawNL==2) {
2007-03-30 14:05:54 +00:00
/* ok, that's end of input */
return nObjects;
};
} else {
sawNL=0;
if(!otype) {
2007-03-30 14:05:54 +00:00
/* that's the first line of object */
char* c=strchr(request,':');
if(c) {
2007-03-30 14:05:54 +00:00
*c=0;
otype=strdup(request);
c++;
while((isspace((int)*c))) c++;
2007-03-30 14:05:54 +00:00
object=strdup(c);
c=strchr(object,'\n');
if(c) *c=0;
};
} else if(!strncmp(request,"origin",6)) {
if(origin) free(origin);
origin=strdup(request);
2007-03-30 14:05:54 +00:00
};
};
};
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",
strerror(errno));
2007-03-30 14:05:54 +00:00
};
return 0;
};
2015-06-23 14:56:05 +03:00
int bgpq_pipeline_dequeue(FILE* f, struct bgpq_expander* b);
2008-05-19 13:33:32 +00:00
int
bgpq_pipeline(FILE* f, int (*callback)(char*, void*), void* udata,
char* fmt, ...)
{
2008-05-19 13:33:32 +00:00
char request[128];
2015-06-23 14:56:05 +03:00
int ret, rlen;
2008-05-19 13:33:32 +00:00
struct bgpq_prequest* bp=NULL;
struct bgpq_expander* d=(struct bgpq_expander*)udata;
va_list ap;
va_start(ap,fmt);
vsnprintf(request,sizeof(request),fmt,ap);
va_end(ap);
2015-06-23 14:56:05 +03:00
rlen=strlen(request);
if(rlen+d->qsize >= d->socksize) {
SX_DEBUG(debug_expander, "looks like socket buffer shortage, "
"queued %i of %i, dequeueing\n", d->qsize, d->socksize);
if (d->family==AF_INET6) {
bgpq_pipeline_dequeue_ripe(f, d);
} else {
bgpq_pipeline_dequeue(f, d);
};
};
SX_DEBUG(debug_expander,"expander: sending '%s' (queued %i of %i)\n",
2015-06-23 14:56:05 +03:00
request, d->qsize, d->socksize);
2007-03-30 14:05:54 +00:00
2008-05-19 13:33:32 +00:00
bp=malloc(sizeof(struct bgpq_prequest));
if(!bp) {
sx_report(SX_FATAL,"Unable to allocate %lu bytes: %s\n",
2013-05-09 13:41:35 +00:00
(unsigned long)sizeof(struct bgpq_prequest),strerror(errno));
2008-05-19 13:33:32 +00:00
exit(1);
};
2013-05-09 13:37:01 +00:00
memset(bp,0,sizeof(struct bgpq_prequest));
2008-05-19 13:33:32 +00:00
ret=fwrite(request,1,strlen(request),f);
2015-06-23 14:56:05 +03:00
if(ret!=rlen) {
2008-05-19 13:33:32 +00:00
sx_report(SX_FATAL,"Partial write to radb, only %i bytes written: %s\n",
ret,strerror(errno));
exit(1);
};
strlcpy(bp->request,request,sizeof(bp->request));
bp->callback=callback;
bp->udata=udata;
2015-06-23 14:56:05 +03:00
bp->size=rlen;
d->qsize+=rlen;
2008-05-19 13:33:32 +00:00
if(d->lastpipe) {
2008-05-19 13:33:32 +00:00
d->lastpipe->next=bp;
d->lastpipe=bp;
} else {
2008-05-19 13:33:32 +00:00
d->firstpipe=d->lastpipe=bp;
};
d->piped++;
return 0;
};
int
bgpq_pipeline_dequeue(FILE* f, struct bgpq_expander* b)
{
while(b->piped>0) {
2008-05-19 13:33:32 +00:00
char request[128];
struct bgpq_prequest* pipe;
memset(request,0,sizeof(request));
if(!fgets(request,sizeof(request),f)) {
if(ferror(f)) {
sx_report(SX_FATAL,"Error reading data from RADB: %s (dequeue)"
"\n", strerror(errno));
} else {
sx_report(SX_FATAL,"EOF from RADB (dequeue)\n");
2008-05-19 13:33:32 +00:00
};
exit(1);
};
if(request[0]=='A') {
2008-05-19 13:33:32 +00:00
char* eon, *c;
unsigned long togot=strtoul(request+1,&eon,10);
char recvbuffer[togot+2];
memset(recvbuffer,0,togot+2);
2008-05-19 13:33:32 +00:00
if(eon && *eon!='\n') {
2008-05-19 13:33:32 +00:00
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)) {
sx_report(SX_FATAL,"Error reading RADB: %s (dequeue, "
"result)\n", strerror(errno));
} else {
sx_report(SX_FATAL,"EOF from RADB (dequeue, result)\n");
2008-05-19 13:33:32 +00:00
};
exit(1);
};
SX_DEBUG(debug_expander>=3,"Got %s in response to %s",recvbuffer,
b->firstpipe->request);
2008-05-19 13:33:32 +00:00
for(c=recvbuffer; c<recvbuffer+togot;) {
2008-05-19 13:33:32 +00:00
size_t spn=strcspn(c," \n");
if(spn) c[spn]=0;
if(c[0]==0) break;
if(b->firstpipe->callback) {
2008-05-19 13:33:32 +00:00
b->firstpipe->callback(c,b->firstpipe->udata);
};
c+=spn+1;
};
/* Final code */
if(fgets(recvbuffer,togot,f)==NULL) {
if(ferror(f)) {
sx_report(SX_FATAL,"Error reading RADB: %s (dequeue,final)"
")\n", strerror(errno));
} else {
sx_report(SX_FATAL,"EOF from RADB (dequeue,final)\n");
2008-05-19 13:33:32 +00:00
};
exit(1);
};
} else if(request[0]=='C') {
2008-05-19 13:33:32 +00:00
/* No data */
} else if(request[0]=='D') {
2008-05-19 13:33:32 +00:00
/* .... */
} else if(request[0]=='E') {
2008-05-19 13:33:32 +00:00
/* XXXXX */
} else if(request[0]=='F') {
2008-05-19 13:33:32 +00:00
/* XXXXX */
} else {
sx_report(SX_ERROR,"Wrong reply: %s to %s\n", request,
2008-05-19 13:33:32 +00:00
b->firstpipe->request);
};
pipe=b->firstpipe;
b->firstpipe=b->firstpipe->next;
b->piped--;
2015-06-23 14:56:05 +03:00
b->qsize-=pipe->size;
2008-05-19 13:33:32 +00:00
free(pipe);
};
2015-06-23 14:56:05 +03:00
b->lastpipe=NULL;
2008-05-19 13:33:32 +00:00
return 0;
};
2007-03-30 14:05:54 +00:00
2007-03-22 18:12:32 +00:00
int
bgpq_expand_radb(FILE* f, int (*callback)(char*, void*), void* udata,
2007-03-22 18:12:32 +00:00
char* fmt, ...)
{
2007-03-22 18:12:32 +00:00
char request[128];
va_list ap;
int ret;
va_start(ap,fmt);
vsnprintf(request,sizeof(request),fmt,ap);
va_end(ap);
SX_DEBUG(debug_expander,"expander: sending '%s'\n", request);
ret=fwrite(request,1,strlen(request),f);
if(ret!=strlen(request)) {
sx_report(SX_FATAL,"Partial write to radb, only %i bytes written: %s\n",
ret,strerror(errno));
2007-03-22 18:12:32 +00:00
exit(1);
};
memset(request,0,sizeof(request));
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);
};
sx_report(SX_FATAL,"EOF from radb (expand,radb)\n");
2007-03-22 18:12:32 +00:00
exit(1);
};
2013-05-09 13:37:01 +00:00
SX_DEBUG(debug_expander>2,"expander: initially got %lu bytes, '%s'\n",
2013-05-09 13:41:35 +00:00
(unsigned long)strlen(request),request);
if(request[0]=='A') {
2007-03-22 18:12:32 +00:00
char* eon, *c;
long togot=strtoul(request+1,&eon,10);
char recvbuffer[togot+1];
if(eon && *eon!='\n') {
sx_report(SX_ERROR,"A-code finised with wrong char '%c' (%s)\n",
*eon,request);
2007-03-22 18:12:32 +00:00
exit(1);
};
if(fgets(recvbuffer,togot+1,f)==NULL) {
if(feof(f)) {
sx_report(SX_FATAL,"EOF from radb (expand,radb,result)\n");
} else {
sx_report(SX_FATAL,"Error reading radb: %s (expand,radb,"
"result)\n", strerror(errno));
2007-03-22 18:12:32 +00:00
};
exit(1);
2007-03-22 18:12:32 +00:00
};
2013-05-09 13:37:01 +00:00
SX_DEBUG(debug_expander>2,"expander: final reply of %lu bytes, '%s'\n",
2013-05-09 13:41:35 +00:00
(unsigned long)strlen(recvbuffer),recvbuffer);
2015-06-23 14:56:05 +03:00
for(c=recvbuffer; c<recvbuffer+togot;) {
2007-03-22 18:12:32 +00:00
size_t spn=strcspn(c," \n");
if(spn) c[spn]=0;
if(c[0]==0) break;
if(callback) callback(c,udata);
c+=spn+1;
};
if(fgets(recvbuffer,togot,f)==NULL) {
if(feof(f)) {
sx_report(SX_FATAL,"EOF from radb (expand,radb,final)\n");
} else {
sx_report(SX_FATAL,"ERROR from radb: %s\n", strerror(errno));
};
exit(1);
};
} else if(request[0]=='C') {
2007-03-22 18:12:32 +00:00
/* no data */
} else if(request[0]=='D') {
2007-03-22 18:12:32 +00:00
/* ... */
} else if(request[0]=='E') {
2007-03-22 18:12:32 +00:00
/* XXXXXX */
} else if(request[0]=='F') {
2007-03-22 18:12:32 +00:00
/* XXXXXX */
} else {
2007-03-22 18:12:32 +00:00
sx_report(SX_ERROR,"Wrong reply: %s\n", request);
exit(0);
};
return 0;
};
int
bgpq_expand(struct bgpq_expander* b)
{
int fd=-1, err, ret;
2007-03-22 18:12:32 +00:00
struct sx_slentry* mc;
struct addrinfo hints, *res=NULL, *rp;
FILE* f=NULL;
2007-03-22 18:12:32 +00:00
memset(&hints,0,sizeof(struct addrinfo));
hints.ai_socktype=SOCK_STREAM;
2008-12-19 17:39:15 +00:00
err=getaddrinfo(b->server,"43",&hints,&res);
if(err) {
2008-12-19 17:39:15 +00:00
sx_report(SX_ERROR,"Unable to resolve %s: %s\n",
b->server, gai_strerror(err));
2007-03-22 18:12:32 +00:00
exit(1);
};
for(rp=res; rp; rp=rp->ai_next) {
2007-03-22 18:12:32 +00:00
fd=socket(rp->ai_family,rp->ai_socktype,0);
if(fd==-1) {
2007-03-22 18:12:32 +00:00
if(errno==EPROTONOSUPPORT) continue;
sx_report(SX_ERROR,"Unable to create socket: %s\n",
2007-03-22 18:12:32 +00:00
strerror(errno));
exit(1);
};
err=connect(fd,rp->ai_addr,rp->ai_addrlen);
if(err) {
2007-03-22 18:12:32 +00:00
shutdown(fd,SHUT_RDWR);
close(fd);
fd=-1;
continue;
};
2015-06-23 14:56:05 +03:00
err=sx_maxsockbuf(fd,SO_SNDBUF);
if(err>0) {
SX_DEBUG(debug_expander, "Acquired sendbuf of %i bytes\n", err);
b->socksize=err;
} else {
shutdown(fd, SHUT_RDWR);
close(fd);
fd=-1;
continue;
};
f=fdopen(fd,"a+");
if(!f) {
shutdown(fd,SHUT_RDWR);
close(fd);
fd=-1;
f=NULL;
continue;
};
2007-03-22 18:12:32 +00:00
break;
};
freeaddrinfo(res);
if(!f) {
2007-03-22 18:12:32 +00:00
/* all our attempts to connect failed */
2008-12-19 17:41:06 +00:00
sx_report(SX_ERROR,"All attempts to connect %s failed, last"
" error: %s\n", b->server, strerror(errno));
2007-03-22 18:12:32 +00:00
exit(1);
};
2015-06-23 14:56:05 +03:00
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);
};
2007-03-22 18:12:32 +00:00
if(b->sources && b->sources[0]!=0) {
2007-03-22 18:12:32 +00:00
char sources[128];
snprintf(sources,sizeof(sources),"!s%s\n", b->sources);
fwrite(sources,strlen(sources),1,f);
2008-05-20 13:12:44 +00:00
fgets(sources,sizeof(sources),f);
if(sources[0]!='C') {
sx_report(SX_ERROR, "Invalid source(s) '%s': %s\n", b->sources,
sources);
exit(1);
};
2007-03-22 18:12:32 +00:00
};
if(b->identify) {
char ident[128];
snprintf(ident,sizeof(ident),"!n" PACKAGE_STRING "\n");
fwrite(ident,strlen(ident),1,f);
2008-05-20 13:12:44 +00:00
fgets(ident,sizeof(ident),f);
};
for(mc=b->macroses;mc;mc=mc->next) {
bgpq_expand_radb(f,bgpq_expanded_macro,b,"!i%s,1\n",mc->text);
2007-03-22 18:12:32 +00:00
};
if(b->generation>=T_PREFIXLIST) {
unsigned i, j, k;
for(mc=b->rsets;mc;mc=mc->next) {
if(b->family==AF_INET) {
2008-06-02 11:32:25 +00:00
bgpq_expand_radb(f,bgpq_expanded_prefix,b,"!i%s,1\n",mc->text);
} else {
if(!pipelining) {
2008-06-02 11:32:25 +00:00
bgpq_expand_ripe(f,bgpq_expanded_v6prefix,b,
"-T route6 -i member-of %s\n",mc->text);
} else {
2008-06-02 11:32:25 +00:00
bgpq_pipeline(f,bgpq_expanded_v6prefix,b,
"-T route6 -i member-of %s\n", mc->text);
};
};
};
for(k=0;k<sizeof(b->asn32s)/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)
bgpq_expand_ripe(f,bgpq_expanded_v6prefix,b,
"-T route6 -i origin as%u.%u\r\n", k,
i*8+j);
else
bgpq_expand_ripe(f,bgpq_expanded_v6prefix,b,
"-T route6 -i origin as%u\r\n", i*8+j);
} 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
bgpq_pipeline(f,bgpq_expanded_v6prefix,b,
"-T route6 -i origin as%u\r\n", i*8+j);
};
} else {
if(!pipelining) {
if(k>0)
2008-05-19 13:33:32 +00:00
bgpq_expand_radb(f,bgpq_expanded_prefix,b,
"!gas%u.%u\n", k, i*8+j);
else
2008-05-19 13:33:32 +00:00
bgpq_expand_radb(f,bgpq_expanded_prefix,b,
"!gas%u\n", i*8+j);
} else {
if(k>0)
2008-05-19 13:33:32 +00:00
bgpq_pipeline(f,bgpq_expanded_prefix,b,
"!gas%u.%u\n", k, i*8+j);
else
2008-05-19 13:33:32 +00:00
bgpq_pipeline(f,bgpq_expanded_prefix,b,
"!gas%u\n", i*8+j);
};
};
2007-03-30 14:05:54 +00:00
};
2007-03-22 18:12:32 +00:00
};
};
};
if(pipelining && b->firstpipe) {
if(b->family==AF_INET6) {
bgpq_pipeline_dequeue_ripe(f,b);
} else {
bgpq_pipeline_dequeue(f,b);
};
2008-05-19 13:33:32 +00:00
};
2007-03-22 18:12:32 +00:00
};
2015-06-23 14:56:05 +03:00
fwrite("!q\n",1,3,f);
fclose(f);
2007-03-22 18:12:32 +00:00
return 1;
};