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