Changeset View
Changeset View
Standalone View
Standalone View
sbin/route/route.c
Show First 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | |||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <sysexits.h> | #include <sysexits.h> | ||||
#include <time.h> | #include <time.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <ifaddrs.h> | #include <ifaddrs.h> | ||||
#include <libroute.h> | |||||
struct fibl { | struct fibl { | ||||
TAILQ_ENTRY(fibl) fl_next; | TAILQ_ENTRY(fibl) fl_next; | ||||
int fl_num; | int fl_num; | ||||
int fl_error; | int fl_error; | ||||
int fl_errno; | int fl_errno; | ||||
}; | }; | ||||
Show All 14 Lines | |||||
static int locking, lockrest, debugonly; | static int locking, lockrest, debugonly; | ||||
static struct rt_metrics rt_metrics; | static struct rt_metrics rt_metrics; | ||||
static u_long rtm_inits; | static u_long rtm_inits; | ||||
static uid_t uid; | static uid_t uid; | ||||
static int defaultfib; | static int defaultfib; | ||||
static int numfibs; | static int numfibs; | ||||
static char domain[MAXHOSTNAMELEN + 1]; | static char domain[MAXHOSTNAMELEN + 1]; | ||||
static bool domain_initialized; | static bool domain_initialized; | ||||
static int rtm_seq; | |||||
static char rt_line[NI_MAXHOST]; | static char rt_line[NI_MAXHOST]; | ||||
static char net_line[MAXHOSTNAMELEN + 1]; | static char net_line[MAXHOSTNAMELEN + 1]; | ||||
static struct { | |||||
struct rt_msghdr m_rtm; | |||||
char m_space[512]; | |||||
} m_rtmsg; | |||||
static TAILQ_HEAD(fibl_head_t, fibl) fibl_head; | static TAILQ_HEAD(fibl_head_t, fibl) fibl_head; | ||||
static void printb(int, const char *); | static void printb(int, const char *); | ||||
static void flushroutes(int argc, char *argv[]); | static void flushroutes(int argc, char *argv[]); | ||||
static int flushroutes_fib(int); | static int flushroutes_fib(int); | ||||
static int getaddr(int, char *, struct hostent **, int); | static int getaddr(int, char *, struct hostent **, int); | ||||
static int keyword(const char *); | static int keyword(const char *); | ||||
#ifdef INET | #ifdef INET | ||||
static void inet_makenetandmask(u_long, struct sockaddr_in *, | static void inet_makenetandmask(u_long, struct sockaddr_in *, | ||||
struct sockaddr_in *, u_long); | struct sockaddr_in *, u_long); | ||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
static int inet6_makenetandmask(struct sockaddr_in6 *, const char *); | static int inet6_makenetandmask(struct sockaddr_in6 *, const char *); | ||||
#endif | #endif | ||||
static void interfaces(void); | static void interfaces(void); | ||||
static void monitor(int, char*[]); | static void monitor(int, char*[]); | ||||
static const char *netname(struct sockaddr *); | static const char *netname(struct sockaddr *); | ||||
static void newroute(int, char **); | static void newroute(int, char **); | ||||
static int newroute_fib(int, char *, int); | |||||
static void pmsg_addrs(char *, int, size_t); | static void pmsg_addrs(char *, int, size_t); | ||||
static void pmsg_common(struct rt_msghdr *, size_t); | static void pmsg_common(struct rt_msghdr *, size_t); | ||||
static int prefixlen(const char *); | static int prefixlen(const char *); | ||||
static void print_getmsg(struct rt_msghdr *, int, int); | static void print_getmsg(struct rt_msghdr *, int, int); | ||||
static void print_rtmsg(struct rt_msghdr *, size_t); | static void print_rtmsg(struct rt_msghdr *, size_t); | ||||
static const char *routename(struct sockaddr *); | static const char *routename(struct sockaddr *); | ||||
static int rtmsg(int, int, int); | |||||
static void set_metric(char *, int); | static void set_metric(char *, int); | ||||
static int set_sofib(int); | static int set_sofib(int); | ||||
static void sockaddr(char *, struct sockaddr *, size_t); | static void sockaddr(char *, struct sockaddr *, size_t); | ||||
static void sodump(struct sockaddr *, const char *); | static void sodump(struct sockaddr *, const char *); | ||||
static int fiboptlist_csv(const char *, struct fibl_head_t *); | static int fiboptlist_csv(const char *, struct fibl_head_t *); | ||||
static int fiboptlist_range(const char *, struct fibl_head_t *); | static int fiboptlist_range(const char *, struct fibl_head_t *); | ||||
static void usage(const char *) __dead2; | static void usage(const char *) __dead2; | ||||
▲ Show 20 Lines • Show All 636 Lines • ▼ Show 20 Lines | |||||
#define F_FORCENET 0x02 | #define F_FORCENET 0x02 | ||||
#define F_FORCEHOST 0x04 | #define F_FORCEHOST 0x04 | ||||
#define F_PROXY 0x08 | #define F_PROXY 0x08 | ||||
#define F_INTERFACE 0x10 | #define F_INTERFACE 0x10 | ||||
static void | static void | ||||
newroute(int argc, char **argv) | newroute(int argc, char **argv) | ||||
{ | { | ||||
rt_handle *h; | |||||
struct rt_msg_t rtmsg_local; | |||||
int operation; | |||||
struct sigaction sa; | struct sigaction sa; | ||||
thj: I think there is an extra newline here | |||||
struct hostent *hp; | struct hostent *hp; | ||||
struct fibl *fl; | struct fibl *fl; | ||||
char *cmd; | char *cmd; | ||||
const char *dest, *gateway, *errmsg; | const char *dest, *gateway, *errmsg; | ||||
int key, error, flags, nrflags, fibnum; | int key, error, flags, nrflags, fibnum; | ||||
if (uid != 0 && !debugonly && !tflag) | if (uid != 0 && !debugonly && !tflag) | ||||
errx(EX_NOPERM, "must be root to alter routing table"); | errx(EX_NOPERM, "must be root to alter routing table"); | ||||
▲ Show 20 Lines • Show All 202 Lines • ▼ Show 20 Lines | #endif | ||||
if (gateway == NULL) | if (gateway == NULL) | ||||
gateway = ""; | gateway = ""; | ||||
if (TAILQ_EMPTY(&fibl_head)) { | if (TAILQ_EMPTY(&fibl_head)) { | ||||
error = fiboptlist_csv("default", &fibl_head); | error = fiboptlist_csv("default", &fibl_head); | ||||
if (error) | if (error) | ||||
errx(EX_OSERR, "fiboptlist_csv failed."); | errx(EX_OSERR, "fiboptlist_csv failed."); | ||||
} | } | ||||
if (cmd[0] == 'a') | |||||
operation = RTM_ADD; | |||||
else if (cmd[0] == 'c') | |||||
operation = RTM_CHANGE; | |||||
else if (cmd[0] == 'g' || cmd[0] == 's') | |||||
operation = RTM_GET; | |||||
else | |||||
operation = RTM_DELETE; | |||||
error = 0; | error = 0; | ||||
h = libroute_open(defaultfib); | |||||
if(h == NULL){ | |||||
errx(EX_OSERR, "Failed to open libroute handle"); | |||||
} | |||||
TAILQ_FOREACH(fl, &fibl_head, fl_next) { | TAILQ_FOREACH(fl, &fibl_head, fl_next) { | ||||
fl->fl_error = newroute_fib(fl->fl_num, cmd, flags); | libroute_setfib(h, fl->fl_num); | ||||
fl->fl_error = libroute_modify(h, &rtmsg_local, | |||||
Done Inline Actionsthis line is very long, but it can be sensibly broken up. thj: this line is very long, but it can be sensibly broken up. | |||||
(struct sockaddr *)&so[RTAX_DST], | |||||
(struct sockaddr *)&so[RTAX_GATEWAY], operation, flags); | |||||
if (fl->fl_error) | if (fl->fl_error) | ||||
fl->fl_errno = errno; | fl->fl_errno = errno; | ||||
error += fl->fl_error; | error += fl->fl_error; | ||||
if(operation == RTM_GET && fl->fl_error == 0){ | |||||
print_getmsg(&rtmsg_local.m_rtm, rtmsg_local.m_rtm.rtm_msglen, | |||||
Done Inline ActionsThis might be a little long too, but I can't tell from phabricator. thj: This might be a little long too, but I can't tell from phabricator. | |||||
fl->fl_num); | |||||
} | } | ||||
} | |||||
libroute_close(h); | |||||
if (*cmd == 'g' || *cmd == 's') | if (*cmd == 'g' || *cmd == 's') | ||||
exit(error); | exit(error); | ||||
error = 0; | error = 0; | ||||
if (!qflag) { | if (!qflag) { | ||||
fibnum = 0; | fibnum = 0; | ||||
TAILQ_FOREACH(fl, &fibl_head, fl_next) { | TAILQ_FOREACH(fl, &fibl_head, fl_next) { | ||||
if (fl->fl_error == 0) | if (fl->fl_error == 0) | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | if (fl->fl_error != 0) { | ||||
} | } | ||||
printf(": %s\n", errmsg); | printf(": %s\n", errmsg); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
exit(error); | exit(error); | ||||
} | } | ||||
static int | |||||
newroute_fib(int fib, char *cmd, int flags) | |||||
{ | |||||
int error; | |||||
error = set_sofib(fib); | |||||
if (error) { | |||||
warn("fib number %d is ignored", fib); | |||||
return (error); | |||||
} | |||||
error = rtmsg(*cmd, flags, fib); | |||||
return (error); | |||||
} | |||||
#ifdef INET | #ifdef INET | ||||
static void | static void | ||||
inet_makenetandmask(u_long net, struct sockaddr_in *sin, | inet_makenetandmask(u_long net, struct sockaddr_in *sin, | ||||
struct sockaddr_in *sin_mask, u_long bits) | struct sockaddr_in *sin_mask, u_long bits) | ||||
{ | { | ||||
u_long mask = 0; | u_long mask = 0; | ||||
rtm_addrs |= RTA_NETMASK; | rtm_addrs |= RTA_NETMASK; | ||||
▲ Show 20 Lines • Show All 365 Lines • ▼ Show 20 Lines | monitor(int argc, char *argv[]) | ||||
} | } | ||||
for (;;) { | for (;;) { | ||||
time_t now; | time_t now; | ||||
n = read(s, msg, 2048); | n = read(s, msg, 2048); | ||||
now = time(NULL); | now = time(NULL); | ||||
(void)printf("\ngot message of size %d on %s", n, ctime(&now)); | (void)printf("\ngot message of size %d on %s", n, ctime(&now)); | ||||
print_rtmsg((struct rt_msghdr *)(void *)msg, n); | print_rtmsg((struct rt_msghdr *)(void *)msg, n); | ||||
} | } | ||||
} | |||||
static int | |||||
rtmsg(int cmd, int flags, int fib) | |||||
{ | |||||
int rlen; | |||||
char *cp = m_rtmsg.m_space; | |||||
int l; | |||||
#define NEXTADDR(w, u) \ | |||||
if (rtm_addrs & (w)) { \ | |||||
l = SA_SIZE(&(u)); \ | |||||
memmove(cp, (char *)&(u), l); \ | |||||
cp += l; \ | |||||
if (verbose) \ | |||||
sodump((struct sockaddr *)&(u), #w); \ | |||||
} | |||||
errno = 0; | |||||
memset(&m_rtmsg, 0, sizeof(m_rtmsg)); | |||||
if (cmd == 'a') | |||||
cmd = RTM_ADD; | |||||
else if (cmd == 'c') | |||||
cmd = RTM_CHANGE; | |||||
else if (cmd == 'g' || cmd == 's') { | |||||
cmd = RTM_GET; | |||||
if (so[RTAX_IFP].ss_family == 0) { | |||||
so[RTAX_IFP].ss_family = AF_LINK; | |||||
so[RTAX_IFP].ss_len = sizeof(struct sockaddr_dl); | |||||
rtm_addrs |= RTA_IFP; | |||||
} | |||||
} else { | |||||
cmd = RTM_DELETE; | |||||
flags |= RTF_PINNED; | |||||
} | |||||
#define rtm m_rtmsg.m_rtm | |||||
rtm.rtm_type = cmd; | |||||
rtm.rtm_flags = flags; | |||||
rtm.rtm_version = RTM_VERSION; | |||||
rtm.rtm_seq = ++rtm_seq; | |||||
rtm.rtm_addrs = rtm_addrs; | |||||
rtm.rtm_rmx = rt_metrics; | |||||
rtm.rtm_inits = rtm_inits; | |||||
NEXTADDR(RTA_DST, so[RTAX_DST]); | |||||
NEXTADDR(RTA_GATEWAY, so[RTAX_GATEWAY]); | |||||
NEXTADDR(RTA_NETMASK, so[RTAX_NETMASK]); | |||||
NEXTADDR(RTA_GENMASK, so[RTAX_GENMASK]); | |||||
NEXTADDR(RTA_IFP, so[RTAX_IFP]); | |||||
NEXTADDR(RTA_IFA, so[RTAX_IFA]); | |||||
rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; | |||||
if (verbose) | |||||
print_rtmsg(&rtm, l); | |||||
if (debugonly) | |||||
return (0); | |||||
if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { | |||||
switch (errno) { | |||||
case EPERM: | |||||
err(1, "writing to routing socket"); | |||||
break; | |||||
case ESRCH: | |||||
warnx("route has not been found"); | |||||
break; | |||||
case EEXIST: | |||||
/* Handled by newroute() */ | |||||
break; | |||||
default: | |||||
warn("writing to routing socket"); | |||||
} | |||||
return (-1); | |||||
} | |||||
if (cmd == RTM_GET) { | |||||
stop_read = 0; | |||||
alarm(READ_TIMEOUT); | |||||
do { | |||||
l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); | |||||
} while (l > 0 && stop_read == 0 && | |||||
(rtm.rtm_type != RTM_GET || rtm.rtm_seq != rtm_seq || | |||||
rtm.rtm_pid != pid)); | |||||
if (stop_read != 0) { | |||||
warnx("read from routing socket timed out"); | |||||
return (-1); | |||||
} else | |||||
alarm(0); | |||||
if (l < 0) | |||||
warn("read from routing socket"); | |||||
else | |||||
print_getmsg(&rtm, l, fib); | |||||
} | |||||
#undef rtm | |||||
return (0); | |||||
} | } | ||||
static const char *const msgtypes[] = { | static const char *const msgtypes[] = { | ||||
"", | "", | ||||
"RTM_ADD: Add Route", | "RTM_ADD: Add Route", | ||||
"RTM_DELETE: Delete Route", | "RTM_DELETE: Delete Route", | ||||
"RTM_CHANGE: Change Metrics or flags", | "RTM_CHANGE: Change Metrics or flags", | ||||
"RTM_GET: Report Metrics", | "RTM_GET: Report Metrics", | ||||
▲ Show 20 Lines • Show All 374 Lines • Show Last 20 Lines |
I think there is an extra newline here