xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/in.routed/common.c (revision 0:68f95e015346)
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