17c478bd9Sstevel@tonic-gate /* 2*2a9459bdSsangeeta * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 77c478bd9Sstevel@tonic-gate 87c478bd9Sstevel@tonic-gate /* 97c478bd9Sstevel@tonic-gate * Common (shared) routines used by in.routed daemon and the 107c478bd9Sstevel@tonic-gate * the rtquery utility program 117c478bd9Sstevel@tonic-gate */ 127c478bd9Sstevel@tonic-gate 137c478bd9Sstevel@tonic-gate #include "defs.h" 147c478bd9Sstevel@tonic-gate #include <ctype.h> 157c478bd9Sstevel@tonic-gate 167c478bd9Sstevel@tonic-gate /* Return the classical netmask for an IP address. */ 177c478bd9Sstevel@tonic-gate in_addr_t /* host byte order */ 187c478bd9Sstevel@tonic-gate std_mask(in_addr_t addr) /* network byte order */ 197c478bd9Sstevel@tonic-gate { 207c478bd9Sstevel@tonic-gate addr = ntohl(addr); 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate if (addr == 0) /* default route has mask 0 */ 237c478bd9Sstevel@tonic-gate return (0); 247c478bd9Sstevel@tonic-gate if (IN_CLASSA(addr)) 257c478bd9Sstevel@tonic-gate return (IN_CLASSA_NET); 267c478bd9Sstevel@tonic-gate if (IN_CLASSB(addr)) 277c478bd9Sstevel@tonic-gate return (IN_CLASSB_NET); 28*2a9459bdSsangeeta if (IN_CLASSC(addr)) 297c478bd9Sstevel@tonic-gate return (IN_CLASSC_NET); 30*2a9459bdSsangeeta return (IN_CLASSE_NET); 317c478bd9Sstevel@tonic-gate } 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate /* 347c478bd9Sstevel@tonic-gate * Get a network number as a name or a number, with an optional "/xx" 357c478bd9Sstevel@tonic-gate * netmask. 367c478bd9Sstevel@tonic-gate */ 377c478bd9Sstevel@tonic-gate boolean_t /* 0=bad */ 387c478bd9Sstevel@tonic-gate getnet(const char *name, 397c478bd9Sstevel@tonic-gate in_addr_t *netp, /* network in host byte order */ 407c478bd9Sstevel@tonic-gate in_addr_t *maskp) /* masks are always in host order */ 417c478bd9Sstevel@tonic-gate { 427c478bd9Sstevel@tonic-gate int i; 437c478bd9Sstevel@tonic-gate struct netent *np; 447c478bd9Sstevel@tonic-gate in_addr_t mask; /* in host byte order */ 457c478bd9Sstevel@tonic-gate struct in_addr in; /* a network and so host byte order */ 467c478bd9Sstevel@tonic-gate char hname[MAXHOSTNAMELEN+1]; 477c478bd9Sstevel@tonic-gate char *mname, *p; 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate /* 517c478bd9Sstevel@tonic-gate * The "name" argument of this function can be one of 527c478bd9Sstevel@tonic-gate * the follwoing: 537c478bd9Sstevel@tonic-gate * a) network name/mask 547c478bd9Sstevel@tonic-gate * b) network name 557c478bd9Sstevel@tonic-gate * c) network number/mask 567c478bd9Sstevel@tonic-gate * d) network number 577c478bd9Sstevel@tonic-gate * e) host IP address/mask 587c478bd9Sstevel@tonic-gate * f) host IP address 597c478bd9Sstevel@tonic-gate * g) "default" 607c478bd9Sstevel@tonic-gate * 617c478bd9Sstevel@tonic-gate * Detect and separate "1.2.3.4/24" 627c478bd9Sstevel@tonic-gate */ 637c478bd9Sstevel@tonic-gate if (NULL != (mname = strrchr(name, '/'))) { 647c478bd9Sstevel@tonic-gate i = (int)(mname - name); 657c478bd9Sstevel@tonic-gate if (i > (int)sizeof (hname)-1) /* name too long */ 667c478bd9Sstevel@tonic-gate return (_B_FALSE); 677c478bd9Sstevel@tonic-gate (void) memmove(hname, name, i); 687c478bd9Sstevel@tonic-gate hname[i] = '\0'; 697c478bd9Sstevel@tonic-gate mname++; 707c478bd9Sstevel@tonic-gate name = hname; 717c478bd9Sstevel@tonic-gate } 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate if ((in.s_addr = inet_network(name)) == (in_addr_t)-1) { 747c478bd9Sstevel@tonic-gate if (mname == NULL && strcasecmp(name, "default") == 0) 757c478bd9Sstevel@tonic-gate in.s_addr = ntohl(RIP_DEFAULT); 767c478bd9Sstevel@tonic-gate else if ((np = getnetbyname(name)) != NULL) 777c478bd9Sstevel@tonic-gate in.s_addr = np->n_net; 787c478bd9Sstevel@tonic-gate else 797c478bd9Sstevel@tonic-gate return (_B_FALSE); 807c478bd9Sstevel@tonic-gate } 817c478bd9Sstevel@tonic-gate /* Left-align the host-byte-order result from above. */ 827c478bd9Sstevel@tonic-gate if (0 == (in.s_addr & 0xff000000)) 837c478bd9Sstevel@tonic-gate in.s_addr <<= 8; 847c478bd9Sstevel@tonic-gate if (0 == (in.s_addr & 0xff000000)) 857c478bd9Sstevel@tonic-gate in.s_addr <<= 8; 867c478bd9Sstevel@tonic-gate if (0 == (in.s_addr & 0xff000000)) 877c478bd9Sstevel@tonic-gate in.s_addr <<= 8; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate if (mname == NULL) { 907c478bd9Sstevel@tonic-gate mask = std_mask(htonl(in.s_addr)); 917c478bd9Sstevel@tonic-gate if ((~mask & in.s_addr) != 0) 927c478bd9Sstevel@tonic-gate mask = HOST_MASK; 937c478bd9Sstevel@tonic-gate } else { 947c478bd9Sstevel@tonic-gate mask = (uint32_t)strtoul(mname, &p, 0); 957c478bd9Sstevel@tonic-gate if (*p != '\0' || mask > 32 || mname == p) 967c478bd9Sstevel@tonic-gate return (_B_FALSE); 977c478bd9Sstevel@tonic-gate if (mask != 0) 987c478bd9Sstevel@tonic-gate mask = HOST_MASK << (32-mask); 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* must have mask of 0 with default */ 1027c478bd9Sstevel@tonic-gate if (mask != 0 && in.s_addr == RIP_DEFAULT) 1037c478bd9Sstevel@tonic-gate return (_B_FALSE); 1047c478bd9Sstevel@tonic-gate /* no host bits allowed in a network number */ 1057c478bd9Sstevel@tonic-gate if ((~mask & in.s_addr) != 0) 1067c478bd9Sstevel@tonic-gate return (_B_FALSE); 1077c478bd9Sstevel@tonic-gate /* require non-zero network number */ 1087c478bd9Sstevel@tonic-gate if ((mask & in.s_addr) == 0 && in.s_addr != RIP_DEFAULT) 1097c478bd9Sstevel@tonic-gate return (_B_FALSE); 1107c478bd9Sstevel@tonic-gate if ((in.s_addr >> 24) == 0 && in.s_addr != RIP_DEFAULT) 1117c478bd9Sstevel@tonic-gate return (_B_FALSE); 1127c478bd9Sstevel@tonic-gate if ((in.s_addr >> 24) == 0xff) 1137c478bd9Sstevel@tonic-gate return (_B_FALSE); 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate *netp = in.s_addr; 1167c478bd9Sstevel@tonic-gate *maskp = mask; 1177c478bd9Sstevel@tonic-gate return (_B_TRUE); 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* 1217c478bd9Sstevel@tonic-gate * Convert string to printable characters 1227c478bd9Sstevel@tonic-gate */ 1237c478bd9Sstevel@tonic-gate char * 1247c478bd9Sstevel@tonic-gate qstring(const uchar_t *srcp, int len) 1257c478bd9Sstevel@tonic-gate { 1267c478bd9Sstevel@tonic-gate /* 1277c478bd9Sstevel@tonic-gate * Authentication schemes for RIPv2 uses the space of an 1287c478bd9Sstevel@tonic-gate * 20-octet route entry. 1297c478bd9Sstevel@tonic-gate */ 1307c478bd9Sstevel@tonic-gate static char buf[8*20+1]; 1317c478bd9Sstevel@tonic-gate char *prcp, *tmp_ptr; 1327c478bd9Sstevel@tonic-gate uchar_t c; 1337c478bd9Sstevel@tonic-gate const uchar_t *s2; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate s2 = srcp + len; 1367c478bd9Sstevel@tonic-gate while (s2 > srcp && *--s2 == '\0') 1377c478bd9Sstevel@tonic-gate len--; 1387c478bd9Sstevel@tonic-gate for (prcp = buf; len != 0 && prcp < &buf[sizeof (buf)-1]; len--) { 1397c478bd9Sstevel@tonic-gate c = *srcp++; 1407c478bd9Sstevel@tonic-gate if (isprint(c) && c != '\\') { 1417c478bd9Sstevel@tonic-gate *prcp++ = c; 1427c478bd9Sstevel@tonic-gate continue; 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate *prcp++ = '\\'; 1467c478bd9Sstevel@tonic-gate tmp_ptr = strchr("\\\\\nn\rr\tt\bb\aa\ff", c); 1477c478bd9Sstevel@tonic-gate if (tmp_ptr != NULL) 1487c478bd9Sstevel@tonic-gate *prcp++ = tmp_ptr[1]; 1497c478bd9Sstevel@tonic-gate else 1507c478bd9Sstevel@tonic-gate prcp += snprintf(prcp, 1517c478bd9Sstevel@tonic-gate (sizeof (buf) - (strlen(buf)+1)), "%o", c); 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate *prcp = '\0'; 1547c478bd9Sstevel@tonic-gate return (buf); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate /* like strtok(), but honoring backslash and not changing the source string */ 1587c478bd9Sstevel@tonic-gate int /* 0=ok, -1=bad */ 1597c478bd9Sstevel@tonic-gate parse_quote(char **linep, /* look here */ 1607c478bd9Sstevel@tonic-gate const char *delims, /* for these delimiters */ 1617c478bd9Sstevel@tonic-gate char *delimp, /* 0 or put found delimiter here */ 1627c478bd9Sstevel@tonic-gate char *buf, /* copy token to here */ 1637c478bd9Sstevel@tonic-gate int lim) /* at most this many bytes */ 1647c478bd9Sstevel@tonic-gate { 1657c478bd9Sstevel@tonic-gate char c = '\0', *pc; 1667c478bd9Sstevel@tonic-gate const char *p; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate pc = *linep; 1707c478bd9Sstevel@tonic-gate if (*pc == '\0') 1717c478bd9Sstevel@tonic-gate return (-1); 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate while (lim != 0) { 1747c478bd9Sstevel@tonic-gate c = *pc++; 1757c478bd9Sstevel@tonic-gate if (c == '\0') 1767c478bd9Sstevel@tonic-gate break; 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate if (c == '\\' && *pc != '\0') { 1797c478bd9Sstevel@tonic-gate c = *pc++; 1807c478bd9Sstevel@tonic-gate switch (c) { 1817c478bd9Sstevel@tonic-gate case 'n': 1827c478bd9Sstevel@tonic-gate c = '\n'; 1837c478bd9Sstevel@tonic-gate break; 1847c478bd9Sstevel@tonic-gate case 'r': 1857c478bd9Sstevel@tonic-gate c = '\r'; 1867c478bd9Sstevel@tonic-gate break; 1877c478bd9Sstevel@tonic-gate case 't': 1887c478bd9Sstevel@tonic-gate c = '\t'; 1897c478bd9Sstevel@tonic-gate break; 1907c478bd9Sstevel@tonic-gate case 'b': 1917c478bd9Sstevel@tonic-gate c = '\b'; 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate if (c >= '0' && c <= '7') { 1947c478bd9Sstevel@tonic-gate c -= '0'; 1957c478bd9Sstevel@tonic-gate if (*pc >= '0' && *pc <= '7') { 1967c478bd9Sstevel@tonic-gate c = (c<<3)+(*pc++ - '0'); 1977c478bd9Sstevel@tonic-gate if (*pc >= '0' && *pc <= '7') 1987c478bd9Sstevel@tonic-gate c = (c<<3)+(*pc++ - '0'); 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate } else { 2037c478bd9Sstevel@tonic-gate for (p = delims; *p != '\0'; ++p) { 2047c478bd9Sstevel@tonic-gate if (*p == c || isspace(c) && *p == ' ') 2057c478bd9Sstevel@tonic-gate goto exit; 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate *buf++ = c; 2107c478bd9Sstevel@tonic-gate --lim; 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate exit: 2137c478bd9Sstevel@tonic-gate if (lim == 0) 2147c478bd9Sstevel@tonic-gate return (-1); 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate *buf = '\0'; /* terminate copy of token */ 2177c478bd9Sstevel@tonic-gate if (delimp != NULL) 2187c478bd9Sstevel@tonic-gate *delimp = c; /* return delimiter */ 2197c478bd9Sstevel@tonic-gate *linep = pc-1; /* say where we ended */ 2207c478bd9Sstevel@tonic-gate return (0); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate /* 2247c478bd9Sstevel@tonic-gate * Find the option buffer in the msg corresponding to cmsg_type. 2257c478bd9Sstevel@tonic-gate */ 2267c478bd9Sstevel@tonic-gate void * 2277c478bd9Sstevel@tonic-gate find_ancillary(struct msghdr *msg, int cmsg_type) 2287c478bd9Sstevel@tonic-gate { 2297c478bd9Sstevel@tonic-gate struct cmsghdr *cmsg; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; 2327c478bd9Sstevel@tonic-gate cmsg = CMSG_NXTHDR(msg, cmsg)) { 2337c478bd9Sstevel@tonic-gate if (cmsg->cmsg_level == IPPROTO_IP && 2347c478bd9Sstevel@tonic-gate cmsg->cmsg_type == cmsg_type) { 2357c478bd9Sstevel@tonic-gate return (CMSG_DATA(cmsg)); 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate return (NULL); 2397c478bd9Sstevel@tonic-gate } 240