mirror of
https://github.com/bgp/bgpq4
synced 2025-02-28 08:53:11 +00:00
Merge pull request #21 from ccaputo/master
Various for consideration...
This commit is contained in:
@@ -290,6 +290,7 @@ example below:
|
||||
ipfw add pass all from 193.193.192.0/19 to any
|
||||
|
||||
Recognized format characters: '%n' - network, '%l' - mask length,
|
||||
'%a' - aggregate low mask length, '%A' - aggregate high mask length,
|
||||
'%N' - object name, '%m' - object mask and '%i' - inversed mask.
|
||||
Recognized escape characters: '\n' - new line, '\t' - tabulation.
|
||||
Please note that no new lines inserted automatically after each sentence,
|
||||
|
||||
1
bgpq4.8
1
bgpq4.8
@@ -251,6 +251,7 @@ ipfw add pass all from 193.193.192.0/19 to any
|
||||
.fi
|
||||
.Pp
|
||||
Recognized format characters: %n - network, %l - mask length,
|
||||
%a - aggregate low mask length, %A - aggregate high mask length,
|
||||
%N - object name, %m - object mask and %i - inversed mask.
|
||||
Recognized escape characters: \\n - new line, \\t - tabulation.
|
||||
Please note that no new lines inserted automatically after each sentence,
|
||||
|
||||
12
bgpq4.c
12
bgpq4.c
@@ -459,12 +459,6 @@ main(int argc, char* argv[])
|
||||
sx_report(SX_FATAL, "Sorry, only prefix-lists supported in formatted "
|
||||
"output\n");
|
||||
|
||||
if (expander.vendor == V_FORMAT && (refine || refineLow)) {
|
||||
sx_report(SX_FATAL, "Sorry, formatted output (-F <fmt>) in not "
|
||||
"compatible with -R/-r options\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (expander.vendor == V_HUAWEI && expander.generation != T_ASPATH &&
|
||||
expander.generation != T_OASPATH && expander.generation != T_PREFIXLIST)
|
||||
sx_report(SX_FATAL, "Sorry, only as-paths and prefix-lists supported "
|
||||
@@ -486,12 +480,6 @@ main(int argc, char* argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(aggregate && expander.vendor == V_FORMAT) {
|
||||
sx_report(SX_FATAL, "Sorry, aggregation (-A) is not compatible with "
|
||||
"formatted output (-F <fmt>)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (aggregate && (expander.vendor == V_NOKIA_MD || expander.vendor == V_NOKIA)
|
||||
&& expander.generation != T_PREFIXLIST) {
|
||||
sx_report(SX_FATAL, "Sorry, aggregation (-A) is not supported with "
|
||||
|
||||
@@ -1633,24 +1633,39 @@ struct fpcbdata {
|
||||
void
|
||||
bgpq4_print_format_prefix(struct sx_radix_node* n, void* ff)
|
||||
{
|
||||
char prefix[128];
|
||||
struct fpcbdata* fpc = (struct fpcbdata*)ff;
|
||||
FILE* f = fpc->f;
|
||||
struct bgpq_expander* b = fpc->b;
|
||||
|
||||
if (n->isGlue)
|
||||
return;
|
||||
goto checkSon;
|
||||
|
||||
if (!f)
|
||||
f = stdout;
|
||||
|
||||
memset(prefix, 0, sizeof(prefix));
|
||||
if (!n->isAggregate) {
|
||||
sx_prefix_snprintf_fmt(n->prefix, f,
|
||||
b->name ? b->name : "NN",
|
||||
b->format,
|
||||
n->prefix->masklen,
|
||||
n->prefix->masklen);
|
||||
} else if (n->aggregateLow > n->prefix->masklen) {
|
||||
sx_prefix_snprintf_fmt(n->prefix, f,
|
||||
b->name ? b->name : "NN",
|
||||
b->format,
|
||||
n->aggregateLow,
|
||||
n->aggregateHi);
|
||||
} else {
|
||||
sx_prefix_snprintf_fmt(n->prefix, f,
|
||||
b->name ? b->name : "NN",
|
||||
b->format,
|
||||
n->prefix->masklen,
|
||||
n->aggregateHi);
|
||||
}
|
||||
|
||||
sx_prefix_snprintf_fmt(n->prefix, prefix, sizeof(prefix),
|
||||
b->name ? b->name : "NN",
|
||||
b->format);
|
||||
|
||||
fprintf(f, "%s", prefix);
|
||||
checkSon:
|
||||
if (n->son)
|
||||
bgpq4_print_format_prefix(n->son, ff);
|
||||
}
|
||||
|
||||
|
||||
@@ -1658,10 +1673,13 @@ int
|
||||
bgpq4_print_format_prefixlist(FILE* f, struct bgpq_expander* b)
|
||||
{
|
||||
struct fpcbdata ff = {.f=f, .b=b};
|
||||
int len = strlen(b->format);
|
||||
|
||||
sx_radix_tree_foreach(b->tree, bgpq4_print_format_prefix, &ff);
|
||||
|
||||
if (strcmp(b->format + strlen(b->format - 2), "\n"))
|
||||
// Add newline if format doesn't already end with one.
|
||||
if (len < 2 ||
|
||||
!(b->format[len-2] == '\\' && b->format[len-1] == 'n'))
|
||||
fprintf(f, "\n");
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -914,7 +914,7 @@ bgpq_expand(struct bgpq_expander* b)
|
||||
SX_DEBUG(debug_expander, "Sending '!!' to server to request for the"
|
||||
"connection to remain open\n");
|
||||
if ((ret = write(fd, "!!\n", 3)) != 3) {
|
||||
sx_report(SX_ERROR,"Partial write to IRRd: %i bytes, %s\n",
|
||||
sx_report(SX_ERROR, "Partial write of multiple command mode to IRRd: %i bytes, %s\n",
|
||||
ret, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
@@ -923,24 +923,48 @@ bgpq_expand(struct bgpq_expander* b)
|
||||
SX_DEBUG(debug_expander, "b->identify: Sending '!n "
|
||||
PACKAGE_STRING "' to server.\n");
|
||||
char ident[128];
|
||||
snprintf(ident, sizeof(ident), "!n" PACKAGE_STRING "\n");
|
||||
write(fd, ident, strlen(ident));
|
||||
read(fd, ident, sizeof(ident));
|
||||
int ilen = snprintf(ident, sizeof(ident), "!n" PACKAGE_STRING "\n");
|
||||
if (ilen > 0) {
|
||||
if ((ret = write(fd, ident, ilen)) != ilen) {
|
||||
sx_report(SX_ERROR, "Partial write of identifier to IRRd: %i bytes, %s\n",
|
||||
ret, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
memset(ident, 0, sizeof(ident));
|
||||
if (0 < read(fd, ident, sizeof(ident))) {
|
||||
SX_DEBUG(debug_expander, "Got answer %s", ident);
|
||||
} else {
|
||||
sx_report(SX_ERROR, "ident - failed read from IRRd\n");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
sx_report(SX_ERROR, "snprintf(ident) failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Test whether the server has support for the A query */
|
||||
if (b->generation >= T_PREFIXLIST) {
|
||||
if (b->generation >= T_PREFIXLIST && !STAILQ_EMPTY(&b->macroses)) {
|
||||
char aret[128];
|
||||
char aresp[] = "F Missing required set name for A query";
|
||||
SX_DEBUG(debug_expander, "Testing support for A queries\n");
|
||||
write(fd, "!a\n", 3);
|
||||
if ((ret = write(fd, "!a\n", 3)) != 3) {
|
||||
sx_report(SX_ERROR, "Partial write of '!a' test query to IRRd: %i bytes, %s\n",
|
||||
ret, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
memset(aret, 0, sizeof(aret));
|
||||
read(fd, aret, sizeof(aret));
|
||||
if (strncmp(aret, aresp, strlen(aresp)) == 0) {
|
||||
SX_DEBUG(debug_expander, "Server supports A query\n");
|
||||
aquery = 1;
|
||||
} else
|
||||
SX_DEBUG(debug_expander, "No support for A queries\n");
|
||||
if (0 < read(fd, aret, sizeof(aret))) {
|
||||
if (strncmp(aret, aresp, strlen(aresp)) == 0) {
|
||||
SX_DEBUG(debug_expander, "Server supports A query\n");
|
||||
aquery = 1;
|
||||
} else {
|
||||
SX_DEBUG(debug_expander, "No support for A queries\n");
|
||||
}
|
||||
} else {
|
||||
sx_report(SX_ERROR, "'!a' query test - failed read from IRRd\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (b->sources && b->sources[0] != 0) {
|
||||
@@ -948,15 +972,28 @@ bgpq_expand(struct bgpq_expander* b)
|
||||
if (slen < 128)
|
||||
slen = 128;
|
||||
char sources[slen];
|
||||
snprintf(sources, sizeof(sources), "!s%s\n", b->sources);
|
||||
SX_DEBUG(debug_expander, "Requesting sources %s", sources);
|
||||
write(fd, sources, strlen(sources));
|
||||
memset(sources, 0, slen);
|
||||
read(fd, sources, slen);
|
||||
SX_DEBUG(debug_expander,"Got answer %s", sources);
|
||||
if (sources[0] != 'C') {
|
||||
sx_report(SX_ERROR, "Invalid source(s) '%s': %s\n",
|
||||
b->sources, sources);
|
||||
slen = snprintf(sources, sizeof(sources), "!s%s\n", b->sources);
|
||||
if (slen > 0) {
|
||||
SX_DEBUG(debug_expander, "Requesting sources %s", sources);
|
||||
if ((ret = write(fd, sources, slen)) != slen) {
|
||||
sx_report(SX_ERROR, "Partial write of sources to IRRd: %i bytes, %s\n",
|
||||
ret, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
memset(sources, 0, sizeof(sources));
|
||||
if (0 < read(fd, sources, sizeof(sources))) {
|
||||
SX_DEBUG(debug_expander, "Got answer %s", sources);
|
||||
if (sources[0] != 'C') {
|
||||
sx_report(SX_ERROR, "Invalid source(s) '%s': %s\n",
|
||||
b->sources, sources);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
sx_report(SX_ERROR, "sources - failed read from IRRd\n");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
sx_report(SX_ERROR, "snprintf(sources) failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -1037,7 +1074,11 @@ bgpq_expand(struct bgpq_expander* b)
|
||||
}
|
||||
}
|
||||
|
||||
write(fd, "!q\n",3);
|
||||
if ((ret = write(fd, "!q\n", 3)) != 3) {
|
||||
sx_report(SX_ERROR, "Partial write of quit to IRRd: %i bytes, %s\n",
|
||||
ret, strerror(errno));
|
||||
// not worth exiting due to this
|
||||
}
|
||||
if (pipelining) {
|
||||
int fl = fcntl(fd, F_GETFL);
|
||||
fl &= ~O_NONBLOCK;
|
||||
|
||||
62
sx_prefix.c
62
sx_prefix.c
@@ -399,74 +399,88 @@ sx_prefix_snprintf(struct sx_prefix* p, char* rbuffer, int srb)
|
||||
return sx_prefix_snprintf_sep(p, rbuffer, srb, "/");
|
||||
}
|
||||
|
||||
int
|
||||
sx_prefix_snprintf_fmt(struct sx_prefix* p, char* buffer, int size,
|
||||
const char* name, const char* format)
|
||||
void
|
||||
sx_prefix_snprintf_fmt(struct sx_prefix* p, FILE* f,
|
||||
const char* name, const char* format,
|
||||
unsigned int aggregateLow, unsigned int aggregateHi)
|
||||
{
|
||||
unsigned off = 0;
|
||||
const char* c = format;
|
||||
struct sx_prefix *q = sx_prefix_alloc(NULL);
|
||||
char prefix[128];
|
||||
|
||||
while (*c) {
|
||||
if(*c == '%') {
|
||||
switch (*(c + 1)) {
|
||||
case 'r':
|
||||
case 'n':
|
||||
inet_ntop(p->family, &p->addr, buffer+off, size-off);
|
||||
off = strlen(buffer);
|
||||
if (NULL != inet_ntop(p->family, &p->addr, prefix, sizeof(prefix))) {
|
||||
fprintf(f, "%s", prefix);
|
||||
} else {
|
||||
sx_report(SX_ERROR, "inet_ntop failed\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
off += snprintf(buffer + off, size - off,
|
||||
"%i", p->masklen);
|
||||
fprintf(f, "%i", p->masklen);
|
||||
break;
|
||||
case 'a':
|
||||
fprintf(f, "%u", aggregateLow);
|
||||
break;
|
||||
case 'A':
|
||||
fprintf(f, "%u", aggregateHi);
|
||||
break;
|
||||
case '%':
|
||||
buffer[off++] = '%';
|
||||
fprintf(f, "%%");
|
||||
break;
|
||||
case 'N':
|
||||
off += snprintf(buffer + off, size - off,
|
||||
"%s", name);
|
||||
fprintf(f, "%s", name);
|
||||
break;
|
||||
case 'm':
|
||||
sx_prefix_mask(p, q);
|
||||
inet_ntop(p->family, &q->addr, buffer + off,
|
||||
size - off);
|
||||
off = strlen(buffer);
|
||||
if (NULL != inet_ntop(p->family, &q->addr, prefix, sizeof(prefix))) {
|
||||
fprintf(f, "%s", prefix);
|
||||
} else {
|
||||
sx_report(SX_ERROR, "inet_ntop failed\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
sx_prefix_imask(p, q);
|
||||
inet_ntop(p->family, &q->addr, buffer + off,
|
||||
size - off);
|
||||
off = strlen(buffer);
|
||||
if (NULL != inet_ntop(p->family, &q->addr, prefix, sizeof(prefix))) {
|
||||
fprintf(f, "%s", prefix);
|
||||
} else {
|
||||
sx_report(SX_ERROR, "inet_ntop failed\n");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default :
|
||||
sx_report(SX_ERROR, "Unknown format char "
|
||||
"'%c'\n", *(c + 1));
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
c += 2;
|
||||
} else if (*c == '\\') {
|
||||
switch(*(c+1)) {
|
||||
case 'n':
|
||||
buffer[off++] = '\n';
|
||||
fprintf(f, "\n");
|
||||
break;
|
||||
case 't':
|
||||
buffer[off++] = '\t';
|
||||
fprintf(f, "\t");
|
||||
break;
|
||||
case '\\':
|
||||
buffer[off++] = '\\';
|
||||
fprintf(f, "\\");
|
||||
break;
|
||||
default:
|
||||
buffer[off++] = *(c + 1);
|
||||
fprintf(f, "%c", *(c + 1));
|
||||
break;
|
||||
}
|
||||
c += 2;
|
||||
} else {
|
||||
buffer[off++] = *c;
|
||||
fprintf(f, "%c", *c);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
return strlen(buffer);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -51,8 +51,9 @@ 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_snprintf_sep(struct sx_prefix* p, char* rbuffer, int srb, char*);
|
||||
int sx_prefix_snprintf_fmt(struct sx_prefix* p, char* rbuffer, int srb,
|
||||
const char* name, const char* fmt);
|
||||
void sx_prefix_snprintf_fmt(struct sx_prefix* p, FILE* f,
|
||||
const char* name, const char* fmt,
|
||||
unsigned int aggregateLow, unsigned int aggregateHi);
|
||||
int sx_prefix_jsnprintf(struct sx_prefix* p, char* rbuffer, int srb);
|
||||
struct sx_radix_tree* sx_radix_tree_new(int af);
|
||||
struct sx_radix_node* sx_radix_node_new(struct sx_prefix* prefix);
|
||||
|
||||
Reference in New Issue
Block a user