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