mirror of
https://github.com/openbsd/src.git
synced 2025-01-04 23:35:36 -08:00
Controller for the ripd.
All relevant information in the rip daemon can be displayed with this controller. Not connected to builds yet. ok claudio@
This commit is contained in:
parent
ddeeec1440
commit
8eeeb81e66
15
usr.sbin/ripctl/Makefile
Normal file
15
usr.sbin/ripctl/Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
# $OpenBSD: Makefile,v 1.1 2006/10/18 16:15:25 norby Exp $
|
||||
|
||||
.PATH: ${.CURDIR}/../ripd
|
||||
|
||||
PROG= ripctl
|
||||
SRCS= buffer.c imsg.c log.c ripctl.c parser.c
|
||||
CFLAGS+= -Wall
|
||||
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
|
||||
CFLAGS+= -Wmissing-declarations
|
||||
CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
|
||||
CFLAGS+= -Wsign-compare
|
||||
CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../ripd
|
||||
MAN= ripctl.8
|
||||
|
||||
.include <bsd.prog.mk>
|
304
usr.sbin/ripctl/parser.c
Normal file
304
usr.sbin/ripctl/parser.c
Normal file
@ -0,0 +1,304 @@
|
||||
/* $OpenBSD: parser.c,v 1.1 2006/10/18 16:15:25 norby Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it>
|
||||
* Copyright (c) 2004 Esben Norby <norby@openbsd.org>
|
||||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ripd.h"
|
||||
|
||||
#include "parser.h"
|
||||
|
||||
enum token_type {
|
||||
NOTOKEN,
|
||||
ENDTOKEN,
|
||||
KEYWORD,
|
||||
ADDRESS,
|
||||
FLAG,
|
||||
PREFIX,
|
||||
IFNAME
|
||||
};
|
||||
|
||||
struct token {
|
||||
enum token_type type;
|
||||
const char *keyword;
|
||||
int value;
|
||||
const struct token *next;
|
||||
};
|
||||
|
||||
static const struct token t_main[];
|
||||
static const struct token t_fib[];
|
||||
static const struct token t_show[];
|
||||
static const struct token t_show_iface[];
|
||||
static const struct token t_show_db[];
|
||||
static const struct token t_show_area[];
|
||||
static const struct token t_show_nbr[];
|
||||
static const struct token t_show_rib[];
|
||||
static const struct token t_show_fib[];
|
||||
|
||||
static const struct token t_main[] = {
|
||||
/* {KEYWORD, "reload", RELOAD, NULL}, */
|
||||
{KEYWORD, "fib", FIB, t_fib},
|
||||
{KEYWORD, "show", SHOW, t_show},
|
||||
{ENDTOKEN, "", NONE, NULL}
|
||||
};
|
||||
|
||||
static const struct token t_fib[] = {
|
||||
{ KEYWORD, "couple", FIB_COUPLE, NULL},
|
||||
{ KEYWORD, "decouple", FIB_DECOUPLE, NULL},
|
||||
{ ENDTOKEN, "", NONE, NULL}
|
||||
};
|
||||
|
||||
static const struct token t_show[] = {
|
||||
{NOTOKEN, "", NONE, NULL},
|
||||
{KEYWORD, "interfaces", SHOW_IFACE, t_show_iface},
|
||||
{KEYWORD, "neighbor", SHOW_NBR, t_show_nbr},
|
||||
{KEYWORD, "rib", SHOW_RIB, t_show_rib},
|
||||
{KEYWORD, "fib", SHOW_FIB, t_show_fib},
|
||||
{ENDTOKEN, "", NONE, NULL}
|
||||
};
|
||||
|
||||
static const struct token t_show_iface[] = {
|
||||
{NOTOKEN, "", NONE, NULL},
|
||||
{ENDTOKEN, "", NONE, NULL}
|
||||
};
|
||||
|
||||
static const struct token t_show_nbr[] = {
|
||||
{NOTOKEN, "", NONE, NULL},
|
||||
{ENDTOKEN, "", NONE, NULL}
|
||||
};
|
||||
|
||||
static const struct token t_show_rib[] = {
|
||||
{NOTOKEN, "", NONE, NULL},
|
||||
{ENDTOKEN, "", NONE, NULL}
|
||||
};
|
||||
|
||||
static const struct token t_show_fib[] = {
|
||||
{NOTOKEN, "", NONE, NULL},
|
||||
{KEYWORD, "interface", SHOW_FIB_IFACE, t_show_iface},
|
||||
{FLAG, "connected", F_CONNECTED, t_show_fib},
|
||||
{FLAG, "static", F_STATIC, t_show_fib},
|
||||
{FLAG, "rip", F_RIPD_INSERTED, t_show_fib},
|
||||
{ADDRESS, "", NONE, NULL},
|
||||
{ENDTOKEN, "", NONE, NULL}
|
||||
};
|
||||
|
||||
static struct parse_result res;
|
||||
|
||||
struct parse_result *
|
||||
parse(int argc, char *argv[])
|
||||
{
|
||||
const struct token *table = t_main;
|
||||
const struct token *match;
|
||||
|
||||
bzero(&res, sizeof(res));
|
||||
|
||||
while (argc > 0) {
|
||||
if ((match = match_token(argv[0], table)) == NULL) {
|
||||
fprintf(stderr, "valid commands/args:\n");
|
||||
show_valid_args(table);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (match->type == NOTOKEN || match->next == NULL)
|
||||
break;
|
||||
|
||||
table = match->next;
|
||||
}
|
||||
|
||||
if (argc > 0) {
|
||||
fprintf(stderr, "superfluous argument: %s\n", argv[0]);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (&res);
|
||||
}
|
||||
|
||||
const struct token *
|
||||
match_token(const char *word, const struct token table[])
|
||||
{
|
||||
u_int i, match;
|
||||
const struct token *t = NULL;
|
||||
|
||||
match = 0;
|
||||
|
||||
for (i = 0; table[i].type != ENDTOKEN; i++) {
|
||||
switch (table[i].type) {
|
||||
case NOTOKEN:
|
||||
if (word == NULL || strlen(word) == 0) {
|
||||
match++;
|
||||
t = &table[i];
|
||||
}
|
||||
break;
|
||||
case KEYWORD:
|
||||
if (word != NULL && strncmp(word, table[i].keyword,
|
||||
strlen(word)) == 0) {
|
||||
match++;
|
||||
t = &table[i];
|
||||
if (t->value)
|
||||
res.action = t->value;
|
||||
}
|
||||
break;
|
||||
case FLAG:
|
||||
if (word != NULL && strncmp(word, table[i].keyword,
|
||||
strlen(word)) == 0) {
|
||||
match++;
|
||||
t = &table[i];
|
||||
res.flags |= t->value;
|
||||
}
|
||||
break;
|
||||
case ADDRESS:
|
||||
if (parse_addr(word, &res.addr)) {
|
||||
match++;
|
||||
t = &table[i];
|
||||
if (t->value)
|
||||
res.action = t->value;
|
||||
}
|
||||
break;
|
||||
case PREFIX:
|
||||
if (parse_prefix(word, &res.addr, &res.prefixlen)) {
|
||||
match++;
|
||||
t = &table[i];
|
||||
if (t->value)
|
||||
res.action = t->value;
|
||||
}
|
||||
break;
|
||||
case IFNAME:
|
||||
if (!match && word != NULL && strlen(word) > 0) {
|
||||
if (strlcpy(res.ifname, word,
|
||||
sizeof(res.ifname)) >=
|
||||
sizeof(res.ifname))
|
||||
err(1, "interface name too long");
|
||||
match++;
|
||||
t = &table[i];
|
||||
if (t->value)
|
||||
res.action = t->value;
|
||||
}
|
||||
break;
|
||||
|
||||
case ENDTOKEN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (match != 1) {
|
||||
if (match > 1)
|
||||
fprintf(stderr, "ambiguous argument: %s\n", word);
|
||||
if (match < 1)
|
||||
fprintf(stderr, "unknown argument: %s\n", word);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (t);
|
||||
}
|
||||
|
||||
void
|
||||
show_valid_args(const struct token table[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; table[i].type != ENDTOKEN; i++) {
|
||||
switch (table[i].type) {
|
||||
case NOTOKEN:
|
||||
fprintf(stderr, " <cr>\n");
|
||||
break;
|
||||
case KEYWORD:
|
||||
case FLAG:
|
||||
fprintf(stderr, " %s\n", table[i].keyword);
|
||||
break;
|
||||
case ADDRESS:
|
||||
fprintf(stderr, " <address>\n");
|
||||
break;
|
||||
case PREFIX:
|
||||
fprintf(stderr, " <address>[/<len>]\n");
|
||||
break;
|
||||
case IFNAME:
|
||||
fprintf(stderr, " <interface>\n");
|
||||
case ENDTOKEN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
parse_addr(const char *word, struct in_addr *addr)
|
||||
{
|
||||
struct in_addr ina;
|
||||
|
||||
if (word == NULL)
|
||||
return (0);
|
||||
|
||||
bzero(addr, sizeof(struct in_addr));
|
||||
bzero(&ina, sizeof(ina));
|
||||
|
||||
if (inet_pton(AF_INET, word, &ina)) {
|
||||
addr->s_addr = ina.s_addr;
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
parse_prefix(const char *word, struct in_addr *addr, u_int8_t *prefixlen)
|
||||
{
|
||||
struct in_addr ina;
|
||||
int bits = 32;
|
||||
|
||||
if (word == NULL)
|
||||
return (0);
|
||||
|
||||
bzero(addr, sizeof(struct in_addr));
|
||||
bzero(&ina, sizeof(ina));
|
||||
|
||||
if (strrchr(word, '/') != NULL) {
|
||||
if ((bits = inet_net_pton(AF_INET, word,
|
||||
&ina, sizeof(ina))) == -1)
|
||||
return (0);
|
||||
addr->s_addr = ina.s_addr & htonl(prefixlen2mask(bits));
|
||||
*prefixlen = bits;
|
||||
return (1);
|
||||
} else {
|
||||
*prefixlen = 32;
|
||||
return (parse_addr(word, addr));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* XXX local copy from kroute.c, should go to shared file */
|
||||
in_addr_t
|
||||
prefixlen2mask(u_int8_t prefixlen)
|
||||
{
|
||||
if (prefixlen == 0)
|
||||
return (0);
|
||||
|
||||
return (0xffffffff << (32 - prefixlen));
|
||||
}
|
57
usr.sbin/ripctl/parser.h
Normal file
57
usr.sbin/ripctl/parser.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* $OpenBSD: parser.h,v 1.1 2006/10/18 16:15:25 norby Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it>
|
||||
* Copyright (c) 2004 Esben Norby <norby@openbsd.org>
|
||||
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _PARSER_H_
|
||||
#define _PARSER_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
enum actions {
|
||||
NONE,
|
||||
FIB,
|
||||
FIB_COUPLE,
|
||||
FIB_DECOUPLE,
|
||||
SHOW,
|
||||
SHOW_IFACE,
|
||||
SHOW_NBR,
|
||||
SHOW_RIB,
|
||||
SHOW_FIB,
|
||||
SHOW_FIB_IFACE,
|
||||
RELOAD
|
||||
};
|
||||
|
||||
struct parse_result {
|
||||
struct in_addr addr;
|
||||
char ifname[IF_NAMESIZE];
|
||||
int flags;
|
||||
enum actions action;
|
||||
u_int8_t prefixlen;
|
||||
};
|
||||
|
||||
struct parse_result *parse(int, char *[]);
|
||||
const struct token *match_token(const char *, const struct token []);
|
||||
void show_valid_args(const struct token []);
|
||||
int parse_addr(const char *, struct in_addr *);
|
||||
int parse_prefix(const char *, struct in_addr *,
|
||||
u_int8_t *);
|
||||
|
||||
#endif /* _PARSER_H_ */
|
96
usr.sbin/ripctl/ripctl.8
Normal file
96
usr.sbin/ripctl/ripctl.8
Normal file
@ -0,0 +1,96 @@
|
||||
.\" $OpenBSD: ripctl.8,v 1.1 2006/10/18 16:15:25 norby Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it>
|
||||
.\" Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\"
|
||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd June 27, 2006
|
||||
.Dt RIPCTL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ripctl
|
||||
.Nd control the Routing Information Protocol daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Ar command
|
||||
.Op Ar arguments ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
program controls the
|
||||
.Xr ripd 8
|
||||
daemon.
|
||||
.Pp
|
||||
The following commands are available:
|
||||
.Bl -tag -width Ds
|
||||
.It Cm fib couple
|
||||
Insert the learned routes into the Forward Information Base a.k.a. the kernel
|
||||
routing table.
|
||||
.It Cm fib decouple
|
||||
Remove the learned routes from the Forward Information Base a.k.a. the kernel
|
||||
routing table.
|
||||
Decoupling the FIB from an RIP router may create routing loops and could cause
|
||||
major routing issues.
|
||||
.It Cm show fib Op Ar destination | filter
|
||||
Show the Forwarding Information Base.
|
||||
.Ar destination
|
||||
can be specified to show the route matching a destination IP address.
|
||||
.Ar filter
|
||||
can be any of the following:
|
||||
.Pp
|
||||
.Bl -tag -width "interfaceXXinterfaceXX" -compact
|
||||
.It Cm connected
|
||||
Show only connected routes.
|
||||
.It Cm interface Op Ar interface
|
||||
Show only interfaces or the specified
|
||||
.Ar interface .
|
||||
.It Cm rip
|
||||
Show only RIP routes.
|
||||
.It Cm static
|
||||
Show only static routes.
|
||||
.El
|
||||
.Pp
|
||||
.Cm connected ,
|
||||
.Cm rip ,
|
||||
and
|
||||
.Cm static
|
||||
may be specified together.
|
||||
.It Cm show interfaces Op Ar interface
|
||||
Show details for all interfaces or the specified
|
||||
.Ar interface .
|
||||
.It Cm show neighbor Op Cm detail
|
||||
Show neighbors.
|
||||
.Cm detail
|
||||
can be specified for additional detail.
|
||||
.It Cm show rib Op Cm detail
|
||||
Show the Routing Information Base.
|
||||
.Cm detail
|
||||
can be specified for additional detail.
|
||||
.It Cm show summary
|
||||
Show summary information.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width "/var/run/ripd.sockXX" -compact
|
||||
.It /var/run/ripd.sock
|
||||
Unix-domain socket used for communication with
|
||||
.Xr ripd 8 .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr ripd.conf 5 ,
|
||||
.Xr ripd 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
program first appeared in
|
||||
.Ox 4.0 .
|
539
usr.sbin/ripctl/ripctl.c
Normal file
539
usr.sbin/ripctl/ripctl.c
Normal file
@ -0,0 +1,539 @@
|
||||
/* $OpenBSD: ripctl.c,v 1.1 2006/10/18 16:15:25 norby Exp $
|
||||
*
|
||||
* Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it>
|
||||
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
|
||||
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
|
||||
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_types.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "rip.h"
|
||||
#include "ripd.h"
|
||||
#include "ripe.h"
|
||||
#include "parser.h"
|
||||
|
||||
__dead void usage(void);
|
||||
const char *fmt_timeframe_core(time_t);
|
||||
const char *get_linkstate(int, int);
|
||||
int show_interface_msg(struct imsg *);
|
||||
int get_ifms_type(int);
|
||||
int show_rib_msg(struct imsg *);
|
||||
int show_nbr_msg(struct imsg *);
|
||||
void show_fib_head(void);
|
||||
int show_fib_msg(struct imsg *);
|
||||
void show_interface_head(void);
|
||||
int show_fib_interface_msg(struct imsg *);
|
||||
const char *get_media_descr(int);
|
||||
void print_baudrate(u_long);
|
||||
|
||||
struct imsgbuf *ibuf;
|
||||
|
||||
__dead void
|
||||
usage(void)
|
||||
{
|
||||
extern char *__progname;
|
||||
|
||||
fprintf(stderr, "usage: %s <command> [arg [...]]\n", __progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* dummy function to allow ripctl to run without libevent */
|
||||
void
|
||||
imsg_event_add(struct imsgbuf *i)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct sockaddr_un sun;
|
||||
struct parse_result *res;
|
||||
struct imsg imsg;
|
||||
unsigned int ifidx = 0;
|
||||
int ctl_sock;
|
||||
int done = 0;
|
||||
int n;
|
||||
|
||||
/* parse options */
|
||||
if ((res = parse(argc - 1, argv + 1)) == NULL)
|
||||
exit(1);
|
||||
|
||||
/* connect to ripd control socket */
|
||||
if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||
err(1, "socket");
|
||||
|
||||
bzero(&sun, sizeof(sun));
|
||||
sun.sun_family = AF_UNIX;
|
||||
strlcpy(sun.sun_path, RIPD_SOCKET, sizeof(sun.sun_path));
|
||||
if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
|
||||
err(1, "connect: %s", RIPD_SOCKET);
|
||||
|
||||
if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
|
||||
err(1, NULL);
|
||||
imsg_init(ibuf, ctl_sock, NULL);
|
||||
done = 0;
|
||||
|
||||
/* process user request */
|
||||
switch (res->action) {
|
||||
case NONE:
|
||||
usage();
|
||||
/* not reached */
|
||||
case SHOW:
|
||||
case SHOW_IFACE:
|
||||
printf("%-11s %-18s %-10s %-10s %-8s\n",
|
||||
"Interface", "Address", "State", "Linkstate",
|
||||
"Uptime");
|
||||
if (*res->ifname) {
|
||||
ifidx = if_nametoindex(res->ifname);
|
||||
if (ifidx == 0)
|
||||
errx(1, "no such interface %s", res->ifname);
|
||||
}
|
||||
imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0,
|
||||
&ifidx, sizeof(ifidx));
|
||||
break;
|
||||
case SHOW_NBR:
|
||||
printf("%-15s %-15s %-15s %-9s %-10s\n", "ID",
|
||||
"State", "Address", "Iface", "Uptime");
|
||||
imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, NULL, 0);
|
||||
break;
|
||||
case SHOW_RIB:
|
||||
printf("%-20s %-17s %-7s\n", "Destination",
|
||||
"Nexthop", "Cost");
|
||||
imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, NULL, 0);
|
||||
break;
|
||||
case SHOW_FIB:
|
||||
if (!res->addr.s_addr)
|
||||
imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0,
|
||||
&res->flags, sizeof(res->flags));
|
||||
else
|
||||
imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0,
|
||||
&res->addr, sizeof(res->addr));
|
||||
show_fib_head();
|
||||
break;
|
||||
case SHOW_FIB_IFACE:
|
||||
if (*res->ifname)
|
||||
imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0,
|
||||
res->ifname, sizeof(res->ifname));
|
||||
else
|
||||
imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, NULL, 0);
|
||||
show_interface_head();
|
||||
break;
|
||||
case FIB:
|
||||
errx(1, "fib couple|decouple");
|
||||
break;
|
||||
case FIB_COUPLE:
|
||||
imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, NULL, 0);
|
||||
printf("couple request sent.\n");
|
||||
done = 1;
|
||||
break;
|
||||
case FIB_DECOUPLE:
|
||||
imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, NULL, 0);
|
||||
printf("decouple request sent.\n");
|
||||
done = 1;
|
||||
break;
|
||||
case RELOAD:
|
||||
imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, NULL, 0);
|
||||
printf("reload request sent.\n");
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
while (ibuf->w.queued)
|
||||
if (msgbuf_write(&ibuf->w) < 0)
|
||||
err(1, "write error");
|
||||
|
||||
while (!done) {
|
||||
if ((n = imsg_read(ibuf)) == -1)
|
||||
errx(1, "imsg_read error");
|
||||
if (n == 0)
|
||||
errx(1, "pipe closed");
|
||||
|
||||
while (!done) {
|
||||
if ((n = imsg_get(ibuf, &imsg)) == -1)
|
||||
errx(1, "imsg_get error");
|
||||
if (n == 0)
|
||||
break;
|
||||
switch (res->action) {
|
||||
case SHOW:
|
||||
case SHOW_IFACE:
|
||||
done = show_interface_msg(&imsg);
|
||||
break;
|
||||
case SHOW_NBR:
|
||||
done = show_nbr_msg(&imsg);
|
||||
break;
|
||||
case SHOW_RIB:
|
||||
done = show_rib_msg(&imsg);
|
||||
break;
|
||||
case SHOW_FIB:
|
||||
done = show_fib_msg(&imsg);
|
||||
break;
|
||||
case SHOW_FIB_IFACE:
|
||||
done = show_fib_interface_msg(&imsg);
|
||||
break;
|
||||
case NONE:
|
||||
case FIB:
|
||||
case FIB_COUPLE:
|
||||
case FIB_DECOUPLE:
|
||||
case RELOAD:
|
||||
break;
|
||||
}
|
||||
imsg_free(&imsg);
|
||||
}
|
||||
}
|
||||
close(ctl_sock);
|
||||
free(ibuf);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
get_ifms_type(int mediatype)
|
||||
{
|
||||
switch (mediatype) {
|
||||
case IFT_ETHER:
|
||||
return (IFM_ETHER);
|
||||
break;
|
||||
case IFT_FDDI:
|
||||
return (IFM_FDDI);
|
||||
break;
|
||||
case IFT_ISO88025:
|
||||
return (IFM_TOKEN);
|
||||
break;
|
||||
case IFT_CARP:
|
||||
return (IFM_CARP);
|
||||
break;
|
||||
default:
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define TF_BUFS 8
|
||||
#define TF_LEN 9
|
||||
|
||||
const char *
|
||||
fmt_timeframe_core(time_t t)
|
||||
{
|
||||
char *buf;
|
||||
static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */
|
||||
static int idx = 0;
|
||||
unsigned sec, min, hrs, day, week;
|
||||
|
||||
if (t == 0)
|
||||
return ("Stopped");
|
||||
|
||||
buf = tfbuf[idx++];
|
||||
if (idx == TF_BUFS)
|
||||
idx = 0;
|
||||
|
||||
week = t;
|
||||
|
||||
sec = week % 60;
|
||||
week /= 60;
|
||||
min = week % 60;
|
||||
week /= 60;
|
||||
hrs = week % 24;
|
||||
week /= 24;
|
||||
day = week % 7;
|
||||
week /= 7;
|
||||
|
||||
if (week > 0)
|
||||
snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs);
|
||||
else if (day > 0)
|
||||
snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
|
||||
else
|
||||
snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
|
||||
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/* prototype defined in ripd.h and shared with the kroute.c version */
|
||||
u_int8_t
|
||||
mask2prefixlen(in_addr_t ina)
|
||||
{
|
||||
if (ina == 0)
|
||||
return (0);
|
||||
else
|
||||
return (33 - ffs(ntohl(ina)));
|
||||
}
|
||||
|
||||
int
|
||||
show_interface_msg(struct imsg *imsg)
|
||||
{
|
||||
struct ctl_iface *iface;
|
||||
char *netid;
|
||||
|
||||
switch (imsg->hdr.type) {
|
||||
case IMSG_CTL_SHOW_IFACE:
|
||||
iface = imsg->data;
|
||||
|
||||
if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr),
|
||||
mask2prefixlen(iface->mask.s_addr)) == -1)
|
||||
err(1, NULL);
|
||||
printf("%-11s %-18s %-10s %-10s %-8s\n",
|
||||
iface->name, netid, if_state_name(iface->state),
|
||||
get_linkstate(get_ifms_type(iface->mediatype),
|
||||
iface->linkstate), iface->uptime == 0 ? "00:00:00" :
|
||||
fmt_timeframe_core(iface->uptime));
|
||||
free(netid);
|
||||
break;
|
||||
case IMSG_CTL_END:
|
||||
printf("\n");
|
||||
return (1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
show_rib_msg(struct imsg *imsg)
|
||||
{
|
||||
struct ctl_rt *rt;
|
||||
char *dstnet;
|
||||
|
||||
switch (imsg->hdr.type) {
|
||||
case IMSG_CTL_SHOW_RIB:
|
||||
rt = imsg->data;
|
||||
if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix),
|
||||
mask2prefixlen(rt->netmask.s_addr)) == -1)
|
||||
err(1, NULL);
|
||||
|
||||
printf("%-20s %-17s %-7d\n", dstnet,
|
||||
inet_ntoa(rt->nexthop),
|
||||
rt->metric);
|
||||
free(dstnet);
|
||||
|
||||
break;
|
||||
case IMSG_CTL_END:
|
||||
printf("\n");
|
||||
return (1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
show_nbr_msg(struct imsg *imsg)
|
||||
{
|
||||
struct ctl_nbr *nbr;
|
||||
char *state;
|
||||
|
||||
switch (imsg->hdr.type) {
|
||||
case IMSG_CTL_SHOW_NBR:
|
||||
nbr = imsg->data;
|
||||
if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
|
||||
if_state_name(nbr->iface_state)) == -1)
|
||||
err(1, NULL);
|
||||
printf("%-15s %-16s", inet_ntoa(nbr->id),
|
||||
state);
|
||||
printf("%-15s %-10s", inet_ntoa(nbr->addr), nbr->name);
|
||||
printf("%-15s\n", nbr->uptime == 0 ? "-" :
|
||||
fmt_timeframe_core(nbr->uptime));
|
||||
free(state);
|
||||
break;
|
||||
case IMSG_CTL_END:
|
||||
printf("\n");
|
||||
return (1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
show_fib_head(void)
|
||||
{
|
||||
printf("flags: * = valid, R = RIP, C = Connected, S = Static\n");
|
||||
printf("%-6s %-20s %-17s\n", "Flags", "Destination", "Nexthop");
|
||||
}
|
||||
|
||||
int
|
||||
show_fib_msg(struct imsg *imsg)
|
||||
{
|
||||
struct kroute *k;
|
||||
char *p;
|
||||
|
||||
switch (imsg->hdr.type) {
|
||||
case IMSG_CTL_KROUTE:
|
||||
if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
|
||||
errx(1, "wrong imsg len");
|
||||
k = imsg->data;
|
||||
|
||||
if (k->flags & F_DOWN)
|
||||
printf(" ");
|
||||
else
|
||||
printf("*");
|
||||
|
||||
if (!(k->flags & F_KERNEL))
|
||||
printf("R");
|
||||
else if (k->flags & F_CONNECTED)
|
||||
printf("C");
|
||||
else if (k->flags & F_STATIC)
|
||||
printf("S");
|
||||
else
|
||||
printf(" ");
|
||||
|
||||
printf(" ");
|
||||
if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix),
|
||||
mask2prefixlen(k->netmask.s_addr)) == -1)
|
||||
err(1, NULL);
|
||||
printf("%-20s ", p);
|
||||
free(p);
|
||||
|
||||
if (k->nexthop.s_addr)
|
||||
printf("%s", inet_ntoa(k->nexthop));
|
||||
else if (k->flags & F_CONNECTED)
|
||||
printf("link#%u", k->ifindex);
|
||||
printf("\n");
|
||||
|
||||
break;
|
||||
case IMSG_CTL_END:
|
||||
printf("\n");
|
||||
return (1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
show_interface_head(void)
|
||||
{
|
||||
printf("%-15s%-15s%s\n", "Interface", "Flags",
|
||||
"Link state");
|
||||
}
|
||||
|
||||
int
|
||||
show_fib_interface_msg(struct imsg *imsg)
|
||||
{
|
||||
struct kif *k;
|
||||
int ifms_type;
|
||||
|
||||
switch (imsg->hdr.type) {
|
||||
case IMSG_CTL_IFINFO:
|
||||
k = imsg->data;
|
||||
printf("%-15s", k->ifname);
|
||||
printf("%-15s", k->flags & IFF_UP ? "UP" : "");
|
||||
switch (k->media_type) {
|
||||
case IFT_ETHER:
|
||||
ifms_type = IFM_ETHER;
|
||||
break;
|
||||
case IFT_FDDI:
|
||||
ifms_type = IFM_FDDI;
|
||||
break;
|
||||
case IFT_ISO88025:
|
||||
ifms_type = IFM_TOKEN;
|
||||
break;
|
||||
case IFT_CARP:
|
||||
ifms_type = IFM_CARP;
|
||||
break;
|
||||
default:
|
||||
ifms_type = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ifms_type)
|
||||
printf("%s, %s", get_media_descr(ifms_type),
|
||||
get_linkstate(ifms_type, k->link_state));
|
||||
else if (k->link_state == LINK_STATE_UNKNOWN)
|
||||
printf("unknown");
|
||||
else
|
||||
printf("link state %u", k->link_state);
|
||||
|
||||
if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) {
|
||||
printf(", ");
|
||||
print_baudrate(k->baudrate);
|
||||
}
|
||||
printf("\n");
|
||||
break;
|
||||
case IMSG_CTL_END:
|
||||
printf("\n");
|
||||
return (1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
const int ifm_status_valid_list[] = IFM_STATUS_VALID_LIST;
|
||||
const struct ifmedia_status_description
|
||||
ifm_status_descriptions[] = IFM_STATUS_DESCRIPTIONS;
|
||||
const struct ifmedia_description
|
||||
ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
|
||||
|
||||
const char *
|
||||
get_media_descr(int media_type)
|
||||
{
|
||||
const struct ifmedia_description *p;
|
||||
|
||||
for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
|
||||
if (media_type == p->ifmt_word)
|
||||
return (p->ifmt_string);
|
||||
|
||||
return ("unknown");
|
||||
}
|
||||
|
||||
const char *
|
||||
get_linkstate(int media_type, int link_state)
|
||||
{
|
||||
const struct ifmedia_status_description *p;
|
||||
int i;
|
||||
|
||||
if (link_state == LINK_STATE_UNKNOWN)
|
||||
return ("unknown");
|
||||
|
||||
for (i = 0; ifm_status_valid_list[i] != 0; i++)
|
||||
for (p = ifm_status_descriptions; p->ifms_valid != 0; p++) {
|
||||
if (p->ifms_type != media_type ||
|
||||
p->ifms_valid != ifm_status_valid_list[i])
|
||||
continue;
|
||||
return (p->ifms_string[link_state == LINK_STATE_UP]);
|
||||
}
|
||||
|
||||
return ("unknown link state");
|
||||
}
|
||||
|
||||
void
|
||||
print_baudrate(u_long baudrate)
|
||||
{
|
||||
if (baudrate > IF_Gbps(1))
|
||||
printf("%lu GBit/s", baudrate / IF_Gbps(1));
|
||||
else if (baudrate > IF_Mbps(1))
|
||||
printf("%lu MBit/s", baudrate / IF_Mbps(1));
|
||||
else if (baudrate > IF_Kbps(1))
|
||||
printf("%lu KBit/s", baudrate / IF_Kbps(1));
|
||||
else
|
||||
printf("%lu Bit/s", baudrate);
|
||||
}
|
Loading…
Reference in New Issue
Block a user