Merge pull request #21 from ccaputo/master

Various for consideration...
This commit is contained in:
Job Snijders
2020-03-11 18:09:09 +01:00
committed by GitHub
7 changed files with 133 additions and 69 deletions

View File

@@ -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,

View File

@@ -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
View File

@@ -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 "

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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);