Mercurial > illumos > onarm
diff usr/src/cmd/cmd-inet/usr.sbin/in.routed/common.c @ 0:c9caec207d52 b86
Initial porting based on b86
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Tue, 02 Jun 2009 18:56:50 +0900 |
parents | |
children | 1a15d5aaf794 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/cmd/cmd-inet/usr.sbin/in.routed/common.c Tue Jun 02 18:56:50 2009 +0900 @@ -0,0 +1,239 @@ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "@(#)common.c 2.2 07/12/03 SMI" + +/* + * Common (shared) routines used by in.routed daemon and the + * the rtquery utility program + */ + +#include "defs.h" +#include <ctype.h> + +/* Return the classical netmask for an IP address. */ +in_addr_t /* host byte order */ +std_mask(in_addr_t addr) /* network byte order */ +{ + addr = ntohl(addr); + + if (addr == 0) /* default route has mask 0 */ + return (0); + if (IN_CLASSA(addr)) + return (IN_CLASSA_NET); + if (IN_CLASSB(addr)) + return (IN_CLASSB_NET); + if (IN_CLASSC(addr)) + return (IN_CLASSC_NET); + return (IN_CLASSE_NET); +} + +/* + * Get a network number as a name or a number, with an optional "/xx" + * netmask. + */ +boolean_t /* 0=bad */ +getnet(const char *name, + in_addr_t *netp, /* network in host byte order */ + in_addr_t *maskp) /* masks are always in host order */ +{ + int i; + struct netent *np; + in_addr_t mask; /* in host byte order */ + struct in_addr in; /* a network and so host byte order */ + char hname[MAXHOSTNAMELEN+1]; + char *mname, *p; + + + /* + * The "name" argument of this function can be one of + * the follwoing: + * a) network name/mask + * b) network name + * c) network number/mask + * d) network number + * e) host IP address/mask + * f) host IP address + * g) "default" + * + * Detect and separate "1.2.3.4/24" + */ + if (NULL != (mname = strrchr(name, '/'))) { + i = (int)(mname - name); + if (i > (int)sizeof (hname)-1) /* name too long */ + return (_B_FALSE); + (void) memmove(hname, name, i); + hname[i] = '\0'; + mname++; + name = hname; + } + + if ((in.s_addr = inet_network(name)) == (in_addr_t)-1) { + if (mname == NULL && strcasecmp(name, "default") == 0) + in.s_addr = ntohl(RIP_DEFAULT); + else if ((np = getnetbyname(name)) != NULL) + in.s_addr = np->n_net; + else + return (_B_FALSE); + } + /* Left-align the host-byte-order result from above. */ + if (0 == (in.s_addr & 0xff000000)) + in.s_addr <<= 8; + if (0 == (in.s_addr & 0xff000000)) + in.s_addr <<= 8; + if (0 == (in.s_addr & 0xff000000)) + in.s_addr <<= 8; + + if (mname == NULL) { + mask = std_mask(htonl(in.s_addr)); + if ((~mask & in.s_addr) != 0) + mask = HOST_MASK; + } else { + mask = (uint32_t)strtoul(mname, &p, 0); + if (*p != '\0' || mask > 32 || mname == p) + return (_B_FALSE); + if (mask != 0) + mask = HOST_MASK << (32-mask); + } + + /* must have mask of 0 with default */ + if (mask != 0 && in.s_addr == RIP_DEFAULT) + return (_B_FALSE); + /* no host bits allowed in a network number */ + if ((~mask & in.s_addr) != 0) + return (_B_FALSE); + /* require non-zero network number */ + if ((mask & in.s_addr) == 0 && in.s_addr != RIP_DEFAULT) + return (_B_FALSE); + if ((in.s_addr >> 24) == 0 && in.s_addr != RIP_DEFAULT) + return (_B_FALSE); + if ((in.s_addr >> 24) == 0xff) + return (_B_FALSE); + + *netp = in.s_addr; + *maskp = mask; + return (_B_TRUE); +} + +/* + * Convert string to printable characters + */ +char * +qstring(const uchar_t *srcp, int len) +{ + /* + * Authentication schemes for RIPv2 uses the space of an + * 20-octet route entry. + */ + static char buf[8*20+1]; + char *prcp, *tmp_ptr; + uchar_t c; + const uchar_t *s2; + + s2 = srcp + len; + while (s2 > srcp && *--s2 == '\0') + len--; + for (prcp = buf; len != 0 && prcp < &buf[sizeof (buf)-1]; len--) { + c = *srcp++; + if (isprint(c) && c != '\\') { + *prcp++ = c; + continue; + } + + *prcp++ = '\\'; + tmp_ptr = strchr("\\\\\nn\rr\tt\bb\aa\ff", c); + if (tmp_ptr != NULL) + *prcp++ = tmp_ptr[1]; + else + prcp += snprintf(prcp, + (sizeof (buf) - (strlen(buf)+1)), "%o", c); + } + *prcp = '\0'; + return (buf); +} + +/* like strtok(), but honoring backslash and not changing the source string */ +int /* 0=ok, -1=bad */ +parse_quote(char **linep, /* look here */ + const char *delims, /* for these delimiters */ + char *delimp, /* 0 or put found delimiter here */ + char *buf, /* copy token to here */ + int lim) /* at most this many bytes */ +{ + char c = '\0', *pc; + const char *p; + + + pc = *linep; + if (*pc == '\0') + return (-1); + + while (lim != 0) { + c = *pc++; + if (c == '\0') + break; + + if (c == '\\' && *pc != '\0') { + c = *pc++; + switch (c) { + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'b': + c = '\b'; + } + if (c >= '0' && c <= '7') { + c -= '0'; + if (*pc >= '0' && *pc <= '7') { + c = (c<<3)+(*pc++ - '0'); + if (*pc >= '0' && *pc <= '7') + c = (c<<3)+(*pc++ - '0'); + } + } + + } else { + for (p = delims; *p != '\0'; ++p) { + if (*p == c || isspace(c) && *p == ' ') + goto exit; + } + } + + *buf++ = c; + --lim; + } +exit: + if (lim == 0) + return (-1); + + *buf = '\0'; /* terminate copy of token */ + if (delimp != NULL) + *delimp = c; /* return delimiter */ + *linep = pc-1; /* say where we ended */ + return (0); +} + +/* + * Find the option buffer in the msg corresponding to cmsg_type. + */ +void * +find_ancillary(struct msghdr *msg, int cmsg_type) +{ + struct cmsghdr *cmsg; + + for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(msg, cmsg)) { + if (cmsg->cmsg_level == IPPROTO_IP && + cmsg->cmsg_type == cmsg_type) { + return (CMSG_DATA(cmsg)); + } + } + return (NULL); +}