Changeset View
Changeset View
Standalone View
Standalone View
sbin/route/route.c
Show First 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | static struct { | ||||
char m_space[512]; | char m_space[512]; | ||||
} m_rtmsg; | } 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 *, int); | ||||
static int keyword(const char *); | static int keyword(const char *); | ||||
#ifdef INET | #ifdef INET | ||||
static void inet_makemask(struct sockaddr_in *, u_long); | static void inet_makemask(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); | ||||
▲ Show 20 Lines • Show All 656 Lines • ▼ Show 20 Lines | |||||
#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) | ||||
{ | { | ||||
struct sigaction sa; | struct sigaction sa; | ||||
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"); | ||||
dest = NULL; | dest = NULL; | ||||
gateway = NULL; | gateway = NULL; | ||||
flags = RTF_STATIC; | flags = RTF_STATIC; | ||||
nrflags = 0; | nrflags = 0; | ||||
hp = NULL; | |||||
TAILQ_INIT(&fibl_head); | TAILQ_INIT(&fibl_head); | ||||
sigemptyset(&sa.sa_mask); | sigemptyset(&sa.sa_mask); | ||||
sa.sa_flags = 0; | sa.sa_flags = 0; | ||||
sa.sa_handler = stopit; | sa.sa_handler = stopit; | ||||
if (sigaction(SIGALRM, &sa, 0) == -1) | if (sigaction(SIGALRM, &sa, 0) == -1) | ||||
warn("sigaction SIGALRM"); | warn("sigaction SIGALRM"); | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | #endif | ||||
error = fiboptlist_csv(*++argv, &fibl_head); | error = fiboptlist_csv(*++argv, &fibl_head); | ||||
if (error) | if (error) | ||||
errx(EX_USAGE, | errx(EX_USAGE, | ||||
"invalid fib number: %s", *argv); | "invalid fib number: %s", *argv); | ||||
break; | break; | ||||
case K_IFA: | case K_IFA: | ||||
if (!--argc) | if (!--argc) | ||||
usage(NULL); | usage(NULL); | ||||
getaddr(RTAX_IFA, *++argv, NULL, nrflags); | getaddr(RTAX_IFA, *++argv, nrflags); | ||||
break; | break; | ||||
case K_IFP: | case K_IFP: | ||||
if (!--argc) | if (!--argc) | ||||
usage(NULL); | usage(NULL); | ||||
getaddr(RTAX_IFP, *++argv, NULL, nrflags); | getaddr(RTAX_IFP, *++argv, nrflags); | ||||
break; | break; | ||||
case K_GENMASK: | case K_GENMASK: | ||||
if (!--argc) | if (!--argc) | ||||
usage(NULL); | usage(NULL); | ||||
getaddr(RTAX_GENMASK, *++argv, NULL, nrflags); | getaddr(RTAX_GENMASK, *++argv, nrflags); | ||||
break; | break; | ||||
case K_GATEWAY: | case K_GATEWAY: | ||||
if (!--argc) | if (!--argc) | ||||
usage(NULL); | usage(NULL); | ||||
getaddr(RTAX_GATEWAY, *++argv, NULL, nrflags); | getaddr(RTAX_GATEWAY, *++argv, nrflags); | ||||
gateway = *argv; | gateway = *argv; | ||||
break; | break; | ||||
case K_DST: | case K_DST: | ||||
if (!--argc) | if (!--argc) | ||||
usage(NULL); | usage(NULL); | ||||
if (getaddr(RTAX_DST, *++argv, &hp, nrflags)) | if (getaddr(RTAX_DST, *++argv, nrflags)) | ||||
nrflags |= F_ISHOST; | nrflags |= F_ISHOST; | ||||
dest = *argv; | dest = *argv; | ||||
break; | break; | ||||
case K_NETMASK: | case K_NETMASK: | ||||
if (!--argc) | if (!--argc) | ||||
usage(NULL); | usage(NULL); | ||||
getaddr(RTAX_NETMASK, *++argv, NULL, nrflags); | getaddr(RTAX_NETMASK, *++argv, nrflags); | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case K_NET: | case K_NET: | ||||
nrflags |= F_FORCENET; | nrflags |= F_FORCENET; | ||||
break; | break; | ||||
case K_PREFIXLEN: | case K_PREFIXLEN: | ||||
if (!--argc) | if (!--argc) | ||||
usage(NULL); | usage(NULL); | ||||
if (prefixlen(*++argv) == -1) { | if (prefixlen(*++argv) == -1) { | ||||
Show All 18 Lines | #endif | ||||
set_metric(*++argv, key); | set_metric(*++argv, key); | ||||
break; | break; | ||||
default: | default: | ||||
usage(1+*argv); | usage(1+*argv); | ||||
} | } | ||||
} else { | } else { | ||||
if ((rtm_addrs & RTA_DST) == 0) { | if ((rtm_addrs & RTA_DST) == 0) { | ||||
dest = *argv; | dest = *argv; | ||||
if (getaddr(RTAX_DST, *argv, &hp, nrflags)) | if (getaddr(RTAX_DST, *argv, nrflags)) | ||||
nrflags |= F_ISHOST; | nrflags |= F_ISHOST; | ||||
} else if ((rtm_addrs & RTA_GATEWAY) == 0) { | } else if ((rtm_addrs & RTA_GATEWAY) == 0) { | ||||
gateway = *argv; | gateway = *argv; | ||||
getaddr(RTAX_GATEWAY, *argv, &hp, nrflags); | getaddr(RTAX_GATEWAY, *argv, nrflags); | ||||
} else { | } else { | ||||
getaddr(RTAX_NETMASK, *argv, NULL, nrflags); | getaddr(RTAX_NETMASK, *argv, nrflags); | ||||
nrflags |= F_FORCENET; | nrflags |= F_FORCENET; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
/* Do some sanity checks on resulting request */ | /* Do some sanity checks on resulting request */ | ||||
if (so[RTAX_DST].ss_len == 0) { | if (so[RTAX_DST].ss_len == 0) { | ||||
warnx("destination parameter required"); | warnx("destination parameter required"); | ||||
▲ Show 20 Lines • Show All 175 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* Interpret an argument as a network address of some kind, | * Interpret an argument as a network address of some kind, | ||||
* returning 1 if a host address, 0 if a network address. | * returning 1 if a host address, 0 if a network address. | ||||
*/ | */ | ||||
static int | static int | ||||
getaddr(int idx, char *str, struct hostent **hpp, int nrflags) | getaddr(int idx, char *str, int nrflags) | ||||
{ | { | ||||
struct sockaddr *sa; | struct sockaddr *sa; | ||||
#if defined(INET) | #if defined(INET) | ||||
struct sockaddr_in *sin; | struct sockaddr_in *sin; | ||||
struct hostent *hp; | struct hostent *hp; | ||||
char *q; | char *q; | ||||
#elif defined(INET6) | #elif defined(INET6) | ||||
char *q; | char *q; | ||||
#endif | #endif | ||||
if (idx < 0 || idx >= RTAX_MAX) | if (idx < 0 || idx >= RTAX_MAX) | ||||
usage("internal error"); | usage("internal error"); | ||||
if (af == 0) { | if (af == 0) { | ||||
#if defined(INET) | #if defined(INET) | ||||
af = AF_INET; | af = AF_INET; | ||||
aflen = sizeof(struct sockaddr_in); | aflen = sizeof(struct sockaddr_in); | ||||
#elif defined(INET6) | #elif defined(INET6) | ||||
af = AF_INET6; | af = AF_INET6; | ||||
aflen = sizeof(struct sockaddr_in6); | aflen = sizeof(struct sockaddr_in6); | ||||
#else | #else | ||||
af = AF_LINK; | af = AF_LINK; | ||||
aflen = sizeof(struct sockaddr_dl); | aflen = sizeof(struct sockaddr_dl); | ||||
#endif | #endif | ||||
} | } | ||||
#ifndef INET | |||||
hpp = NULL; | |||||
#endif | |||||
rtm_addrs |= (1 << idx); | rtm_addrs |= (1 << idx); | ||||
sa = (struct sockaddr *)&so[idx]; | sa = (struct sockaddr *)&so[idx]; | ||||
sa->sa_family = af; | sa->sa_family = af; | ||||
sa->sa_len = aflen; | sa->sa_len = aflen; | ||||
switch (idx) { | switch (idx) { | ||||
case RTAX_GATEWAY: | case RTAX_GATEWAY: | ||||
if (nrflags & F_INTERFACE) { | if (nrflags & F_INTERFACE) { | ||||
Show All 35 Lines | #endif | ||||
} | } | ||||
if (strcmp(str, "default") == 0) { | if (strcmp(str, "default") == 0) { | ||||
/* | /* | ||||
* Default is net 0.0.0.0/0 | * Default is net 0.0.0.0/0 | ||||
*/ | */ | ||||
switch (idx) { | switch (idx) { | ||||
case RTAX_DST: | case RTAX_DST: | ||||
nrflags |= F_FORCENET; | nrflags |= F_FORCENET; | ||||
getaddr(RTAX_NETMASK, str, NULL, nrflags); | getaddr(RTAX_NETMASK, str, nrflags); | ||||
break; | break; | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
switch (sa->sa_family) { | switch (sa->sa_family) { | ||||
#ifdef INET6 | #ifdef INET6 | ||||
case AF_INET6: | case AF_INET6: | ||||
{ | { | ||||
Show All 30 Lines | #ifdef INET | ||||
case AF_INET: | case AF_INET: | ||||
#endif | #endif | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
#ifdef INET | #ifdef INET | ||||
sin = (struct sockaddr_in *)(void *)sa; | sin = (struct sockaddr_in *)(void *)sa; | ||||
if (hpp == NULL) | |||||
hpp = &hp; | |||||
*hpp = NULL; | |||||
q = strchr(str,'/'); | q = strchr(str,'/'); | ||||
if (q != NULL && idx == RTAX_DST) { | if (q != NULL && idx == RTAX_DST) { | ||||
/* A.B.C.D/NUM */ | /* A.B.C.D/NUM */ | ||||
*q = '\0'; | *q = '\0'; | ||||
if (inet_aton(str, &sin->sin_addr) == 0) | if (inet_aton(str, &sin->sin_addr) == 0) | ||||
errx(EX_NOHOST, "bad address: %s", str); | errx(EX_NOHOST, "bad address: %s", str); | ||||
int masklen = strtol(q + 1, NULL, 10); | int masklen = strtol(q + 1, NULL, 10); | ||||
if (masklen < 0 || masklen > 32) | if (masklen < 0 || masklen > 32) | ||||
errx(EX_NOHOST, "bad mask length: %s", q + 1); | errx(EX_NOHOST, "bad mask length: %s", q + 1); | ||||
inet_makemask((struct sockaddr_in *)&so[RTAX_NETMASK],masklen); | inet_makemask((struct sockaddr_in *)&so[RTAX_NETMASK],masklen); | ||||
return (0); | return (0); | ||||
} | } | ||||
if (inet_aton(str, &sin->sin_addr) != 0) | if (inet_aton(str, &sin->sin_addr) != 0) | ||||
return (1); | return (1); | ||||
hp = gethostbyname(str); | hp = gethostbyname(str); | ||||
if (hp != NULL) { | if (hp != NULL) { | ||||
*hpp = hp; | |||||
sin->sin_family = hp->h_addrtype; | sin->sin_family = hp->h_addrtype; | ||||
memmove((char *)&sin->sin_addr, hp->h_addr, | memmove((char *)&sin->sin_addr, hp->h_addr, | ||||
MIN((size_t)hp->h_length, sizeof(sin->sin_addr))); | MIN((size_t)hp->h_length, sizeof(sin->sin_addr))); | ||||
return (1); | return (1); | ||||
} | } | ||||
#endif | #endif | ||||
errx(EX_NOHOST, "bad address: %s", str); | errx(EX_NOHOST, "bad address: %s", str); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 623 Lines • Show Last 20 Lines |