1
0
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:
norby 2006-10-18 16:15:25 +00:00
parent ddeeec1440
commit 8eeeb81e66
5 changed files with 1011 additions and 0 deletions

15
usr.sbin/ripctl/Makefile Normal file
View 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
View 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
View 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
View 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
View 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);
}