1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate /* 9*0Sstevel@tonic-gate * Common (shared) routines used by in.routed daemon and the 10*0Sstevel@tonic-gate * the rtquery utility program 11*0Sstevel@tonic-gate */ 12*0Sstevel@tonic-gate 13*0Sstevel@tonic-gate #include "defs.h" 14*0Sstevel@tonic-gate #include <ctype.h> 15*0Sstevel@tonic-gate 16*0Sstevel@tonic-gate /* Return the classical netmask for an IP address. */ 17*0Sstevel@tonic-gate in_addr_t /* host byte order */ 18*0Sstevel@tonic-gate std_mask(in_addr_t addr) /* network byte order */ 19*0Sstevel@tonic-gate { 20*0Sstevel@tonic-gate addr = ntohl(addr); 21*0Sstevel@tonic-gate 22*0Sstevel@tonic-gate if (addr == 0) /* default route has mask 0 */ 23*0Sstevel@tonic-gate return (0); 24*0Sstevel@tonic-gate if (IN_CLASSA(addr)) 25*0Sstevel@tonic-gate return (IN_CLASSA_NET); 26*0Sstevel@tonic-gate if (IN_CLASSB(addr)) 27*0Sstevel@tonic-gate return (IN_CLASSB_NET); 28*0Sstevel@tonic-gate return (IN_CLASSC_NET); 29*0Sstevel@tonic-gate } 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate /* 32*0Sstevel@tonic-gate * Get a network number as a name or a number, with an optional "/xx" 33*0Sstevel@tonic-gate * netmask. 34*0Sstevel@tonic-gate */ 35*0Sstevel@tonic-gate boolean_t /* 0=bad */ 36*0Sstevel@tonic-gate getnet(const char *name, 37*0Sstevel@tonic-gate in_addr_t *netp, /* network in host byte order */ 38*0Sstevel@tonic-gate in_addr_t *maskp) /* masks are always in host order */ 39*0Sstevel@tonic-gate { 40*0Sstevel@tonic-gate int i; 41*0Sstevel@tonic-gate struct netent *np; 42*0Sstevel@tonic-gate in_addr_t mask; /* in host byte order */ 43*0Sstevel@tonic-gate struct in_addr in; /* a network and so host byte order */ 44*0Sstevel@tonic-gate char hname[MAXHOSTNAMELEN+1]; 45*0Sstevel@tonic-gate char *mname, *p; 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate /* 49*0Sstevel@tonic-gate * The "name" argument of this function can be one of 50*0Sstevel@tonic-gate * the follwoing: 51*0Sstevel@tonic-gate * a) network name/mask 52*0Sstevel@tonic-gate * b) network name 53*0Sstevel@tonic-gate * c) network number/mask 54*0Sstevel@tonic-gate * d) network number 55*0Sstevel@tonic-gate * e) host IP address/mask 56*0Sstevel@tonic-gate * f) host IP address 57*0Sstevel@tonic-gate * g) "default" 58*0Sstevel@tonic-gate * 59*0Sstevel@tonic-gate * Detect and separate "1.2.3.4/24" 60*0Sstevel@tonic-gate */ 61*0Sstevel@tonic-gate if (NULL != (mname = strrchr(name, '/'))) { 62*0Sstevel@tonic-gate i = (int)(mname - name); 63*0Sstevel@tonic-gate if (i > (int)sizeof (hname)-1) /* name too long */ 64*0Sstevel@tonic-gate return (_B_FALSE); 65*0Sstevel@tonic-gate (void) memmove(hname, name, i); 66*0Sstevel@tonic-gate hname[i] = '\0'; 67*0Sstevel@tonic-gate mname++; 68*0Sstevel@tonic-gate name = hname; 69*0Sstevel@tonic-gate } 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate if ((in.s_addr = inet_network(name)) == (in_addr_t)-1) { 72*0Sstevel@tonic-gate if (mname == NULL && strcasecmp(name, "default") == 0) 73*0Sstevel@tonic-gate in.s_addr = ntohl(RIP_DEFAULT); 74*0Sstevel@tonic-gate else if ((np = getnetbyname(name)) != NULL) 75*0Sstevel@tonic-gate in.s_addr = np->n_net; 76*0Sstevel@tonic-gate else 77*0Sstevel@tonic-gate return (_B_FALSE); 78*0Sstevel@tonic-gate } 79*0Sstevel@tonic-gate /* Left-align the host-byte-order result from above. */ 80*0Sstevel@tonic-gate if (0 == (in.s_addr & 0xff000000)) 81*0Sstevel@tonic-gate in.s_addr <<= 8; 82*0Sstevel@tonic-gate if (0 == (in.s_addr & 0xff000000)) 83*0Sstevel@tonic-gate in.s_addr <<= 8; 84*0Sstevel@tonic-gate if (0 == (in.s_addr & 0xff000000)) 85*0Sstevel@tonic-gate in.s_addr <<= 8; 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate if (mname == NULL) { 88*0Sstevel@tonic-gate mask = std_mask(htonl(in.s_addr)); 89*0Sstevel@tonic-gate if ((~mask & in.s_addr) != 0) 90*0Sstevel@tonic-gate mask = HOST_MASK; 91*0Sstevel@tonic-gate } else { 92*0Sstevel@tonic-gate mask = (uint32_t)strtoul(mname, &p, 0); 93*0Sstevel@tonic-gate if (*p != '\0' || mask > 32 || mname == p) 94*0Sstevel@tonic-gate return (_B_FALSE); 95*0Sstevel@tonic-gate if (mask != 0) 96*0Sstevel@tonic-gate mask = HOST_MASK << (32-mask); 97*0Sstevel@tonic-gate } 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate /* must have mask of 0 with default */ 100*0Sstevel@tonic-gate if (mask != 0 && in.s_addr == RIP_DEFAULT) 101*0Sstevel@tonic-gate return (_B_FALSE); 102*0Sstevel@tonic-gate /* no host bits allowed in a network number */ 103*0Sstevel@tonic-gate if ((~mask & in.s_addr) != 0) 104*0Sstevel@tonic-gate return (_B_FALSE); 105*0Sstevel@tonic-gate /* require non-zero network number */ 106*0Sstevel@tonic-gate if ((mask & in.s_addr) == 0 && in.s_addr != RIP_DEFAULT) 107*0Sstevel@tonic-gate return (_B_FALSE); 108*0Sstevel@tonic-gate if ((in.s_addr >> 24) == 0 && in.s_addr != RIP_DEFAULT) 109*0Sstevel@tonic-gate return (_B_FALSE); 110*0Sstevel@tonic-gate if ((in.s_addr >> 24) == 0xff) 111*0Sstevel@tonic-gate return (_B_FALSE); 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate *netp = in.s_addr; 114*0Sstevel@tonic-gate *maskp = mask; 115*0Sstevel@tonic-gate return (_B_TRUE); 116*0Sstevel@tonic-gate } 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate /* 119*0Sstevel@tonic-gate * Convert string to printable characters 120*0Sstevel@tonic-gate */ 121*0Sstevel@tonic-gate char * 122*0Sstevel@tonic-gate qstring(const uchar_t *srcp, int len) 123*0Sstevel@tonic-gate { 124*0Sstevel@tonic-gate /* 125*0Sstevel@tonic-gate * Authentication schemes for RIPv2 uses the space of an 126*0Sstevel@tonic-gate * 20-octet route entry. 127*0Sstevel@tonic-gate */ 128*0Sstevel@tonic-gate static char buf[8*20+1]; 129*0Sstevel@tonic-gate char *prcp, *tmp_ptr; 130*0Sstevel@tonic-gate uchar_t c; 131*0Sstevel@tonic-gate const uchar_t *s2; 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate s2 = srcp + len; 134*0Sstevel@tonic-gate while (s2 > srcp && *--s2 == '\0') 135*0Sstevel@tonic-gate len--; 136*0Sstevel@tonic-gate for (prcp = buf; len != 0 && prcp < &buf[sizeof (buf)-1]; len--) { 137*0Sstevel@tonic-gate c = *srcp++; 138*0Sstevel@tonic-gate if (isprint(c) && c != '\\') { 139*0Sstevel@tonic-gate *prcp++ = c; 140*0Sstevel@tonic-gate continue; 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate *prcp++ = '\\'; 144*0Sstevel@tonic-gate tmp_ptr = strchr("\\\\\nn\rr\tt\bb\aa\ff", c); 145*0Sstevel@tonic-gate if (tmp_ptr != NULL) 146*0Sstevel@tonic-gate *prcp++ = tmp_ptr[1]; 147*0Sstevel@tonic-gate else 148*0Sstevel@tonic-gate prcp += snprintf(prcp, 149*0Sstevel@tonic-gate (sizeof (buf) - (strlen(buf)+1)), "%o", c); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate *prcp = '\0'; 152*0Sstevel@tonic-gate return (buf); 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate /* like strtok(), but honoring backslash and not changing the source string */ 156*0Sstevel@tonic-gate int /* 0=ok, -1=bad */ 157*0Sstevel@tonic-gate parse_quote(char **linep, /* look here */ 158*0Sstevel@tonic-gate const char *delims, /* for these delimiters */ 159*0Sstevel@tonic-gate char *delimp, /* 0 or put found delimiter here */ 160*0Sstevel@tonic-gate char *buf, /* copy token to here */ 161*0Sstevel@tonic-gate int lim) /* at most this many bytes */ 162*0Sstevel@tonic-gate { 163*0Sstevel@tonic-gate char c = '\0', *pc; 164*0Sstevel@tonic-gate const char *p; 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate pc = *linep; 168*0Sstevel@tonic-gate if (*pc == '\0') 169*0Sstevel@tonic-gate return (-1); 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate while (lim != 0) { 172*0Sstevel@tonic-gate c = *pc++; 173*0Sstevel@tonic-gate if (c == '\0') 174*0Sstevel@tonic-gate break; 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate if (c == '\\' && *pc != '\0') { 177*0Sstevel@tonic-gate c = *pc++; 178*0Sstevel@tonic-gate switch (c) { 179*0Sstevel@tonic-gate case 'n': 180*0Sstevel@tonic-gate c = '\n'; 181*0Sstevel@tonic-gate break; 182*0Sstevel@tonic-gate case 'r': 183*0Sstevel@tonic-gate c = '\r'; 184*0Sstevel@tonic-gate break; 185*0Sstevel@tonic-gate case 't': 186*0Sstevel@tonic-gate c = '\t'; 187*0Sstevel@tonic-gate break; 188*0Sstevel@tonic-gate case 'b': 189*0Sstevel@tonic-gate c = '\b'; 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate if (c >= '0' && c <= '7') { 192*0Sstevel@tonic-gate c -= '0'; 193*0Sstevel@tonic-gate if (*pc >= '0' && *pc <= '7') { 194*0Sstevel@tonic-gate c = (c<<3)+(*pc++ - '0'); 195*0Sstevel@tonic-gate if (*pc >= '0' && *pc <= '7') 196*0Sstevel@tonic-gate c = (c<<3)+(*pc++ - '0'); 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate } 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate } else { 201*0Sstevel@tonic-gate for (p = delims; *p != '\0'; ++p) { 202*0Sstevel@tonic-gate if (*p == c || isspace(c) && *p == ' ') 203*0Sstevel@tonic-gate goto exit; 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate *buf++ = c; 208*0Sstevel@tonic-gate --lim; 209*0Sstevel@tonic-gate } 210*0Sstevel@tonic-gate exit: 211*0Sstevel@tonic-gate if (lim == 0) 212*0Sstevel@tonic-gate return (-1); 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate *buf = '\0'; /* terminate copy of token */ 215*0Sstevel@tonic-gate if (delimp != NULL) 216*0Sstevel@tonic-gate *delimp = c; /* return delimiter */ 217*0Sstevel@tonic-gate *linep = pc-1; /* say where we ended */ 218*0Sstevel@tonic-gate return (0); 219*0Sstevel@tonic-gate } 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate /* 222*0Sstevel@tonic-gate * Find the option buffer in the msg corresponding to cmsg_type. 223*0Sstevel@tonic-gate */ 224*0Sstevel@tonic-gate void * 225*0Sstevel@tonic-gate find_ancillary(struct msghdr *msg, int cmsg_type) 226*0Sstevel@tonic-gate { 227*0Sstevel@tonic-gate struct cmsghdr *cmsg; 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; 230*0Sstevel@tonic-gate cmsg = CMSG_NXTHDR(msg, cmsg)) { 231*0Sstevel@tonic-gate if (cmsg->cmsg_level == IPPROTO_IP && 232*0Sstevel@tonic-gate cmsg->cmsg_type == cmsg_type) { 233*0Sstevel@tonic-gate return (CMSG_DATA(cmsg)); 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate return (NULL); 237*0Sstevel@tonic-gate } 238