Mercurial > illumos > illumos-gate
changeset 156:c695cfe8957f onnv_19
backout 4727117/4809265: breaks punchin
author | dduvall |
---|---|
date | Mon, 11 Jul 2005 20:24:25 -0700 |
parents | 585e2e169bd6 |
children | 74b7c7bed4da |
files | usr/src/cmd/cmd-inet/usr.sbin/route.c usr/src/cmd/svc/milestone/net-init |
diffstat | 2 files changed, 422 insertions(+), 1097 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/cmd-inet/usr.sbin/route.c Mon Jul 11 19:27:08 2005 -0700 +++ b/usr/src/cmd/cmd-inet/usr.sbin/route.c Mon Jul 11 20:24:25 2005 -0700 @@ -1,10 +1,10 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ -/* All Rights Reserved */ +/* All Rights Reserved */ /* Copyright (c) 1990 Mentat Inc. */ @@ -51,11 +51,9 @@ #include <sys/file.h> #include <sys/socket.h> #include <sys/ioctl.h> -#include <sys/stat.h> #include <sys/stream.h> +#include <sys/tihdr.h> #include <sys/sysmacros.h> -#include <sys/tihdr.h> -#include <sys/types.h> #include <net/if.h> #include <net/route.h> @@ -66,7 +64,6 @@ #include <inet/mib2.h> #include <inet/ip.h> -#include <limits.h> #include <locale.h> #include <errno.h> @@ -76,8 +73,6 @@ #include <string.h> #include <stropts.h> #include <fcntl.h> -#include <setjmp.h> -#include <stdarg.h> #include <assert.h> static struct keytab { @@ -166,48 +161,15 @@ {"multirt", K_MULTIRT}, #define K_SETSRC 42 {"setsrc", K_SETSRC}, -#define K_SHOW 43 - {"show", K_SHOW}, {0, 0} }; -/* - * Size of buffers used to hold command lines from the saved route file as - * well as error strings. - */ -#define BUF_SIZE 2048 - -typedef union sockunion { +static union sockunion { struct sockaddr sa; struct sockaddr_in sin; struct sockaddr_dl sdl; struct sockaddr_in6 sin6; -} su_t; - -/* - * This structure represents the digested information from parsing arguments - * to route add, change, delete, and get. - * - */ -typedef struct rtcmd_irep { - int ri_cmd; - int ri_flags; - int ri_af; - int ri_masklen; - ulong_t ri_inits; - struct rt_metrics ri_metrics; - int ri_addrs; - su_t ri_dst; - char *ri_dest_str; - su_t ri_src; - su_t ri_gate; - struct hostent *ri_gate_hp; - char *ri_gate_str; - su_t ri_mask; - su_t ri_ifa; - su_t ri_ifp; - char *ri_ifp_str; -} rtcmd_irep_t; +} so_dst, so_gate, so_mask, so_ifa, so_ifp, so_src; typedef struct mib_item_s { struct mib_item_s *next_item; @@ -217,38 +179,21 @@ intmax_t *valp; } mib_item_t; -typedef enum { - ADDR_TYPE_ANY, - ADDR_TYPE_HOST, - ADDR_TYPE_NET -} addr_type_t; +typedef union sockunion *sup; -typedef enum { - SEARCH_MODE_NULL, - SEARCH_MODE_PRINT, - SEARCH_MODE_DEL -} search_mode_t; - -static boolean_t args_to_rtcmd(rtcmd_irep_t *rcip, char **argv, - char *cmd_string); static void bprintf(FILE *fp, int b, char *s); -static boolean_t compare_rtcmd(rtcmd_irep_t *srch_rt, - rtcmd_irep_t *file_rt); static void delRouteEntry(mib2_ipRouteEntry_t *rp, mib2_ipv6RouteEntry_t *rp6, int seqno); -static void del_rtcmd_irep(rtcmd_irep_t *rcip); static void flushroutes(int argc, char *argv[]); -static boolean_t getaddr(rtcmd_irep_t *rcip, int which, char *s, - addr_type_t atype); +static boolean_t getaddr(int which, char *s, struct hostent **hpp); static boolean_t in6_getaddr(char *s, struct sockaddr_in6 *sin6, int *plenp, struct hostent **hpp); static boolean_t in_getaddr(char *s, struct sockaddr_in *sin, - int *plenp, int which, struct hostent **hpp, addr_type_t atype, - rtcmd_irep_t *rcip); + int *plenp, int which, struct hostent **hpp); static int in_getprefixlen(char *addr, int max_plen); static boolean_t in_prefixlentomask(int prefixlen, int maxlen, uchar_t *mask); -static void inet_makenetandmask(rtcmd_irep_t *rcip, in_addr_t net, +static void inet_makenetandmask(in_addr_t net, struct sockaddr_in *sin); static in_addr_t inet_makesubnetmask(in_addr_t addr, in_addr_t mask); static int keyword(char *cp); @@ -256,61 +201,32 @@ static char *link_ntoa(const struct sockaddr_dl *sdl); static mib_item_t *mibget(int sd); static char *netname(struct sockaddr *sa); -static int newroute(char **argv); -static rtcmd_irep_t *new_rtcmd_irep(void); +static int newroute(int argc, char **argv); static void pmsg_addrs(char *cp, int addrs); static void pmsg_common(struct rt_msghdr *rtm); -static void print_getmsg(rtcmd_irep_t *req_rt, - struct rt_msghdr *rtm, int msglen); -static void print_rtcmd_short(FILE *to, rtcmd_irep_t *rcip, - boolean_t gw_good, boolean_t to_saved); +static void print_getmsg(struct rt_msghdr *rtm, int msglen); static void print_rtmsg(struct rt_msghdr *rtm, int msglen); static void quit(char *s, int err); static char *routename(struct sockaddr *sa); static void rtmonitor(int argc, char *argv[]); -static int rtmsg(rtcmd_irep_t *rcip); +static int rtmsg(int cmd, int flags); static int salen(struct sockaddr *sa); -static void save_route(int argc, char **argv); -static void save_string(char **dst, char *src); -static int search_rtfile(FILE *fp, FILE *temp_fp, rtcmd_irep_t *rt, - search_mode_t mode); -static void set_metric(rtcmd_irep_t *rcip, char *value, int key, - boolean_t lock); -static int show_saved_routes(int argc); +static void set_metric(char *value, int key); static void sockaddr(char *addr, struct sockaddr *sa); -static void sodump(su_t *su, char *which); -static void syntax_arg_missing(char *keyword); -static void syntax_bad_keyword(char *keyword); -static void syntax_error(char *err, ...); +static void sodump(sup su, char *which); static void usage(char *cp); -static void write_to_rtfile(FILE *fp, int argc, char **argv); -static pid_t pid; +static int pid, rtm_addrs; static int s; -static boolean_t nflag; +static boolean_t forcehost, forcenet, nflag; static int af = AF_INET; static boolean_t qflag, tflag; -static boolean_t verbose; -static boolean_t debugonly; +static boolean_t iflag, verbose; +static boolean_t locking, lockrest, debugonly; static boolean_t fflag; -static boolean_t perm_flag; -static char perm_file_sfx[] = "/etc/inet/static_routes"; -static char *perm_file; -static char *root_dir; -static char temp_file_sfx[] = "/etc/inet/static_routes.tmp"; -static char *temp_file; - -/* - * WARNING: - * This next variable indicates whether certain functions exit when an error - * is detected in the user input. Currently, exit_on_error is only set false - * in search_rtfile(), when argument are being parsed. Only those functions - * used by search_rtfile() to parse its arguments are designed to work in - * both modes. Take particular care in setting this false to ensure that any - * functions you call that might act on this flag properly return errors when - * exit_on_error is false. - */ -static int exit_on_error = B_TRUE; +static struct rt_metrics rt_metrics; +static ulong_t rtm_inits; +static int masklen; static struct { struct rt_msghdr m_rtm; @@ -336,48 +252,18 @@ #define BAD_ADDR -1 /* prefix is invalid */ #define NO_PREFIX -2 /* no prefix was found */ - void usage(char *cp) { - if (cp != NULL) { + if (cp != NULL) (void) fprintf(stderr, gettext("route: botched keyword: %s\n"), cp); - } - (void) fprintf(stderr, gettext("usage: route [ -fnpqv ] " - "[ -R <root-dir> ] cmd [[ -<qualifers> ] args ]\n")); + (void) fprintf(stderr, + gettext("usage: route [ -fnqv ] cmd [[ -<qualifers> ] args ]\n")); exit(1); /* NOTREACHED */ } -/*PRINTFLIKE1*/ -void -syntax_error(char *err, ...) -{ - va_list args; - - if (exit_on_error) { - va_start(args, err); - (void) vfprintf(stderr, err, args); - va_end(args); - exit(1); - } - /* NOTREACHED */ -} - -void -syntax_bad_keyword(char *keyword) -{ - syntax_error(gettext("route: botched keyword: %s\n"), keyword); -} - -void -syntax_arg_missing(char *keyword) -{ - syntax_error(gettext("route: argument required following keyword %s\n"), - keyword); -} - void quit(char *s, int sverrno) { @@ -393,11 +279,8 @@ main(int argc, char **argv) { extern int optind; - extern char *optarg; int ch; int key; - int rval; - size_t size; (void) setlocale(LC_ALL, ""); @@ -409,7 +292,7 @@ if (argc < 2) usage((char *)NULL); - while ((ch = getopt(argc, argv, "R:nqdtvfp")) != EOF) { + while ((ch = getopt(argc, argv, "nqdtvf")) != EOF) { switch (ch) { case 'n': nflag = B_TRUE; @@ -429,12 +312,6 @@ case 'f': fflag = B_TRUE; break; - case 'p': - perm_flag = B_TRUE; - break; - case 'R': - root_dir = optarg; - break; case '?': default: usage((char *)NULL); @@ -451,29 +328,6 @@ s = socket(PF_ROUTE, SOCK_RAW, 0); if (s < 0) quit("socket", errno); - - /* - * Handle the -p and -R flags. The -R flag only applies - * when the -p flag is set. - */ - if (root_dir == NULL) { - perm_file = perm_file_sfx; - temp_file = temp_file_sfx; - } else { - size = strlen(root_dir) + sizeof (perm_file_sfx); - perm_file = malloc(size); - if (perm_file == NULL) - quit("malloc", errno); - (void) snprintf(perm_file, size, "%s%s", root_dir, - perm_file_sfx); - size = strlen(root_dir) + sizeof (temp_file_sfx); - temp_file = malloc(size); - if (temp_file == NULL) - quit("malloc", errno); - (void) snprintf(temp_file, size, "%s%s", root_dir, - temp_file_sfx); - } - if (fflag) { /* * Accept an address family keyword after the -f. Since the @@ -492,56 +346,24 @@ break; } } - if (perm_flag && root_dir != NULL) { - /* - * Act only on the file. - */ - save_route(argc, argv); - } else { - flushroutes(0, NULL); - } + flushroutes(0, NULL); } - if (*argv != NULL) { - fflag = 0; switch (keyword(*argv)) { case K_GET: case K_CHANGE: case K_ADD: case K_DELETE: - if (perm_flag && root_dir != NULL) { - /* - * Act only on the file. - */ - rval = 0; - } else { - rval = newroute(argv); - } - if (perm_flag && (rval == 0 || rval == EEXIST || - rval == ESRCH)) { - save_route(argc, argv); - return (0); - } - return (rval); - case K_SHOW: - if (perm_flag) { - return (show_saved_routes(argc)); - } else { - syntax_error(gettext( - "route: show command requires -p")); - } - /* NOTREACHED */ + return (newroute(argc, argv)); + case K_MONITOR: rtmonitor(argc, argv); /* NOTREACHED */ case K_FLUSH: flushroutes(argc, argv); - if (perm_flag) { - fflag = 1; - save_route(argc, argv); - } - return (0); + exit(0); + /* NOTREACHED */ } } if (!fflag) @@ -1003,140 +825,14 @@ return (line); } -/* - * Initialize a new structure. Keep in mind that ri_dst_str, ri_gate_str and - * ri_ifp_str will be freed by det_rtcmd_irep, so they should either be NULL - * or point to dynamically allocated memory. - */ -rtcmd_irep_t * -new_rtcmd_irep(void) -{ - rtcmd_irep_t *rcip; - - rcip = calloc(1, sizeof (rtcmd_irep_t)); - if (rcip == NULL) { - quit("calloc", errno); - } - rcip->ri_af = AF_INET; - rcip->ri_flags = RTF_STATIC; - return (rcip); -} - void -del_rtcmd_irep(rtcmd_irep_t *rcip) -{ - free(rcip->ri_dest_str); - free(rcip->ri_gate_str); - free(rcip->ri_ifp_str); - if (rcip->ri_gate_hp != NULL) { - freehostent(rcip->ri_gate_hp); - } - free(rcip); -} - -void -save_string(char **dst, char *src) -{ - free(*dst); - *dst = strdup(src); - if (*dst == NULL) { - quit("malloc", errno); - } -} - -/* - * Print the short form summary of a route command. - * Eg. "add net default: gateway 10.0.0.1" - * The final newline is not added, allowing the caller to append additional - * information. - */ -void -print_rtcmd_short(FILE *to, rtcmd_irep_t *rcip, boolean_t gw_good, - boolean_t to_saved) -{ - char *cmd; - char obuf[INET6_ADDRSTRLEN]; - - switch (rcip->ri_cmd) { - case RTM_ADD: - cmd = "add"; - break; - case RTM_CHANGE: - cmd = "change"; - break; - case RTM_DELETE: - cmd = "delete"; - break; - case RTM_GET: - cmd = "get"; - break; - default: - assert(0); - } - - (void) fprintf(to, "%s%s %s %s", cmd, - (to_saved) ? " persistent" : "", - (rcip->ri_flags & RTF_HOST) ? "host" : "net", - (rcip->ri_dest_str == NULL) ? "NULL" : rcip->ri_dest_str); - - if (rcip->ri_gate_str != NULL) { - switch (rcip->ri_af) { - case AF_INET: - if (nflag) { - (void) fprintf(to, ": gateway %s", - inet_ntoa(rcip->ri_gate.sin.sin_addr)); - } else if (gw_good && - rcip->ri_gate_hp != NULL && - rcip->ri_gate_hp->h_addr_list[1] != NULL) { - /* - * Print the actual address used in the case - * where there was more than one address - * available for the name, and one was used - * successfully. - */ - (void) fprintf(to, ": gateway %s (%s)", - rcip->ri_gate_str, - inet_ntoa(rcip->ri_gate.sin.sin_addr)); - } else { - (void) fprintf(to, ": gateway %s", - rcip->ri_gate_str); - } - break; - case AF_INET6: - if (inet_ntop(AF_INET6, - &rcip->ri_gate.sin6.sin6_addr, obuf, - INET6_ADDRSTRLEN) != NULL) { - if (nflag) { - (void) fprintf(to, ": gateway %s", - obuf); - break; - } - if (gw_good && - rcip->ri_gate_hp->h_addr_list[1] != NULL) { - (void) fprintf(to, ": gateway %s (%s)", - rcip->ri_gate_str, obuf); - break; - } - } - /* FALLTHROUGH */ - default: - (void) fprintf(to, ": gateway %s", - rcip->ri_gate_str); - break; - } - } -} - -void -set_metric(rtcmd_irep_t *rcip, char *value, int key, boolean_t lock) +set_metric(char *value, int key) { int flag = 0; uint_t noval, *valp = &noval; switch (key) { -#define caseof(x, y, z) \ - case (x): valp = &(rcip->ri_metrics.z); flag = (y); break - +#define caseof(x, y, z) case (x): valp = &rt_metrics.z; flag = (y); break caseof(K_MTU, RTV_MTU, rmx_mtu); caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount); caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire); @@ -1147,248 +843,165 @@ caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar); #undef caseof } - rcip->ri_inits |= flag; - if (lock) - rcip->ri_metrics.rmx_locks |= flag; + rtm_inits |= flag; + if (lockrest || locking) + rt_metrics.rmx_locks |= flag; + if (locking) + locking = B_FALSE; *valp = atoi(value); } -/* - * Parse the options give in argv[], filling in rcip with the results. - * If cmd_string is non-null, argc and argv are ignored, and cmd_string is - * tokenized to produce the command line. Cmd_string is tokenized using - * strtok, which will overwrite whitespace in the string with nulls. - * - * Returns B_TRUE on success and B_FALSE on failure. - */ -boolean_t -args_to_rtcmd(rtcmd_irep_t *rcip, char **argv, char *cmd_string) +int +newroute(int argc, char **argv) { - const char *ws = "\f\n\r\t\v "; - char *tok = cmd_string; - char *keyword_str; - addr_type_t atype = ADDR_TYPE_ANY; - boolean_t iflag = B_FALSE; - boolean_t locknext = B_FALSE; - boolean_t lockrest = B_FALSE; - boolean_t dash_keyword; + char *cmd, *dest = "", *gateway = "", *err; + boolean_t ishost = B_FALSE; + int ret, attempts, oerrno, flags = RTF_STATIC; int key; - char *err; - - if (cmd_string == NULL) { - tok = argv[0]; - } else { - tok = strtok(cmd_string, ws); - } - - /* - * The command keywords are already fully checked by main() or - * search_rtfile(). - */ - switch (*tok) { - case 'a': - rcip->ri_cmd = RTM_ADD; - break; - case 'c': - rcip->ri_cmd = RTM_CHANGE; - break; - case 'd': - rcip->ri_cmd = RTM_DELETE; - break; - case 'g': - rcip->ri_cmd = RTM_GET; - break; - default: - /* NOTREACHED */ - quit(gettext("Internal Error"), EINVAL); - /* NOTREACHED */ - } - -#define NEXTTOKEN \ - ((tok = (cmd_string == NULL ? *++argv : strtok(NULL, ws))) != NULL) + struct hostent *hp = NULL; + static char obuf[INET6_ADDRSTRLEN]; - while (NEXTTOKEN) { - keyword_str = tok; - if (*tok == '-') { - dash_keyword = B_TRUE; - key = keyword(tok + 1); - } else { - dash_keyword = B_FALSE; - key = keyword(tok); - if (key != K_HOST && key != K_NET) { - /* All others must be preceded by '-' */ - key = 0; - } - } - switch (key) { - case K_HOST: - if (atype == ADDR_TYPE_NET) { - syntax_error(gettext("route: -host and -net " - "are mutually exclusive\n")); - return (B_FALSE); - } - atype = ADDR_TYPE_HOST; - break; - case K_NET: - if (atype == ADDR_TYPE_HOST) { - syntax_error(gettext("route: -host and -net " - "are mutually exclusive\n")); - return (B_FALSE); - } - atype = ADDR_TYPE_NET; - break; - case K_LINK: - rcip->ri_af = AF_LINK; - break; - case K_INET: - rcip->ri_af = AF_INET; - break; - case K_SA: - rcip->ri_af = PF_ROUTE; - break; - case K_INET6: - rcip->ri_af = AF_INET6; - break; - case K_IFACE: - case K_INTERFACE: - iflag = B_TRUE; - break; - case K_NOSTATIC: - rcip->ri_flags &= ~RTF_STATIC; - break; - case K_LOCK: - locknext = B_TRUE; - break; - case K_LOCKREST: - lockrest = B_TRUE; - break; - case K_REJECT: - rcip->ri_flags |= RTF_REJECT; - break; - case K_BLACKHOLE: - rcip->ri_flags |= RTF_BLACKHOLE; - break; - case K_PROTO1: - rcip->ri_flags |= RTF_PROTO1; - break; - case K_PROTO2: - rcip->ri_flags |= RTF_PROTO2; - break; - case K_CLONING: - rcip->ri_flags |= RTF_CLONING; - break; - case K_XRESOLVE: - rcip->ri_flags |= RTF_XRESOLVE; - break; - case K_STATIC: - rcip->ri_flags |= RTF_STATIC; - break; - case K_IFA: - if (!NEXTTOKEN) { - syntax_arg_missing(keyword_str); - return (B_FALSE); - } - if (!getaddr(rcip, RTA_IFA, tok, atype)) { - return (B_FALSE); - } - break; - case K_IFP: - if (!NEXTTOKEN) { - syntax_arg_missing(keyword_str); - return (B_FALSE); - } - if (!getaddr(rcip, RTA_IFP, tok, atype)) { - return (B_FALSE); - } - break; - case K_GATEWAY: - if (!NEXTTOKEN) { - syntax_arg_missing(keyword_str); - return (B_FALSE); - } - if (!getaddr(rcip, RTA_GATEWAY, tok, atype)) { - return (B_FALSE); - } - break; - case K_DST: - if (!NEXTTOKEN) { - syntax_arg_missing(keyword_str); - return (B_FALSE); - } - if (!getaddr(rcip, RTA_DST, tok, atype)) { - return (B_FALSE); - } - break; - case K_NETMASK: - if (!NEXTTOKEN) { - syntax_arg_missing(keyword_str); - return (B_FALSE); - } - if (!getaddr(rcip, RTA_NETMASK, tok, atype)) { - return (B_FALSE); - } - atype = ADDR_TYPE_NET; - break; - case K_MTU: - case K_HOPCOUNT: - case K_EXPIRE: - case K_RECVPIPE: - case K_SENDPIPE: - case K_SSTHRESH: - case K_RTT: - case K_RTTVAR: - if (!NEXTTOKEN) { - syntax_arg_missing(keyword_str); - return (B_FALSE); - } - set_metric(rcip, tok, key, locknext || lockrest); - locknext = B_FALSE; - break; - case K_PRIVATE: - rcip->ri_flags |= RTF_PRIVATE; - break; - case K_MULTIRT: - rcip->ri_flags |= RTF_MULTIRT; - break; - case K_SETSRC: - if (!NEXTTOKEN) { - syntax_arg_missing(keyword_str); - return (B_FALSE); - } - if (!getaddr(rcip, RTA_SRC, tok, atype)) { - return (B_FALSE); - } - rcip->ri_flags |= RTF_SETSRC; - break; - default: - if (dash_keyword) { - syntax_bad_keyword(tok + 1); - return (B_FALSE); - } - if ((rcip->ri_addrs & RTA_DST) == 0) { - if (!getaddr(rcip, RTA_DST, tok, atype)) { - return (B_FALSE); - } - } else if ((rcip->ri_addrs & RTA_GATEWAY) == 0) { + cmd = argv[0]; + if (*cmd != 'g' && !tflag) { + /* Don't want to read back our messages */ + (void) shutdown(s, 0); + } + while (--argc > 0) { + key = keyword(*(++argv)); + if (key == K_HOST) { + forcehost = B_TRUE; + } else if (key == K_NET) { + forcenet = B_TRUE; + } else if (**(argv) == '-') { + switch (key = keyword(1 + *argv)) { + case K_LINK: + af = AF_LINK; + break; + case K_INET: + af = AF_INET; + break; + case K_SA: + af = PF_ROUTE; + break; + case K_INET6: + af = AF_INET6; + break; + case K_IFACE: + case K_INTERFACE: + iflag = B_TRUE; + /* FALLTHROUGH */ + case K_NOSTATIC: + flags &= ~RTF_STATIC; + break; + case K_LOCK: + locking = B_TRUE; + break; + case K_LOCKREST: + lockrest = B_TRUE; + break; + case K_HOST: + forcehost = B_TRUE; + break; + case K_REJECT: + flags |= RTF_REJECT; + break; + case K_BLACKHOLE: + flags |= RTF_BLACKHOLE; + break; + case K_PROTO1: + flags |= RTF_PROTO1; + break; + case K_PROTO2: + flags |= RTF_PROTO2; + break; + case K_CLONING: + flags |= RTF_CLONING; + break; + case K_XRESOLVE: + flags |= RTF_XRESOLVE; + break; + case K_STATIC: + flags |= RTF_STATIC; + break; + case K_IFA: + argc--; + (void) getaddr(RTA_IFA, *++argv, NULL); + break; + case K_IFP: + argc--; + (void) getaddr(RTA_IFP, *++argv, NULL); + break; + case K_GATEWAY: /* * For the gateway parameter, retrieve the * pointer to the struct hostent so that all * possible addresses can be tried until one * is successful. */ - if (!getaddr(rcip, RTA_GATEWAY, tok, atype)) { - return (B_FALSE); - } + argc--; + gateway = *++argv; + (void) getaddr(RTA_GATEWAY, *argv, &hp); + break; + case K_DST: + argc--; + ishost = getaddr(RTA_DST, *++argv, NULL); + dest = *argv; + break; + case K_NETMASK: + argc--; + (void) getaddr(RTA_NETMASK, *++argv, NULL); + /* FALLTHROUGH */ + case K_NET: + forcenet = B_TRUE; + break; + case K_MTU: + case K_HOPCOUNT: + case K_EXPIRE: + case K_RECVPIPE: + case K_SENDPIPE: + case K_SSTHRESH: + case K_RTT: + case K_RTTVAR: + argc--; + set_metric(*++argv, key); + break; + case K_PRIVATE: + flags |= RTF_PRIVATE; + break; + case K_MULTIRT: + flags |= RTF_MULTIRT; + break; + case K_SETSRC: + argc--; + (void) getaddr(RTA_SRC, *++argv, NULL); + flags |= RTF_SETSRC; + break; + default: + usage(*argv + 1); + /* NOTREACHED */ + } + } else { + if ((rtm_addrs & RTA_DST) == 0) { + dest = *argv; + ishost = getaddr(RTA_DST, *argv, NULL); + } else if ((rtm_addrs & RTA_GATEWAY) == 0) { + /* + * For the gateway parameter, retrieve the + * pointer to the struct hostent so that all + * possible addresses can be tried until one + * is successful. + */ + gateway = *argv; + (void) getaddr(RTA_GATEWAY, *argv, &hp); } else { - ulong_t metric; + ulong_t metric = strtoul(*argv, &err, 10); + /* * Assume that a regular number is a metric. * Needed for compatibility with old route * command syntax. */ - errno = 0; - metric = strtoul(tok, &err, 10); - if (errno == 0 && *err == '\0' && + if (*argv != err && *err == '\0' && metric < 0x80000000ul) { iflag = (metric == 0); if (verbose) { @@ -1399,359 +1012,60 @@ } continue; } - if (!getaddr(rcip, RTA_NETMASK, tok, atype)) { - return (B_FALSE); - } + (void) getaddr(RTA_NETMASK, *argv, NULL); } } } -#undef NEXTTOKEN - - if ((rcip->ri_addrs & RTA_DST) == 0) { - syntax_error(gettext("route: destination required\n")); - return (B_FALSE); - } else if ((rcip->ri_cmd == RTM_ADD || rcip->ri_cmd == RTM_DELETE) && - (rcip->ri_addrs & RTA_GATEWAY) == 0) { - syntax_error(gettext( - "route: gateway required for add or delete command\n")); - return (B_FALSE); - } - - if (!iflag) { - rcip->ri_flags |= RTF_GATEWAY; - } - - if (atype != ADDR_TYPE_NET && (rcip->ri_addrs & RTA_NETMASK)) { - if ((rcip->ri_af == AF_INET && - rcip->ri_mask.sin.sin_addr.s_addr == IP_HOST_MASK) || - (rcip->ri_af == AF_INET6 && - rcip->ri_masklen == IPV6_ABITS)) { - atype = ADDR_TYPE_HOST; - } else { - atype = ADDR_TYPE_NET; - } - } - if (atype == ADDR_TYPE_HOST) { - rcip->ri_flags |= RTF_HOST; - } - return (B_TRUE); -} - -/* - * This command always seeks to the end of the file prior to writing. - */ -void -write_to_rtfile(FILE *fp, int argc, char **argv) -{ - char file_line[BUF_SIZE]; - int len; - int i; - - len = 0; - for (i = 0; argc > 0 && len < BUF_SIZE; i++, argc--) { - len += snprintf(&file_line[len], BUF_SIZE - len, "%s ", - argv[i]); - } - if (len >= BUF_SIZE) - quit(gettext("Internal Error"), EINVAL); - file_line[len - 1] = '\n'; - if (fseek(fp, 0, SEEK_END) != 0 || - fputs(file_line, fp) == EOF) { - quit(gettext("failed to write to route file"), - errno); - } -} - -boolean_t -compare_rtcmd(rtcmd_irep_t *srch_rt, rtcmd_irep_t *file_rt) -{ - if (strcmp(srch_rt->ri_dest_str, file_rt->ri_dest_str) != 0 || - memcmp(&srch_rt->ri_mask, &file_rt->ri_mask, sizeof (su_t)) != 0) { - return (B_FALSE); - } - return (srch_rt->ri_gate_str == NULL || - strcmp(srch_rt->ri_gate_str, file_rt->ri_gate_str) == 0); -} - -/* - * Search the route file for routes matching the supplied route. There are 3 - * modes of operation: - * SEARCH_MODE_RET - no side effects. - * SEARCH_MODE_PRINT - prints each matching line. - * SEARCH_MODE_DEL - copies all valid, non-matching lines to tmp_fp. - * - * In all cases, the number of matches is returned. If rt is NULL, all routes - * matching the global af value are considered matching. - */ -int -search_rtfile(FILE *fp, FILE *temp_fp, rtcmd_irep_t *rt, search_mode_t mode) -{ - char *tmp_buf; - int match_cnt; - boolean_t match; - char file_line[BUF_SIZE + 4] = "add "; - rtcmd_irep_t *thisrt; - - match_cnt = 0; - - /* - * Leave space at the beginning of file_line for "add ". - */ - while (fgets(file_line + 4, BUF_SIZE, fp) != NULL) { - - if (file_line[4] == '#' || file_line[4] == '\n') { - /* Handle comments and blank lines */ - if (mode == SEARCH_MODE_DEL && - fputs(file_line + 4, temp_fp) == EOF) { - quit(gettext( - "route: failed to write to temp file"), - errno); - } - continue; - } - thisrt = new_rtcmd_irep(); - - exit_on_error = B_FALSE; - tmp_buf = strdup(file_line); - /* args_to_rtcmd() will mangle the string passed. */ - if (!args_to_rtcmd(thisrt, NULL, tmp_buf)) { - /* There was an error in args_to_rtcmd() or helpers */ - del_rtcmd_irep(thisrt); - free(tmp_buf); - continue; - } - exit_on_error = B_TRUE; - free(tmp_buf); - - if (thisrt->ri_gate_str == NULL) { - del_rtcmd_irep(thisrt); - continue; - } - match = (rt == NULL) ? (thisrt->ri_af == af) : - compare_rtcmd(rt, thisrt); - - if (match) match_cnt++; - if (match && mode == SEARCH_MODE_PRINT) { - (void) printf("persistent: route %s", file_line); - } - if (match && mode == SEARCH_MODE_DEL) { - thisrt->ri_cmd = RTM_DELETE; - print_rtcmd_short(stdout, thisrt, B_FALSE, B_TRUE); - (void) printf("\n"); - } - del_rtcmd_irep(thisrt); - - if (!match && mode == SEARCH_MODE_DEL && - fputs(file_line + 4, temp_fp) == EOF) { - quit(gettext("failed to write to temp file"), - errno); - } - } - return (match_cnt); -} - -/* - * Perform the route operation given in argv on the persistent route file. - * If fflag is set, argc and argv are ignored, and the persisten route file - * is flushed of all routes matching the global family. - */ -void -save_route(int argc, char **argv) -{ - rtcmd_irep_t *rt; - int perm_fd; - FILE *perm_fp; - FILE *temp_fp; - mode_t fmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - struct flock lock; - struct stat st; - const char commentstr[] = - "# File generated by route(1M) - do not edit.\n"; - - perm_fd = open(perm_file, O_RDWR | O_CREAT, fmode); - if (perm_fd == -1 || fstat(perm_fd, &st) == -1) - quit("failed to open route file", errno); - - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - if (fcntl(perm_fd, F_SETLK, &lock) != 0) { - quit(gettext("failed to lock route file"), errno); - /* NOTREACHED */ - } - if (st.st_size == 0 && - write(perm_fd, commentstr, sizeof (commentstr) - 1) != - sizeof (commentstr) - 1) - quit(gettext("failed to open route file"), errno); - - if ((perm_fp = fdopen(perm_fd, "r+")) == NULL) { - quit(gettext("failed to open route file"), errno); - /* NOTREACHED */ - } - - if (!fflag) { - rt = new_rtcmd_irep(); - (void) args_to_rtcmd(rt, argv, NULL); - } - if (fflag || rt->ri_cmd == RTM_DELETE) { - if ((temp_fp = fopen(temp_file, "w")) == NULL) { - quit(gettext("failed to open temp file"), errno); - /* NOTREACHED */ - } - } - if (fflag) { - (void) search_rtfile(perm_fp, temp_fp, NULL, SEARCH_MODE_DEL); - if (fclose(temp_fp) != 0 || rename(temp_file, perm_file) != 0) { - quit(gettext("failed to update route file"), errno); - /* NOTREACHED */ - } - (void) fclose(perm_fp); - return; - } - - switch (rt->ri_cmd) { - case RTM_ADD: - if (search_rtfile(perm_fp, NULL, rt, SEARCH_MODE_NULL) > 0) { - /* Route is already in the file */ - print_rtcmd_short(stderr, rt, B_FALSE, B_TRUE); - (void) fprintf(stderr, ": entry exists\n"); - exit(1); - } - write_to_rtfile(perm_fp, argc - 1, argv + 1); - print_rtcmd_short(stdout, rt, B_FALSE, B_TRUE); - (void) printf("\n"); - break; - - case RTM_CHANGE: - syntax_error( - gettext("route: change command not supported with -p\n")); - /* NOTREACHED */ - - case RTM_DELETE: - if (search_rtfile(perm_fp, temp_fp, rt, SEARCH_MODE_DEL) <= 0) { - /* Route not found */ - print_rtcmd_short(stderr, rt, B_FALSE, B_TRUE); - (void) fprintf(stderr, gettext(": not in file\n")); - exit(1); - } - if (fclose(temp_fp) != 0 || rename(temp_file, perm_file) != 0) { - quit(gettext("failed to update route file"), errno); - /* NOTREACHED */ - } - break; - - case RTM_GET: - if (search_rtfile(perm_fp, temp_fp, rt, SEARCH_MODE_PRINT) <= - 0) { - print_rtcmd_short(stdout, rt, B_FALSE, B_TRUE); - (void) printf(gettext(": not in file\n")); - } - break; - - default: - quit(gettext("Internal Error"), EINVAL); - /* NOTREACHED */ + if ((rtm_addrs & RTA_DST) == 0) { + (void) fprintf(stderr, + gettext("route: destination required following command\n")); + usage((char *)NULL); + } else if ((*cmd == 'a' || *cmd == 'd') && + (rtm_addrs & RTA_GATEWAY) == 0) { + (void) fprintf(stderr, + gettext("route: gateway required for add or delete " + "command\n")); + usage((char *)NULL); } /* - * Closing the file unlocks it. + * If the netmask has been specified use it to determine RTF_HOST. + * Otherwise rely on the "-net" and "-host" specifiers. + * Final fallback is whether ot not any bits were set in the address + * past the classful network component. */ - (void) fclose(perm_fp); -} - -int -show_saved_routes(int argc) -{ - int perm_fd; - FILE *perm_fp; - struct flock lock; - int count = 0; - - if (argc != 1) { - syntax_error(gettext("route: invalid arguments for show\n")); - } - - perm_fd = open(perm_file, O_RDONLY, 0); - - if (perm_fd == -1) { - if (errno == ENOENT) { - (void) printf("No persistent routes are defined\n"); - return (0); - } else { - quit(gettext("failed to open route file"), errno); - } - } - lock.l_type = F_RDLCK; - lock.l_whence = SEEK_SET; - lock.l_start = 0; - lock.l_len = 0; - if (fcntl(perm_fd, F_SETLK, &lock) != 0) { - quit(gettext("failed to lock route file"), - errno); - /* NOTREACHED */ - } - if ((perm_fp = fdopen(perm_fd, "r")) == NULL) { - quit(gettext("failed to open route file"), errno); - /* NOTREACHED */ + if (rtm_addrs & RTA_NETMASK) { + if ((af == AF_INET && + so_mask.sin.sin_addr.s_addr == IP_HOST_MASK) || + (af == AF_INET6 && masklen == IPV6_ABITS)) + forcehost = B_TRUE; + else + forcenet = B_TRUE; } - count += search_rtfile(perm_fp, NULL, NULL, SEARCH_MODE_PRINT); - (void) fseek(perm_fp, 0, SEEK_SET); - af = AF_INET6; - count += search_rtfile(perm_fp, NULL, NULL, SEARCH_MODE_PRINT); - - if (count == 0) - (void) printf("No persistent routes are defined\n"); - - (void) fclose(perm_fp); - return (0); -} - -int -newroute(char **argv) -{ - rtcmd_irep_t *newrt; - int ret, attempts, oerrno; - char *err; - char obuf[INET6_ADDRSTRLEN]; -#define hp (newrt->ri_gate_hp) - - newrt = new_rtcmd_irep(); - (void) args_to_rtcmd(newrt, argv, NULL); - - if (newrt->ri_cmd != RTM_GET && !tflag) { - /* Don't want to read back our messages */ - (void) shutdown(s, 0); - } - if (newrt->ri_addrs & RTA_IFP) { - newrt->ri_ifp.sdl.sdl_index = if_nametoindex(newrt->ri_ifp_str); - if (newrt->ri_ifp.sdl.sdl_index == 0) { - if (errno != ENXIO) { - quit("if_nametoindex", errno); - } else { - (void) fprintf(stderr, - gettext("route: %s: no such interface\n"), - newrt->ri_ifp_str); - exit(1); - } - } - newrt->ri_ifp.sdl.sdl_family = AF_LINK; - } + if (forcehost) + ishost = B_TRUE; + if (forcenet) + ishost = B_FALSE; + flags |= RTF_UP; + if (ishost) + flags |= RTF_HOST; + if (!iflag) + flags |= RTF_GATEWAY; for (attempts = 1; ; attempts++) { errno = 0; - if ((ret = rtmsg(newrt)) == 0) + if ((ret = rtmsg(*cmd, flags)) == 0) break; if (errno != ENETUNREACH && errno != ESRCH) break; - if ((newrt->ri_addrs & RTA_GATEWAY) && hp != NULL && + if (*gateway != '\0' && hp != NULL && hp->h_addr_list[attempts] != NULL) { switch (af) { case AF_INET: - (void) memmove(&newrt->ri_gate.sin.sin_addr, + (void) memmove(&so_gate.sin.sin_addr, hp->h_addr_list[attempts], hp->h_length); continue; case AF_INET6: - (void) memmove(&newrt->ri_gate.sin6.sin6_addr, + (void) memmove(&so_gate.sin6.sin6_addr, hp->h_addr_list[attempts], hp->h_length); continue; } @@ -1759,40 +1073,69 @@ break; } oerrno = errno; - - if (newrt->ri_cmd != RTM_GET) { - print_rtcmd_short(stdout, newrt, (ret == 0), B_FALSE); - if (ret == 0) - (void) printf("\n"); - } else if (ret != 0) { - /* - * Note: there is nothing additional to print for get - * if ret == 0. - */ - if (nflag) { - switch (newrt->ri_af) { + if (*cmd != 'g') { + (void) printf("%s %s %s", cmd, ishost ? "host" : "net", dest); + if (*gateway != '\0') { + switch (af) { case AF_INET: - (void) printf(" %s", - inet_ntoa(newrt->ri_dst.sin.sin_addr)); + if (nflag) { + (void) printf(": gateway %s", + inet_ntoa(so_gate.sin.sin_addr)); + } else if (attempts > 1 && ret == 0) { + (void) printf(": gateway %s (%s)", + gateway, + inet_ntoa(so_gate.sin.sin_addr)); + } else { + (void) printf(": gateway %s", gateway); + } break; case AF_INET6: if (inet_ntop(AF_INET6, - (void *)&newrt->ri_dst.sin6.sin6_addr, - obuf, INET6_ADDRSTRLEN) != NULL) { - (void) printf(" %s", obuf); + (void *)&so_gate.sin6.sin6_addr, obuf, + INET6_ADDRSTRLEN) != NULL) { + if (nflag) { + (void) printf(": gateway %s", + obuf); + } else if (attempts > 1 && ret == 0) { + (void) printf(": gateway %s " + "(%s)", + gateway, obuf); + } break; } /* FALLTHROUGH */ default: - (void) printf("%s", newrt->ri_dest_str); + (void) printf(": gateway %s", gateway); break; } - } else { - (void) printf("%s", newrt->ri_dest_str); } + if (ret == 0) + (void) printf("\n"); } - if (ret != 0) { + if (*cmd == 'g') { + if (nflag) { + switch (af) { + case AF_INET: + (void) printf(" %s", + inet_ntoa(so_dst.sin.sin_addr)); + break; + case AF_INET6: + if (inet_ntop(AF_INET6, + (void *)&so_dst.sin6.sin6_addr, + obuf, INET6_ADDRSTRLEN) != NULL) { + (void) printf(" %s", obuf); + break; + } + /* FALLTHROUGH */ + default: + (void) printf("%s", dest); + break; + } + } else { + (void) printf("%s", dest); + } + } switch (oerrno) { case ESRCH: err = "not in table"; @@ -1815,11 +1158,14 @@ } (void) printf(": %s\n", err); } - - del_rtcmd_irep(newrt); + /* + * In the case of AF_INET6, one of the getipnodebyX() functions was used + * so free the allocated hostent. + */ + if (af == AF_INET6 && hp != NULL) + freehostent(hp); return (oerrno); -#undef hp } @@ -1829,9 +1175,10 @@ * on the class of address. */ static void -inet_makenetandmask(rtcmd_irep_t *rcip, in_addr_t net, struct sockaddr_in *sin) +inet_makenetandmask(in_addr_t net, struct sockaddr_in *sin) { in_addr_t addr, mask; + char *cp; if (net == 0) { mask = addr = 0; @@ -1866,11 +1213,14 @@ } sin->sin_addr.s_addr = htonl(addr); - if (!(rcip->ri_addrs & RTA_NETMASK)) { - rcip->ri_addrs |= RTA_NETMASK; - sin = &rcip->ri_mask.sin; + if (!(rtm_addrs & RTA_NETMASK)) { + rtm_addrs |= RTA_NETMASK; + sin = &so_mask.sin; sin->sin_addr.s_addr = htonl(mask); sin->sin_family = AF_INET; + cp = (char *)(&sin->sin_addr + 1); + while (*--cp == 0 && cp > (char *)sin) + ; } } @@ -1946,61 +1296,67 @@ } /* - * Interpret an argument as a network address of some kind. + * Interpret an argument as a network address of some kind, + * returning B_TRUE if a host address, B_FALSE if a network address. * * If the address family is one looked up in getaddr() using one of the * getipnodebyX() functions (currently only AF_INET6), then callers should * freehostent() the returned "struct hostent" pointer if one was passed in. - * - * If exit_on_error is true, this function will cause route to exit on error by - * calling syntax_error(). Otherwise, it returns B_TRUE on success or B_FALSE - * on failure. */ static boolean_t -getaddr(rtcmd_irep_t *rcip, int which, char *s, addr_type_t atype) +getaddr(int which, char *s, struct hostent **hpp) { - su_t *su; - struct hostent **hpp; + sup su; struct hostent *hp; boolean_t ret; - if (which == RTA_GATEWAY) { - hpp = &(rcip->ri_gate_hp); - } else { + if (s == NULL) { + (void) fprintf(stderr, + gettext("route: argument required following keyword\n")); + usage((char *)NULL); + } + if (hpp == NULL) hpp = &hp; - } *hpp = NULL; - - rcip->ri_addrs |= which; + rtm_addrs |= which; switch (which) { case RTA_DST: - save_string(&rcip->ri_dest_str, s); - su = &rcip->ri_dst; - su->sa.sa_family = rcip->ri_af; + su = &so_dst; + su->sa.sa_family = af; break; case RTA_GATEWAY: - save_string(&rcip->ri_gate_str, s); - su = &rcip->ri_gate; - su->sa.sa_family = rcip->ri_af; + su = &so_gate; + su->sa.sa_family = af; break; case RTA_NETMASK: - su = &rcip->ri_mask; - su->sa.sa_family = rcip->ri_af; + su = &so_mask; + su->sa.sa_family = af; break; case RTA_IFP: - save_string(&rcip->ri_ifp_str, s); - return (B_TRUE); + so_ifp.sdl.sdl_index = if_nametoindex(s); + if (so_ifp.sdl.sdl_index == 0) { + if (errno == ENXIO) { + (void) fprintf(stderr, + gettext("route: %s: no such interface\n"), + s); + exit(1); + } else { + quit("if_nametoindex", errno); + } + } + so_ifp.sdl.sdl_family = AF_LINK; + return (B_FALSE); /* * RTA_SRC has overloaded meaning. It can represent the * src address of incoming or outgoing packets. */ case RTA_IFA: - su = &rcip->ri_ifa; - su->sa.sa_family = rcip->ri_af; + su = &so_ifa; + su->sa.sa_family = af; break; case RTA_SRC: - su = &rcip->ri_src; - su->sa.sa_family = rcip->ri_af; + su = &so_src; + su->sa.sa_family = af; break; default: /* NOTREACHED */ @@ -2009,14 +1365,15 @@ } if (strcmp(s, "default") == 0) { if (which == RTA_DST) { - return (getaddr(rcip, RTA_NETMASK, s, ADDR_TYPE_NET)); + forcenet = B_TRUE; + (void) getaddr(RTA_NETMASK, s, NULL); } if (which == RTA_SRC) { return (B_TRUE); } - return (B_TRUE); + return (B_FALSE); } - switch (rcip->ri_af) { + switch (af) { case AF_LINK: link_addr(s, &su->sdl); return (B_TRUE); @@ -2027,47 +1384,47 @@ switch (which) { case RTA_DST: if (s[0] == '/') { - syntax_error(gettext( - "route: %s: unexpected '/'\n"), s); - return (B_FALSE); + (void) fprintf(stderr, + gettext("route: %s: unexpected '/'\n"), s); + exit(1); } - ret = in6_getaddr(s, &su->sin6, &rcip->ri_masklen, hpp); - if (ret == B_FALSE) { - return (B_FALSE); - } - switch (rcip->ri_masklen) { + ret = in6_getaddr(s, &su->sin6, &masklen, hpp); + switch (masklen) { case NO_PREFIX: /* Nothing there - ok */ - return (B_TRUE); + return (ret); case BAD_ADDR: - syntax_error(gettext( - "route: bad prefix length in %s\n"), s); - return (B_FALSE); + (void) fprintf(stderr, + gettext("route: bad prefix length in %s\n"), + s); + exit(1); + /* NOTREACHED */ default: - (void) memset(&rcip->ri_mask.sin6.sin6_addr, 0, - sizeof (rcip->ri_mask.sin6.sin6_addr)); - if (!in_prefixlentomask(rcip->ri_masklen, - IPV6_ABITS, - (uchar_t *)&rcip->ri_mask.sin6.sin6_addr)) { - syntax_error(gettext( - "route: bad prefix length: %d\n"), - rcip->ri_masklen); - return (B_FALSE); + (void) memset(&so_mask.sin6.sin6_addr, 0, + sizeof (so_mask.sin6.sin6_addr)); + if (!in_prefixlentomask(masklen, IPV6_ABITS, + (uchar_t *)&so_mask.sin6.sin6_addr)) { + (void) fprintf(stderr, + gettext("route: bad prefix length: " + "%d\n"), masklen); + exit(1); } break; } - rcip->ri_mask.sin6.sin6_family = rcip->ri_af; - rcip->ri_addrs |= RTA_NETMASK; - return (B_TRUE); + so_mask.sin6.sin6_family = af; + rtm_addrs |= RTA_NETMASK; + return (ret); case RTA_GATEWAY: case RTA_IFA: case RTA_SRC: - return (in6_getaddr(s, &su->sin6, NULL, hpp)); + ret = in6_getaddr(s, &su->sin6, NULL, hpp); + return (ret); case RTA_NETMASK: - syntax_error( + (void) fprintf(stderr, gettext("route: -netmask not supported for IPv6: " - "use <prefix>/<prefix-length> instead\n")); - return (B_FALSE); + "use <prefix>/<prefix-length> instead")); + exit(1); + /* NOTREACHED */ default: quit(gettext("Internal Error"), EINVAL); /* NOTREACHED */ @@ -2076,45 +1433,42 @@ switch (which) { case RTA_DST: if (s[0] == '/') { - syntax_error(gettext( - "route: %s: unexpected '/'\n"), s); - return (B_FALSE); + (void) fprintf(stderr, + gettext("route: %s: unexpected '/'\n"), s); + exit(1); } - ret = in_getaddr(s, &su->sin, &rcip->ri_masklen, which, - hpp, atype, rcip); - if (ret == B_FALSE) { - return (B_FALSE); - } - switch (rcip->ri_masklen) { + ret = in_getaddr(s, &su->sin, &masklen, which, hpp); + switch (masklen) { case NO_PREFIX: /* Nothing there - ok */ - return (B_TRUE); + return (ret); case BAD_ADDR: - syntax_error(gettext( - "route: bad prefix length in %s\n"), s); - return (B_FALSE); + (void) fprintf(stderr, + gettext("route: bad prefix length in %s\n"), + s); + exit(1); + /* NOTREACHED */ default: - (void) memset(&rcip->ri_mask.sin.sin_addr, 0, - sizeof (rcip->ri_mask.sin.sin_addr)); - if (!in_prefixlentomask(rcip->ri_masklen, - IP_ABITS, - (uchar_t *)&rcip->ri_mask.sin.sin_addr)) { - syntax_error(gettext( - "route: bad prefix length: %d\n"), - rcip->ri_masklen); - return (B_FALSE); + (void) memset(&so_mask.sin.sin_addr, 0, + sizeof (so_mask.sin.sin_addr)); + if (!in_prefixlentomask(masklen, IP_ABITS, + (uchar_t *)&so_mask.sin.sin_addr)) { + (void) fprintf(stderr, + gettext("route: bad prefix length: " + "%d\n"), masklen); + exit(1); } break; } - rcip->ri_mask.sin.sin_family = rcip->ri_af; - rcip->ri_addrs |= RTA_NETMASK; - return (B_TRUE); + so_mask.sin.sin_family = af; + rtm_addrs |= RTA_NETMASK; + return (ret); case RTA_GATEWAY: case RTA_IFA: case RTA_NETMASK: case RTA_SRC: - return (in_getaddr(s, &su->sin, NULL, which, hpp, atype, - rcip)); + ret = in_getaddr(s, &su->sin, NULL, which, hpp); + return (ret); default: quit(gettext("Internal Error"), EINVAL); /* NOTREACHED */ @@ -2123,14 +1477,12 @@ quit(gettext("Internal Error"), EINVAL); /* NOTREACHED */ } - return (B_TRUE); + } /* * Interpret an argument as an IPv4 network address of some kind, - * returning B_TRUE on success or B_FALSE on failure. - * This function will cause an exit() on failure if exit_on_failure is set. - * + * returning B_TRUE if a host address, B_FALSE if a network address. * Note that this *always* tries host interpretation before network * interpretation. * @@ -2141,7 +1493,7 @@ */ static boolean_t in_getaddr(char *s, struct sockaddr_in *sin, int *plenp, int which, - struct hostent **hpp, addr_type_t atype, rtcmd_irep_t *rcip) + struct hostent **hpp) { struct hostent *hp; struct netent *np; @@ -2163,8 +1515,9 @@ if (cp != NULL) *cp = '\0'; } else if (strchr(str, '/') != NULL) { - syntax_error(gettext("route: %s: unexpected '/'\n"), str); - return (B_FALSE); + (void) fprintf(stderr, gettext("route: %s: unexpected '/'\n"), + str); + exit(1); } (void) memset(sin, 0, sizeof (*sin)); @@ -2176,50 +1529,42 @@ */ if ((((val = inet_addr(str)) != (in_addr_t)-1) || strcmp(str, "255.255.255.255") == 0) && - (which != RTA_DST || atype != ADDR_TYPE_NET)) { + (which != RTA_DST || !forcenet)) { sin->sin_addr.s_addr = val; if (inet_lnaof(sin->sin_addr) != INADDR_ANY || - atype == ADDR_TYPE_HOST) { - if (rcip->ri_masklen == NO_PREFIX) { - rcip->ri_masklen = 32; - } + forcehost) return (B_TRUE); - } val = ntohl(val); if (which == RTA_DST) - inet_makenetandmask(rcip, val, sin); - return (B_TRUE); + inet_makenetandmask(val, sin); + return (B_FALSE); } - if (atype != ADDR_TYPE_HOST && (val = inet_network(str)) != - (in_addr_t)-1) { + if (!forcehost && (val = inet_network(str)) != (in_addr_t)-1) { if (which == RTA_DST) - inet_makenetandmask(rcip, val, sin); - return (B_TRUE); + inet_makenetandmask(val, sin); + return (B_FALSE); } - if ((which != RTA_DST || atype != ADDR_TYPE_NET) && + if ((which != RTA_DST || !forcenet) && (hp = gethostbyname(str)) != NULL) { *hpp = hp; (void) memmove(&sin->sin_addr, hp->h_addr, hp->h_length); - if (rcip->ri_masklen == NO_PREFIX) { - rcip->ri_masklen = 32; - } return (B_TRUE); } - if (atype != ADDR_TYPE_HOST && (np = getnetbyname(str)) != NULL && + if (!forcehost && (np = getnetbyname(str)) != NULL && (val = np->n_net) != 0) { if (which == RTA_DST) - inet_makenetandmask(rcip, val, sin); - return (B_TRUE); + inet_makenetandmask(val, sin); + return (B_FALSE); } - syntax_error(gettext("%s: bad value\n"), s); - return (B_FALSE); + (void) fprintf(stderr, gettext("%s: bad value\n"), s); + exit(1); + /* NOTREACHED */ } /* * Interpret an argument as an IPv6 network address of some kind, - * returning B_TRUE on success or B_FALSE on failure. - * This function will cause an exit() on failure if exit_on_failure is set. + * returning B_TRUE if a host address, B_FALSE if a network address. * * If the last argument is non-NULL allow a <addr>/<n> syntax and * pass out <n> in *plenp. @@ -2249,8 +1594,9 @@ if (cp != NULL) *cp = '\0'; } else if (strchr(str, '/') != NULL) { - syntax_error(gettext("route: %s: unexpected '/'\n"), str); - return (B_FALSE); + (void) fprintf(stderr, gettext("route: %s: unexpected '/'\n"), + str); + exit(1); } (void) memset(sin6, 0, sizeof (struct sockaddr_in6)); @@ -2263,19 +1609,13 @@ return (B_TRUE); } if (error_num == TRY_AGAIN) { - /* - * This isn't a problem if we aren't going to use the address - * right away. - */ - if (!exit_on_error) { - return (B_TRUE); - } - syntax_error(gettext("route: %s: bad address (try " + (void) fprintf(stderr, gettext("route: %s: bad address (try " "again later)\n"), s); - return (B_FALSE); + } else { + (void) fprintf(stderr, gettext("route: %s: bad address\n"), s); } - syntax_error(gettext("route: %s: bad address\n"), s); - return (B_FALSE); + exit(1); + /* NOTREACHED */ } /* @@ -2374,7 +1714,7 @@ } int -rtmsg(rtcmd_irep_t *newrt) +rtmsg(int cmd, int flags) { static int seq; int rlen; @@ -2383,39 +1723,46 @@ errno = 0; (void) memset(&m_rtmsg, 0, sizeof (m_rtmsg)); - - if (newrt->ri_cmd == RTM_GET) { - newrt->ri_ifp.sa.sa_family = AF_LINK; - newrt->ri_addrs |= RTA_IFP; + if (cmd == 'a') { + cmd = RTM_ADD; + } else if (cmd == 'c') { + cmd = RTM_CHANGE; + } else if (cmd == 'g') { + cmd = RTM_GET; + if (so_ifp.sa.sa_family == 0) { + so_ifp.sa.sa_family = AF_LINK; + rtm_addrs |= RTA_IFP; + } + } else { + cmd = RTM_DELETE; } - #define rtm m_rtmsg.m_rtm - rtm.rtm_type = newrt->ri_cmd; - rtm.rtm_flags = newrt->ri_flags; + rtm.rtm_type = cmd; + rtm.rtm_flags = flags; rtm.rtm_version = RTM_VERSION; rtm.rtm_seq = ++seq; - rtm.rtm_addrs = newrt->ri_addrs; - rtm.rtm_rmx = newrt->ri_metrics; - rtm.rtm_inits = newrt->ri_inits; + rtm.rtm_addrs = rtm_addrs; + rtm.rtm_rmx = rt_metrics; + rtm.rtm_inits = rtm_inits; #define NEXTADDR(w, u) \ - if (newrt->ri_addrs & (w)) { \ + if (rtm_addrs & (w)) { \ l = ROUNDUP_LONG(salen(&u.sa)); \ (void) memmove(cp, &(u), l); \ cp += l; \ if (verbose) \ sodump(&(u), #u); \ } - NEXTADDR(RTA_DST, newrt->ri_dst); - NEXTADDR(RTA_GATEWAY, newrt->ri_gate); - NEXTADDR(RTA_NETMASK, newrt->ri_mask); - NEXTADDR(RTA_IFP, newrt->ri_ifp); - NEXTADDR(RTA_IFA, newrt->ri_ifa); + NEXTADDR(RTA_DST, so_dst); + NEXTADDR(RTA_GATEWAY, so_gate); + NEXTADDR(RTA_NETMASK, so_mask); + NEXTADDR(RTA_IFP, so_ifp); + NEXTADDR(RTA_IFA, so_ifa); /* * RTA_SRC has overloaded meaning. It can represent the * src address of incoming or outgoing packets. */ - NEXTADDR(RTA_SRC, newrt->ri_src); + NEXTADDR(RTA_SRC, so_src); #undef NEXTADDR rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; if (verbose) @@ -2443,7 +1790,7 @@ "len\n"), rlen); return (-1); } - if (newrt->ri_cmd == RTM_GET) { + if (cmd == RTM_GET) { do { l = read(s, (char *)&m_rtmsg, sizeof (m_rtmsg)); } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); @@ -2452,7 +1799,7 @@ gettext("route: read from routing socket: %s\n"), strerror(errno)); } else { - print_getmsg(newrt, &rtm, l); + print_getmsg(&rtm, l); } } #undef rtm @@ -2549,7 +1896,7 @@ } void -print_getmsg(rtcmd_irep_t *req_rt, struct rt_msghdr *rtm, int msglen) +print_getmsg(struct rt_msghdr *rtm, int msglen) { struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL, *src = NULL; struct sockaddr_dl *ifp = NULL; @@ -2557,7 +1904,7 @@ char *cp; int i; - (void) printf(" route to: %s\n", routename(&req_rt->ri_dst.sa)); + (void) printf(" route to: %s\n", routename(&so_dst.sa)); if (rtm->rtm_version != RTM_VERSION) { (void) fprintf(stderr, gettext("routing message version %d not understood\n"), @@ -2740,7 +2087,7 @@ } void -sodump(su_t *su, char *which) +sodump(sup su, char *which) { static char obuf[INET6_ADDRSTRLEN];
--- a/usr/src/cmd/svc/milestone/net-init Mon Jul 11 19:27:08 2005 -0700 +++ b/usr/src/cmd/svc/milestone/net-init Mon Jul 11 20:24:25 2005 -0700 @@ -21,7 +21,7 @@ # CDDL HEADER END # # -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -219,16 +219,6 @@ defrouters= fi -# Make a first pass through /etc/inet/static_routes, attempting to add -# each route. Ignore any errors since this will be attempted again once -# the tunnels are up. -# -if [ -f /etc/inet/static_routes ]; then - /usr/bin/egrep -v "^(#|$)" /etc/inet/static_routes | while read line; do - /usr/sbin/route add $line - done > /dev/null 2>&1 -fi - # # Use routeadm(1M) to configure forwarding and launch routing daemons for # IPv4 and IPv6 based on preset values. These settings only apply to the @@ -368,17 +358,5 @@ fi fi -# -# Make a second pass through /etc/inet/static_routes, attempting to add -# each route. This time, any errors except those for duplicates entries -# are reported. -# -if [ -f /etc/inet/static_routes ]; then - /usr/bin/egrep -v "^(#|$)" /etc/inet/static_routes | while read line; do - /usr/sbin/route add $line - done | /usr/bin/egrep -v "^[^:]+:[^:]+(: entry exists)?\$" >\ - /dev/msglog 2>&1 -fi - # Clear exit status. exit 0