diff options
Diffstat (limited to 'sbin/routed/rtquery/rtquery.c')
-rw-r--r-- | sbin/routed/rtquery/rtquery.c | 232 |
1 files changed, 219 insertions, 13 deletions
diff --git a/sbin/routed/rtquery/rtquery.c b/sbin/routed/rtquery/rtquery.c index 7d6913a048d7..0579141b667b 100644 --- a/sbin/routed/rtquery/rtquery.c +++ b/sbin/routed/rtquery/rtquery.c @@ -65,6 +65,17 @@ static char rcsid[] = "$NetBSD$"; #define _HAVE_SIN_LEN #endif +#define MD5_DIGEST_LEN 16 +typedef struct { + u_int32_t state[4]; /* state (ABCD) */ + u_int32_t count[2]; /* # of bits, modulo 2^64 (LSB 1st) */ + unsigned char buffer[64]; /* input buffer */ +} MD5_CTX; +extern void MD5Init(MD5_CTX*); +extern void MD5Update(MD5_CTX*, u_char*, u_int); +extern void MD5Final(u_char[MD5_DIGEST_LEN], MD5_CTX*); + + #define WTIME 15 /* Time to wait for all responses */ #define STIME (250*1000) /* usec to wait for another response */ @@ -90,8 +101,10 @@ int pflag; /* play the `gated` game */ int ripv2 = 1; /* use RIP version 2 */ int wtime = WTIME; int rflag; /* 1=ask about a particular route */ -int trace; -int not_trace; +int trace, not_trace; /* send trace command or not */ +int auth_type = RIP_AUTH_NONE; +char passwd[RIP_AUTH_PW_LEN]; +u_long keyid; struct timeval sent; /* when query sent */ @@ -101,6 +114,7 @@ static void trace_loop(char *argv[]); static void query_loop(char *argv[], int); static int getnet(char *, struct netinfo *); static u_int std_mask(u_int); +static int parse_quote(char **, char *, char *, char *, int); int @@ -108,14 +122,14 @@ main(int argc, char *argv[]) { int ch, bsize; - char *p, *options, *value; + char *p, *options, *value, delim; OMSG.rip_nets[0].n_dst = RIP_DEFAULT; OMSG.rip_nets[0].n_family = RIP_AF_UNSPEC; OMSG.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY); pgmname = argv[0]; - while ((ch = getopt(argc, argv, "np1w:r:t:")) != EOF) + while ((ch = getopt(argc, argv, "np1w:r:t:a:")) != EOF) switch (ch) { case 'n': not_trace = 1; @@ -208,6 +222,31 @@ main(int argc, } break; + case 'a': + not_trace = 1; + p = strchr(optarg,'='); + if (!p) + goto usage; + *p++ = '\0'; + if (!strcasecmp("passwd",optarg)) + auth_type = RIP_AUTH_PW; + else if (!strcasecmp("md5_passwd",optarg)) + auth_type = RIP_AUTH_MD5; + else + goto usage; + if (0 > parse_quote(&p,"|",&delim, + passwd,sizeof(passwd))) + goto usage; + if (auth_type == RIP_AUTH_MD5 + && delim == '|') { + keyid = strtoul(p+1,&p,0); + if (keyid > 255 || *p != '\0') + goto usage; + } else if (delim != '\0') { + goto usage; + } + break; + default: goto usage; } @@ -215,8 +254,9 @@ main(int argc, argc -= optind; if ((not_trace && trace) || argc == 0) { usage: fprintf(stderr, "%s: [-np1v] [-r tgt_rt] [-w wtime]" - " host1 [host2 ...]\n" - "or\t-t {on=filename|more|off} host1 host2 ...\n", + " [-a type=passwd] host1 [host2 ...]\n" + "or\t-t {on=filename|more|off|on=dump/../table}" + " host1 [host2 ...]\n", pgmname); exit(1); } @@ -294,6 +334,8 @@ trace_loop(char *argv[]) static void query_loop(char *argv[], int argc) { +# define NA0 (OMSG.rip_auths[0]) +# define NA2 (OMSG.rip_auths[2]) struct seen { struct seen *next; struct in_addr addr; @@ -304,11 +346,38 @@ query_loop(char *argv[], int argc) struct timeval now, delay; struct sockaddr_in from; int fromlen; + MD5_CTX md5_ctx; OMSG.rip_cmd = (pflag) ? RIPCMD_POLL : RIPCMD_REQUEST; if (ripv2) { OMSG.rip_vers = RIPv2; + if (auth_type == RIP_AUTH_PW) { + OMSG.rip_nets[1] = OMSG.rip_nets[0]; + NA0.a_family = RIP_AF_AUTH; + NA0.a_type = RIP_AUTH_PW; + bcopy(passwd, NA0.au.au_pw, + RIP_AUTH_PW_LEN); + omsg_len += sizeof(OMSG.rip_nets[0]); + + } else if (auth_type == RIP_AUTH_MD5) { + OMSG.rip_nets[1] = OMSG.rip_nets[0]; + NA0.a_family = RIP_AF_AUTH; + NA0.a_type = RIP_AUTH_MD5; + NA0.au.a_md5.md5_keyid = (int8_t)keyid; + NA0.au.a_md5.md5_auth_len = RIP_AUTH_PW_LEN; + NA0.au.a_md5.md5_seqno = 0; + NA0.au.a_md5.md5_pkt_len = sizeof(OMSG.rip_nets[1]); + NA2.a_family = RIP_AF_AUTH; + NA2.a_type = 1; + bcopy(passwd, NA2.au.au_pw, sizeof(NA2.au.au_pw)); + MD5Init(&md5_ctx); + MD5Update(&md5_ctx, (u_char *)&NA0, + (char *)(&NA2+1) - (char *)&NA0); + MD5Final(NA2.au.au_pw, &md5_ctx); + omsg_len += 2*sizeof(OMSG.rip_nets[0]); + } + } else { OMSG.rip_vers = RIPv1; OMSG.rip_nets[0].n_mask = 0; @@ -393,7 +462,7 @@ query_loop(char *argv[], int argc) } -/* sent do one host +/* send to one host */ static int out(char *host) @@ -432,6 +501,60 @@ out(char *host) /* + * Convert string to printable characters + */ +static char * +qstring(u_char *s, int len) +{ + static char buf[8*20+1]; + char *p; + u_char *s2, c; + + + for (p = buf; len != 0 && p < &buf[sizeof(buf)-1]; len--) { + c = *s++; + if (c == '\0') { + for (s2 = s+1; s2 < &s[len]; s2++) { + if (*s2 != '\0') + break; + } + if (s2 >= &s[len]) + goto exit; + } + + if (c >= ' ' && c < 0x7f && c != '\\') { + *p++ = c; + continue; + } + *p++ = '\\'; + switch (c) { + case '\\': + *p++ = '\\'; + break; + case '\n': + *p++= 'n'; + break; + case '\r': + *p++= 'r'; + break; + case '\t': + *p++ = 't'; + break; + case '\b': + *p++ = 'b'; + break; + default: + p += sprintf(p,"%o",c); + break; + } + } +exit: + *p = '\0'; + return buf; +} + + +/* * Handle an incoming RIP packet. */ static void @@ -447,7 +570,7 @@ rip_input(struct sockaddr_in *from, int i; struct hostent *hp; struct netent *np; - struct netauth *a; + struct netauth *na; if (nflag) { @@ -544,11 +667,33 @@ rip_input(struct sockaddr_in *from, } } else if (n->n_family == RIP_AF_AUTH) { - a = (struct netauth*)n; - (void)printf(" authentication type %d: ", - a->a_type); - for (i = 0; i < sizeof(a->au.au_pw); i++) - (void)printf("%02x ", a->au.au_pw[i]); + na = (struct netauth*)n; + if (na->a_type == RIP_AUTH_PW + && n == IMSG.rip_nets) { + (void)printf(" Password Authentication:" + " \"%s\"\n", + qstring(na->au.au_pw, + RIP_AUTH_PW_LEN)); + continue; + } + + if (na->a_type == RIP_AUTH_MD5 + && n == IMSG.rip_nets) { + (void)printf(" MD5 Authentication" + " len=%d KeyID=%d" + " seqno=%d" + " rsvd=%#x,%#x\n", + na->au.a_md5.md5_pkt_len, + na->au.a_md5.md5_keyid, + na->au.a_md5.md5_seqno, + na->au.a_md5.rsvd[0], + na->au.a_md5.rsvd[1]); + continue; + } + (void)printf(" Authentication type %d: ", + ntohs(na->a_type)); + for (i = 0; i < sizeof(na->au.au_pw); i++) + (void)printf("%02x ", na->au.au_pw[i]); putc('\n', stdout); continue; @@ -652,3 +797,64 @@ getnet(char *name, rt->n_mask = htonl(mask); return 1; } + + +/* strtok(), but honoring backslash + */ +static int /* -1=bad */ +parse_quote(char **linep, + char *delims, + char *delimp, + char *buf, + int lim) +{ + char c, *pc, *p; + + + pc = *linep; + if (*pc == '\0') + return -1; + + for (;;) { + if (lim == 0) + return -1; + c = *pc++; + if (c == '\0') + break; + + if (c == '\\' && pc != '\0') { + if ((c = *pc++) == 'n') { + c = '\n'; + } else if (c == 'r') { + c = '\r'; + } else if (c == 't') { + c = '\t'; + } else if (c == 'b') { + c = '\b'; + } else if (c >= '0' && c <= '7') { + c -= '0'; + if (*pc >= '0' && *pc <= '7') { + c = (c<<3)+(*pc++ - '0'); + if (*pc >= '0' && *pc <= '7') + c = (c<<3)+(*pc++ - '0'); + } + } + + } else { + for (p = delims; *p != '\0'; ++p) { + if (*p == c) + goto exit; + } + } + + *buf++ = c; + --lim; + } +exit: + if (delimp != 0) + *delimp = c; + *linep = pc-1; + if (lim != 0) + *buf = '\0'; + return 0; +} |